体验一下:https://oleolema.github.io/Plane%20Wars/
Game类
(function () { var Game = window.Game = function () { //获取画布 this.canvas = document.getElementsByClassName('mycanvas')[0]; this.ctx = this.canvas.getContext('2d'); //初始化窗口 this.init(); //资源对象 this.R; //所有定时器 this.allTimer = []; //加载资源 var self = this; this.loadResources(function () { self.start(); }); } Game.prototype.start = function () { //备份game对象 var self = this; //帧数 self.fno = 0; //背景对象 this.background = new Background(); //界面对象 this.interface = new Interface(); this.interface.printBegin(); this.interface.beginClick(function () { game.background.playAudio(); //飞机对象 self.plane = new Plane(); //敌人对象 self.enemy = new Enemy(); //道具对象 self.prop = new Prop(); //游戏管理对象 self.gameManager = new GameManager(self.plane, self.enemy, self.prop); self.gameManager.addEnemy(); self.gameManager.addProp(); self.begin(); }); } Game.prototype.begin = function () { var self = this; //定时器 this.timer = setInterval(function () { //清屏 self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height); //背景 self.background.print(); self.background.move(); //敌人 self.enemy.print(); self.enemy.move(); //游戏管理 self.gameManager.enemyIsDie(); self.gameManager.getProp(); self.gameManager.upGrade(); self.gameManager.planeDie(); self.gameManager.printScore(); //道具 self.prop.print(); self.prop.move(); //飞机 self.plane.arms.print(); self.plane.arms.move(); self.plane.print(); self.plane.move(); //FNO self.fno++; self.ctx.textAlign = 'left'; self.ctx.font = '12px 黑体'; self.ctx.fillText('FNO:' + self.fno, 0, 10); }, 20); this.allTimer.push(this.timer); } Game.prototype.init = function () { var windowW = document.documentElement.clientWidth; var windowH = document.documentElement.clientHeight; if (windowW > 414) { //大屏居中 this.canvas.style.marginLeft = windowW / 2 - 207 + 'px'; windowW = 414; } //812 if (windowH > 750) { windowH = 750; } this.canvas.width = windowW; this.canvas.height = windowH; //禁止滑动 window.ontouchmove = function (e) { e.preventDefault && e.preventDefault(); e.returnValue = false; e.stopPropagation && e.stopPropagation(); return false; }; } Game.prototype.loadResources = function (callback) { this.R = {}; var self = this; //备份R,因为在xhr的监听函数中要用到 var loadCount = 0; var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState == 4) { var Robj = JSON.parse(xhr.responseText); //console.info(this); 这个this是xhr对象的 for (i in Robj.image) { self.R[Robj.image[i].name] = new Image(); self.R[Robj.image[i].name].src = Robj.image[i].url; self.R[Robj.image[i].name].onload = function () { self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height); self.ctx.font = '20px 楷体'; self.ctx.textAlign = 'center'; self.ctx.fillText('正在加载资源' + ++loadCount + '/' + Robj.image.length, self.canvas.width / 2, self.canvas.height / 2); if (loadCount == Robj.image.length) { callback(); } } } // console.info(self.R); } } xhr.open('get', 'game.json', true); xhr.send(null); } Game.prototype.rand = function (a, b) { return parseInt(Math.random() * (b - a) + a); } }());
背景类
(function () { var Background = window.Background = function () { this.image = game.R.background; this.w = 480; this.h = 852; this.x = 0; this.y = -this.h; } Background.prototype.print = function () { game.ctx.drawImage(this.image, this.x, this.y, this.w, this.h); game.ctx.drawImage(this.image, this.x, this.y + this.h, this.w, this.h); } Background.prototype.move = function () { this.y++; if (this.y > 0) { this.y = -this.h; } } Background.prototype.playAudio = function () { this.audio = document.createElement("AUDIO"); this.audio.src = "R/sound/game_music.mp3"; document.body.appendChild(this.audio); this.audio.loop = true; this.audio.volume = 0.5; this.audio.play(); } Background.prototype.pauseAudio = function () { this.audio.pause(); } }());
飞机类
(function () { var Plane = window.Plane = function () { this.image = game.R.hero; this.dieImage = [game.R.hero1, game.R.hero2, game.R.hero3, game.R.hero4]; this.w = 100; this.h = 124; this.x = game.canvas.width / 2 - this.w / 2; this.y = game.canvas.height - this.h; this.canvasLeft = game.canvas.offsetLeft; this.canvasTop = game.canvas.offsetTop; this.arms = new Arms(this); } Plane.prototype.print = function () { game.ctx.drawImage(this.image, this.x, this.y, this.w, this.h); } Plane.prototype.move = function () { var self = this; window.onmousemove = function (event) { if (event.x > self.canvasLeft && event.x < self.canvasLeft + game.canvas.width) { self.x = event.x - self.w / 2 - self.canvasLeft; } if (event.y > self.canvasTop && event.y < self.canvasTop + game.canvas.height) { self.y = event.y - self.h / 2; } } window.addEventListener("touchmove", function (event) { var ex = event.targetTouches[0].pageX; var ey = event.targetTouches[0].pageY; if (ex > self.canvasLeft && ex < self.canvasLeft + game.canvas.width) { self.x = ex - self.w / 2 - self.canvasLeft; } if (ey > self.canvasTop && ey < self.canvasTop + game.canvas.height) { self.y = ey - self.h / 2; } },false); } }());
敌人类
(function () { var Enemy = window.Enemy = function () { var self = this; this.allEnemy = []; this.audio = []; for (var i = 1; i < 4; i++) { this.audio[i] = document.createElement("AUDIO"); document.body.appendChild(this.audio[i]); } this.audio[1].src = "R/sound/enemy0_down.mp3"; this.audio[1].src = "R/sound/enemy1_down.mp3"; this.audio[1].src = "R/sound/enemy2_down.mp3"; this.Enemy0 = function () { this.num = 1; this.image = [game.R.enemy00, game.R.enemy01, game.R.enemy02, game.R.enemy03, game.R.enemy04]; this.w = 51; this.h = 39; this.x = game.rand(0, game.canvas.width - this.w); this.y = -this.h; this.ms = game.rand(4, 10); this.hp = 1; self.allEnemy.push(this); } this.Enemy1 = function () { this.num = 2; this.image = [game.R.enemy10, game.R.enemy11, game.R.enemy12, game.R.enemy13, game.R.enemy14]; this.w = 69; this.h = 89; this.x = game.rand(0, game.canvas.width - this.w); this.y = -this.h; this.ms = game.rand(2, 5); this.hp = 10; self.allEnemy.push(this); } this.Enemy2 = function () { this.num = 3; this.image = [game.R.enemy20, game.R.enemy21, game.R.enemy22, game.R.enemy23, game.R.enemy24]; this.w = 165; this.h = 246; this.x = game.rand(0, game.canvas.width - this.w); this.y = -this.h; this.ms = game.rand(0.5, 2); this.hp = 30; self.allEnemy.push(this); } } Enemy.prototype.print = function () { for (i in this.allEnemy) { game.ctx.drawImage(this.allEnemy[i].image[0], this.allEnemy[i].x, this.allEnemy[i].y, this.allEnemy[i].w, this.allEnemy[i].h); } } Enemy.prototype.move = function () { for (i in this.allEnemy) { this.allEnemy[i].y += this.allEnemy[i].ms; if (this.allEnemy[i].y > game.canvas.height) { this.allEnemy.splice(i, 1); } } } }());
武器类
(function () { var Arms = window.Arms = function (plane) { var self = this; //屏幕上的子弹 this.box = []; this.plane = plane; //所有的武器 this.allArms = { bullet: function () { return setInterval(function () { self.audio.load(); self.box.push(new self.Bullet(0, 0)); self.audio.play(); self.audio.play(); }, 200); }, bullet1: function () { return setInterval(function () { self.audio.load(); self.box.push(new self.Bullet1(0, 0)); self.audio.play(); }, 130); }, bomb: function () { return setInterval(function () { self.audio.load(); self.box.push(new self.Bomb(0, 0)); self.audio.play(); }, 500); }, bulletTwo: function () { return setInterval(function () { self.audio.load(); self.box.push(new self.Bullet(-30, 30)); self.box.push(new self.Bullet(30, 30)); self.audio.play(); }, 200); }, bullet2: function () { return setInterval(function () { self.audio.load(); self.box.push(new self.Bullet2(0, 0)); self.audio.play(); }, 80); }, bulletTwo1: function () { return setInterval(function () { self.audio.load(); self.box.push(new self.Bullet1(-30, 30)); self.box.push(new self.Bullet1(30, 30)); self.audio.play(); }, 130); }, bulletTwo2: function () { return setInterval(function () { self.audio.load(); self.box.push(new self.Bullet2(-30, 30)); self.box.push(new self.Bullet2(30, 30)); self.audio.play(); }, 80); }, bulletThree: function () { return setInterval(function () { self.audio.load(); self.box.push(new self.Bullet(-30, 30)); self.box.push(new self.Bullet(0, 0)); self.box.push(new self.Bullet(30, 30)); self.audio.play(); }, 200); }, bulletThree1: function () { return setInterval(function () { self.audio.load(); self.box.push(new self.Bullet1(-30, 30)); self.box.push(new self.Bullet1(0, 0)); self.box.push(new self.Bullet1(30, 30)); self.audio.play(); }, 130); }, bulletThree2: function () { return setInterval(function () { self.audio.load(); self.box.push(new self.Bullet2(-30, 30)); self.box.push(new self.Bullet2(0, 0)); self.box.push(new self.Bullet2(30, 30)); self.audio.play(); }, 80); }, } //初始化武器 this.grade = []; this.gradeTop = 0; for (i in this.allArms) { if (i != "bomb") { this.grade.push(i); } } this.use = this.allArms[this.grade[this.gradeTop]](); game.allTimer.push(this.use); //加载音乐 this.audio = document.createElement("AUDIO"); this.audio.src = "R/sound/bullet.mp3"; document.body.appendChild(this.audio); this.audio1 = document.createElement("AUDIO"); this.audio1.src = "R/sound/out_porp.mp3"; document.body.appendChild(this.audio1); this.Bullet = function (x, y) { this.image = game.R.bullet; this.w = 22; this.h = 22; this.x = x; this.y = y; this.ms = 40; this.power = 1; this.x = this.x + self.plane.w / 2 + self.plane.x - this.w / 2; this.y += self.plane.y; } this.Bullet1 = function (x, y) { this.image = game.R.bullet1; this.w = 9; this.h = 21; this.x = x; this.y = y; this.ms = 30; this.fm = 150; this.power = 1.5; this.x = this.x + self.plane.w / 2 + self.plane.x - this.w / 2; this.y += self.plane.y; } this.Bullet2 = function (x, y) { this.image = game.R.bullet2; this.w = 9; this.h = 21; this.x = x; this.y = y; this.ms = 30; this.fm = 50; this.power = 2; this.x = this.x + self.plane.w / 2 + self.plane.x - this.w / 2; this.y += self.plane.y; } this.Bomb = function (x, y) { this.image = game.R.bomb; this.w = 63; this.h = 53; this.x = x; this.y = y; this.ms = 5; this.fm = 500; this.power = 20; this.x = this.x + self.plane.w / 2 + self.plane.x - this.w / 2; this.y += self.plane.y; } } Arms.prototype.useNext = function (flag) { if (flag != undefined) { clearInterval(this.use); this.use = this.allArms[this.grade[++this.gradeTop]](); } else if (this.gradeTop < this.grade.length - 1) { var self = this; clearInterval(this.use); this.use = this.allArms[this.grade[++this.gradeTop]](); var timer = setTimeout(function () { self.usePrevious(); self.audio1.load(); self.audio1.play(); }, 5000); } } Arms.prototype.usePrevious = function () { if (this.gradeTop > 0) { clearInterval(this.use); this.use = this.allArms[this.grade[--this.gradeTop]](); } } Arms.prototype.useBomb = function () { var self = this; clearInterval(this.use); this.use = this.allArms['bomb'](); var timer = setTimeout(function () { self.audio1.load(); clearInterval(self.use); self.use = self.allArms[self.grade[self.gradeTop]](); self.audio1.play(); }, 8000); } Arms.prototype.print = function () { for (i in this.box) { game.ctx.drawImage(this.box[i].image, this.box[i].x, this.box[i].y, this.box[i].w, this.box[i].h); } } Arms.prototype.changeUse = function (bullet) { clearInterval(this.use); this.use = bullet(); } Arms.prototype.move = function () { for (i in this.box) { this.box[i].y -= this.box[i].ms; //清理屏幕外面的子弹 if (this.box[i].x < 0 || this.box[i].y < 0 || this.box[i].x > game.canvas.width || this.box[i].y > game.canvas.height) { this.box.splice(i, 1); } } } }());
道具类
(function () { var Prop = window.Prop = function () { var self = this; this.allProp = []; this.Prop1 = function () { this.num = 1; this.image = game.R.prop1; this.w = 58; this.h = 88; this.x = game.rand(0, game.canvas.width - this.w); this.y = -this.h; this.ms = 1.5; self.allProp.push(this); } this.Prop2 = function () { this.num = 2; this.image = game.R.prop2; this.w = 60 this.h = 103; this.x = game.rand(0, game.canvas.width - this.w); this.y = -this.h; this.ms = 1.5; self.allProp.push(this); } this.audio = document.createElement("AUDIO"); this.audio.src = "R/sound/get_double_laser.mp3"; document.body.appendChild(this.audio); } Prop.prototype.print = function () { for (i in this.allProp) { game.ctx.drawImage(this.allProp[i].image, this.allProp[i].x, this.allProp[i].y, this.allProp[i].w, this.allProp[i].h); } } Prop.prototype.move = function () { for (i in this.allProp) { this.allProp[i].y += this.allProp[i].ms; } } }());
游戏管理类
(function () { var GameManager = window.GameManager = function (plane, enemy, prop) { this.plane = plane; this.enemy = enemy; this.prop = prop; this.box = this.plane.arms.box; this.allEnemy = this.enemy.allEnemy; this.allProp = this.prop.allProp; this.score = 0; this.maxScore = parseInt(localStorage.getItem("maxScore") || 0); this.previousScore = this.score; this.audio = document.createElement("AUDIO"); document.body.appendChild(this.audio); } GameManager.prototype.enemyIsDie = function () { //子弹是否射到敌人 for (i in this.box) { for (var j = 0; j < this.allEnemy.length; j++) { if (this.box[i].x + this.box[i].w > this.allEnemy[j].x && this.box[i].x < this.allEnemy[j].x + this.allEnemy[j].w && this.box[i].y < this.allEnemy[j].y + this.allEnemy[j].h && this.box[i].y + this.box[i].h > this.allEnemy[j].y && this.allEnemy[j].hp > 0) { var power = this.box[i].power; this.box[i].power -= this.allEnemy[j].hp; this.allEnemy[j].hp -= power; if (this.allEnemy[j].hp <= 0) { if (this.allEnemy[j].num == 1) { this.enemy.audio[1].load(); this.score += 10; this.enemy.audio[1].play(); } else if (this.allEnemy[j].num == 2) { this.enemy.audio[1].load(); this.score += 50; this.enemy.audio[1].play(); } else if (this.allEnemy[j].num == 3) { this.enemy.audio[1].load(); this.score += 100; this.enemy.audio[1].play(); } //备份对象 var self = this; var x = self.allEnemy[j].x; var y = self.allEnemy[j].y; var w = self.allEnemy[j].w; var h = self.allEnemy[j].h; var image = self.allEnemy[j].image.splice(0, 4); this.allEnemy.splice(j, 1); //击败动画 (function () { var step = 0; var timer = setInterval(function () { if (game.fno % 10 == 0) { step++; } if (step > 3) { clearInterval(timer); return; } game.ctx.drawImage(image[step], x, y, w, h); }, 20); }()); } if (--this.box[i].power <= 0) { this.box.splice(i, 1); break; } } } } } GameManager.prototype.getProp = function () { for (i in this.allProp) { if (this.allProp[i].x + this.allProp[i].w > this.plane.x && this.allProp[i].x < this.plane.x + this.plane.w && this.allProp[i].y + this.allProp[i].h > this.plane.y && this.allProp[i].y < this.plane.y + this.plane.h) { game.prop.audio.load(); if (this.allProp[i].num == 1) { this.allProp.splice(i, 1); this.plane.arms.useNext(); } else if (this.allProp[i].num == 2) { this.allProp.splice(i, 1); this.plane.arms.useBomb(); } game.prop.audio.play(); } } } GameManager.prototype.addEnemy = function () { var self = this; var time = 0; var timer = setInterval(function () { time++; for (var i = 0; i <= (self.score / 1000); i++) { if (time % 100 == 0) { new self.enemy.Enemy0(); } if (time % 300 == 0) { new self.enemy.Enemy1(); } if (time % 500 == 0) { new self.enemy.Enemy2(); } } }, 20); game.allTimer.push(timer); } GameManager.prototype.addProp = function () { var self = this; var time = 0 var timer; setInterval(function () { time++; if (time % 600 == 0 || time == 20) { new self.prop.Prop1(); } if (time % 1100 == 0) { new self.prop.Prop2(); } }, 20); game.allTimer.push(timer); } GameManager.prototype.printScore = function () { game.ctx.font = "20px 楷体" game.ctx.fillText("分数 " + this.score, game.canvas.width - 150, 20); game.ctx.closePath(); } GameManager.prototype.upGrade = function () { if (this.score > this.previousScore * 1.7 && this.score >= 500) { this.audio.load(); this.audio.volume = 1; this.audio.src = "R/sound/get_bomb.mp3"; this.audio.play(); this.previousScore = this.score; this.plane.arms.useNext(1); } } //游戏结束 GameManager.prototype.planeDie = function () { for (i in this.allEnemy) { if (this.allEnemy[i].x + this.allEnemy[i].w > this.plane.x + 20 && this.allEnemy[i].x < this.plane.x + this.plane.w - 20 && this.allEnemy[i].y + this.allEnemy[i].h > this.plane.y + 30 && this.allEnemy[i].y < this.plane.y + this.plane.h - 30) { var self = this; this.audio.src = "R/sound/game_over.mp3"; this.audio.volume = 0.5; this.audio.play(); game.background.audio.pause(); //击败动画 (function () { var step = 0; var timer = setInterval(function () { if (game.fno % 15 == 0) { step++; } if (step > 3) { clearInterval(timer); for (i in game.allTimer) { clearInterval(game.allTimer[i]); } clearInterval(game.plane.arms.use); setTimeout(function () { clearInterval(game.plane.arms.use); }, 8000); game.interface.printGameover(); return; } game.ctx.drawImage(self.plane.dieImage[step], self.plane.x, self.plane.y, self.plane.w, self.plane.h); }, 10); }()); console.info("over"); } } } }());
界面类
(function () { var Interface = window.Interface = function () { this.canvasLeft = game.canvas.offsetLeft; this.begin = { image: game.R.name, w: 429 * 0.7, h: 84 * 0.7, x: game.canvas.width / 2 - 429 * 0.7 / 2, y: 20, } this.beginText = { text: "开始游戏", x: game.canvas.width / 2 - 60, y: game.canvas.height / 2, w: 120, h: 30 } this.pause = { image: [game.R.resume, game.R.restart, game.R.quit], w: [54, 110, 112], h: [26, 28, 24], x: [game.canvas.width / 2 - 25, game.canvas.width / 2 - 50, game.canvas.width / 2 - 50], y: [game.canvas.height / 2 * 0.618, game.canvas.height / 2 * 0.618 + 100, game.canvas.height / 2 * 0.618 + 200], } this.gameover = { image: game.R.gameover, w: game.canvas.width, h: 852 / 480 * game.canvas.width, x: 0, y: 0 } } Interface.prototype.printBegin = function () { //清屏 game.ctx.clearRect(0, 0, game.canvas.width, game.canvas.height); game.background.print(); game.background.move(); game.ctx.drawImage(this.begin.image, this.begin.x, this.begin.y, this.begin.w, this.begin.h); game.ctx.textAlign = 'left'; game.ctx.font = '30px 楷体'; game.ctx.fillText("开始游戏", this.beginText.x, this.beginText.y); } Interface.prototype.beginClick = function (callback) { var self = this; game.canvas.onmousedown = function (e) { var x = e.x - self.canvasLeft; var y = e.y; if (x > self.beginText.x && x < self.beginText.x + self.beginText.w && y > self.beginText.y - self.beginText.h && y < self.beginText.y) { callback(); } } } Interface.prototype.printPause = function () { for (var i = 0; i < 3; i++) { game.ctx.drawImage(this.pause.image[i], this.pause.x[i], this.pause.y[i], this.pause.w[i], this.pause.h[i]); } } Interface.prototype.printGameover = function () { if (game.gameManager.maxScore < game.gameManager.score) { game.gameManager.maxScore = game.gameManager.score; } localStorage.setItem("maxScore", game.gameManager.maxScore); game.ctx.clearRect(0, 0, game.canvas.width, game.canvas.height); game.ctx.drawImage(this.gameover.image, this.gameover.x, this.gameover.y, this.gameover.w, this.gameover.h); game.ctx.textAlign = 'center'; game.ctx.font = '70px 楷体'; game.ctx.fillText(game.gameManager.maxScore, this.beginText.x, this.beginText.y - 30); game.ctx.fillText(game.gameManager.score, this.beginText.x, this.beginText.y + 230); var click = window.onclick = function(){ window.location.reload(); } } }());
html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" /> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Game</title> <style> * { margin: 0px; padding: 0px; } </style> </head> <body> <canvas class="mycanvas"></canvas> <audio class="myaudio"></audio> </body> <script src="Game.js"></script> <script src="Background.js"></script> <script src="Plane.js"></script> <script src="Arms.js"></script> <script src="Enemy.js"></script> <script src="GameManager.js"></script> <script src="Prop.js"></script> <script src="Interface.js"></script> <script> var game = new Game(); </script> </html>
json文件
{ "image": [ { "name": "background", "url": "R/image/background.png" }, { "name": "bullet", "url": "R/image/bullet.png" }, { "name": "bullet1", "url": "R/image/bullet1.png" }, { "name": "bullet2", "url": "R/image/bullet2.png" }, { "name": "bomb", "url": "R/image/bomb.png" }, { "name": "enemy00", "url": "R/image/enemy0.png" }, { "name": "enemy01", "url": "R/image/enemy0_down1.png" }, { "name": "enemy02", "url": "R/image/enemy0_down2.png" }, { "name": "enemy03", "url": "R/image/enemy0_down3.png" }, { "name": "enemy04", "url": "R/image/enemy0_down4.png" }, { "name": "enemy10", "url": "R/image/enemy1.png" }, { "name": "enemy11", "url": "R/image/enemy1_down1.png" }, { "name": "enemy12", "url": "R/image/enemy1_down2.png" }, { "name": "enemy13", "url": "R/image/enemy1_down3.png" }, { "name": "enemy14", "url": "R/image/enemy1_down4.png" }, { "name": "enemy20", "url": "R/image/enemy2.png" }, { "name": "enemy21", "url": "R/image/enemy2_down1.png" }, { "name": "enemy22", "url": "R/image/enemy2_down2.png" }, { "name": "enemy23", "url": "R/image/enemy2_down3.png" }, { "name": "enemy24", "url": "R/image/enemy2_down4.png" }, { "name": "hero", "url": "R/image/hero1.png" }, { "name": "hero1", "url": "R/image/hero_blowup_n1.png" }, { "name": "hero2", "url": "R/image/hero_blowup_n2.png" }, { "name": "hero3", "url": "R/image/hero_blowup_n3.png" }, { "name": "hero4", "url": "R/image/hero_blowup_n4.png" }, { "name": "prop1", "url": "R/image/prop_type_0.png" }, { "name": "prop2", "url": "R/image/prop_type_1.png" }, { "name": "name", "url": "R/image/name.png" }, { "name": "button1", "url": "R/image/button_nor.png" }, { "name": "quit", "url": "R/image/quit_nor.png" }, { "name": "restart", "url": "R/image/restart_nor.png" }, { "name": "resume", "url": "R/image/resume_nor.png" }, { "name": "gameover", "url": "R/image/gameover.png" } ] }