The mobile video game ecosystem has took a new turn in recent years. Pokemon Go in 2018 or more recently Harry Potter Wizards Unite are location-based applications that allow us to capture and collect a variety of creatures around the world (although they mostly prefer large cities).
Like any good self-respecting developer, at Kuzzle we were keen to tinker with our own version of a GO-like app. Why don't we create (with Kuzzle) the new app to capture and collect programming languages?
Pokemon Go, Wizards Unite... Kuzzle Go soon?
Laying the foundations
The architecture of our project is divided as such: an app/ folder where we will put our Flutter application and a backend/ folder where we will put our Kuzzle server.
You can follow this guide to initialize the Flutter app in the app/ folder.
For the backend, we will use the Kuzzle core plugin boilerplate, we just need to clone the rest in our folder and name it backend/.
Let's get into it.
View Google map
First step: display the map of where you really are!
First of all, the main widget of our application ("App") contains a "DefaultTabController", it is a widget imported from the Flutter Material Design library. There is only one tab so far which is our map:
All that remains is to create our "GoMap" widget which contains the official Flutter Google Map widget (you will need to "create and import your API key" beforehand for the widget to work).
We also use the "geolocator" package to regularly retrieve the geolocation and move the camera on the map accordingly:
And here's the result! An... empty map.
Setting up collectables
We will now move on to Kuzzle to set up our languages, their apparition in the world, etc.
For this, we will use two collections: "entities" and "collectable".
"entities": this is where we will put the characteristics of the languages that we can find in the game (name, description, image, etc...).
"collectable": it is in this collection that all the instances of a language in the world will be placed. A collectable is an instance of an entity that can be caught in the game.
We will therefore start by creating the mapping of these two collections by editing the server/fixtures/default-mappings.json file:
The "collectable" collection will be filled automatically but we can already edit the server/fixtures/default-fixtures.json file the "entities" collection with the languages we want to see to appear in the game:
You can fill this file with the entities you want (other languages, cars, fruits, famous characters...).
Establishment of entities
To choose or instantiate entities in our world, we will choose the following technique: first, each client of the application will regularly register its geolocation with the backend. Then, we check if there are any collectables in an arbitrary perimeter around the player. If there are none, then an X number of randomly selected entities can be instantiated.
Let's make the code of the action "register" that will be called by the different clients to record their positions:
You must then setup this action in the plugin so that you can call it from the client!
Our work on the back end is already finished! We can now go back to our mobile application (it's fast with Kuzzle :p).
Kuzzle connection & data loading
On the mobile application side, we now need to connect to our backend and then load the data we will need to run our application: the images of each entity (our languages) and the "shared_preferences" in which we will store the entities caught by the player.
We then modify our "App" widget which now looks like this:
We can see in this code the use of the "loadNetworkImage" function which is a helper function to download an image and crop it into a specific size:
Now that we have our data loaded and transmitted to our "GoMap" widget, we can start detecting and capturing languages!
Detection and display of entities
We will add some methods to our "GoMap" widget in order to be able to hunt languages correctly.
First, we need a method that will allow us to use the action "register" (which we did earlier in our backend) by sending the position passed as an argument:
Then we need a method that will look for all entities within a 50-meter radius of our position:
Now we have to think about how the collectables will be displayed on our map: we will use Google Map markers. Simply add a "_markers" property to our widget:
We then pass this property to our map:
Once the markers are in place, we can easily create a method that will allow us to define the markers displayed on the map. A new method is created that takes the results of the previously created "_searchEntities" method as parameters and converts them into markers on the map:
Now that we have all the required methods, our previously created "_synchronize" function can evolve to this:
With all this new code, we can now see languages appear on our map:
Let’s catch them all!
Capture of entities
Only a little code remains to be added to make the capture functional. We will make a method that takes a marker ID and a collectable as parameters and removes the marker, removes the collectable from the map, displays an alert and registers in the shared preferences a counter of the number of this entity we have collected:
You must also create the alert widget, a simple window that displays the name, image and description of a captured entity:
Once all this is done, the last step is to modify our "_updateMarkers" method to add an event handler on the click of the markers to be able to call our previously created "_catchEntity" method:
You can now click on a language on the map to see what is happening and magic happens:
Before you run outside to collect all the programming languages in the world, why not add a page to view all the entities we have collected?
Listing of collected entities
We will simply add a second page to our "DefaultTabController" which will only be used to list the entries recorded in the "shared_preferences". We start by creating our new widget. It is a simple list that takes in props the entities present in the game as well as the player's "shared_preferences". The widget will then search in the preferences for the number of captures for each possible entity of the game:
All that remains is to add this widget to our "App" widget to create the new page:
We can now see in our application this superb page which will be a little bit like our language-dex (less sexy than pokedex...).
There you go! You can also try to add some features to the app:
- give a probability of occurrence to each entity
- a way to capture entities without simply clicking on them (why not write a hello world in the language you want to capture?)
- bonus objects (to make more languages appear for example)
Happy hunting ;)