原文:http://blog.csdn.net/vivian_shuang/article/details/52159584
loading.js文件
// 三个参数:
// 1. 所有要加载的图片对象
// 2.加载进度函数
// 3.加载完成函数
function loading(imgsObj, handleObj) {
// 遍历对象,得到对象中属性的个数,即有多少张图片
var count = 0;
var currentIndex = 0;
for(prop in imgsObj) {
count++;
}
// 图片全部加载完成之后传出的对象
var imgObj = {};
for(prop in imgsObj) {
var img = new Image();
img.src = imgsObj[prop];
img.onload = (function(prop) {
return function() {
currentIndex++;
var scale = currentIndex / count * 100;
if(handleObj.progress) {
handleObj.progress(scale);
}
imgObj[prop] = this;
if(handleObj.complete) {
if(currentIndex == count) {
handleObj.complete(imgObj);
}
}
}
})(prop)
}
}
HTML文件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"/>
<title></title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
#gameOver {
width: 80px;
height: 35px;
border: 1px solid #000;
border-radius: 8px;
position: absolute;
top: 400px;
left: 50%;
transform: translateX(-40px);
text-align: center;
display: none;
}
</style>
</head>
<body>
<div id="gameOver">游戏结束<button id="reStart">再来一次</button></div>
<canvas id="canvas" width="500" height="500"></canvas>
<script src="js/loading.js" type="text/JavaScript" charset="utf-8"></script>
<script type="text/javascript">
var gameOver = document.getElementById("gameOver");
var reStart = document.getElementById("reStart");
// 用来标记动画是否执行
var start = true;
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
// 屏幕宽高
var SCREEN_WIDTH = document.documentElement.clientWidth;
var SCREEN_HEIGHT = document.documentElement.clientHeight;
canvas.width = SCREEN_WIDTH;
canvas.height = SCREEN_HEIGHT;
loading({
background_2: "img/background_2.png",
hero_fly_1: "img/hero_fly_1.png",
hero_fly_2: "img/hero_fly_2.png",
bullet1: "img/bullet1.png",
enemy1_fly_1: "img/enemy1_fly_1.png",
enemy2_fly_1: "img/enemy2_fly_1.png",
enemy3_fly_1: "img/enemy3_fly_1.png",
enemy4_fly_1: "img/enemy4_fly_1.png",
enemy5_fly_1: "img/enemy5_fly_1.png",
enemy1_blowup_1: "img/enemy1_blowup_2.png",
enemy1_blowup_2: "img/enemy1_blowup_2.png",
enemy1_blowup_3: "img/enemy1_blowup_3.png",
enemy1_blowup_4: "img/enemy1_blowup_4.png",
enemy2_blowup_1: "img/enemy2_blowup_2.png",
enemy2_blowup_2: "img/enemy2_blowup_2.png",
enemy2_blowup_3: "img/enemy2_blowup_3.png",
enemy2_blowup_4: "img/enemy2_blowup_4.png",
enemy2_blowup_5: "img/enemy2_blowup_5.png",
enemy2_blowup_6: "img/enemy2_blowup_6.png",
enemy2_blowup_7: "img/enemy2_blowup_7.png",
enemy3_blowup_1: "img/enemy2_blowup_2.png",
enemy3_blowup_2: "img/enemy3_blowup_2.png",
enemy3_blowup_3: "img/enemy3_blowup_3.png",
enemy3_blowup_4: "img/enemy3_blowup_4.png"
}, {
complete: main
});
function rand(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
function checkP(obj1, obj2) {
if(Math.abs(obj1.x + obj1.w / 2 - (obj2.x + obj2.w / 2)) <= obj1.w / 2 + obj2.w / 2 && Math.abs(obj1.y + obj1.h / 2 - (obj2.y +obj2.h / 2)) <= obj1.h / 2 + obj2.h / 2) {
return true;
} else {
return false;
}
}
// 图片加载完成之后执行的函数
function main(obj) {
planeImg = obj.hero_fly_1;
var plane = {
img: planeImg,
w: planeImg.width,
h: planeImg.height,
x: SCREEN_WIDTH / 2 - planeImg.width / 2,
y: SCREEN_HEIGHT - planeImg.height - 20
}
// 数组用来装子弹
var bullets = [];
// 子弹
function Bullet() {
this.img = obj.bullet1;
this.w = this.img.width;
this.h = this.img.height;
this.x = plane.x + plane.w / 2 - this.w / 2;
this.y = plane.y - this.h;
this.speed = 1;
}
// 画子弹
Bullet.prototype.draw = function() {
ctx.drawImage(this.img, this.x, this.y, this.w, this.h);
}
Bullet.prototype.move = function() {
this.y -= this.speed;
}
// 判断子弹是否应该被清除
Bullet.prototype.canClear = function() {
if(this.y <= -this.h) {
return true;
} else {
return false;
}
}
// 敌机
function Enemy() {
this.img = obj.enemy1_fly_1;
this.w = this.img.width;
this.h = this.img.height;
this.x = rand(0, SCREEN_WIDTH - this.w);
this.y = -this.h;
this.speed = 2;
this.blood = 1;
this.type = 2;
// 图片的个数
this.length = 4;
// 播放第几张,当这个值等于图片个数时,播放完成,应该把敌机删掉
this.playIndex = 1;
}
Enemy.prototype.draw = function() {
ctx.drawImage(this.img, this.x, this.y, this.w, this.h);
}
Enemy.prototype.move = function() {
this.y += this.speed;
}
// 判断敌机是否应该被清除
Enemy.prototype.canClear = function() {
if(this.y >= SCREEN_HEIGHT) {
return true;
} else {
return false;
}
}
Enemy.prototype.changeType = function(type) {
this.type = type;
switch(this.type) {
case 1:
break;
case 2:
this.img = obj.enemy2_fly_1;
this.w = this.img.width;
this.h = this.img.height;
this.x = rand(0, SCREEN_WIDTH - this.w);
this.y = -this.h;
this.blood = 3;
this.speed = 1;
break;
case 3:
this.img = obj.enemy3_fly_1;
this.w = this.img.width;
this.h = this.img.height;
this.x = rand(0, SCREEN_WIDTH - this.w);
this.y = -this.h;
this.blood = 2;
this.speed = 1.5;
break;
default:
break;
}
}
// 爆炸动画
Enemy.prototype.play = function() {
this.img = obj["enemy1_blowup_" + this.playIndex]
}
// 用来保存被击中的飞机的下标
var removeIndex = [];
var enemys = [];
var scrollY = 0;
function drawAll() {
ctx.clearRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
scrollY++;
if(scrollY >= SCREEN_HEIGHT) {
scrollY = 0;
}
// 给飞机换图片,模拟动态的效果
if(scrollY % 10 == 0) {
plane.img = obj.hero_fly_1;
} else {
plane.img = obj.hero_fly_2;
}
// 创建子弹
if(scrollY % 20 == 0) {
var bullet = new Bullet();
bullets.push(bullet);
}
// 创建敌机
if(scrollY % 40 == 0) {
var enemy = new Enemy(obj.enemy1_fly_1);
if(scrollY % 299 == 0) {
enemy.changeType(2);
} else if(scrollY % 3 == 0) {
enemy.changeType(3);
}
enemys.push(enemy);
}
// 画背景
ctx.drawImage(obj.background_2, 0, scrollY, SCREEN_WIDTH, SCREEN_HEIGHT);
ctx.drawImage(obj.background_2, 0, scrollY - SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT);
// 画子弹
for(var i = 0; i < bullets.length; i++) {
var bullet = bullets[i];
bullet.draw();
bullet.move();
if(bullet.canClear()) {
bullets.splice(i, 1);
i--;
}
}
// 画敌机
for(var i = 0; i < enemys.length; i++) {
var enemy = enemys[i];
if(enemy.canClear()) {
enemys.splice(i, 1);
i--;
}
enemy.draw();
enemy.move();
}
// 画飞机
ctx.drawImage(plane.img, plane.x, plane.y /*, plane.w, plane.h*/ );
// 检测碰撞
for(var i = 0; i < bullets.length; i++) {
for(var j = 0; j < enemys.length; j++) {
if(checkP(bullets[i], enemys[j])) {
enemys[j].blood--;
if(enemys[j].blood == 0) {
// 先删飞机,后删子弹
// enemys.splice(j, 1);
// 记录下被击中敌机
removeIndex.push(enemys[j]);
}
bullets.splice(i, 1);
// 在当前这一帧画面内,只要判断一次碰撞,只要有碰撞,后面的就不需要再判断了,新的碰撞会产生在之后的画面里
break;
}
}
}
// 处理敌机爆炸的动画
// 不等于-1表示,某个敌机被击中,需要动画
if(removeIndex.length > 0) {
for(var i = 0; i < removeIndex.length; i++) {
var enemy = removeIndex[i];
// 图片改变
enemy.playIndex++;
enemy.play();
// 如果图片换完
if(enemy.playIndex == enemy.length) {
// 删掉
for (var j = 0; j < enemys.length; j++) {
if (enemy === enemys[j]) {
enemys.splice(j,1);
}
}
// removeIndex改为-1,等待接收之后的值
removeIndex.splice(i, 1);
if(i < removeIndex.length) {
i--;
}
}
}
}
// 检测飞机碰撞
for(var i = 0; i < enemys.length; i++) {
if(checkP(plane, enemys[i])) {
gameOver.style.display = "block";
start = false;
}
}
if(start) {
window.requestAnimationFrame(drawAll);
}
}
drawAll();
reStart.onclick = function() {
// 防止之前的敌机爆炸未完成,开始新游戏时清空
removeIndex = [];
// 调整飞机位置
plane.x = SCREEN_WIDTH / 2 - planeImg.width / 2;
plane.y = SCREEN_HEIGHT - planeImg.height - 20;
// 清空子弹和敌机
bullets = [];
enemys = [];
// 重新开始绘制
gameOver.style.display = "none";
start = true;
drawAll();
}
canvas.addEventListener("touchstart", function() {
var x = event.touches[0].clientX;
var y = event.touches[0].clientY;
// 判断有没有点到飞机
if(x >= plane.x && x <= plane.x + plane.w && y >= plane.y && y <= plane.y + plane.h) {
// 绑定手势移动事件
var disX = x - plane.x;
var disY = y - plane.y;
canvas.addEventListener("touchmove", function() {
var x = event.touches[0].clientX;
var y = event.touches[0].clientY;
plane.x = x - disX;
plane.y = y - disY;
}, false);
}
}, false);
canvas.addEventListener("touchstart", function() {
canvas.addEventListener("touchmove", function() {
event.preventDefault();
}, false);
}, false);
}
</script>
</body>
</html>