Hi ALL
小弟最近在做砲台射擊
但遇到一個問題, 射擊出的砲彈, 無法有效執行碰撞, 只有第一發有用
之後射擊的都無法產生碰撞
請大大指點一下, 到底是那邊有問題, 讓我無法正確產生碰撞
原始檔如下
for CS5.5
https://www.asuswebstorage.com/navigate/share/GYYI459SIY
如果是 CS5.0 用戶請開這個檔案
https://www.asuswebstorage.com/navigate/share/GYYQUS9SIY
稍微看過一下你的code,看看錯誤是不是發生在此。
首先關於砲彈,除了第一發放在舞台上有用之外,其它用click產生出來的砲彈就沒有用了。所以關鍵在於你用click產生出來的砲彈沒有辦法偵測到撞擊。
你是用飛出的ball01、02、03來偵測是否撞擊,然後偵測的方法是去測試myroot.ball是否與和這些發生撞擊,但是myroot.ball這個實體物件,在第一次撞擊之後,就已經被移除了。所以之後的myroot.ball就不存在了。
所以現在改進的方法,一個是將ball這個實體名稱再指定給滑鼠生出的ball,不然就是用一個變數如currentBall來記住砲彈,然後在ball01、02、02中去存取這個值。
我想這樣應該就可以解決問題了。
另外,寫actionscript最好能將程式用外部文件的方式獨立出來,這樣子比較容易維護。寫在flash的影片物件中,放一段時間後,你自己要debug就會覺得痛苦了。
感謝大大指點, 小弟有機會會報達~
有個問題, 這點我知到
但我的問題在於, 小弟用addChild出來的物件, 我不知到有那個指令可以指定它的名稱
所以我也很疑惑~
至於用變數記住砲彈這招, 更是沒聽說過這要怎做
這幾天一直在google上面找範例, 貌似台灣不討論這個問題似的, 沒發現
國外對岸比較多, 但也沒找到可以參考的範例或指令可用
可能偶太笨吧 = =
要動態指定砲彈的名稱很簡單,例如我們可以利用reaction這個物件,給他一個ballCounter的變數:
reaction.ballCounter =0
然後在生成砲彈的froth函式中,讓counter+1
reaction.ballCounter++
再指定給砲彈:
amissile.name = "ball"+reaction.ballCounter;
這樣就可以動態給予每個砲彈不同的實體名稱
至於我原本建議指定砲彈名稱的作法,後來發現不合用,原因在於舞台上可以一次出現多個砲彈,如果是這樣,就不能指定唯一的instance name。
所以我想應該用一個陣列來放生成的砲彈,然後碰撞測試時,去檢查是否撞擊在這陣列中的物件。
首先我把舞台上的ball移掉,只用以滑鼠生成的ball。接下來就是在生成砲彈時,放進陣列中。以你的code來改的話,就是這樣:
<pre class="c" name="code">import flash.events.MouseEvent;
import flash.events.Event;
stage.addEventListener(Event.ENTER_FRAME,rotatee);
//增加一個放砲彈的陣列
reaction.allBalls = [];
function rotatee(e:Event)
{
var theX:int = mouseX - theArrow.x;
var theY:int = (mouseY - theArrow.y) * -1;
var angle = Math.atan(theY/theX)/(Math.PI/180);
if (theX<0)
{
angle += 180;
}
if (theX>=0 && theY<0)
{
angle += 360;
}
theArrow.rotation = (angle * -1) + 1;
}
reaction.addEventListener(MouseEvent.CLICK, froth)
function froth(MouseEvent){
var amissile:missile=new missile();
amissile.x = 18;
amissile.y = 158;
amissile.rotation = theArrow.rotation;
//把砲彈放進陣列
reaction.allBalls.push(amissile);
addChild(amissile);
}
接下來,原本碰撞測試的元件3、5、6的go函式改成這樣:
<pre class="c" name="code">function go(e)
{
this.x -= 1;
//取得放砲彈陣列的長度
var total = myroot.reaction.allBalls.length;
//檢查是否撞擊到
for(var i=0; i<total;i++)
{
if (this.hitTestObject(myroot.reaction.allBalls[i]))
{
myroot.score += 10;
this.removeEventListener(Event.ENTER_FRAME,go);
myroot.removeChild(this);
}
}
}
這樣就可以運作了。
上面只是在解決碰撞的問題,至於架構、效能面等東西就沒有多加考量。像是砲彈如果飛出舞台後,應該把它移除,一方面一直增加砲彈會佔用記憶體,另外陣列裡面放一些沒有用到的砲彈,也會增加檢測的時間。
簡單來說,就是用Array.splice的方法,移除掉陣列中已經飛出舞台的砲彈。
我把修改過的檔案放在:
https://docs.google.com/open?id=0B-4_2_Uw2gP-UUpNYVctd3RUOGlrRjB3aWF1MWR5dw
可以從[檔案][下載]