2011-10-22 152 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

可能不是最好的答案,但你必须承认,你没有给了很多信息给你更准确的答案。