Canvas Game Level Builder

This was kind of an interesting question. Someone was building a top-down game (ala Zelda) and wanted to supply a multi-dimensional array, with values that represent different ground types, and have that translated into a gameboard. This way, they could modify the array to create new levels:
var map=[[1,1,1,1,1,1,1,1,1,1],[1,3,0,0,0,0,2,4,0,1],[1,1,1,1,1,1,1,1,1,1]];
Here is the basic code I used, it edits the canvas size to match the map contents, then loops through the map, drawing each block:
var blocksize=30;
var can=document.getElementById('can')
if(can){ctx=can.getContext('2d');}
function init(){
can.width=map[0].length*blocksize;
can.height=map.length*blocksize;
for(y=0;y<map.length;y++){
for(x=0;x<map[y].length;x++){
draw(y,x);
}
}
can.addEventListener('click',builder);
}

function draw(y,x){
kind=map[y][x];
switch(kind){
case 0:
ctx.drawImage(floorimg,x*blocksize,y*blocksize);
break;
case 1:
ctx.drawImage(wallimg,x*blocksize,y*blocksize);
break;
case 2:
ctx.drawImage(blockimg,x*blocksize,y*blocksize);
break;
case 3:
ctx.drawImage(playerimg,x*blocksize,y*blocksize);
break;
case 4:
ctx.drawImage(goalimg,x*blocksize,y*blocksize);
break;
}
}

function ExtractNumber(value){
var n = parseInt(value);
return n == null || isNaN(n) ? 0 : n;
}
You'll see it's using images such as playerimg, which I'm leaving out here for brevity, but it's just along the lines of:
var floorimg=new Image();
floorimg.src=some_image_here;
Which would yield:
Sorry, your browser doesn't support HTML5 Canvas, please try another

So that's cool, change the values in the array (perhaps supply an entirely new map variable via AJAX?), new level. But their real request was that they'd be able to turn this into a level editor, so they'd be able to dynamically change the map by clicking. So, we needed to create a process that would 1) determine where the user clicked 2) convert that to a particular block of the canvas 3) redraw that block with the new texture value. You can see in the init() function near the top of this page that we added an event listener that would fire the builder function when the canvas is clicked. That code is shown here:
function builder(e){
if (e == null) {e = window.event;}
x = e.clientX; //where the click was
y = e.clientY;
offsetX = ExtractNumber(can.offsetLeft)-window.pageXOffset;//where the canvas is
offsetY = ExtractNumber(can.offsetTop)-window.pageYOffset;
x_grid=Math.floor((x-offsetX)/blocksize); //which block in the canvas was clicked
y_grid=Math.floor((y-offsetY)/blocksize);
map[y_grid][x_grid]++;
if(map[y_grid][x_grid]>4){map[y_grid][x_grid]=0;}
draw(y_grid,x_grid);
}

The offsetX and offsetY lines are a bit touchy, because offsetLeft and offsetTop are defined relative to the parent element, so if the canvas is within some other div which has position, it needs to be taken into account...there is this post that provides some other code that handles this dynamism. It may or may not be necessary depending on the design of your site.

You can see the map change if you play with it. The next step in that project was to create an AJAX call that would JSON.stringify the map variable, and submit it to a web service, which would append it to a text file (along with a level name)...later, that file could be retrieved in a similar manner, so levels could be loaded, edited, and saved.

The canvas element is quite versatile. I saw this game the other day and I'm hooked. Are you using canvas in any interesting projects?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>