游戲開發系列一:游戲中的敵人(1)
http://www.flashempire.com/school/tutorview.php?id=530
對於目前的 Flash 來說,開發一些像模像樣的游戲並不是什麼奇怪的事情了。我這裡所涉及到的內容和開發游戲有關,但是都是一些比較基本的知識。如果您是游戲開發方面的高手,那麼完全可以忽略我這裡所描述的內容。我的計劃是要做一系列的教程,這是其中一個系列。
游戲是一個交互作品,簡單說,就是通過用戶的行為,會對這個作品的進程產生一定的影響。說到游戲,總要提到難度,游戲的難度在於:當你想要達到某種目的的時候,你會發現它的實現多少有些困難,困難越難克服,難度也就越大。不同類型的游戲有不同的難度,以及不同的實現方法。比如:俄羅斯方塊通過改變方塊下落的速度來改變游戲的難度,空戰射擊游戲通過不同的敵機以及不同的 Boss 來實現不同的難度。
在這個系列裡面,我們想和大家一起研究一下游戲中敵人的運動方式,一點一點來。AS 基礎最好是有一些,不然會稍微有些頭疼。
一、最直接的跟蹤
首先看看這個例子:
假定紅色圓圈是玩家,綠色圓圈是敵人,移動你的鼠標,敵人就會跟著你跑。
這就是最簡單的跟蹤敵人,它的原理是:如果(玩家x坐標 <> 敵人x坐標){ 調整敵人x坐標,趨近玩家x坐標}如果(玩家y坐標 <> 敵人y坐標){ 調整敵人y坐標,趨近玩家y坐標}
這應該是極其容易理解的。那麼具體的代碼實現應該是什麼樣子的呢?
我們先把兩個不同的 MovieClip 放置在舞台上,一個實例名叫做 player,另外一個叫做 enemy。
為了方便,我們僅僅通過鼠標來實現玩家的移動,於是代碼就很簡單了:player._x = _xmouse-10;player._y = _ymouse-10;updateAfterEvent();
玩家可以移動了,下面來解決坐標調整的問題。
看上面的圖片,不管玩家和敵人處於什麼位置,只要不重合,兩個角色之間總是具有一定距離的,我們用 dx 和 dy 來代表 x 方向和 y 方向的差值。根據 dx 和 dy,基於敵人靠近玩家的概念,我們就可以得出敵人應該前進的方向。
敵人應該具有一定的速度,根據這個速度向玩家靠近。所以我們可以先定義一個變量來代表敵人的速度:enemySpeed。
根據分析,我們可以得出下面的計算公式: dx = player._x-enemy._x; dy = player._y-enemy._y; if (Math.abs(dx)>=enemySpeed) { enemy._x += ((dx>=0) ? enemySpeed : -enemySpeed); } if (Math.abs(dy)>=enemySpeed) { enemy._y += ((dy>=0) ? enemySpeed : -enemySpeed); }
觀察到,我們用了一個 Math.abs(dx)>=enemySpeed 來限制敵人運動,其實也可以不限制,但是那樣在敵人速度比較高的時候,就會發生抖動現象。因為這種情況下,敵人的坐標和玩家坐標之間差值小,敵人可能會在逼近過程中不斷搖擺。大家可以去掉限制嘗試一下。
對於 AS 不太熟悉的,我來解釋一下這句: enemy._x += ((dx>=0) ? enemySpeed : -enemySpeed),其實是相當於下面這句: if (dx >= 0){ enemy._x = enemy._x + enemySpeed; } else { enemy._x = enemy._x - enemySpeed; }
這是用來判斷敵人的運動方向的,根據 dx dy 的正負情況,來決定向哪個方向運動。
好,到此為止,我想已經都解釋清楚了,下面是完整的第一幀源代碼:var enemySpeed:Number = 2;var dx, dy:Number;/* functions */tracker = function () { player._x = _xmouse-10; player._y = _ymouse-10; dx = player._x-enemy._x; dy = player._y-enemy._y; if (Math.abs(dx)>=enemySpeed) { enemy._x += ((dx>=0) ? enemySpeed : -enemySpeed); } if (Math.abs(dy)>=enemySpeed) { enemy._y += ((dy>=0) ? enemySpeed : -enemySpeed); } updateAfterEvent();};/* run it*/setInterval(tracker, 10);
針對 AS 新手:程序先定義了變量,確定了敵人的運動速度,這個是可以更改的,函數 tracker 則主要用來處理玩家移動以及敵人移動。 updateAfterEvent 是為了保證流暢度設定的,沒有也可以。
如果不觸發 tracker 函數,那麼這個程序是不會跑起來的,所以,我們使用了 setInterval,每隔 10 毫秒觸發一次 tracker 函數,這樣,程序就正常運行了。
這一次的介紹就到這裡了,很簡單是不是?下一次我們要給目前的這個敵人增加一些小功能,或者說,限制一下它。
這次的源代碼請在這裡下載。