射擊
你可以用很多方法殺死敵人。你可以通過刀劍、槍或者其他的東西。讓我們來看看我們怎樣向敵人射擊(使用shift鍵射擊)。
當(dāng)我說到“子彈”的時候,我的意思是那些從英雄處飛出來的、看起來要去殺死敵人的東西。它可以是球、箭頭、冰激凌、企鵝等等。
首先,我們還是應(yīng)該考慮一下,射擊應(yīng)該是怎樣的過程,子彈是怎樣運(yùn)動。一旦shift鍵被按下,首先,子彈對象、子彈剪輯被創(chuàng)建,子彈剪輯的位置應(yīng)該是英雄所在的位置。而且子彈應(yīng)該朝英雄面對的方向運(yùn)動。如果子彈遇到墻或者敵人,它應(yīng)該自動消失。如果它碰到的是敵人,那么敵人也要消失。
子彈的速度應(yīng)當(dāng)比英雄的速度大,除非你準(zhǔn)備讓英雄可以用某種方式阻擋飛行的子彈。通常那些傻乎乎的敵人不會看到飛行的子彈,但是你也可以創(chuàng)建會躲避子彈的敵人。你也可以做一些能朝英雄射擊的敵人。
準(zhǔn)備射擊
畫一個子彈的mc,然后做一個linkage,ID是bullet,以便用AS復(fù)制到舞臺中。子彈MC中的圖像應(yīng)該居中對齊。
讓我們聲明一下子彈對象:
game.Bullet= function () {}; game.Bullet.prototype.speed=5; game.Bullet.prototype.dirx=0; game.Bullet.prototype.diry=-1; game.Bullet.prototype.width=2; game.Bullet.prototype.height=2;
子彈每步移動的距離是5,高度和寬度都是2象素,這已經(jīng)足夠殺死敵人了。
dirx/diry屬性確定了子彈移動的方向。實(shí)際上我們還是通過moveChar函數(shù)移動子彈。如果dirx=1,子彈向右移動,diry=-1則向上移動。我可以從英雄(或敵人)對象中得到方向參數(shù),設(shè)定dirx/diry的值,但是在游戲剛開始的時候,英雄還沒有移動,這時候玩家如果要射擊,就用上面這個默認(rèn)的方向(dirx=0,diry=-1,朝上移動)。
給game對象添加兩個新的屬性:
game={tileW:30, tileH:30, currentMap:1, bulletcounter:0}; game.bullets= new Array();
bulletcounter屬性用來記錄子彈的數(shù)目,以便我們給新產(chǎn)生的子彈取不重復(fù)的名稱。游戲里第一發(fā)子彈名稱是bullet0,然后是bullet1、bullet2……最多是bullet100,接下來返回到bullet0。我們可以讓數(shù)目無限增長,但是誰也不能保證到最后會發(fā)生什么。
game.bullets數(shù)組用來放置舞臺上的子彈對象。一開始的時候它是一個空的數(shù)組。
然后給角色對象加上一個shootspeed屬性,設(shè)置每次發(fā)彈的最小時間間隔:
char={xtile:2, ytile:1, speed:4, shootspeed:1000};
更高的shootspeed值代表更長的間隔、更慢的射擊速度,單位是毫秒。
敵人死亡后,我們還要把他們從game對象中刪除。改變buildMap函數(shù)的創(chuàng)建敵人的部分:
game.currentEnemies = []; for (var i = 0; i<enemies.length; ++i) { var name = "enemy"+i; game[name]= new game["Enemy"+enemies[i][0]]; game[name].id=i; game.currentEnemies.push(game[name]);
然后在enemyBrain函數(shù)中,把這句:
var name = "enemy"+i; 換成 :var name = "enemy"+game.currentEnemies[i].id;
我通過currentEnemies數(shù)組來放置舞臺上活動的敵人。一旦敵人被殺死,我們就會把它從currentEnemies數(shù)組中刪除。新的屬性“id”幫助我們找到敵人在enemies數(shù)組中的位置。
在detectKeys函數(shù)檢查完按鍵后添加代碼:
if (Key.isDown(Key.SHIFT) and getTimer()>ob.lastshot+ob.shootspeed) { _root.shoot(ob); }
如果SHIFT鍵被按下,而且時間間隔足夠長,調(diào)用shoot函數(shù)。
在moveChar函數(shù)的開頭添加兩行代碼,用來保存當(dāng)前對象的方向:
ob.dirx=dirx; ob.diry=diry;
我們可以用這個來指定子彈運(yùn)行的方向。
開槍
為了成功的讓子彈按照我們預(yù)定的想法飛行,我們要寫一個新的函數(shù)shoot:
function shoot (ob) { ob.lastshot=getTimer(); game.bulletcounter++; if (game.bulletcounter>100) { game.bulletcounter=0; } var name = "bullet"+game.bulletcounter; game[name]= new game.Bullet; game[name].id=game.bulletcounter; game.bullets.push(game[name]); if (ob.dirx or ob.diry) { game[name].dirx= ob.dirx; game[name].diry= ob.diry; } game[name].xtile= ob.xtile; game[name].ytile= ob.ytile; game.clip.attachMovie("bullet", name, 10100+game.bulletcounter); game[name].clip=game.clip[name]; game[name].x = (ob.x+game[name].dirx*ob.width); game[name].y = (ob.y+game[name].diry*ob.height); game.clip[name]._x = game[name].x; game.clip[name]._y = game[name].y; }
首先我們傳遞了一個obj對象給函數(shù)。如果開槍的是英雄,這個obj就是英雄;如果是敵人射擊,obj就是敵人對象。
我們通過getTimer()函數(shù)把當(dāng)前的時間保存到lastshot屬性中。
接著給game.bulletcounter屬性增加1,如果它大于100,我們就讓他回到0。
現(xiàn)在用bulletcounter產(chǎn)生一個新的子彈名字,創(chuàng)建一個子彈對象,然后把這個數(shù)字存到該對象中,把這個對象的地址放入game.bullets數(shù)組中。
下面的if判斷用來檢測角色對象是否移動過(dirx/diry有值),如果是,則把這兩個方向?qū)傩詡鬟f給新建的子彈對象。否則子彈會有默認(rèn)的運(yùn)行方向。
為了讓子彈從角色處出現(xiàn),我們把角色的xtile和ytile屬性復(fù)制給子彈對象。
代碼的最后部分創(chuàng)建了新的子彈剪輯,計算坐標(biāo),最后顯示到該位置。有趣的地方在于如何計算子彈的象素坐標(biāo):
game[name].x = (ob.x+game[name].dirx*ob.width);
首先我們得到角色的位置(ob.x),這是角色的中心坐標(biāo)。通常子彈并不是從角色的正中心發(fā)出,我們給他加上了角色的寬度。這個地方的巧妙之處在于乘了子彈的dirx屬性,dirx取-1,0,1都能適合。當(dāng)dirx為0的時候,子彈的x坐標(biāo)就是角色的中心,不過這時候子彈是豎直運(yùn)動的,出現(xiàn)在角色的正上方或正下方。
殺死敵人!
在detectKeys函數(shù)的結(jié)尾添加一行,調(diào)用一個新的函數(shù)來移動子彈,并且檢查是不是打到了什么東西。
_root.moveBullets();
moveBullets函數(shù):
function moveBullets () { for (var i = 0; i<game.bullets.length; ++i) { var ob=game.bullets[i]; getMyCorners (ob.x+ob.speed*ob.dirx, ob.y+ob.speed*ob.diry, ob); if (ob.downleft and ob.upleft and ob.downright and ob.upright) { moveChar(ob, ob.dirx, ob.diry); } else { ob.clip.removeMovieClip(); delete game["bullet"+game.bullets[i].id]; game.bullets.splice(i,1); } for (var j = 0; j<game.currentEnemies.length; ++j) { var name = "enemy"+game.currentEnemies[j].id; var obenemy = game[name]; var xdist = ob.x - obenemy.x; var ydist = ob.y - obenemy.y; if (Math.sqrt(xdist*xdist+ydist*ydist) < ob.width+obenemy.width) { obenemy.clip.removeMovieClip(); delete game["enemy"+game.currentEnemies[j].id]; game.currentEnemies.splice(j,1); ob.clip.removeMovieClip(); delete game["bullet"+game.bullets[i].id]; game.bullets.splice(i,1); } } } }
這個函數(shù)通過循環(huán)來操作放在bullets數(shù)組中的每一個子彈對象。
使用getMyCorners函數(shù)我們得知子彈下一步是不是打在了障礙物上。如果不是,我們就調(diào)用moveChar函數(shù)移動子彈。
如果子彈確實(shí)擊中了障礙物,我們就要刪除它了。有3樣事情要做:+ 刪除子彈mc (使用removeMovieClip)+ 刪除子彈對象 (使用delete函數(shù))+ 從子彈數(shù)組中刪除當(dāng)前的子彈
盡管我們可以只刪除子彈mc而留下子彈對象,這樣做不會有大問題。因?yàn)樽訌梞c已經(jīng)不存在,對它的所有的操作不能被執(zhí)行。但是這樣做會降低效率,子彈數(shù)組越來越大,而且里面全是垃圾數(shù)據(jù)。
當(dāng)移動了子彈而且子彈沒有撞上障礙物,我們開始檢查它是不是擊中了敵人。循環(huán)currentEnemies數(shù)組,計算出子彈和敵人的距離。如果他們離得太近,我們就刪除他們——子彈和敵人都消失。
如果你要永久清楚這個被殺的敵人(當(dāng)你再一次進(jìn)入這個房間的時候,它不會再出現(xiàn)),在這里再添加一行:myEnemies[game.currentMap][obenemy.id]=0;
你也可以讓射擊變得更加豐富多彩:
+限制子彈的總數(shù) 。你可以設(shè)置一個變量,每次創(chuàng)建一個子彈,變量就減1,只有這個變量值大于0才能創(chuàng)建對象。+限制舞臺上只有1顆子彈 。當(dāng)子彈數(shù)組長度>0時不創(chuàng)建子彈。+讓敵人也能發(fā)彈 。讓敵人射擊也很容易做到,方法和他們改變移動方向一樣。+創(chuàng)建不同的武器 。你可以聲明多種子彈模板,規(guī)定不同的傷害值,你可以得到更強(qiáng)的武器,更快的殺死敵人。
玩的開心 :-)
下載上例的源文件
在側(cè)視圖中射擊:
下載本例的源文件
出處:藍(lán)色理想
責(zé)任編輯:qhwa
上一頁 更多關(guān)于敵人的東西 下一頁 拾取物品
◎進(jìn)入論壇Flash專欄 版塊參加討論