A lost world, an explorable realm

In the realm of ROAM, a world parallel of ours is left abandoned by humanity. Futuristic structures stand in states of disrepair, ruin, and rust. Explore it at your own risk.

What is ROAM?

Without leaving your world, you can explore this post-apocalyptic world on your mobile devices. Defend yourself against foes that will keep you from advancing and discover the lost world and its abandoned technologies.

Your gameplay will depend on both your current location and current weather! These characteristics in your real world will affect your performance in-game, based on what class you choose!

Roam (Backend)

An augmented reality game set in a futuristic post-apocalyptic world. Battle your enemies, team up with your friends, scavenge for inventory items and conquer bosses!


Our backend server is in charge of data storage, GeoJSON location-based polygon shape generation, AI-based generation of items and bosses, user authentication, live multiplayer tallying (both of scores and positions), weather checkup (to augment game environment) and other sorts of stuff. Of course, this is all accessible both as a RESTful API and as a realtime websocket-based interface!


We used the following technology stack for our game:

  • Redis - quick in-memory key-value store for storing user location
  • Postgres - good ol' relational database to store good ol' relational data. We'll also be using the Postgres PostGIS
  • Python - backend application server language of choice
  • Docker - for containerizing our backend application


Encryption and good software engineering practices are important for us. We used JWT for issuing out authentication tokens like any good API and we hash our passwords with 14 rounds of salt generation and Bcrypt. Take that, crackers!

As we're using Docker, our backend is completely portable! Just make sure to have Docker and Docker-Compose installed and run docker-compose up!

API Routes

  • POST /signup
    • Request Body: {username:string, password:string, class_id:int}
    • Response: {status:int, message:"success"|"failure"}
  • POST /login

    • Request Body: {username:string, password:string}
    • Response: {jwt_token:string}
  • GET /user/me/account

    • Request Header: User's JWT Token
    • Response: { username: string, hp: int, xp: int, inventory: [{ id: int, quantity: int, name: string, description: string }] }
  • POST /user/me/account

    • Request Header: User's JWT Token
    • Request Body { username: string, hp: int, xp: int, inventory: [{ id: int, quantity: int }] }
  • POST /maprender

    • Request Header: User's JWT Token
    • Request Body: { x:int, y:int, { latitude: float, longitude:float } }
    • Response: { image_url: string, weather: "sunny"|"rainy"|"cloudy", render_objects:[ { type: "player"|"ai"|"marker"|"item", description: string, latitude: float, longitude: float, ... } ] }
  • GET /items

    • Response: items_schema as JSON
  • GET /experiences

    • Response: experiences_schema as JSON

Database Schema

The schema of the data, as represented in Postgres

  • classes - id:int, name:varchar, description:text
  • items - id:int, name:varchar, description:text
  • ais - id:int, name:varchar, description:text
  • experiences - id:int, name:varchar, description:text, xp:int
  • users - id:int, username:varchar, password:varchar, class_id:int, created_at:timestamp, xp:int, hp:int
  • users_items - user_id:int, item_id:int, quantity:int
  • users_experiences - user_id:int, experience_id:string
Share this project: