模擬微信打飛機的demo
<html>
<head>
<meta charset="UTF-8">
<title>打飛機</title>
<style type='css/text'>
* {
margin: 0;
padding: 0;
}
body {
overflow-x: hidden;
}
/*載入樣式*/
#load {
/*background: url(../img/loading.gif) no-repeat center center;*/
height: 100%;
width: 100%;
position: absolute;
left: 0;
top: 0;
}
#load div {
width: 100px;
height: 100px;
border-radius: 50%;
background: gray;
color: white;
line-height: 100px;
text-align: center;
font-size: 30px;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
}
#per {
color: white;
font-size: 30px;
}
#lt {
position: absolute;
left: 0;
top: 0;
display: none;
}
#score {
}
#game {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
margin: auto;
width: 200px;
height: 150px;
border: 1px solid grey;
background: #ccc;
display: none;
text-align: center;
line-height: 50px;
}
a {
width: 100px;
height: 30px;
font-size: 20px;
/*border: 2px solid gray;*/
text-decoration: none;
color: red;
display: inline-block;
}
</style>
</head><body>
<!--整體思路
1.載入樣式
2.背景圖移動
3.玩家飛機 由於玩家只有一個所以可以使用物件的方式去設定,即設定一個物件
4.敵機 共三種 可以設定為一個類,即設定建構函式,可以使用該建構函式建立三個敵機類
5.彈夾型別,雙彈,清屏彈,鐳射,也可以是一個類,即設定一個彈夾的建構函式
6.擊中目標,子彈碰到敵機,矩形碰撞
7.被撞擊,敵機撞到玩家飛機,矩形碰撞
8.計時器,計分器
-->
<!--載入樣式-->
<div id="load">
<div><span id="per">0</span>%</div>
</div>
<canvas id="canvas" width="400" height="600"></canvas>
<!--設定音效-->
<audio id="gameMusic" src="audio/game_music.mp3" loop="loop" ></audio>
<audio id="gameOver" src="audio/game_over.mp3"></audio>
<audio id="bulletMusic" src="audio/bullet.mp3"></audio>
<audio id="boomMusic1" src="audio/enemy1_down.mp3"></audio>
<audio id="boomMusic2" src="audio/enemy2_down.mp3"></audio>
<audio id="boomMusic3" src="audio/enemy3_down.mp3"></audio>
<!--注意音訊路徑-->
<span id="score">0</span>分
</div>
<div id="game">遊戲結束<br />得分:<span id="count"></span><br /><a href="http://127.0.0.1:8020/%E8%AF%BE%E5%A0%82%E4%BB%A3%E7%A0%81/JS/Day26-%E6%89%93%E9%A3%9E%E6%9C%BA%E6%B8%B8%E6%88%8F/game.html">重新開始</a></div>
</body>
<script type="text/javascript" charset="utf-8">
//獲取id方法
function getId(id) {
return document.getElementById(id);
}
//設定img載入
var imgBox = ['img/background.png', 'img/bullet1.png', 'img/bullet2.png', 'img/enemy1.png', 'img/enemy2.png', 'img/enemy3.png', 'img/herofly.png', 'img/prop.png'];
//獲取頁面當中的dom節點
var canvas = getId("canvas");
var cx = canvas.getContext("2d");
//背景音樂
var gameMusic = getId("gameMusic"); //全域性音樂
var gameOver = getId("gameOver"); //玩家死亡音樂
var bulletMusic = getId("bulletMusic"); //槍聲
var boomMusic1 = getId("boomMusic1"); //小型敵機聲音
var boomMusic2 = getId("boomMusic2"); //中型敵機聲音
var boomMusic3 = getId("boomMusic3"); //大型敵機聲音
//重新設定canvas大小,使其和window視窗一致
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
//載入圖片
var imgLength = imgBox.length;
var count = 0; //宣告迴圈次數
for (var i = 0; i < imgLength; i++) {
var img = new Image();
img.src = imgBox[i];
//載入完畢
img.onload = function() {
count++; //每載入一個就新增一次
//獲取百分比
var per = Math.floor(count / imgLength * 100);
getId("per").innerHTML = per;
//判斷是否載入90%
if (per >= 90) {
//去掉載入中效果
getId("load").style.display = "none";
//新增背景音樂,渲染氣氛
gameMusic.play();
}
}
}
//載入圖片
//背景圖片
var bgImg = new Image();
bgImg.src = imgBox[0];
//玩家圖片
var hero = new Image();
hero.src = imgBox[6];
//單行子彈圖片
var dBullet = new Image();
dBullet.src = imgBox[1];
//兩行子彈圖片
var dBullet2 = new Image();
dBullet2.src = imgBox[2];
//道具圖片
var prop = new Image();
prop.src = imgBox[7];
//敵機圖片
var enemy1 = new Image();
enemy1.src = imgBox[3];
var enemy2 = new Image();
enemy2.src = imgBox[4];
var enemy3 = new Image();
enemy3.src = imgBox[5];
//背景圖移動
var h = 0;
function moveBg() {
h++;
cx.drawImage(bgImg, 0, h, canvas.width, canvas.height);
cx.drawImage(bgImg, 0, h - canvas.height, canvas.width, canvas.height);
//判斷復位
if (h >= canvas.height) {
h = 0;
}
}
//設定玩家
var Hero = {
h: 82, //玩家的高
w: 66, //玩家的寬
x: (canvas.width - 66) / 2,
y: canvas.height - 100,
bx: 0,
//繪製玩家
draw: function() {
cx.drawImage(hero, this.bx, 0, 66, 82, this.x, this.y, 66, 82);
}
};
//滑鼠拖動事件
window.addEventListener("mousemove", function(event) {
var x = event.clientX - canvas.offsetLeft;
var y = event.clientY - canvas.offsetTop;
//把滑鼠的位置給玩家
Hero.x = x - 33;
Hero.y = y - 35;
//防止事件冒泡和預設事件
event.stopPropagation();
event.preventDefault();
}, false);
//建立子彈類 x值,y值,寬,高,子彈型別,傷害值
function Bullet(x, y, w, h, buts, hurt) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.buts = buts;
this.hurt = hurt;
}
//存放子彈的陣列
var bulletBox = [];
//控制子彈時間間隔,為索引值
var bulletNum = 0;
var box = 6;
//子彈移動
Bullet.prototype.move = function() {
bulletNum++;
if (bulletNum >= box) {
//單行子彈移動
var b = new Bullet(this.x, this.y, this.w, this.h, this.buts, this.hurt);
//把子彈放進彈夾
bulletBox.push(b);
bulletNum = 0;
}
//迴圈繪製陣列中子彈
for (var i = 0; i < bulletBox.length; i++) {
var bb = bulletBox[i];
bb.y -= 5;
//到達頂部刪除陣列中的資料
if (bb.y <= -bb.h) {
bulletBox.splice(i, 1);
}
if (bb) {
//如果該元素沒有從陣列中刪除則繪製子彈
cx.drawImage(bb.buts, bb.x, bb.y);
bulletMusic.play(); //給子彈加聲音
}
}
};
//建立一個道具類 bx代表從道具圖中哪個地方獲取道具 speed代表下落速度
function Prop(x, y, w, h, bx, speed) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.bx = this.w * bx;
this.speed = speed;
}
//道具下落方法
Prop.prototype.move = function() {
this.y += this.speed;
//繪製道具
cx.drawImage(prop, this.bx, 0, this.w, this.h, this.x, this.y, this.w, this.h);
};
//建立敵機類
function EnemyPlane(x, y, w, h, type, hp, speed, die, score) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.type = type; //敵機型別
this.hp = hp; //剩餘血量
this.speed = speed;
this.die = die; //死亡動畫
this.score = score; //不同敵機不同分數
this.bx = 0;
this.bol = true; //判斷是否爆炸
this.sayDie = false; //告訴程式物件的死亡狀態,便於及時清除敵機殘害
}
//敵機爆炸 也就是血量為0
EnemyPlane.prototype.boom = function() {
this.bol = false;
}
//敵機下落
EnemyPlane.prototype.move = function() {
//繪製敵機
if (this.bol) {
this.y += this.speed;
} else { //死亡
this.die--; //死亡動畫執行的關鍵幀間隔
this.bx += this.w; //圖片移動
if (this.die <= 0) { //告知死亡
this.sayDie = true;
}
}
//繪製敵機
cx.drawImage(this.type, this.bx, 0, this.w, this.h, this.x, this.y, this.w, this.h);
}
//定義初始值
var score = 0; //設定分數
var enemyArr = []; //設定敵機陣列
var lifeBol = true; //玩家活著
var da = true; //判斷是否是單雙子彈,預設為單
var buttled; //宣告子彈型別
var fire = 0; //替換飛機噴火
var heronum = 0;
var baoBol = true; //設定整個頁面只有一個子彈包裹的布林值
var bao; //子彈包裹
var timer = 0; //設定雙排子彈出現的關鍵幀
//設定主函式
function main() {
//清除畫布
cx.clearRect(0, 0, canvas.width, canvas.height);
//背景圖移動
moveBg();
Hero.draw(); //繪製玩家
//新增敵機
var enemRan = randomNum(1, 5000); //獲取新增敵機的概率
var butRan = randomNum(1, 3000);
var baoRan = randomNum(1, 3000); //獲取新增子彈型別的概率
//判斷敵機出現的位置
var x1 = randomNum(0, canvas.width - 38); //設定小敵機出現位置的x座標
var x2 = randomNum(0, canvas.width - 46); //設定中敵機出現位置的x座標
var x3 = randomNum(0, canvas.width - 110); //設定大敵機出現位置的x座標
var x4 = randomNum(0, canvas.width - 38); //設定彈夾出現位置的x座標
var enemySpeed = randomNum(5, 10); //設定敵機速度
//建立敵機
if (enemRan < 200) {
//建立小敵機
enemyArr.push(new EnemyPlane(x1, -34, 38, 34, enemy1, 1, 5, 5, 10));
}
if (enemRan > 40 && enemRan < 80) {
//建立中敵機
enemyArr.push(new EnemyPlane(x2, -64, 46, 64, enemy2, 3, 4, 6, 50));
}
if (enemRan > 100 && enemRan < 110) {
//建立大敵機
enemyArr.push(new EnemyPlane(x3, -164, 110, 164, enemy3, 7, 2, 10, 100));
}
//建立子彈
var hx = Hero.x;
var hy = Hero.y;
if (lifeBol) { //玩家活著
fire++; //當飛機正常飛行的時候,改變圖的位置,顯示噴火效果
if (fire > 1) {
fire = 0;
}
Hero.bx = Hero.w * fire;
if (da) { //單行子彈
//建立單行子彈 6*14
buttled = new Bullet(hx + 30, hy - 14, 6, 14, dBullet, 10);
} else { //雙行子彈
buttled = new Bullet(hx + 9, hy - 14, 48, 14, dBullet2, 20);
}
buttled.move();
} else { //如果英雄死亡
//清空子彈陣列
bulletBox.length = 0;
heronum++;
if (heronum % 10 == 0) {
Hero.bx = Math.floor(heronum / 10) * Hero.w;
}
}
//遍歷enemyArr陣列 新增敵機
for (var i = 0; i < enemyArr.length; i++) {
//遍歷子彈陣列
for (var j = 0; j < bulletBox.length; j++) {
if (enemyArr[i].bol) {
//判斷子彈與敵機相撞
if (crash(enemyArr[i], bulletBox[j])) {
//子彈碰到敵機
enemyArr[i].hp -= bulletBox[j].hurt;
if (enemyArr[i].hp < 0) {
enemyArr[i].boom(); //執行爆炸
}
//根據每個敵機攜帶的分數,判斷敵機型別,獲取相應的分數,新增聲音
if (enemyArr[i].score == 10) {
//小型機
boomMusic1.play();
} else if (enemyArr[i].score == 50) {
//中型機
boomMusic2.play();
} else if (enemyArr[i].score == 100) {
//大型機
boomMusic3.play();
}
//新增分數
score += enemyArr[i].score;
//刪除子彈
bulletBox.splice(j, 1);
}
}
}
//檢測玩家撞到了飛機
if (crash(enemyArr[i], Hero) && lifeBol) {
lifeBol = false; //玩家死亡
gameOver.play(); //結束音樂響起
gameMusic.pause(); //背景音樂暫停
getId("game").style.display = "block";
}
//刪除沒有碰到子彈和飛機的敵機
if (enemyArr[i].y > canvas.height) {
enemyArr.splice(i, 1);
}
//繪製敵機
if (enemyArr[i]) {
enemyArr[i].move();
//檢測敵機動畫執行完畢
if (enemyArr[i].sayDie) {
enemyArr.splice(i, 1); //刪除敵機
}
}
//新增子彈包裹
//console.log(butRan < 100 , baoBol);
if (butRan < 100 && baoBol) { //滿足概率,並且新增true
baoBol = false;
var typeNum = baoRan < 50 ? 0 : 1;
bao = new Prop(x4, -68, 38, 68, typeNum, 0.5);
}
//當baoBol為false的時候
if (!baoBol && bao) {
bao.move();
//當包裹超出canvas範圍時消失 可以重新設定包裹
if (bao && bao.y > canvas.height) {
baoBol = true;
}
//當包裹和玩家碰撞的時候消失
if (crash(bao, Hero) && lifeBol) {
baoBol = true;
if (bao.bx == 0) { //碰到了清屏彈
for (var k = 0; k < enemyArr.length; k++) {
enemyArr[k].boom(); //每一個都要執行爆炸方法
if (enemyArr[k].score == 10) {
boomMusic1.play();
} else if (enemyArr[k].score == 50) {
boomMusic2.play();
} else {
boomMusic3.play();
}
//加分
if (enemyArr[k].sayDie) {
score += enemyArr[k].score;
enemyArr.splice(k, 1);
}
}
} else if (bao.bx == 38) { //碰到了雙彈
da = false;
timer = 0;
}
}
}
if (!da) {
timer++;
if (timer > 3000) {
da = true;
timer = 0;
}
}
}
//設定分數
getId("score").innerHTML = score;
getId("count").innerHTML = score;
//執行動畫
requestAnimationFrame(main);
}
//頁面資源載入完畢後執行
window.onload = function() {
//執行主函式
main();
}
//隨機數
function randomNum(x, y) {
return Math.floor(Math.random() * (y - x + 1) + x);
}
//碰撞檢測 (矩形碰撞檢測)
function crash(obj1, obj2) {
var x1 = obj1.x;
var y1 = obj1.y;
var rx1 = obj1.x + obj1.w / 2;
var ry1 = obj1.y + obj1.h / 2;
var x2 = obj2.x;
var y2 = obj2.y;
var rx2 = obj2.x + obj2.w / 2;
var ry2 = obj2.y + obj2.h / 2;
//判斷碰撞
if (Math.abs(rx1 - rx2) <= (obj1.w + obj2.w) / 2 && Math.abs(ry1 - ry2) <= (obj1.h + obj2.h) / 2) {
return true;
} else {
return false;
}
}
</script>
</html>