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