###简易的 利用canvas 实现打飞机
h5里的canvas应该是很强大的,能做的东西很多,因为也是刚接触,所以,尝试用canvas实现了一个简易的网页打飞机小游戏。本来想用一下worker工作线程,但是一下也没想到很好的方案,而且,本来js也没有多线程的概念,因为js是单线程的。
canvas基本的api我前面的博客也介绍了,有这些基本api方法已经可以做很多事情了。
今天我们就来实现一个简单的网页打飞机
最下面是玩家,我这里的飞机都还是方块,没有替换成飞机的图片,不过没什么影响,重要的是逻辑实现。玩家可以发子弹,敌机随机从上面直线落下来,玩家需要拦截所有敌机,如果飞机越过底线,或者玩家撞上敌机游戏就结束了,并显示相应的分数。
好了,下面就来简单介绍一下,这个网页打飞机是怎么实现。
首先,我们要知道一个游戏是有主循环的,代码逻辑类似下面这样
最简单的主循环
bool game_is_running = true;//游戏状态
while( game_is_running ) {
update_game();//更新游戏状态
display_game();//刷新页面
}
//每秒的循环次数,就是我们玩游戏常说的帧数(fps)
其实,这里,我的实现可能不是标准的一个游戏开发逻辑,由于我也不是游戏开发人员,所以,游戏主循环实现这方面,也暂时没有理解很清楚是一个怎么样的步骤,应该是有固定套路的,感兴趣的盆友,可以详细了解一下
我这里就是简单实现一个打飞机的小逻辑,规范性和优化性完整性可能都需要再深一步优化和规范。
首先,页面就摆一个canvas画布就可以了,我们的游戏界面和内容都是这一个canvas内完成。
html代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>planeShoot</title>
<link rel="stylesheet" href="style/default.css"/>
<script src="script/jquery-1.12.4.js"></script>
</head>
<body>
<div class="background-center">
<canvas id="bgCanvas" width="400" height="600"></canvas>
</div>
<script src="script/default.js"></script>
</body>
</html>
因为用到了jquery,所以需要引入jquery的js包,default.js是我们实现逻辑的地方
为了方便理解,我这里直接贴出完成js代码,并加上注释
(function (window) {
var plane = {
state: true,//游戏状态,true游戏中,false游戏结束
init: function () {
var that = this;
var $canvas = $("#bgCanvas");//获取画布
var canvas = $canvas[0];
var ctx = canvas.getContext("2d");//获取画笔
//fps 60 1s 60次刷新
//监听用户操作
that.mianlistener($canvas);
},
mianlistener: function ($canvas) {//用户动作监听
var that = this;
//鼠标动作监听
$canvas.on("mousemove mousedown touchstart touchmove", function (e) {
if (e.type === "mousemove" || e.type === "touchmove") {
that.attribute.plane = that.getLocation($canvas[0], e.clientX, e.clientY);
} else if (e.type === "mousedown" || e.type === "touchstart") {
//新增一个子弹进数组
that.attribute.bullet.push(that.getLocation($canvas[0], e.clientX, e.clientY));
}
});
//开一个定时器,固定时间建造随机位置的敌机
setInterval(function () {
//判断当前敌机数量
if (!that.state) {
return;
}
if (that.attribute.enemy.length >= 20) {
console.log("够多了不造了");
return;
}
var x = Math.random() * $canvas[0].width;
var y = 0;
that.attribute.enemy.push({x: x, y: y});
}, 500);
//fps 60 1s 60次刷新 游戏主循环,也是用定时器实现的
setInterval(function () {
that.drawCanvas($canvas[0], that.attribute);//刷屏
}, 16);
},
/**
* 屏幕坐标与cavas画布坐标转化
* @param canvas 画布节点对象
* @param x 屏幕坐标x
* @param y 屏幕坐标y
* @returns {{x: number, y: number}} cavas画布坐标
*/
getLocation: function (canvas, x, y) {
var bbox = canvas.getBoundingClientRect();
return {
x: (x - bbox.left) * (canvas.width / bbox.width),
y: (y - bbox.top) * (canvas.height / bbox.height)
// x: (x - bbox.left),
// y: (y - bbox.top)
/*
* 此处不用下面两行是为了防止使用CSS和JS改变了canvas的高宽之后是表面积拉大而实际
* 显示像素不变而造成的坐标获取不准的情况
*/
};
},
drawCanvas: function (canvas, attribute) {//游戏刷屏
var that = this;
//清空屏幕
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (!that.state) {
//绘制重写开始
ctx.font = "20px Arial";
ctx.fillText(JSON.stringify(attribute.code), canvas.width / 2 - 1, canvas.height / 2 - 1);
return;
}
//碰撞检测
//子弹和敌机
that.destroyEnemy(attribute.enemy, attribute.bullet);
that.destroyPlane(attribute.plane, attribute.enemy);
//根据属性绘制其他元素
//飞机
that.drawPlane(ctx, attribute.plane);
//子弹
that.drawBullet(ctx, attribute.bullet);
//敌机
that.drawEnemy(ctx, attribute.enemy, canvas.height);
},
drawPlane: function (ctx, location) {//画用户飞机
ctx.fillRect(location.x - 4, location.y - 4, 8, 8);
},
drawBullet: function (ctx, location) {//画飞机的子弹
var that = this;
if (location && location.length > 0) {
var bullet = [];
for (var i = 0, len = location.length; i < len; i++) {
var x = location[i].x;
var y = location[i].y;
ctx.fillRect(x - 1.5, y - 1.5, 3, 3);
//改变子弹位置,y值-10
if (y > 10) {
y = y - 10;
} else {
//移除这个子弹
continue;
}
bullet.push({x: x, y: y});
}
//更新数据
that.attribute.bullet = JSON.parse(JSON.stringify(bullet));
}
},
drawEnemy: function (ctx, locations, height) {//画敌机
var that = this;
if (locations && locations.length > 0) {
var enemy = [];
for (var i = 0, len = locations.length; i < len; i++) {
var x = locations[i].x;
var y = locations[i].y;
ctx.fillRect(x - 4, y - 4, 8, 8);
//改变敌机位置,y值+1
if (y < height) {
y = y + 1;//敌机速度 直线下落
} else {
//敌机越过底线,游戏结束
that.state = false;
continue;
}
enemy.push({x: x, y: y});//把最新的敌机位置坐标存起来
}
//更新敌机位置集合数据
that.attribute.enemy = JSON.parse(JSON.stringify(enemy));
}
},
destroyEnemy: function (enemey, bullet) {//子弹与敌机碰撞检测
var that = this;
//遍历两个数组
if (enemey && enemey.length > 0 && bullet && bullet.length) {
for (var i = enemey.length-1; i >= 0; i--) {
for (var j = bullet.length-1; j >= 0; j--) {
if (Math.abs(enemey[i].x - bullet[j].x) <= 8 && Math.abs(enemey[i].y - bullet[j].y) <= 8) {
//子弹打中敌机 移除敌机
that.attribute.code = that.attribute.code + 1;
console.log("打中了敌机 = " + that.attribute.code);
enemey.splice(enemey.indexOf(enemey[i]), 1);//移除敌机
bullet.splice(bullet.indexOf(bullet[j]), 1);//移除子弹
}
}
}
}
},
destroyPlane: function (palne, enemey) {//飞机与敌机碰撞检测
var that = this;
//遍历两个数组
if (enemey && enemey.length > 0 && palne) {
for (var i = 0; i < enemey.length; i++) {
if (Math.abs(enemey[i].x - palne.x) <= 8 && Math.abs(enemey[i].y - palne.y) <= 8) {
//飞机撞到了敌机
console.log("撞到了敌机");
that.state = false;//游戏结束
return;
}
}
}
},
attribute: {//游戏公共参数,关系到canvas绘画位置
plane: {x: 50, y: 50},//飞机位置
bullet: [],//子弹位置
enemy: [],//敌机位置
enemyBullet: [],//敌机子弹位置
drug: {x: -1, y: -1},//药位置
code: 0//分数
}
};
window.onload = function () {
plane.init();
};
window.plane = plane;
return window;
})(window);
简单的打飞机,实现就是这么简单,有什么问题,大家可以留言,有更好的实现方案,各位可以分享一下。
完成项目下载地址:https://download.csdn.net/download/lakebobo/10641387