The Playable Locations API serves collections of curated and generated geographic points (playable locations). Each playable location is chosen by Google based on its suitability for use in location-based games as spawn points for things like repair depots and game prizes.
Some playable locations are situated near prominent points of interest, some are located on sidewalks along roadways, while others are randomly located within parks, playgrounds, town squares, and other publicly accessible areas.
The goal of this document is to provide an overview of how the API was implemented so that 3P developers may leverage the key concepts to generate their own set of playable locations using an alternate data source.
This section provides an overview of the support libraries used, and introduces basic concepts related to playable locations.
The following support libraries are used throughout this guide.
|S2 Geometry||Flexible support for spatial indexing.|
|Protocol Buffers||A language-neutral, platform-neutral, extensible way of serializing structured data for use in communications protocols, data storage, and more.|
The S2 Geometry Library
The S2 Geometry Library is a geographic information system that represents data on a three-dimensional sphere. The library includes the following features:
- Support for spatial indexing.
- This allows you to approximate arbitrary areas as collections of discrete S2 Cells.
- Fast in-memory spatial indexing of collections of points, polylines, and polygons.
- Robust constructive operations (such as intersection, union, and simplification) and boolean predicates (such as testing for containment).
- Efficient query operations for finding nearby objects, measuring distances, and computing centroids.
- A collection of mathematical predicates for testing relationships among geometric primitives.
- Snap rounding.
S2 cell statistics
S2 Cell Statistics are useful for computing things like the length of time that it takes to download a data set at a particular QPS.
S2 geometry code repositories
Clone any of these repositories to get started working with S2 Cells.
The SSTable file format is used to efficiently store, process, and exchange datasets. An SSTable provides a persistent, ordered immutable map from keys to values, where both keys and values are arbitrary byte strings.
Generally speaking, a location is a geographic point on a map, but a playable location is a location deemed suitable for placing game objects in real-world games (that is, as spawn points for things like prizes).
Types of playable locations
Curated playable locations are geographic points that are associated with objects that exist at specific locations. They represent the locations of Points of Interest (POI) drawn from a Places database.
If there aren't enough curated playable locations to satisfy your criteria, then the Playable Locations API generates extra playable locations. These generated playable locations are geographic points that aren't associated with existing objects. Instead, these geographic points are programmatically created, and they're randomly placed along sidewalks, within parks, on beaches, and within playgrounds, town squares, and other publicly accessible areas.
The goal is to provide at least a minimum density of playable locations, with consideration given to the following criteria:
|Player safety||Game prizes shouldn't appear in the middle of freeways or inside military bases.|
|Appropriateness for game play||Players shouldn't disturb cemeteries or places of worship.|
Playable Location Properties
The following discusses some of the properties associated with Playable Location objects in Google's implementation that developers may find useful for building location based games.
- An alphanumeric string that uniquely identifies the location. This is a Place ID for curated playable locations (for example, Chlj79ZW1ohQwokRWPhGmWQ2K4). You can use a curated playable location's Place ID to attach game-specific metadata to the location.
- A Plus Code that uniquely identifies the generated playable location. Plus codes are alphanumeric strings. For example, 23CPRV2R+WG76. You can use a generated location's plus code to attach game- specific metadata to the location.
- An array of Playable Location types (strings) that specify the type of playable location. The first type in the array is considered the primary type. For example, you could have a playable location that is both entertainment and outdoor_recreation.
- The geographic coordinates corresponding to the location's center-point. The center-point is used to determine whether a location falls within an area of interest.
- The geographic coordinates corresponding to the location snapped to the sidewalk of the nearest road (when a nearby road exists). You can use the snapped-point to place game objects when business owners don't want game players inside their premises. When a snapped-point is not available, the center-point should be used.
- When a playable location is situated within a biome, then this field is populated with one or more BiomeType values. Examples of biomes are forests, wetlands, and urban areas.
Point Selection for Gaming
Selecting Curated Locations
As mentioned above, curated locations are real-world Points of Interest (POIs) deemed suitable for gameplay. The following will give a high-level overview of a data pipeline (with selection and filtering criteria) that one might use to generate these locations. The goal of this pipeline is to output an SStable of Curated Locations keyed on S2CellIds that could subsequently be fed into a database for real-time queries for Playable Locations in a given region.
The assumption is the developer has access to a Map Feature or Place Repository that contains a candidate set of POIs in addition to geometries of excluded regions (where Playable Locations should not exist).
The pipeline works using a combined allowlist/blocklist approach, where in one phase we select all POIs that match an allowed list of types deemed suitable for gameplay (e.g. cafe, library, florist etc) and in another we filter out all POIs that fall within a set of excluded regions. The excluded regions are formed using the geometry (e.g. bounding boxes) of predefined set of map features that are deemed unsuitable for game play (e.g. military bases, cemeteries) to generate an S2 Covering. Those S2 Coverings can then be used to see if any of the selected POIs fall within the excluded regions and if so filter them out. The final set of curated locations are then indexed by converting their center points to S2CellIds at level 30. This allows for range based lookups of Playable Locations within a specified region.
Selecting Generated Locations
As mentioned above, generated locations are used to supplement Playable Locations in areas where real-world POIs don’t have the required density for gameplay. As a general rule of thumb we have found about 9 Playable Locations in each level 16 S2 cell (~0.02 km^2) should be sufficient density for location-based games.
The generation of these "random" geographic points is also done using a combined allowlist/blocklist approach. The allowlist is a list of map features where it’s deemed suitable to generate points (e.g. parks, sidewalks etc) and the blocklist are areas where points should be excluded (e.g. water bodies, motor vehicle roads etc). In both cases the map feature geometries are used to generate an S2 covering of their respective areas and when the two sets are joined the overlapping excluded regions are subtracted from the included regions to generate the final set of candidate areas for generated locations. As the final step we "randomly" generate geographic points within those areas and write to an SStable indexed using the S2CellIds at level 30 representing the center points. For Generated Locations plus codes are used as Place IDs.
Locations Pipeline Overview
As mentioned above the output of the previous two data pipelines are two SSTables of PlayableLocation objects indexed using S2CellIds at S2 level 30. These files can be loaded into any Ordered Key-Value store for spatially indexed lookups. One option is Google’s distributed SQL database Spanner.
A biome is a community of plants and animals that share common environmental adaptation characteristics. Biomes form in response to a shared physical climate. Examples of biomes are forests, wetlands, and urban areas.
When a playable location is situated within a biome, a biomeType field can be populated with one or more BiomeType values.
You can use biome information to place different game object types on the map. For example, if the biome field contained the value grassland, then it could spawn a different type of creature than if the biome field contained the value urban.
The following describes a process for adding biome information to Playable Locations as part of the Locations pipeline above. Google’s Earth Engine has multiple land cover datasets with information classes such as forest, grassland and water that can be used to source biome information. We recommend the following high level steps for adding biome information:
- Curate data that has both biome and geolocation information.
- Assign the biome information as an attribute to existing Playable Locations
based on their geolocation, and this can usually be done by a spatial join.
For example if Biome information is available at S2 Cell level 17 and
Playable Locations are indexed using their S2CellId’s at level 30 a join can
be performed as follows:
- Map playable Locations to their S2 Cells at level 17: PlayableLocation.s2CellId.parent(17)
- Join with Biome S2CellIds at level 17
- Serve the Playable Location together with the biome attribute when available.
Querying Playable Locations
If the recommendations above are followed and we index Playable Locations using S2CellIds at level 30 (see the S2 Library for converting from LatLng to cell id) we can perform range based scans to retrieve all the playable locations in a particular region.
If we wanted to retrieve all the Playable Locations located within an S2Cell at level 12 (~5km^2) we could issue the following query:
S2CellId: 0x89c2599000000000 Range Min: 0x89c2598000000001 (s2CellId.rangeMin().id()) Range Max: 0x89c2599fffffffff (s2CellId.rangeMax().id())
SELECT * FROM PlayableLocations WHERE S2CellId BETWEEN 0x89c2598000000001 AND 0x89c2599fffffffff;
The S2Library can once again be useful to control the density of Playable Locations in your game. S2 Levels are hierarchical so each cell at level 14 contains 4 cells at level 15 and so on (See S2 Cell Statistics). These properties can be leveraged when placing game objects in your game. For example you may choose to have one "monster" per level 14 cell and in order to evenly distribute 64 "jewels" in that same area you place one "jewel" in each level 17 cell (each level 14 cell contains 64 level 17 cells).
Querying and Caching Interactions
The recommended logic flow between the game client, game server, game-state database and playable locations database is depicted in the following sequence diagram. Note it may be possible to combine the game state and playable locations into a single DB, however they are left separate here for clarity.
Bad Location Reporting
The following describes a process for collecting feedback on the quality of playable locations from within your game by allowing players to report unusable playable locations. These reports can be processed in a data pipeline and used to remove bad locations from the Playable Locations Database.
We recommend implementing bad location reporting using the following steps:
- Build a client-side entry point (mobile or web form) for players to submit structured bad point reports to the game developer.
- Construct a data pipeline to process all received reports and generate signals to help classify how bad each location is.
- Depending on the actual use case, either a pure ML model or a hybrid ML model+Human solution can be used to scale the moderation process, in order to remove inappropriate locations from the PlayableLocationsDB.
The following is a set of example criteria that could be used to help determine whether a Playable Location is bad: