Game making based on canvas

Keywords: Javascript html5

Use canvas canvas to design games

1. Catalogue

1. Introduction to Canvas

2. Cases

2. Introduction to canvas

What is a Canvas element

The canvas element of HTML5 uses JavaScript to draw images on a Web page.The canvas is a rectangular area where you can control each pixel.Canvas has a variety of ways to draw paths, rectangles, circles, characters, and add images to create rich graphic references.

Create Canvas elements

<canvas id="canvas" width="width" height="height" style="border: 2px solid #000;background: #fff;"></canvas>

3. Case Practice

1. Character puzzle game

Run result:

Code:
Difficulty Choice:
<form>
    <label>low</label>
    <input type="range" id="scale" value="4" min="3" max="5" step="1">
    <label>high</label>
</form>

Create a canvas:
<canvas id="puzzle" width="480px" height="480px"></canvas>
Link js:
<script src="slinding.js"></script>
js code:

1. Call the getContext() method to get the context and draw.

2. Create a canvas the same size as the background

var context=document.getElementById('puzzle').getContext('2d');
var img=new Image();
img.src='defa.jpg';
img.addEventListener('load',drawTiles,false);
var boardSize=document.getElementById('puzzle').width;
var tileCount=document.getElementById('scale').value;
var tileSize=boardSize/tileCount;
var clickLoc=new Object;
clickLoc.x=0;
clickLoc.y=0;
var emptyLoc=new Object;
emptyLoc.x=0;
emptyLoc.y=0;
var solved=false;

3. We use a one-dimensional array to store the number of each tile.Each element represents a puzzle, and the initial element's array subscript is the same as the puzzle number, indicating the correct position.And random placement of tiles

var boardParts=new Object;
setBoard();
document.getElementById('scale').onchange=function(){
    tileCount=this.value;
    tileSize=boardSize/tileCount;
    setBoard();
    drawTiles();
};

4. Track mouse events

document.getElementById('puzzle').onmousemove=function(e){
    clickLoc.x=Math.floor((e.pageX-this.offsetLeft)/tileSize);
    clickLoc.y=Math.floor((e.pageY-this.offsetTop)/tileSize);
};

5. In the onmousemove event where the mouse is clicked in the canvas, the grid coordinates clickLoc.x, clickLoc.y are calculated at an interval from the empty space position, and if the interval is 1, the clicked block is moved.And set a delay of 0.5 seconds

document.getElementById('puzzle').onclick=function(){
    if (distance(clickLoc.x,clickLoc.y,emptyLoc.x,emptyLoc.y)==1){
        slideTile(emptyLoc,clickLoc);
        drawTiles();
    }
    if(solved){
        setTimeout(function(){alert("You solved it!");},500);
    }
};

6. Make the clicked location blank

function slideTile(toLoc,fromLoc){
    if(!solved){
        boardParts[toLoc.x][toLoc.y].x=boardParts[fromLoc.x][fromLoc.y].x;
        boardParts[toLoc.x][toLoc.y].y=boardParts[fromLoc.x][fromLoc.y].y;
        boardParts[fromLoc.x][fromLoc.y].x=tileCount-1;
        boardParts[fromLoc.x][fromLoc.y].y=tileCount-1;
        toLoc.x=fromLoc.x;
        toLoc.y=fromLoc.y;
        checkSolved();
    }
}

7. Check that the movement is correct

function checkSolved(){
    var flag=true;
    for(var i=0;i<tileCount;++i){
        for(var j=0;j<tileCount;++j){
            if(boardParts[i][j].x!=i || boardParts[i][j].y!=j){
                flag=false;
            }
        }
    }
    solved=flag;
}

2. Thunder Plane Design Game

Run result:

Full code:

1. Create canvas

<canvas id='myCanvas' width="320" height="480" style="border: solid">
	Your browser does not support canvas elements. Please update your browser to get a presentation.
</canvas>

2. Title and Score Boxes

<div id="message_txt" style="display: block;">Airplane Battle</div>
<div id="score_txt" style="display: block;">Score: 0 points</div>

3.js section 3.1 Canvas and Input Listening

var canvas=document.getElementById('myCanvas');
var context=canvas.getContext('2d');
document.addEventListener('keydown',onKeydown);

3.2 Aircraft Classes and Their Properties

var Plan=function(image,x,y,n){
	this.image=image;
	this.x=x;
	this.y=y;
	this.orignx=x;
	this.origny=y;
	this.width=image.width/n;
	this.height=image.height;
	this.isCaught=false;
	this.frm=0;
	this.dis=0;
	this.n=n;
};
Plan.prototype.getCaught=function(bool){
	this.isCaught=bool;
	if (bool==false){
		this.orignx=0;
		this.origny=this.y;
	}
};
Plan.prototype.testPoint=function(x,y){
	var betweenX=(x>=this.x)&&(x<=this.x+this.width);
	var betweenY=(y>=this.y)&&(y<=this.y+this.height);
	return betweenX&&betweenY;
};
Plan.prototype.move=function(dx,dy){
	this.x+=dx;
	this.y+=dy;
};
Plan.prototype.Y=function(){
	return this.y;
};

3.3 Continuously downward moving aircraft

Plan.prototype.draw=function(ctx){
	ctx.save();
	ctx.translate(this.x,this.y);
	ctx.drawImage(this.image,this.frm*this.width,0,this.width,this.height,0,0,this.width,this.height);
	ctx.restore();
	this.y++;
	this.x=this.orignx+20*Math.sin(Math.PI/100*this.y);
	this.dis++;
	if(this.dis>=3){
		this.dis=0;
		this.frm++;
		if(this.frm>=this.n) this.frm=0;
	}
};

3.4 In-place non-animated aircraft

Plan.prototype.draw2=function(ctx){
	ctx.save();
	ctx.translate(this.x,this.y);
	ctx.drawImage(this.image,this.frm*this.width,0,this.width,this.height,0,0,this.width,this.height);
	ctx.restore();
	this.dis++;
	//3 frames for one picture
	if(this.dis>=3){
		this.dis=0;
		this.frm++;
		if(this.frm>=this.n) this.frm=0;
	}
};

3.5 Detection of aircraft collisions

Plan.prototype.hitTestObject=function(planobj){
	if(iscolliding(this.x,this.y,this.width,this.height,planobj.x,planobj.y,planobj.width,planobj.height))
		return true;
	else
		return false;
}

function iscolliding(ax,ay,aw,ah,bx,by,bw,bh){
	if(ay>by+bh||by>ay+ah||ax>bx+bw||bx>ax+aw)
		return false;
	else
		return true;
}

3.6 Bullets and their attributes

var Bullet=function(image,x,y){
	this.image=image;
	this.x=x;
	this.y=y;
	this.orignx=x;
	this.orignx=y;
	this.width=image.width/4;
	this.height=image.height;
	this.isCaught=false;
	this.frm=0;
	this.dis=0;
}
Bullet.prototype.testPoint=function(x,y){
	var betweenX=(x>=this.x)&&(x<this.x+this.width);
	var betweenY=(y>=this.y)&&(y<this.y+this.height);
	return betweenX&&betweenY;
};
Bullet.prototype.move=function(dx,dy){
	this.x+=dx;
	this.y+=dy;
};
Bullet.prototype.Y=function(){
	return this.y;
};
Bullet.prototype.draw=function(ctx){
	ctx.save();
	ctx.translate(this.x,this.y);
	ctx.drawImage(this.image,this.frm*this.width,0,this.width,this.height,0,0,this.width,this.height);
	ctx.restore();
	this.y--;
	this.dis++;
	if(this.dis>=10){
		this.dis=0;
		this.frm++;
		if(this.frm>=4) this.frm=0;
	}
};

3.7 Detect collisions between bullets and enemies

Bullet.prototype.hitTestObject=function(planobj){
	if(iscolliding(this.x,this.y,this.width,this.height,planobj.x,planobj.y,planobj.width,planobj.height))
		return true;
	else
		return false;
}

3.8 Explosive Animation Classes and Properties

var Bomb=function(image,x,y){
	this.image=image;
	this.x=x;
	this.y=y;
	this.width=image.width/6;
	this.height=image.height;
	this.frm=0;
	this.dis=0;
};
Bomb.prototype.draw2=function(ctx){
	ctx.save();
	ctx.translate(this.x,this.y);
	if(this.frm>=6) return ;
	ctx.drawImage(this.image,this.frm*this.width,0,this.width,this.height,0,0,this.width,this.height);
	ctx.restore();
	this.dis++;
	if(this.dis>=10){
		this.dis=0;
		this.frm++;
	}
};
var plan1,plan2,plan3,plan4,caughtplan=null;
var isClick=false;
var mouseX,mouseY,preX,preY;
var plans=[];
var bullets=[];
var bombs=[];
var score=0;
var overflag=false;
var myplane;

3.9 Import external material drawings to draw aircraft

var image=new Image();
var image2=new Image();
var image3=new Image();
var image4=new Image();
var image5=new Image();
var bakground=new Image();
bakground.src='map_0.png';
image.src='plan.png';
image.onload=function(){
}
image2.src='bomb.png';
image2.onload=function(){
}
image3.src='enemy.png';

3.10 Draw elements and judge collisions

image3.onload=function(){
	myplane=new Plan(image,300*Math.random(),400,6);
	plan_interval=setInterval(function(){
		plans.push(new Plan(image,300*Math.random(),20*Math.random(),2));
	},3000);//3 seconds to generate an enemy plane
	setInterval(function(){
		context.clearRect(0,0,320,480);
		context.drawImage(bakground,0,0);
	//Draw your own plane
		if(!overflag)
			myplane.draw2(context);
	//Enemy Drawing Machine
		for(var i=plans.length-1;i>=0;i--){
			if (plans[i].Y()>400){
				plans.splice(i,1);//Remove enemy aircraft
			}
			else{
				plans[i].draw(context);
			}
		}
	//Draw bullets
		for (var i=bullets.length-1;i>=0;i--){
			if (bullets[i].Y()<100){
				bullets.splice(i,1);//Remove Bullets
			}
			else{
				bullets[i].draw(context);
			}
		}
	//Detect if a player hits an enemy plane
		for (vari=plans.length-1;i>=0;i--){
			e1=plans[i];
			if(e1!=null && myplane!=null && myplane.hitTestObject(e1)){
				clearInterval(plan_interval);
				plans.splice(i,1);//Remove enemy aircraft
				bombs.push(new Bomb(image2,myplane.x,myplane.y));

				message_txt.innerHTML='Enemy plane encounters player's own plane, end of game';
				overflag=true;
			}
		}
    //Judging whether a bullet hit
		for(var j=bullets.length-1;j>=0;j--){
			var b1=bullets[j];
			for(var i=plans.length-1;i>=0;i--){
				e1=plans[i];
				if (e1!=null && b1!=null && b1.hitTestObject(e1)){
					plans.splice(i,1);
					bullets.splice(i,1);
					bombs.push(new Bomb(image2,b1.x,b1.y-36));

					message_txt.innerHTML='Enemy plane hit, plus 20 points';
					score+=20;
					score_txt.innerHTML='Fraction:'+score+'branch';
				}
			}
		}
	//Picture Explosion
		for (var i=bombs.length-1;i>=0;i--){
			if (bombs[i].frm>=6){
				bombs.splice(i,1);
			}
			else{
				bombs[i].draw2(context);
			}
		}
	},1000/60);
};
image4.src='bullet.png';
image4.onload=function(){
};

3.11 Airplane Movement Control

function onKeydown(e){
	if(e.keyCode==32){
		bullets.push(new Bullet(image4,myplane.x,myplane.y-36));
	}else if(e.keyCode==37){
		myplane.move(-10,0);
	}else if(e.keyCode==39){
		myplane.move(10,0);
	}else if(e.keyCode==38){
		myplane.move(0,-10);
	}else if(e.keyCode==40){
		myplane.move(0,10);
	}
}

3. FlappyBird Game

Run result:

Full code:

1. Draw canvas canvas

<canvas id="canvas" width="340" height="453" style="border: 2px solid #000;background: #fff;"></canvas>

2. Link js

<script src="bird.js" type="text/javascript"></script>

3.js section 3.1 Canvas monitoring

var canvas=document.getElementById("canvas");
var c=canvas.getContext("2d");

3.2 Categories - Birds

function Bird(x,y,image) {
    this.x=x,
    this.y=y,
    this.width=image.width/2,
    this.height=image.height,
    this.image=image;
    this.draw=function (context,state) {
        if(state==="up")
            context.drawImage(image,0,0,this.width,this.height,this.x,this.y,this.width,this.height);
        else {
            context.drawImage(image,this.width,0,this,width,this.height,this.x,this.y,this.width,this.height);
        }
    }
};

Class 3.2 - Obstacles

function Obstacle(x,y,h,image) {
    this.x=x,
    this.y=y,
    this.width=image.width/2,
    this.height=h,
    this.flypast=false;
    this.draw=function (context,state) {
        if(state==="up")
            context.drawImage(image,0,0,this.width,this.height,this.x,this.y,this.width,this.height);
        else {
            context.drawImage(image,this.width,image.height-this.height,this.height,this.width,this.height,this.x,this.y,this.width,this.height)
        }
    }
};

Class 3.2 - Game Run (FlappyBird) Class

function FlappyBird() {}
FlappyBird.prototype= {
    bird: null,
    bg: null,
    obs: null,
    obsList: [],
    mapWidth: 340,
    mapHeight: 453,
    startX: 90,
    startY: 225,
    obsDistance: 150,
    obsSpeed: 2,
    obsInterval: 2000,
    upSpeed: 8,
    downSpeed: 3,
    line: 56,
    score: 0,
    touch: false,
    gameOver: false,
    CreateMap: function () {
        //background
        this.bg = new Image();
        this.bg.src = "img/bg.png";
        var startBg = new Image();
        startBg.src = "img/start.jpg";
        startBg.onload = function () {
            c.drawImage(startBg, 0, 0);
        };
        //Birds
        var image = new Image();
        image.src = "img/bird.png";
        image.onload = function () {
            this.bird = new Bird(this.startX, this.startY, image);
        }.bind(this);
        //Obstacle
        this.obs = new Image();
        this.obs.src = "img/obs.png";
        this.obs.onload = function () {
            var h = 100;
            var h2 = this.mapHeight - h - this.obsDistance;
            var obs1 = new Obstacle(this.mapWidth, 0, h, this.obs);
            var obs2 = new Obstacle(this.mapWidth, this.mapHeight - h2, h2 - this.line, this.obs);
            this.obsList.push(obs1);
            this.obsList.push(obs2);
        }.bind(this);
    },
    CreatObs: function () {
        var h = Math.floor(Math.random() * (this.mapHeight - this.obsDistance - this.line));
        var h2 = this.mapHeight - h - this.obsDistance;
        var obs1 = new Obstacle(this.mapWidth, 0, h, this.obs);
        var obs2 = new Obstacle(this.mapWidth, this.mapHeight - h2, h2 - this.line, this.obs);
        this.obsList.push(obs1);
        this.obsList.push(obs2);

        if (this.obsList[0].x < -this.obsList[0].width)
            this.obsList.splice(0, 2);
    },
    DrawObs:function(){
        c.fillStyle="#00ff00";
        for(var i=0;i<this.obsList.length;i++){
            this.obsList[i].x-=this.obsSpeed;
            if(i%2)
                this.obsList[i].draw(c,"up");
            else
                this.obsList[i].draw(c,"down");
        }
    },
    CountScore:function () {
        if(this.obsList[0].x + this.obsList[0].width < this.startX &&this.obsList[0].flypast==false){
            this.score+=1;
            this.obsList[0].flypast=true;
        }
    },
    ShowScore:function () {
        c.strokeStyle="#000";
        c.lineWidth=1;
        c.fillStyle="#fff";
        c.fillText(this.score,10,50);
        c.strokeText(this.score,10,50);
    },
    CanMove:function () {
        if(this.bird.y<0 || this.bird.y > this.mapHeight-this.bird.height-this.line){
            this.gameOver=true;
        }else{
            var boundary=[{
                x:this.bird.x,
                y:this.bird.y
            },{
                x:this.bird.x+this.bird.width,
                y:this.bird.y
            },{
                x:this.bird.x,
                y:this.bird.y+this.bird.height
            },{
                x:this.bird.x+this.bird.width,
                y:this.bird.x+this.bird.height
            }];
            for (var i=0;i<this.obsList.length;i++){
                for(var j=0;j<4;j++)
                    if(boundary[j].x>=this.obsList[i].x && boundary[j].x <= this.obsList[i].x+this.obsList[i].width &&
                    boundary[j].y>=this.obsList[i].y&& boundary[j].y<=this.obsList[i].y+this.obsList[i].height){
                        this.gameOver=false;
                        break;
                    }
                if(this.gameOver)
                    break;
            }
        }
    },
    CheckTouch:function () {
        if(this.touch){
            this.bird.y-=this.upSpeed;
            this.bird.draw(c,"up");
        }else {
            this.bird.y+=this.downSpeed;
            this.bird.draw(c,"down");
        }
    },
    ClearScreen:function () {
        c.drawImage(this.bg,0,0);
    },
    ShowOver:function () {
        var overImg=new Image();
        overImg.src="img/over.png";
        overImg.onload=function () {
            c.drawImage(overImg,(this.mapWidth-overImg.width)/2,(this.mapHeight-overImg.height)/2-50);
        }.bind(this);
        return;
    }
};
var game=new FlappyBird();
var Speed=20;
var IsPlay=false;
var GameTime=null;
var btn_start;
window.onload=InitGame;

function InitGame() {
    c.font="3em Microsoft YaHei";
    game.CreateMap();
    canvas.onmousedown=function () {
        game.touch=true;
    }
    canvas.onmouseup=function () {
        game.touch=false;
    };
    canvas.onclick=function () {
        if (!IsPlay) {
            IsPlay = true;
            GameTime = RunGame(Speed);
        }
    }
}

3.3 Game Run Entry Function

function RunGame(speed) {
    var updateTimer=setInterval(function () {
        game.CanMove();
        if(game.gameOver){
            game.ShowOver();
            clearInterval(updateTimer);
            return;
        }
        game.ClearScreen();
        game.DrawObs();
        game.CheckTouch();
        game.CountScore();
        game.ShowScore();
    },speed);
    var obsTimer=setInterval(function () {
        if (game.gameOver){
            clearInterval(obsTimer);
            return;
        }
        game.CreatObs();
    },game.obsInterval);
}

Posted by spider661 on Mon, 23 Mar 2020 09:54:35 -0700