5

我正在使用 Spritekit 深入研究 GameplayKit,从我收集到的内容中,您可以继承GKEntity,然后开始添加GKComponents到该实体。实体或多或少只是一袋填充某些功能的组件。

我感到困惑的部分是组件之间的通信。你如何让它们解耦。例如,假设我有一个HealthComponent类,我将该组件添加到 aPlayerEntity和 anEnemyEntity中。我也有一个HealthBarComponent ,但我只想在玩家上方出现一个健康栏。当玩家受到伤害时,该信息需要在HealthBarComponent.

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

另一个问题是.. 当玩家的生命值归零时,他应该再生,而敌人应该保持死亡。当玩家的生命耗尽时,游戏结束。

敌人和玩家的健康系统大致相同,但每个人的死亡事件将完全不同。我没有关注如何在保持每个实体的独特行为的同时使用组件系统。

一些伪代码会很棒

4

3 回答 3

5

看起来这个框架的工作方式与我见过的其他框架有点不同,因为系统只在单一类型的组件上工作,而不是在具有组件类型组的实体上工作。

在 GamePlay-Kit 框架中,您可以手动循环并更新您的实体(依次更新每个实体组件)或创建一个继承自 GKComponentSystem 的类。然后,当您更新系统时,它会更新您添加到其中的所有组件,只要它们的类类型与您初始化系统的类型相匹配

为了处理您的健康栏问题,我会说制作一个HealthBarComponent,在其更新期间,HealthComponent从其所有者实体中检索,读取健康值并在每一帧呈现自己。但是你只添加一个HealthBarComponent到你的玩家实体。

您可以从组件中检索所有者实体,反之亦然(请参阅GKComponent.entityGKEntity.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)以及两个不同的相应系统。或者只有一个健康组件,但有两个独立的“死亡”组件。是的,这似乎是多余的,但我很难在这个框架内想出更好的方法。以我的经验,你要么花时间担心让所有东西完全解耦和可重用,要么你开发一个游戏 :)

于 2015-09-08T02:38:08.973 回答
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 实体和组件。

于 2016-03-20T16:09:54.230 回答
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

于 2019-10-10T08:54:50.050 回答