HTML5 game development example

Development tool: vscode

1, Character puzzle

The game is introduced: the jigsaw game divides a picture into several pieces and randomly scrambles them. When all the pieces are put back in place, the puzzle is finished.

In the "game", click the slider to select the game difficult and easy, "easy" is a 3-row 3-column puzzle, in the middle is a 4-row 4-column puzzle, and "difficult" is a 5-Row 5-column puzzle. The tiles are arranged in random order. Players click the four weeks of the blank tiles to exchange their positions until all the tiles return to their original positions.

Programming ideas: HTML5 can integrate pictures into web pages. You can use the canvas element to fill the blank canvas with lines, load picture files, and even animation effects. Here we make a puzzle to show the image processing ability of HTML5 canvas.

The game program first displays the thumbnails of the pictures arranged in the correct order. According to the number of divisions set by the player, the pictures are cut into the corresponding tileCount rows and columns, and numbered in order. Dynamically generate an array of boardParts with the size of tileCounttileCount, and store the number from 0, 1, 2 to tileCount-1. Each number represents a block (for example, 4 * 4 game block number is shown in the figure).

At the beginning of the game, randomly scramble the array of boardParts. If the boardParts[0] is 5, then the number of the puzzle is 5 in the upper left corner. According to the location of the collage and blank block that the player clicks with the mouse, the corresponding elements of the boardParts array are exchanged. Finally, whether the game has been completed is judged according to the order of the elements.

Game reference code:

sliding.js

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;

var boardParts=new Object;
setBoard();

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

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

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);
    }
};

function setBoard(){
    boardParts=new Array(tileCount);
    for(var i=0;i<tileCount;++i) {
        boardParts[i]=new Array(tileCount);
        for (var j=0;j<tileCount;++j){
            boardParts[i][j]=new Object;
            boardParts[i][j].x=(tileCount-1)-i;
            boardParts[i][j].y=(tileCount-1)-j;
        }
    }
    emptyLoc.x=boardParts[tileCount-1][tileCount-1].x;
    emptyLoc.y=boardParts[tileCount-1][tileCount-1].y;
    solved=false;
}

function drawTiles(){
    context.clearRect(0,0,boardSize,boardSize);
    for(var i=0;i<tileCount;++i){
        for(var j=0;j<tileCount;++j){
            var x=boardParts[i][j].x;
            var y=boardParts[i][j].y;
            if(i!=emptyLoc.x || j!=emptyLoc.y || solved==true){
                context.drawImage(img,x*tileSize,y*tileSize,tileSize,tileSize,
                    i*tileSize,j*tileSize,tileSize,tileSize);
            }
        }
    }
}

function distance(x1,y1,x2,y2) {
    return Math.abs(x1-x2)+Math.abs(y1-y2);
}

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();
    }
}

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;
}

index.html

<!doctype html>
<html>
    <head>
        <title>Jigsaw puzzle</title>
        <style>
            .picture{
                border:1px solid black;
            }
        </style>
    </head>
    <body>
        <div id="title">
            <h2>Jigsaw puzzle</h2>
        </div>
        <div id="slider">
            <form>
                <label>low</label>
                <input type="range" id="scale" value="4" min="3" max="5" step="1">
                <label>high</label>
            </form>
            <br>
        </div>
        <div id="main" class="main">
            <canvas id="puzzle" width="480px" height="480px"></canvas>
        </div>
        <script src="sliding.js"></script>
    </body>
</html> 

Operation result:

2, Lightning plane shooting game

On the game: through the up and down around the control of aircraft movement, the space bar to complete shooting

Program design steps: encapsulate the players, enemies and bullets used in the game into classes, and planobj() detects the collision of the aircraft

Game reference code:

<!DOCTYPE html>
<html>
	<head>
		<title>Aircraft Wars</title>
		<meta charset="utf-8">
	</head>
	<body>
		<canvas id='myCanvas' width="320" height="480" style="border: solid">
			//Your browser does not support the canvases canvas element. Please update your browser for demonstration effect.
		</canvas>
		<div id="message_txt" style="display: block;">Aircraft Wars</div>
		<div id="score_txt" style="display: block;">Score: 0</div>
		<script type="text/javascript">
			var canvas=document.getElementById('myCanvas');
			var context=canvas.getContext('2d');
			document.addEventListener('keydown',onKeydown);
			//Aircraft class and its 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;
			};
			//Keep moving the plane down
			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;
				}
			};
			//No animation in place
			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 another picture
				if(this.dis>=3){
					this.dis=0;
					this.frm++;
					if(this.frm>=this.n) this.frm=0;
				}
			};
			//Detect aircraft collision
			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;
			}
			//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;
				}
			};
			//Detect the collision between the bullet and the enemy
			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;
			}
			//Explosion 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;
			//Import external material drawing
			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';
			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);//Three seconds to produce an enemy aircraft
				setInterval(function(){
					context.clearRect(0,0,320,480);
					context.drawImage(bakground,0,0);
				//Draw your plane
					if(!overflag)
						myplane.draw2(context);
				//Draw enemy planes
					for(var i=plans.length-1;i>=0;i--){
						if (plans[i].Y()>400){
							plans.splice(i,1);//Delete enemy planes
						}
						else{
							plans[i].draw(context);
						}
					}
				//Bullet painting
					for (var i=bullets.length-1;i>=0;i--){
						if (bullets[i].Y()<100){
							bullets.splice(i,1);//Delete bullets
						}
						else{
							bullets[i].draw(context);
						}
					}
				//Check whether the player has hit the enemy aircraft
					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);//Delete enemy planes
							bombs.push(new Bomb(image2,myplane.x,myplane.y));

							message_txt.innerHTML='The game is over when the enemy plane encounters the player's own plane';
							overflag=true;
						}
					}
			//Judge if the 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='If the enemy plane is hit, 20 points will be added';
								score+=20;
								score_txt.innerHTML='Fraction:'+score+'branch';
							}
						}
					}
				//Painting 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(){

			};
			//Aircraft 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);
				}
			}
		</script>
	</body>
</html>

Operation result:

3, FlappyBird game

The game is introduced: through the mouse click to control the birds, crossing the obstacles composed of different lengths of water pipes.

Game reference code:

bird.js

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

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);
        }
    }
};
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)
        }
    }
};

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);
        };
        //Little bird
        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);
        }
    }
}


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);
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Flappy Bird</title>
</head>
<body>
<canvas id="canvas" width="340" height="453" style="border: 2px solid #000;background: #fff;"></canvas>
<script src="bird.js" type="text/javascript"></script>
</body>

</html>

Operation result:

Tags: Javascript html5 Programming

Posted on Mon, 06 Apr 2020 03:55:20 -0700 by harman