GameplayKit - 关于在组件之间发送消息的困惑

时间:2015-09-07 21:53:04

标签: ios swift sprite-kit gameplay-kit

我使用Spritekit潜入GameplayKit并从我收集的内容中继承GKEntity,然后开始向该实体添加GKComponents。该实体或多或少只是一个充满某些功能的组件包。

我感到困惑的部分是组件之间的通信。你如何让他们脱钩。例如,假设我有一个HealthComponent类,我将该组件添加到PlayerEntityEnemyEntity。我还有HealthBarComponent ,但我只想在播放器上方显示健康栏。当玩家受到伤害时,需要在HealthBarComponent中更新该信息。

那么该信息应该如何发送?我看到文档中有一个名为GKComponentSystem的类。我不是100%应该如何使用它。

另一个问题是......当玩家的生命值达到零时,他应该在敌人应该死的时候重生。当玩家用完生命时,游戏结束。

敌人和玩家的卫生系统大致相同,但死亡事件对每个人来说都是完全不同的。我没有遵循如何使用组件系统,同时保持每个实体的独特行为。

一些伪代码会很棒

3 个答案:

答案 0 :(得分:5)

看起来这个框架与我见过的其他框架的工作方式略有不同,因为系统只能处理单一类型的组件,而不能处理组件类型为 groups 的实体。

在GamePlay-Kit框架中,您可以手动循环并更新实体(然后更新每个实体组件)或创建一个继承自GKComponentSystem的类。然后,当您更新系统时,它会更新所有组件you have added to it,只要它们的类类型与您initialized the system with

的类型相匹配

要处理您的健康栏问题,我会说HealthBarComponent,在更新过程中,从其所有者实体中检索HealthComponent,读取健康值&每帧渲染自己。但您只有add HealthBarComponent到您的玩家实体。

您可以从组件中检索所有者实体,反之亦然(请参阅GKComponent.entity& GKEntity.components),以便您可以像这样更新健康栏:

/*Note: I'm not an ios developer, this is pseudocode*/

HealthBarComponent.update(){
  int healthValue = self.entity.components.get(HealthComponent).value;
  //Now render your health bar accordingly or hold onto this for later
}

为了处理玩家死亡问题,我认为你最好的选择是拥有两种不同类型的健康组件(PlayerHealth& EnemyHealth)和两个不同的相应系统。那或者有一个健康组件,但有两个独立的'死亡'组件。是的,这似乎是多余的,但我很难想到在这个框架内有更好的方法。根据我的经验,你要么花时间担心保持一切完全脱离和可重复使用,要么建立一个游戏:)

答案 1 :(得分:3)

组件可以通过self.entity属性访问其实体。从那里,您可以查询其他组件以通过实体componentForClass属性传递数据:

guard let moveComponent = entity?.componentForClass(MoveComponent.self) else {
        fatalError("A MovementComponent's entity must have a MoveComponent")
    }

iOS Games by Tutorials本书有一个很好的教程,涵盖了GameplayKit实体和组件。

答案 2 :(得分:0)

通知对于此类问题很好。根本就没有直接的对象耦合,如果一个以上的对象最终需要知道(例如,您的健康条组件,确定游戏结束的更高级别的游戏对象,甚至敌人/盟友AI在以下情况下的行为有所不同),这是非常可扩展的健康低下。)

您可以收到一个名为“ playerHealthChanged”的通知,并让您的健康栏组件和其他对象独立注册以响应该事件。 (您可能需要让HealthComponent实例知道是否应该发布此通知,因此仅玩家可以发布-也许可以在其实体上使用isKind(of :),或者仅具有一个bool字段来启用发布,将其设置为true播放器实例)。

我通常将所有通知名称定义放在一个模块中,以便任何类都可以访问它们:

let kPlayerHealthChangedNotification = Notification.Name("playerHealthChanged")

这是组件发布通知的方式(如果需要,您可以传递self以外的其他对象):

NotificationCenter.default.post(name: kPlayerHealthChangedNotification, object:self)

然后,关心玩家健康状况变化的对象可以像在其初始代码中一样进行注册-创建处理程序函数,而不是将self添加为通知的观察者:

@objc func onPlayerHealthChanged(_ notification:Notification) {
  // do whatever is needed; notification.object 
  // has the object from the post
}

// put this in a setup method - init or similar:
  NotificationCenter.default.addObserver(self,
      selector: #selector(onPlayerHealthChanged(_:)),
      name: kPlayerHealthChangedNotification
      object:nil)

以下是文档:https://developer.apple.com/documentation/foundation/notifications