基于canvas的游戏制作

♀尐吖头ヾ 提交于 2020-03-24 00:32:37

3 月,跳不动了?>>>

使用canvas画布设计游戏

一、目录

1、Canvas介绍

2、案例

二、canvas介绍

什么是Canvas元素

HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像。画布是一个矩形区域,您可以控制其每一像素。canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法,可以创建丰富的图形引用。

创建Canvas元素

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

三、案例实操

1、人物拼图游戏

运行结果:

代码:
难度选择:
<form>
    <label>低</label>
    <input type="range" id="scale" value="4" min="3" max="5" step="1">
    <label>高</label>
</form>

创建画布:
<canvas id="puzzle" width="480px" height="480px"></canvas>
链接js:
<script src="slinding.js"></script>
js代码:

1、调用getContext()方法获取上下文,并画图。

2、创建一个和背景大小一样的画布

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、我们使用一个一维数组存储每个拼块的编号。每一个元素代表一个拼块,初始时元素的数组下标与拼块的编号相同,说明位置正确。并实现拼块的随机放置

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

4、追踪鼠标事件

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.画布中单击鼠标的onmousemove事件中,计算出鼠标所在网格坐标clickLoc.x,clickLoc.y与空块位置间隔,如果间距为1则移动被单击的拼块。并且设置延时0.5秒

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.使单击的位置变成空白块

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.检查移动是否正确

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、雷电飞机设计游戏

运行结果:

完整代码:

1.创建canvas

<canvas id='myCanvas' width="320" height="480" style="border: solid">
	你的浏览器不支持canves画布元素,请更新浏览器获得演示效果。
</canvas>

2.标题框和分数框

<div id="message_txt" style="display: block;">飞机大战</div>
<div id="score_txt" style="display: block;">分数:0分</div>

3.js部分 3.1 画布和输入监听

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

3.2飞机类和其属性

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不断下移飞机

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原地不动画飞机

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帧换一次图片
	if(this.dis>=3){
		this.dis=0;
		this.frm++;
		if(this.frm>=this.n) this.frm=0;
	}
};

3.5检测飞机碰撞

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子弹类和其属性

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检测子弹与敌人的碰撞

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爆炸动画类和属性

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导入外部材料图,画飞机

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绘制元素并判断碰撞

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秒产生一架敌机
	setInterval(function(){
		context.clearRect(0,0,320,480);
		context.drawImage(bakground,0,0);
	//画己方飞机
		if(!overflag)
			myplane.draw2(context);
	//画敌机
		for(var i=plans.length-1;i>=0;i--){
			if (plans[i].Y()>400){
				plans.splice(i,1);//删除敌机
			}
			else{
				plans[i].draw(context);
			}
		}
	//画子弹
		for (var i=bullets.length-1;i>=0;i--){
			if (bullets[i].Y()<100){
				bullets.splice(i,1);//删除子弹
			}
			else{
				bullets[i].draw(context);
			}
		}
	//检测玩家是否撞到敌机
		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);//删除敌机
				bombs.push(new Bomb(image2,myplane.x,myplane.y));

				message_txt.innerHTML='敌机碰到玩家自己飞机,游戏结束';
				overflag=true;
			}
		}
    //判断子弹击中没有
		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='敌机被击中,加20分';
					score+=20;
					score_txt.innerHTML='分数:'+score+'分';
				}
			}
		}
	//画爆炸
		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飞机移动控制

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游戏

运行结果:

完整代码:

1.绘制canvas画布

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

2.链接js

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

3.js部分 3.1画布监听

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

3.2类——鸟(bird)类

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

3.2类——障碍物(obstacle)类

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

3.2类——游戏运行(FlappyBird)类

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 () {
        //背景
        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);
        };
        //小鸟
        var image = new Image();
        image.src = "img/bird.png";
        image.onload = function () {
            this.bird = new Bird(this.startX, this.startY, image);
        }.bind(this);
        //障碍物
        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 微软雅黑";
    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游戏运行入口函数

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);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!