子彈可以飛了,完事兒之后就可以添加敵機(jī)了
其實(shí)這里面所有的敵機(jī)基本上都類(lèi)似,這里只說(shuō)一種,然后現(xiàn)在把代碼弄過(guò)來(lái):
/////////V6版本新增加內(nèi)容/////////
//小號(hào)敵機(jī)
function Enemy1(imgs) {
this.x = Math.random() * (canvasWidth - imgs[0].width);
this.y = -imgs[0].height;
this.width = imgs[0].width;
this.height = imgs[0].height;
this.index = 0; //當(dāng)前繪制的圖片在數(shù)組中的下標(biāo)
this.speed = 7; //小敵機(jī)每42ms移動(dòng)的距離——即飛行速度
this.removable = false; //可以刪除了嗎
this.blood = 1; //小敵機(jī)只有1格血
this.crashed = false; //是否被撞毀
this.draw = function () {
ctx.drawImage(imgs[this.index], this.x, this.y);
}
this.counter = 0;
this.move = function () {
this.counter++;
this.y += this.speed;
this.checkHit(); //碰撞檢查
//若飛出下邊界或炸毀了,則可以刪除了
if (this.crashed && this.counter % 2 === 0) {
if (this.index === 0) this.index = 1;
else if (this.index < imgs.length - 1) this.index++;
else {
this.removable = true;
heroScore += 5;
}
}
if (this.y >= canvasHeight) { //飛出下邊界
this.removable = true;
}
}
////碰撞檢驗(yàn)////
/*
碰撞的四個(gè)條件:
obj1.x + obj1.width >= obj2.x
obj2.x + obj2.width >= obj1.x
obj1.y + obj1.height >= obj2.y
obj2.y + obj2.height >= obj1.y
*/
this.checkHit = function () {
//每個(gè)敵機(jī)必須和我方的每個(gè)子彈進(jìn)行碰撞檢驗(yàn)
for (var i in bulletList.arr) {
var b = bulletList.arr[i];
/*console.log('1'+this.x+'-'+this.y);
console.log('2'+this.width+'-'+this.height);
console.log('3'+b.x+'-'+b.y);
console.log('4'+b.width+'-'+b.height);*/
if ((this.x + this.width >= b.x)
&& (b.x + b.width >= this.x)
&& (this.y + this.height >= b.y)
&& (b.y + b.height >= this.y)) {
this.blood--;
if (this.blood <= 0) { //沒(méi)有血格了,開(kāi)始撞毀進(jìn)程
this.crashed = true;
}
b.removable = true;
}
}
//每個(gè)敵機(jī)必須和我方英雄做碰撞檢驗(yàn)
if ((this.x + this.width >= hero.x)
&& (hero.x + hero.width >= this.x)
&& (this.y + this.height >= hero.y)
&& (hero.y + hero.height >= this.y)) {
hero.crashed = true; //我方英雄開(kāi)始撞毀程序
}
}
}
首先先要設(shè)置下這個(gè)飛機(jī)的參數(shù)變量,先介紹下:
x坐標(biāo),首先是先想下飛機(jī)怎么出來(lái),然后呢因?yàn)閤坐標(biāo)就是屏幕的橫向?qū)挾?,所以直接用canvas的寬度,因?yàn)閳D片從頂點(diǎn)畫(huà)的,到最后的位置只能是圖片的右邊挨著屏幕右邊,所以要減去一個(gè)圖片的寬度
y坐標(biāo),開(kāi)始的時(shí)候基本上可以設(shè)置為圖片的高度,這樣每次移動(dòng)的時(shí)候才能顯示出來(lái),看起來(lái)好點(diǎn)
寬高就是圖片的寬高了
index,用于圖片更換的時(shí)候,也就是這個(gè)敵機(jī)死亡的時(shí)候需要切換動(dòng)畫(huà),這時(shí)候才能用到,否則基本都是0就可以了
speed,也就是敵機(jī)飛行速度,這個(gè)的話可以根據(jù)自己想要的效果去設(shè)置,可以在后面根據(jù)分?jǐn)?shù)去增加減少等等
removable,用于判斷這個(gè)敵機(jī)是不是刪除了
blood,對(duì)于敵機(jī)來(lái)說(shuō)是血格,這個(gè)的話,可以解釋為可以接受幾次子彈的打擊
crashed,是否被撞毀,
移動(dòng)方法呢和上面的子彈差不多,一個(gè)正一個(gè)反,這個(gè)就不說(shuō)了
驗(yàn)證方法,主要是判斷每個(gè)敵機(jī)和子彈,主機(jī)的判斷,先檢驗(yàn)是否和子彈碰撞,因?yàn)樽訌椃旁谧訌椓斜砝铮砸h(huán)判斷下,如果被打了,判斷下是不是有血格,如果沒(méi)有就可以執(zhí)行刪除程序了,然后就是判斷是不是和主機(jī)碰撞
然后就可以弄中號(hào)大號(hào)敵機(jī)了,這里面的方法和小型敵機(jī)幾乎是一模一樣,所以這里就不說(shuō)了
敵機(jī)弄完之后就可以放到敵機(jī)列表里面了:
//所有敵機(jī)組成的列表
var enemyList;
function EnemyList() {
this.arr = []; //保存所有的敵機(jī)
this.add = function (enemy) { //增加新敵機(jī)
this.arr.push(enemy);
}
this.remove = function (i) { //刪除指定的敵機(jī)
this.arr.splice(i, 1);
}
this.draw = function () { //繪制所有的敵機(jī)
for (var i in this.arr) {
this.arr[i].draw();
}
}
this.move = function () { //讓所有的敵機(jī)移動(dòng)
this.generate(); //生成新的敵人
for (var i in this.arr) {
var e = this.arr[i];
e.move();
if (e.removable) {
this.remove(i);
}
}
}
//隨機(jī)生成一個(gè)敵機(jī)
this.generate = function () {
/*敵機(jī)生成的要求:
*何時(shí)生成敵機(jī)是隨機(jī)的,不是定時(shí)或者連續(xù)的
*小號(hào)敵機(jī)的概率最大,中號(hào)其次,大號(hào)最少
*思路:0~199隨機(jī)數(shù) 小號(hào)0/1/2/3/4/5 中號(hào)6/7/8 大號(hào)9 其它值不生成敵機(jī)
*進(jìn)一步擴(kuò)展:可以將6/9/10設(shè)置為變量,以增加游戲難度
*/
var num = Math.floor(Math.random() * 200);
if (num < 6) {
this.add(new Enemy1(imgsEnemy1));
} else if (num < 9) {
this.add(new Enemy2(imgsEnemy2));
} else if (num < 10) {
this.add(new Enemy3(imgsEnemy3));
}
}
}
這個(gè)的話,和子彈列表差不多,都有添加刪除畫(huà)和移動(dòng)方法,最后呢多出來(lái)一個(gè)generate函數(shù),這個(gè)現(xiàn)在來(lái)說(shuō)下,主要就是說(shuō)下生成敵機(jī)的要求,這個(gè)的話主要就隨機(jī)設(shè)置了,設(shè)置完之后直接判斷下生成的數(shù)來(lái)判斷生成的敵機(jī)種類(lèi),這個(gè)的話,也可以修改下,增加游戲難度,也可以和分?jǐn)?shù)掛鉤,這樣就可以變的越來(lái)越難了
最后說(shuō)下分?jǐn)?shù)和剩余主機(jī)生命值的方法里面基本也沒(méi)什么東西,主要就是畫(huà)下數(shù)字文字而已,只是這些分?jǐn)?shù)變化的時(shí)候就可以自己隨意玩了,嘻嘻嘻嘻
后面還有倆函數(shù),一個(gè)暫停和開(kāi)始,這里只是簡(jiǎn)單的改了下?tīng)顟B(tài),大家可以讓用戶(hù)更好的體驗(yàn),可以和其他游戲一樣,弄點(diǎn)按鈕,弄個(gè)設(shè)置啊什么的
因?yàn)橛袀€(gè)暫停,所以函數(shù)也弄了一個(gè),把所有的東西都清空下就可以了,這里的話,用的法子是直接把一個(gè)圖片畫(huà)下,就相當(dāng)于是覆蓋所有東西了
終于到最后了,gameover函數(shù),當(dāng)游戲結(jié)束的時(shí)候可以畫(huà)出自己想要出來(lái)的畫(huà)面,可以用文字來(lái)弄出來(lái),當(dāng)然也可以把現(xiàn)在一些分享啊什么的按鈕弄上去,這里要看大家怎么弄了
//繪制當(dāng)前得分和剩余英雄數(shù)量
function drawStat() { //繪制統(tǒng)計(jì)數(shù)據(jù)
ctx.font = '25px Helvetica';
ctx.fillStyle = '#333';
//繪制當(dāng)前的游戲得分
var score = 'SCORE: ' + heroScore;
ctx.fillText(score, 10, 35);
//繪制剩余的英雄數(shù)量
var heros = 'HEROS: ' + heroCount;
var w = ctx.measureText(heros).width;
ctx.fillText(heros, canvasWidth - w - 10, 35);
}
/***階段5:游戲暫停***/
canvas.onmouseout = function () { //鼠標(biāo)移出畫(huà)布
if (curPhase === PHASE_PLAY) {
curPhase = PHASE_PAUSE;
}
}
canvas.onmouseover = function () { //鼠標(biāo)移入畫(huà)布
if (curPhase === PHASE_PAUSE) {
curPhase = PHASE_PLAY;
}
}
function drawPause() { //繪制暫停提示圖標(biāo)
var x = canvasWidth / 2 - imgGamePauseNor.width / 2;
var y = canvasHeight / 2 - imgGamePauseNor.height / 2;
ctx.drawImage(imgGamePauseNor, x, y);
}
/***階段6:游戲結(jié)束***/
function drawGameover() {
ctx.font = '50px Helvetica';
ctx.fillStyle = '#ccc';
ctx.strokeStyle = '#333';
var txt = 'GAME OVER';
var w = ctx.measureText(txt).width;
var x = canvasWidth / 2 - w / 2;
var y = canvasHeight / 2 + 50 / 2;
ctx.fillText(txt, x, y);
ctx.strokeText(txt, x, y);
}
好了,到此為止,就算是真?zhèn)€項(xiàng)目結(jié)束了,最近看了下,感覺(jué)寫(xiě)這些東西看的人比較多點(diǎn),所以最近我會(huì)找下一些特效什么的,寫(xiě)成公眾號(hào),希望大家也幫忙找找人過(guò)來(lái)關(guān)注下公眾號(hào),我會(huì)努力加油的?。?!