2011-10-22 216 views
1

我在Flash actionscript 3中製作了一個射擊遊戲,並對邏輯流程以及如何巧妙地使用OOP概念提出了一些疑問。ActionScript 3中的遊戲邏輯和遊戲循環

主要有3類:

  1. 主類:初始化在屏幕上的對象。
  2. 敵人級別:用於移動屏幕上的敵人。
  3. 子彈類:射擊。

我想要做的就是找出敵人如果被一顆子彈擊中,做事情必須做,結果......

我在做什麼現在的問題是,我有一個ENTER_FRAME事件,在這個事件中,我用創建的子彈實例檢查每個敵方單位(保存在一個數組中)的碰撞檢測,如果它碰撞,然後在Main類中執行所有必要的操作..堵塞過程中的Main類。

這是正確的技術嗎?或者有更好的解決方案嗎?

回答

4

試着想更多的面向對象,什麼是每個對象負責爲?

我們的敵人至極,我們可以打:

class Enemy : extends NPC implements IHittable { 
    . . . 

    function update(delta) { 
     // move, shoot, etc. 
    } 

    function handleHit(bullet) { 
     // die 
    } 
} 

一個hittable對象:

interface IHittable { 
    function handleHit(bullet); 
} 

子彈是假設移動和命中的事情:

class Bullet : { 
    function update(delta) { 
     // update position 
    } 

    function checkHits(world:World) { 
     for each(var hittable:IHittable in world.objects) { // might want to cluster objects by location if you're handling lots of objects/bullets) 
      if (isColidingWith(hittable)) 
       o.handleHit(bullet); 
     } 
    } 
} 

然後我們擁有一切內在的世界:

class World { 
    var npcs: Array ... 
    var bullets: Array ... 
    var hittables: Array ... 

    function update(delta) { 
     foreach(var c:NPC in npcs) 
      c.update(delta); 

     foreach(var b:Bullet in bullets) { 
      b.update(delta); 
      b.checkCollisions(world); 
     } 
    } 
} 

和你的主循環是,僅僅簡單:

var lastTime:int; 

function onEnterFrame(...) { 
    var now:int = getTimer(); // FlashPlayer utility function to get the time since start (in ms) 

    world.update(now - lastTime); 
    lastTime = now; 
} 

其他一些注意事項:

  • 嘗試做基於時間的delta所有的計算,否則遊戲的速度會隨幀速而變化。

  • 角色死亡時會發生什麼?子彈消失?嗯,你可以做幾種方法:

    • 火災的事件,像EnemyDied以及來自世界
    • 刪除它實現一個接口CanDie具有(get dead():Boolean屬性),並用它來清理整個世界的每一個更新。
    • 但是不要編寫代碼來移除Enemy類中的敵人,因爲那樣你將會使用應該由World處理的代碼污染該類,並且以後很難保留該代碼。

對不起,長的答案,但我控制不住自己:)

+0

嘿感謝這個美好的答覆..:d真的有很多益處 你能解釋一下我的一些事情...... 什麼是接口的器具? 其次 我在這裏有點困惑..假設當我的子彈實例創建時,世界上有9個敵人實例,而子彈移動一個敵人實例被創建..所以,我的子彈實例如何檢查其衝突所有的敵人實例? –

+0

你應該只有一個敵人名單,並且每當你創建一個新的敵人時,將它添加到那個地方,每次你檢查colisions,循環在列表中。在我的例子中,這將是World.npcs列表。 (npc =非玩家角色:p)。 –

+0

接口是一種通過一些常見功能處理不同類型的對象的方法。想想你的電視和吸塵器,他們都可以實現一個名爲CanTurnOn的界面。嘗試做更多的閱讀,這是非常基本和重要的東西。 –

0

當時堵塞主類的問題,或者發現什麼子彈擊中敵人的什麼問題?如果是子彈,你需要描述子彈的行爲 - 它能擊中多個敵人,它移動的速度有多快(有可能當使用「enterFrame」進行測試時,子彈將首先出現在敵人面前,第二幀,它會出現在敵人後面?)。可能將敵人簡化爲一些基本的幾何形狀,如圓形或矩形,還是需要像素完美的精度?最後,你打算在同一時間有多少子彈和多少敵人?如果每個子彈都有一個顯示對象,那麼這可能太昂貴了,如果你將要有數百個顯示對象,那麼將它們繪製成單個形狀/位圖數據會更有意義。

如果問題在於Main類太長,這裏有幾種可能性。

  1. 一個nobrainer對這個問題的答案 - 使用繼承來簡單地把部分代碼放在單獨的文件中。不是最好的方式,但很多人都這麼做。
  2. 如果你做了第一個,那麼你會意識到有一些功能組被放入超類和子類中 - 這將幫助你將「阻塞」類拆分爲幾個較小的獨立部分,這些部分具有更多的特殊性。
  3. 在做了第二個練習之後,您可能會發現在將大類分成更小的類之間存在某種依賴關係,因此您可以嘗試通過某種模式生成這些較小的類。
  4. 然後你寫下堵塞的代碼,將你剛剛設法分割的那些部分進行概括。

上面基本上是從更具體到更通用的代碼的循環。在完善最後一步的過程中,您將再次編寫一些具體的代碼。這會讓你進入第1步。泡沫,沖洗,重複:)實際上,你不想寫OO代碼或程序代碼,或者任何時髦的東西告訴你做的事情。你想編寫好的代碼:)你可以通過從更通用的更具體的回到更通用的,直到它是完美的:P

可能不是最好的答案,但你必須承認,你沒有給了很多信息給你更準確的答案。