Building Games with Leaflet, Turf and Albuquerque Open Data

24 Feb

I remember playing Risk as a kid. It was my first time playing a game that involved a map. When I got older, I loved playing games of world domination and strategy. As I build web maps, I often think, why couldn’t I make a game using Leaflet.js? In this post, I will describe how a game could be built with some sample code.

The Simple Game

There is no point to this game. It is an attempt to

  1. create pieces
  2. load data
  3. move the pieces with rules and
  4. accomplish a goal.

Winning the game is shown in the image below. You can test the game on JsBin.

I won the game by moving my piece in to a park.

I won the game by moving my piece in to a park.

The Game Components

The game board is made of a Leaflet.js map and Albuquerque Parks Data. The park data is loaded as a turf.polygon and pushed in to an array.

var url = “http://coagisweb.cabq.gov/arcgis/rest/services/public/fullviewer/MapServer/33/query?f=json&outSR=4326&outFields=*&where=1=1”;

http=new XMLHttpRequest();
http.open(“GET”, url, true);
http.setRequestHeader(“Content-type”, “application/x-www-form-urlencoded”);
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
console.log(“loading”);
var result= JSON.parse(http.responseText);
for(x=0;x<Object.keys(result.features).length;x++){
var pts=result.features[x].geometry.rings;
polygons.push(turf.polygon(pts));
}
L.geoJson(polygons).addTo(map);

}}
http.send();

Now that I have added the base layer, I want to create game pieces. It would be nice to also use Open Data for the players, but for now I will allow the user to click the map to drop a marker.

map.on(“click”,function(e){

var point=L.marker(e.latlng,{draggable:true}).addTo(map);

CODE BELOW GOES HERE
});

When the user clicks, a marker is added to the map and is set draggable. The game will allow the user to move the marker by dragging and attempt to land on a park. I want rules. The first rule I will create will only allow the user to drag the marker 30 pixels. This creates a problem. 30 pixels is a different distance based on the view level of the map. To fix this, I prevent the map from zooming so I know the 30 pixel fixed distance.

var map = L.map(‘map’, {center: [35.10418, -106.62987], zoom:15, touchZoom:false,scrollWheelZoom:false,doubleClickZoom:false,boxZoom:false
});

Now the user can pan but not zoom. If the user drags the marker too far, I need to set the marker to its original position. When the user starts dragging, we will get the lat,lng of it.

point.on(“dragstart”,function(z){
ll=this._latlng;
});

When the user finishes dragging the marker, we will check the distance. If it is greater than 30, we will alert them to the error and reset the marker position.

point.on(“dragend”,function(x){
if(x.distance>30){
alert(“You cannot move that far on a single turn”);
point.setLatLng(ll);}

Otherwise, we will allow the marker to move and test to see if the marker is inside of a park polygon. If it is, YAY, you win! else, keep going.

else{

for(k=0;k<polygons.length;k++){if(turf.inside(point.toGeoJSON(),polygons[k])){alert(“you made it to a park”);}}

}//else

});

This is the basic foundations of a game. To make it better, you would need to have turns and allow a computer controlled player to intervene. Maybe a zombie chase? Or you could network the game using websockets and allow users to use their real world position to play against each other(PDF) in a capture the flag or race to points type game.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: