我正在参加掘金社区游戏创意投稿大赛个人赛,详情请看:游戏创意投稿大赛
需求描述
请实现一个打飞机游戏,玩家通过键盘方向键来控制飞机的移动,射击不断出现的敌机,并躲避敌机的冲击。效果如下:
任务步骤
1. 技术栈选项
HTML5、CSS3、Canvas、JavaScript
2. 背景
利用「首尾相接」技巧,使用提供的背景图片做循环滚动,实现向前行驶的效果。
3. 子弹
- 初始位置:以所属飞机位置为基准
- 飞行效果:一旦发射,垂直方向移动,水平方向不变
- 回收机制:对于频繁创建和销毁的对象,可利用对象池进行内存优化
4. 敌机
敌机随机初始位置,并选用合理的回收机制
5. 碰撞检测
- 检测一:子弹与敌机的碰撞
- 检测二:敌机与主角的碰撞
编码阶段
请根据提供的初始代码,点击下载初始代码,playGame.html
初始代码如下:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
#map,#aircraft{
position: absolute;
}
#aircraft{
top: 0;
left: 0;
z-index: 2;
}
#map{
background: url("beijing.jpg");
-webkit-animation: mapscroll linear 10s infinite;
}
@-webkit-keyframes mapscroll {
0%{
background-position: 0 0;
}
100%{
background-position: 0 800px;
}
}
</style>
</head>
<body>
<div style="position: relative">
<canvas id="map" width="300" height="400"></canvas>
<canvas id="aircraft" width="300" height="400"></canvas>
</div>
<script>
//1. 定义图片资源的数组:预加载 imgonload (敌人飞机、你的飞机)
//2. init 初始化的方法。方法里面 实例化飞机、实例化敌人、我的子弹
//3. 构建玩家,我方飞机。属性:x,y,w,h 方法:move()、top()、down()、left()、right()
//4. 我方飞机,自带绘制图像,添加一个事件侦听:37-40 上下左右
</script>
</body>
</html>
首先定义 Plane
构造函数,定义飞机的 x、y 坐标、 w、h 宽度和高度,并在 Plane
原型上添加上、下、左、右移动方法。
function Plane(){
this.x=130;//属性 初始化x
this.y=350;//初始化y
this.w=planearr["self.png"].width;//从数组中获取图片的宽度
this.h=planearr["self.png"].height;//从数组中获取图片的高度
context.drawImage(planearr["self.png"],this.x,this.y);
var that=this;
window.addEventListener("keydown",function(e){
if(e.keyCode==37){
that.left();
}
if(e.keyCode==38){
that.top();
}
if(e.keyCode==40){
that.down();
}
if(e.keyCode==39){
that.right();
}
})
}
Plane.prototype.move=function(newx,newy){
//擦除
context.clearRect(this.x,this.y,this.w,this.h);
//绘制
context.drawImage(planearr["self.png"],this.x+=newx,this.y+=newy);
}
Plane.prototype.left=function(){
this.move(-4,0);
}
Plane.prototype.right=function(){
this.move(4,0);
}
Plane.prototype.top=function(){
this.move(0,-4);
}
Plane.prototype.down=function(){
this.move(0,4);
}
定义敌机 Enemy
类,包含敌机的x、y坐标、以及敌机的w、h宽度和高度,并使用定时器完成随机生成敌机。
//敌人 属性:x , y ,w ,h 注意敌人的x 随机数, y=0
//方法:下落 改变y的值 擦除/绘制
//创建敌人,init的方法里new 敌人()
function Enemy(){
this.w=planearr["enemy.png"].width;//从数组中获取图片的宽度
this.h=planearr["enemy.png"].height;//从数组中获取图片的高度
this.x=parseInt(Math.random()*(300-this.w));//敌人随机的位置
this.y=0;//y的话初始值为0
context.drawImage(planearr["enemy.png"],this.x,this.y);
var that=this;
this.timer=setInterval(function(){
if(that.y>400)
{
//停止定制器
that.stop();
}
that.clear();
//绘制
context.drawImage(planearr["enemy.png"],that.x,that.y+=5);
},50);
}
Enemy.prototype.stop=function(){
clearInterval(this.timer);
delete Enemyarr[this.name];//删除敌机
}
Enemy.prototype.clear=function(){
//擦除
context.clearRect(this.x,this.y,this.w,this.h);
}
定义子弹 Bullet
类,包含x、y坐标
//子弹
function Bullet(x,y){
this.x=x+20;
this.y=y;
var that=this;
this.timer=setInterval(function() {
if (that.y < 0) {
clearInterval(that.timer);
}
else {
that.fly();
}
},50);
}
定义初始化方法,生成玩家、敌机
//1. 玩家 敌机 子弹
var mycanvs=document.getElementById("aircraft");
var context=mycanvs.getContext("2d");
//存储图片资源
var planearr=[];//存的我方飞机和敌方飞机 的image对象
//存储敌人
var Enemyarr=[];
//第一个入口
var n=0;
function imgload(url){
var img=new Image();
img.src=url;
img.onload=function(){
planearr[url]=img;
n++;
if(n==2){
//调用初始化的方法
init();
}
}
}
//planearr["self.png"]取值
imgload("self.png");
imgload("enemy.png");
//初始化方法 入口
function init(){
//生成玩家
var player=new Plane();
//生成敌人
var timer=setInterval(function(){
var n=Math.random();
var e1=new Enemy();
Enemyarr[n]=e1;
Enemyarr[n].name=n;//底下delete
},2000)
//生成子弹
setInterval(function(){
var e1=new Bullet(player.x,player.y);
},100)
}
当子弹与敌机发生碰撞时,会将敌机清除,碰撞检测方法如下:
Bullet.prototype.check=function(){
//检测碰撞
var x=this.x,y=this.y,w= 2,h=4;//子弹的
for(var d in Enemyarr){
var en=Enemyarr[d];
var x1=en.x,y1=en.y,w1=en.w,h1=en.h;
//比对位置 x y w h 比较 x y w h
if(x+w>x1 && x<x1+w1 && y+h>y1 && y<h1+y1){
//调用敌机 stop clear
//得先擦除、再去进行绘制
Enemyarr[en.name].clear();
Enemyarr[en.name].stop();
}
}
}
点击下载完整代码。