最近在弄東方果實蠅的配樂音效,過程簡直比繪圖還要慘烈(笑),之前熱帶龍給了蜻蜓一個他自己玩得影片檔(他上傳到youtube上,不過是設不公開,所以是搜尋不到的),雖然說遊戲本身大致已經完成,不過這影片還是可以提供很多訊息來做細部修改(包括一些BUG等)。
上面只是開場隨便說,今天要說的是一些flash製作心得:
記得之前的Super Leafeon Bros.(簡稱SLB)遊戲嗎,其實那遊戲的牆壁判定一直有一個問題,蜻蜓修了很多次、用了很多方法但還是行不通。
陸地判定是用一個條件判斷式"while",是蜻蜓在網路上找到的一段陸地判定寫法,他是用AS2寫的,熱帶龍用他專業的技術修改成可以在AS1上正常運作,不過這段實用的指令只限陸地部分,如果做一面牆就會發生很搞笑的事。
陸地可以這樣做那修改一下不就可以做牆壁判定了嗎?(把判讀y軸改成x軸不就好了?)蜻蜓也是這樣想,不過很可惜的是這做法行不通,如果執行遊戲會死機(基本上是程式終止,用播放器頂多強制關閉就沒事,但如果是在flash裡播放就會非常慘烈了)。
也因為這樣蜻蜓就開始思考這幾個問題:
為什麼一樣的寫法在y軸可以執行而x軸不行呢?
當初找到的程式碼中while裡寫的究竟是甚麼意思?
if和while差異到底何在?
第一個問題最後再說,第二個後來發現其實他和運作不正常並沒有多大的關連,而且其實蜻蜓心中早有答案,所以重點就是第三個,這兩個一樣都是條件判斷式的指令差異究竟在哪,Macromedia(現在是adobe,不過蜻蜓是用MX,所以這樣說比較合理)總不會做兩個功能一樣的指令吧?
昨天特別針對這一點和熱帶龍討論,總算是完全了解差異性了(同時也知道為什麼while在執行時那麼容易死機)。
先來說說一個指令for迴圈
之前有提過這東西,今天在稍微說一下,基本上迴圈就是一個運算式,在還沒有超出條件外(變成false)前會一直執行運算式,舉例:
r++;
if (r == 30) {
for (g=-1; g<2; g++) {
/:eme = Number(/:eme)+1;
_root.attachMovie("arms1","csc"add /:eme, /:eme);
setProperty(_root["csc" add /:eme], _x, _parent._x);
setProperty(_root["csc" add /:eme], _y, _parent._y);
_root["csc" add /:eme].rota=comcon-g*15;
r = 0
}
}
東方果實蠅遊戲中某敵人的一小段指令(有修改),大概的意思就是"r值會一直遞增,當r值等於30時,執行下面指令(也就是發射彈幕),同時r值歸零從頭開始",comcon變數是朝自機射擊的角度。
可以發現裡面有用到for,用for產生一變數g,讓g從-1一直遞增直到1(因為g<2),每遞增一次就執行發射子彈的指令,但由於在角度控制這部分寫了comcon-g*15這一段,所以最後執行時就會是這樣:
一次發射了三個長條形子彈而且朝三的不同的角度發射,假設comcon是180,那執行後子彈發射的角度就分別為165、180、195。
以上就是for的運作方式,不過值得注意的是for在執行時和其他指令不同,就用上述例子中的"++"遞增來比較,遞增就是讓一個變數一直加上一數字(沒有特別寫就是加1),但是以過一影格才加一次,所以有時在執行上會有很微妙的"時間差",好比說上述例子大可改成不用for而是將發射子彈這一段指令重複寫三次,只是角度都不一樣,雖然效果一樣但如果一次太多顆子彈(好比說一次20顆),會發現偶爾會有一個子彈歪掉(較晚發射)。
這些都是一次執行大量指令時出現的問題,即使都會執行但多多少少還是會有先後執行的問題,就像是flash執行程式碼時一定是從最上面往下執行。
而for的好處就是它是在一個影格內一次跑完,它完全沒有因影格運作而有時間差,它會在一個影格內執行運算式直到超出條件,也因此用for來發射20顆子彈正常情況絕對不會有子彈歪掉。
說了一大堆,那和這次主題有甚麼關係?基本上已經講完了,if和while的差異就像是上面例子的++和for,if在一個影格裡只會執行一次,而while則是"只要條件還成立那就不會停止運作"。
當使用while時,可以脫離條件沒事,那如果無法脫離呢?
下面是一段SLB的牆壁判讀程式碼:
while (ground.hitTest(_parent._x+this._x+50, _parent._y, true)) {
_parent._x -=(_parent.leaf.ase.speed+asd);
}
簡言之就是"如果碰到牆壁就會把玩家推走",進而產生了"碰到牆不能前進"的感覺,正常情況沒有甚麼問題,但如果反推出去的值_parent.leaf.ase.speed+asd等於0那要怎麼辦? 程式本身就會一直執行下面那一段反推的指令(由於是0所以怎麼推也推不出去)。
如果是if頂多在這影格執行失敗,到下一影格在重新判斷一次,還沒有甚麼問題,但while是在成功前是不會推進到下一影格,所以就在同一影格去執行根本不可能成功的指令,一直大量執行一個沒有用的東西電腦不燒掉才有鬼(笑)。
最後,也因為這樣開竅,SLB的牆壁問題也完全解決了,除了一些極小的問題外應該是不會在出現其他問題了,可喜可賀阿。

