Arcade games usually use a Grid to display all elements in the correct position on the canvas.
A Grid is a 2 dimensional Array, that divides the canvas into columns and rows of tiles.
For instance the Pacman game below has Grid called "maze".
Each position in the maze[x][y] holds tile-information: Empty-, Wall-, smallPill- or a bigPill- String.
The redraw(x,y) function draws the tiles on the canvas,
in the correct position:( x* tileWidth, y * tileHeight )
Let's make a smaller Grid example with gridWidth=4 and gridHeight=4;
A double for-loop is used to make a 2-dimensional Array (A big Array, with little Arrays in it).
The first for-loop creates little new arrays and puts them inside the big Array as its elements.
The second for-loop fills all of the little arrays with String-elements: 'sky'.
var
grid
=
new
Array()
;
for (
var x=0 ; x < gridWidth ; x++;
) {
grid[x] =
new Array() ;
for (
var y = 0; y < gridHeight; y++ ;
) {
grid[x][y]
=
'sky'
;
}
}
How to make a Grid......... .... "TryoutPanel1"
<script>
var tileSize=50; // change tileSize,
var gridWidth=4; // the gridWidth and
var gridHeight=4; // gridHeight
var grid = new Array() ;
for ( var x=0 ; x < gridWidth ; x++ ) { grid[x] = new Array() ;
for ( var y = 0; y < gridHeight; y++ ) { grid[x][y] = 'sky' ; } }
//////////// DRAW ////////////////////////////////////////////
function draw(x,y){ // draw tile in grid position(x,y)
canvas =document.getElementById("canvas");
context=canvas.getContext('2d');
context.fillStyle="lightBlue";
context.fillRect(x * tileSize , y * tileSize, tileSize , tileSize);
context.strokeRect(x * tileSize , y * tileSize, tileSize , tileSize); // we just stroke the rect here to show the tiles
}
///////// DRAW ALL /////////////////////////////////
function drawAll(){ /// draw all the tiles
for (var x=0;x<grid.length;x++){
for(var y=0;y<grid[x].length;y++){
draw(x,y); }
}
}
drawAll();
</script>
<canvas width="300" height="300" id="canvas" ></canvas>
<p>Play with the Grid: change <b>gridHeight</b>, <b>gridHeight</b>, <b>tileSize</b> <br>
</p>
This is a Duck Shooting game, that is made with a grid.
It's too easy though because the ducks don't fly away.
On this page you will learn to make your own duckShooting Game
And how to make it a lot more exciting, with Ducks that fly away, shoot back, obstacles...anything you want
The draw(x,y) function draws the tile of column x and row y on the right place on the canvas.
It grabs the the rigth element from the grid: grid[x][y].
function
draw (
x
,
y
) {
if (
grid[
x
][
y
]
== 'sky'
) {
context.fillStyle
=
"lightBlue" ;
}
else if(
grid[
x
][
y
]
=='grass'
){
context.fillStyle
=
"green";
}
context.fillRect(
x *
tileSize
,
y *
tileSize
,
tileSize
,
tileSize
) ;
}
In the duckShooting Game above there are some grid elements with 'sky' and some with 'grass'. If and Else statements tell what to draw in each case.
Draw your own Grid Setting......... .... "TryoutPanel2"
<script>
var tileSize=40; // tileSize,
var gridWidth=10; // gridWidth
var gridHeight=10; // gridHeight
///////////// MAKE THE GRID /////////////////////////////////////
var grid = new Array() ;
for ( var x=0 ; x < gridWidth ; x++ ) { grid[x] = new Array() ;
for ( var y = 0; y < gridHeight; y++ ) { grid[x][y] = 'sky' ; } }
for (var x=0 ; x < gridWidth ; x++ ){ grid[x][gridHeight-1] ='grass';} // bottom row is 'grass'
//...............add in more other things like grid[5][9]='fence'
//////////// DRAW ////////////////////////////////////////////
function draw(x,y){ // draw tile in grid position(x,y)
canvas =document.getElementById("canvas");
context=canvas.getContext('2d');
context.fillStyle="black";
if(grid[x][y]=='sky'){ // if grid position is sky
context.fillStyle="lightBlue"; // color blue
}
//......add an else if statement to make the 'grass' tiles green.
//....... add other things like 'fence' 'stairs' etc. (make sure to add them in Grid)
context.fillRect(x * tileSize , y * tileSize, tileSize , tileSize);
context.strokeRect(x * tileSize , y * tileSize, tileSize , tileSize); // comment out this line to remove lines
}
///////// DRAW ALL /////////////////////////////////
function drawAll(){ // draws all tiles
for (var x=0;x<gridWidth;x++){
for(var y=0;y<gridHeight;y++){
draw(x,y); }
}
}
drawAll();
</script>
<h4>Create your own Grid setting</h4>
<canvas width="400" height="400" id="canvas" ></canvas>
<p>Some tiles are <b> 'sky'</b>. Some tiles are <b>'grass'</b>.
<ul>
<li>Add an <b>else if</b> statement in the <b>draw()</b>
function to color the grass <b>green</b>(34).</li>
<li>Add other things like <b>'fence', 'stairs'</b>.(18,36)
</p>
Now you need to place your Characters(Object) in the grid. Let's start with Hunter.
Just create an Hunter Constructer like you normally do.
Only the x and y coords, are now tile positions on the grid, not pixels on the Canvas.
In the this.draw() function, you make sure that Hunter (Object) fits exactly on top of 1 tile.
this.draw
=
function ( ) {
context.drawImage(
huntImg
,
this.x *
tileSize
,
this.y *
tileSize
,
tileSize
,
tileSize
) ;
}
To move Hunter:
redraw the tile where Hunter sits(to erase him)
move Hunter by 1 tile.
Then draw Hunter in his new position
function
keysFunction(){
var
code
=
event
.
keyCode
;
if (
code==39
){
draw(
hunter
.x
,
hunter
.y
) ;
hunter
.x ++ ;
hunter
.draw()
}
....
}
Moving Animating Characters like Duck, goes exactly the same.
Look at a piece of the Duck's this.die() function(when he falls down).
this.die
=
function(){
if (
this
.y
<gridHeight
){
draw(
this
.x
,
this
.y
) ;
this
.y ++ ;
this
.draw()
}
}
Add a Character to the Grid ......... .... "TryoutPanel3"
<script>
var grid= new Array();
var gridWidth=10;
var gridHeight=10;
var tileSize=40;
var canvas;
var context;
var hunter; // global variables
var huntImg= new Image(); //create HUNTER image
huntImg.src="/pics/hunty.gif"
////////////// CREATE SETTING //////////////////////////////////
function createSetting(){ // create grid and characters
canvas=document.getElementById("canvas");
context =canvas.getContext('2d');
var x; // make 2-dimensional grid
for (x=0; x<gridWidth; x++){
grid[x]=new Array();
var y;
for(y=0;y<gridHeight;y++){
grid[x][y]='sky'; // whole grid is filled with SKY
}
}
var X,Y;
for(X=0;X<gridWidth;X++){ // draw the WHOLE GRID
for(Y=0;Y<gridHeight;Y++){
drawTile(X,Y);
}
}
hunter=new Hunter(5,9); // make the HUNTER
hunter.draw(); // draw him
}
/////////////////// DRAW TILE ////////////////////////////////////////////
function drawTile(x,y){ // DRAWTILE function to draw individual TILES
if(grid[x][y]=='sky'){ // pieces of SKY
context.fillStyle='lightBlue';
context.fillRect(x*tileSize,y*tileSize,tileSize,tileSize);
}
}
//////////////// HUNTER ///////////////////////////////////////////////
function Hunter(x,y){ // HUNTER constructor
this.x=x;
this.y=y;
this.animate;
this.draw= function(x,y){ // HUNTER DRAW function
//......... draw the Hunter on top of a tile context.drawImage(img,x,y,width,height)
}
}
////////////// MOVE HUNTER KEYS FUNCTION ///////////////////////////////////
function moveHunter(event){ // Move HUNTER
var code= event.keyCode;
switch(code){
case 37: // LEFT
if(hunter.x-1>=0){ // check if hunter stays inside canvas
drawTile(hunter.x,hunter.y); // erase Hunter
hunter.x--; // hunter shifts 1 tile to the left
hunter.draw(); // redraw hunter
}
break;
case 39: // RIGHT
//.............move Hunter 1 tile to the right. Use LEFT-example(82)
break;
}
}
////////////////////////////////////////START//////////////////////////////
setTimeout(createSetting,200);
</script>
<p id="p" style="height:30px;font-size:18px">Add Hunter to the grid</p>
<canvas id="canvas" height="400" width="400"
tabindex="0" onkeydown="moveHunter(event)"
style="border:1px solid blue"></canvas>
<ul>
<li>Write the this.draw function for Hunter(68)</li>
<li>Move Hunter with right-key (91)</li>
</ul>
That's everything you need to know about a Grid game with moving characters.
The Duckshooting Game in the Tryout Panel below is a bit boring. Make it more interesting with obstacles, flying or egg-dropping Ducks.
Make a Duck Shooting game ......... .... "TryoutPanel4"
<script>
var grid= new Array();
var gridWidth=10;
var gridHeight=10;
var tileSize=40;
var canvas;
var context;
var hunter; // global variables
var ducksArray=new Array();
var bullet;
var duckImg= new Image(); //create DUCK image
duckImg.src="/pics/duck.gif"
var huntImg= new Image(); //create HUNTER image
huntImg.src="/pics/hunty.gif"
///////////// CIRCLE /////////////////////////////////////////////////////
function circle(x,y,radius) { // circle function
context.beginPath();
context.arc(x, y, radius,0, Math.PI*2, true);
context.fill();
context.stroke(); }
////////////// CREATE SETTING //////////////////////////////////
function createSetting(){ // create grid and characters
canvas=document.getElementById("canvas");
context =canvas.getContext('2d');
var x; // make 2-dimensional grid
for (x=0; x<gridWidth; x++){
grid[x]=new Array();
var y;
for(y=0;y<gridHeight;y++){
grid[x][y]='sky'; // whole grid is filled with SKY
}
}
//.... put in obstacles e.g. grid[3][9]='fence';
// in drawTile() define how to draw a fence (82)
var X,Y;
for(X=0;X<gridWidth;X++){ // draw the WHOLE GRID
for(Y=0;Y<gridHeight;Y++){
drawTile(X,Y);
}
}
hunter=new Hunter(5,9); // make the HUNTER
hunter.draw(); // draw him
for ( var i=0;i<2;i++){ // make some Ducks
ducksArray[i]=new Duck(3*i,0); // put in ducksArray
ducksArray[i].draw(); // and draw
//.... if you make them fly, call fly() function
}
}
/////////////////// DRAW TILE ////////////////////////////////////////////
function drawTile(x,y){ // DRAWTILE function to draw individual TILES
if(grid[x][y]=='sky'){ // pieces of SKY
context.fillStyle='lightBlue';
context.fillRect(x*tileSize,y*tileSize,tileSize,tileSize);
}
//......with more else-if statements define how to draw your obstacles
// don't forget to add it in the Grid (48)
}
/////////////// DUCK ///////////////////////////////////////////////////////
function Duck(x,y){ // DUCK constructor
this.x=x;
this.y=y;
this.stop=false;
// ***************** THIS DRAW ********//
// Draw a Duck
this.draw= function(){
context.drawImage(duckImg,this.x*tileSize,this.y*tileSize,tileSize,tileSize);
}
//********** THIS DIE*******************//
this.die = function(){ // animation when duck is shot
if(this.stop==false){ // if duck is not stopped
if(this.y+1>gridHeight){ // check if duck reaches floor
this.stop=true; // stop duck
}
else { // keep falling
drawTile(this.x,this.y); // erase duck
this.y++; // duck FALLS down 1 tile
this.draw();
setTimeout(this.die.bind(this),300); // loop
}
}
if(this.stop==true){ // if duck is stopped
var index=ducksArray.indexOf(this); // get index of duck in array
ducksArray.splice(index,1); // delete this duck from duckArray
if(ducksArray.length==0){
win(); // if no ducks left; WIN
}
}
}
//*********** THIS FLY *******************//
//......make the ducks fly with a this.fly = function(){..}
//look at the this.die function above to help you(104)
//*************** THIS DROP EGGS *************//
// this.dropEggs = function(){ // ... let the ducks shoot back
// .......create an Egg instance in the position of this duck
//...... animate the egg.
// setTimeout(this.dropEggs.bind(this),2000);
//}
// .... to create an Egg Constructer,look at the Bullet Constructer(160)
// Eggs should fall down instead of shoot up
}
//////////////// HUNTER ///////////////////////////////////////////////
function Hunter(x,y){ // HUNTER constructor
this.x=x;
this.y=y;
this.animate;
this.draw= function(x,y){ // HUNTER DRAW funtion
context.drawImage(huntImg,this.x*tileSize,this.y*tileSize,tileSize,tileSize);
}
}
////////////////// BULLET /////////////////////////////////////////////
function Bullet(x,y){ // BULLET constructor
this.x=x;
this.y=y;
this.stop=false;
this.draw= function(x,y){ // BULLEt DRAW funtion
context.fillRect(this.x*tileSize,this.y*tileSize,tileSize,tileSize);
context.fillStyle="white";
circle(this.x*tileSize + 0.5*tileSize,this.y*tileSize + 0.5*tileSize,4);
}
//************SHOOT*********************//
this.shoot = function(){
if(this.y<0){ // if bullet shoots through top canvas
this.stop=true; // stop bullet
}
else{
for (var i=0;i<ducksArray.length;i++){ // check if bullet hits any Duck
if(this.y-1==ducksArray[i].y && this.x == ducksArray[i].x){ // if bullet and duck sit on same tile
ducksArray[i].die();
this.stop=true;
}
}
}
if(this.stop==false){ // if bullet is not stopped
drawTile(this.x,this.y); // erase bullet
this.y--; // shoot up 1 tile
this.draw();
setTimeout(this.shoot.bind(this),200); // loop
}
else { // if bullet is stopped
delete this; // delete the bullet
}
}
}
////////////// MOVE HUNTER KEYS FUNCTION ///////////////////////////////////
function moveHunter(event){ // Move HUNTER
var code= event.keyCode;
switch(code){
case 37: // LEFT
if(hunter.x-1>=0){ // check if hunter stays inside canvas
drawTile(hunter.x,hunter.y); // redraw the tile
hunter.x--; // change hunter x-coord
hunter.draw(); // redraw hunter
}
break;
case 39: // RIGHT
event.preventDefault(); // otherwise window scrolls
if(hunter.x-1<gridWidth){ //.... same as LEFT
drawTile(hunter.x,hunter.y);
hunter.x++;
hunter.draw();
}
break;
case 32: // SPACE
event.preventDefault(); // otherwise window shifts
bullet= new Bullet(hunter.x,hunter.y-1); // make a bullet
bullet.draw();
bullet.shoot(); // shoot() moves bullet
break;
}
}
function win(){ // WIN : set message WIN
document.getElementById('p').innerHTML="YOU WIN !!!";
document.getElementById('p').style.color='green';
document.getElementById('p').style.fontSize='26px';
}
setTimeout(createSetting,200);
</script>
<p id="p" style="height:30px;font-size:18px">Move hunter with left- right arrows, Shoot with space bar</p>
<canvas id="canvas" height="400" width="400"
tabindex="0" onkeydown="moveHunter(event)"
style="border:1px solid blue"></canvas>
<ul>
<li>Make the Ducks fly away(130,68)</li>
<li>Make Obstacles (48,82)</li>
<li>Let the ducks shoot back(134,141)</li></ul>