Example of developing a maze game using HTML5 Canvas

Source: Internet
Author: User
Tags abs cos reset sin

This article describes how to use the canvas canvas to make a simple maze game: When the user presses the arrow keys, the smiley face icon will move in the corresponding direction (animation effect when moving), when encountering the wall (collision detection) will stop.

1, online sample
loaded with difficult maze loading simple maze

2, the principle of realization
(1) Maze generation: We use a maze picture here, and then draw the whole picture onto the canvas.
(2) By setting the Window.onkeydown response function Processkey (), when the user presses the direction key, according to the key code adjusts smiley party's upward speed.
(3) The Drawframe () function refreshes the canvas every 10 milliseconds, and if the smiley face has speed, it moves and plots the trajectory while making collision detection. Finally will detect whether the smiley face, to the words pop-up success message box.

3, collision detection
This is based on pixel color collision detection, we take the area of the smiley face of the pixel (in the smiley face four weeks to slightly expand a little bit) to determine whether there are black pixels, and some words on the wall.

4, complete code

<! DOCTYPE html>
<meta charset= "UTF-8"/>
<title>hangge.com</title>
<style>
Canvas {
BORDER:6PX double black;
Background:white;
}

IMG {
Display:none;
}

button {
padding:3px;
}
</style>
<script>
var canvas;
var context;

Record the current position of the smiley face icon
var x = 0;
var y = 0;

Record how many pixels each frame moves in the X and Y axes of the smiley face
var dx = 0;
var dy = 0;

Window.onload = function () {
Set Canvas
Canvas = document.getElementById ("Canvas");
Context = Canvas.getcontext ("2d");

Draw a maze background
Drawmaze (' Http://www.hangge.com/blog_uploads/201602/2016022313460193716.png ', 5, 5);

When the user presses a key on the keyboard, run the Processkey () function
Window.onkeydown = Processkey;
};


Timer reference, so you can easily stop drawing when you reload the maze
var timer;

function Drawmaze (Mazefile, Startingx, startingy) {
Stop drawing first
Cleartimeout (timer);

Stop Smiling
DX = 0;
DY = 0;

Load Maze Picture
var imgmaze = new Image ();
Imgmaze.onload = function () {
Adjust the canvas size to fit the maze picture
Canvas.width = Imgmaze.width;
Canvas.height = Imgmaze.height;

Draw a Maze
Context.drawimage (Imgmaze, 0,0);

Draw a smiley face
x = STARTINGX;
y = startingy;

var imgface = document.getElementById ("Face");
Context.drawimage (Imgface, x, y);
Context.stroke ();

Draw Next frame after 10 milliseconds
Timer = settimeout (Drawframe, 10);
};
IMGMAZE.SRC = Mazefile;
}


function Processkey (e) {
If the smiley is moving, stop
DX = 0;
DY = 0;

Press the UP ARROW to move up
if (E.keycode = = 38) {
DY =-1;
}

Press DOWN ARROW to move Down
if (E.keycode = = 40) {
DY = 1;
}

Press LEFT ARROW to move left
if (E.keycode = = 37) {
DX =-1;
}

Press the RIGHT ARROW key to move to the right
if (E.keycode = = 39) {
DX = 1;
}
}

function Checkforcollision () {
Get the pixel block of the smiley face and expand a little bit
var imgdata = Context.getimagedata (x-1, Y-1, 15+2, 15+2);
var pixels = imgdata.data;

Detect pixels in one of these
for (var i = 0; n = pixels.length, i < n; i + 4) {
var red = pixels[i];
var green = pixels[i+1];
var blue = pixels[i+2];
var alpha = pixels[i+3];

Detecting black walls (if detected, the description hits the wall)
if (red = 0 && green = 0 && Blue = = 0) {
return true;
}
Detect gray edges (if detected, the description hits the wall)
if (red = 169 && Green = = 169 && Blue = 169) {
return true;
}
}
No wall.
return false;
}


function Drawframe () {
Detect whether the smiley face is moving in which direction, and if not, do nothing.
if (dx!= 0 | | dy!= 0) {
Draws a yellow background (indicates a moving trace) in the current position of the smiley face, then moves the smiley face to the next position
Context.beginpath ();
Context.fillstyle = "RGB (254,244,207)";
Context.rect (x, Y, 15, 15);
Context.fill ()

Increase position Value
x = = DX;
Y + dy;

Collision Detection (the smiley face needs to be put back to the previous position and stop moving)
if (Checkforcollision ()) {
X-= DX;
Y-= dy;
DX = 0;
DY = 0;
}

Here you can draw a smiley face
var imgface = document.getElementById ("Face");
Context.drawimage (Imgface, x, y);

Detect whether the smiley face has reached the bottom of the maze, is the words prompt success
if (Y > (canvas.height-17)) {
Alert ("You win!");
Return
}
}

Draws the next positive after 10 milliseconds
Timer = settimeout (Drawframe, 10);
}

function Loadeasy () {
Drawmaze (' Http://www.hangge.com/blog_uploads/201602/2016022313460193716.png ', 5, 5);
}

function Loadhard () {
Drawmaze (' Http://www.hangge.com/blog_uploads/201602/2016022313455480577.png ', 268, 5);
}

</script>

<body>
<canvas id= "Canvas" >
</canvas>
<div>
<button onclick= "Loadhard ()" > Difficulty in loading Maze </button>
<button onclick= "Loadeasy ()" > Loading simple Maze </button>
</div>


</body>

HTML5 Canvas Small Game practicing

<! DOCTYPE html>
<meta http-equiv= "Content-type" content= text/html; charset =utf-8 "/>
<title> Untitled document </TITLE>
<style type=" Text/css "
*{padding:0;margin:0;color : #fff;}
a {text-decoration:none;}
Html,body{background-color: #000;}
#canvas {background-color: #001022;p osition:absolute;z-index:-1000;top:0}
#game {margin:auto;width:40%; Background-color: #001022;}
#lay {width:100%;height:100%;p osition:relative}
#game p,h2{text-align:center;width:100%}
#gameInfo { position:relative;margin-top:150px.}

#gameState {margin-top:20px;margin-left:-400px;}
#reset {position:absolute;top:20px;text-decoration:none;margin-left:150px;}
#reset: Hover{color:blue}
#play {width:80px;height:40px; font-weight:bold;font-size:25px;margin:10px}
h2{font-size:40px}
#footer {margin-top:120px;display:none}
#play {background: #CCC; color: #333; Border-radius : 5px;}
</style>

<body>
<div id= "Game" >
<p><a href= "#" id= "reset" >Reset</a></p>
<a > Space Bowling </a>
<div id= "Lay" >
<div id= "Gameui" >
<div id= "Gameinfo" >
<p><p>this is a awesome game.</p>
<p><button id= "Play" >Play</buttom>
</div>
<div id= "GameState" >
<p>asteroids:<label id= "Bowlnum" ></label></p>
<p>&nbsp;&nbsp; Clicks:<label id= "Clicknum" ></label></p>

</div>
<div id= "Footer" >
<p>congratulations,you completed</p>
<p>the game in Clicks</p>
<p>play again</p>

</div>
</div>
</div>
<canvas id= "Canvas" ></canvas>
</div>
</body>
<script type= "Text/javascript" >

var bowlnum=0;
var clicknum=0;
var viewwidth = 0;
var viewheight = 0;
try{
Viewwidth=document.documentelement.clientwidth;
Viewheight = Document.documentElement.clientHeight;
}catch (e) {
Viewwidth = Document.body.clientWidth;
Viewheight = Document.body.clientHeight;
}
var canvas = document.getElementById ("Canvas");
canvas.width=546
Canvas.height=viewheight;
canvas.width=viewwidth/2.5;

var context = Canvas.getcontext ("2d");
var play = document.getElementById ("Play");


Play.onclick=function () {//Start the game
document.getElementById ("Gameinfo"). style.display= "None";
document.getElementById ("Footer"). style.display= "None";
Drawbegin ();
}

Create a small ball
function Bowling (x,y,radius,mass,firction) {
this.x = x;
This.y=y;
This.radius = radius;
This.mass = mass;
This.firction=firction;
this.vx=0;
this.vy=0;
This.player=true;
This. r=10;
}
var Bowlingarr = new Array ();


function Drawbegin () {
Context.fillstyle= "#646464";
Context.beginpath ();
Context.arc (canvas.width/2,160,80,0,2*math.pi,true);
Context.closepath ();
Context.fill ();

Context.fillstyle= "#fff";
Context.beginpath ();
Context.arc (canvas.width/2,canvas.height-60,10,0,2*math.pi,true);
var playbowling = new Bowling (canvas.width/2,canvas.height-60,0,100,10);
Bowlingarr.push (playbowling);
Context.closepath ();
Context.fill ();

var radius = 0;
Draw some small balls on the round table
for (Var i=0;i<8;i++) {
var x=canvas.width/2;
var y=100;
radius=math.pi/4* (i);
x = Math.floor (x+math.sin (RADIUS) *60);
y = Math.floor (y+60-math.cos (RADIUS) *60);
var tempalbowling = new Bowling (x,y,10,100,0.95);
tempalbowling.vx=0;
tempalbowling.vy=0;
Bowlingarr.push (tempalbowling);
Context.beginpath ();
Context.arc (x,y,10,0,math.pi*2,true);
Context.closepath ();
Context.fill ();
}

var tempalbowling = new Bowling (canvas.width/2,160,10,100,0.95);
tempalbowling.vx=0;
tempalbowling.vy=0;
Bowlingarr.push (tempalbowling);
Context.beginpath ();
Context.arc (canvas.width/2,160,10,0,math.pi*2,true);
Context.closepath ();
Context.fill ();


Radius = 0;
for (Var i=0;i<5;i++) {
var x=canvas.width/2;
var y=130;
radius=math.pi*0.4* (i+1);
x = Math.floor (x+math.sin (RADIUS) *30);
y = Math.floor (y+30-math.cos (RADIUS) *30);
var tempalbowling = new Bowling (x,y,10,100,0.95);
tempalbowling.vx=0;
tempalbowling.vy=0;
Bowlingarr.push (tempalbowling);
Context.beginpath ();
Context.arc (x,y,10,0,math.pi*2,true);
Context.closepath ();
Context.fill ();
}

Draw a table to drag a circle to describe the range that allows dragging

}


Refresh
function UpdateUI () {
Context.clearrect (0,0,canvas.width,canvas.height);

Context.fillstyle= "#646464";
Context.beginpath ();
Context.arc (Canvas.width/2,canvas.height-60,10,0,math.pi*2,false);
Context.closepath ();
Context.fill ();
//Round Table
context.fillstyle= "#646464";
Context.beginpath ();
Context.arc (canvas.width/2,160,80,0,2* Math.pi,true);
Context.closepath ();
Context.fill ();
//15 Balls
for (Var i=0;i<bowlingarr.length;i++) {
if (bowlingarr.player==false)
continue;
Context.fillstyle= "#ffffff";
Context.beginpath ();
Context.arc (Bowlingarr[i].x,bowlingarr[i].y,bowlingarr[i]. R,0,math.pi*2,false);
Context.closepath ();
Context.fill ();
if (bowlingarr[i].player==true)
bowlnum++;
}
//Update the number of small balls on the round table
document.getElementById ("Bowlnum"). Innerhtml=bowlnum;
//update the number of hits to release the ball
document.getElementById ("Clicknum"). InnerHTML = Clicknum;
Deletebowling ();

}
///Remove the ball reset ball
Function deletebowling () {
for (Var i=1;i<bowlingarr.length;i++) {
if (bowlingarr[i). vx!=0| | bowlingarr[i].vy!=0) {
var dx=math.abs (BOWLINGARR[I].X-CANVAS.WIDTH/2);
var dy=math.abs (bowlingarr[i].y-160 );
var distance = Math.floor (math.sqrt (Dx*dx+dy*dy));
if (distance>80) {
Bowlingarr[i]. r-=0.5;
if (bowlingarr[i). r<=0)
Bowlingarr[i]. r=0;
bowlingarr[i].player=false;//does not count it in the game
}
}
}
//Reset the dragged Ball
if (bowlingarr[0].x>canvas.width| | bowlingarr[0].y<0| | bowlingarr[0].y>canvas.height| | bowlingarr[0].y<0) {
Bowlingarr[0]. r=10;
Bowlingarr[0].x=canvas.width/2;
Bowlingarr[0].y=canvas.height-60;
Bowlingarr[0].vx=0;
Bowlingarr[0].vy=0;
}
}

Reset Game
document.getElementById ("reset"). onclick = function (e) {
var evt = e| | window.event;
if (!! Evt.preventdefualt) {
Evt.preventdefualt ();
}
else{
Evt.returnvalue=false;
}
document.getElementById ("Gameinfo"). style.display= "Block";
Context.clearrect (0,0,canvas.width,canvas.height);
bowlingarr.length=0;
}

Small ball Animation
function animate () {
Bowlingarr[0].y-=bowlingarr[0].vy;
for (Var i=0;i<bowlingarr.length;i++) {
Collision Detection Method is 22 comparison, if collision, energy conversion
var Tempala = bowlingarr[i];
for (Var j=i+1;j<bowlingarr.length;j++) {
var tempalb=bowlingarr[j];
var dx = Math.Abs (tempalb.x-tempala.x);
var dy = Math.Abs (TEMPALB.Y-TEMPALA.Y);
var Distanceab = math.sqrt (Dx*dx+dy*dy); Pythagorean

Detecting collisions
if (DISTANCEAB<=TEMPALA.R+TEMPALB.R) {
Touched the
var angle =math.atan2 (DY,DX);

var sine = Math.sin (angle);
var cosin = Math.Cos (angle);

var x=0;
var y=0;

var xb=dx*cosin+dy*sine;
var yb=dy*cosin+dx*sine;

var vy=tempala.vx*cosin+tempala.vy*sine;
var vx=tempala.vy*cosin+tempala.vx*sine;

var VBX = Tempalb.vx*cosin+tempalb.vy*sine;
var vby = Tempalb.vy*cosin+tempalb.vx*sine;

var xtotal = VX-VBX;
VX = ((tempala.mass-tempalb.mass) *VX+2*TEMPALB.MASS*VBX)/(Tempala.mass+tempalb.mass);
VBX = XTOTAL+VX;
VY = ((tempala.mass-tempalb.mass) *vy+2*tempalb.mass*vby)/(Tempala.mass+tempalb.mass);
Vby = Xtotal+vy;

XB = x+ (Tempala.radius+tempalb.radius);

tempala.x = tempala.x+ (x*cosin-y*sine);
TEMPALA.Y = tempala.y+ (y*cosin+x*sine);

tempalb.x = tempalb.x+ (xb*cosin-yb*sine);
Tempalb.y = tempalb.y+ (yb*cosin+yb*sine);

TEMPALA.VX = Vx*cosin-vy*sine;
Tempala.vy = Vy*cosin + vx*sine;

TEMPALB.VX = Vbx*cosin-vby*sine;
Tempalb.vy = Vby*cosin + vby*sine;

}
}
BOWLINGARR[I].X+=BOWLINGARR[I].VX;
Bowlingarr[i].y+=bowlingarr[i].vy;

}
UpdateUI ();
SetTimeout (arguments.callee,40);
}

Monitor mouse drag, release ball
var Moveable=false;
var Dragable=false;
var Clickyn = false;
Canvas.onmousedown = function () {
if (bowlingarr[0].y>=canvas.height-60)//must be in this range to drag the ball
Clickyn=true;
}
Canvas.onmousemove = function (e) {
if (clickyn==true) {
Dragable=true;
}
if (dragable==true) {

Calculate Drag Angle
bowlingarr[0].x = E.clientx-canvas.offsetleft;
Bowlingarr[0].y = E.clienty-canvas.offsettop;
BOWLINGARR[0].VX =-(BOWLINGARR[0].X-CANVAS.WIDTH/2);
Bowlingarr[0].vy =-(BOWLINGARR[0].Y-CANVAS.HEIGHT+60);
UpdateUI ();
}
}
Canvas.onmouseup = function () {
Clickyn=false;
if (dragable==true) {
clicknum++;//the number of clicks increased
Dragable=false;
Moveable=true;

Start the game
if (moveable)
Animate ();
}
}
</script>

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.