如何使用 swift 将 touchesbegan 事件委托给实体组件?
How can I delegate a touchesbegan event to an entities component using swift?
我正在使用 swift 为 ios 创建游戏。我已经从 Apples GameplayKit 中实现了组件实体系统,与 this tutorial.
中所示的非常相似
我添加了一个正方形网格,我想对点击手势做出不同的响应。当点击 UI 元素时,我将使用状态机更改游戏状态,但我还想更改每个方块对点击手势的反应。根据我目前有限的理解,最好的方法是更改点击手势委托。但是,我一直找不到任何简单的例子来说明如何做到这一点。正方形是 SKSpriteNodes.
代码可应要求提供;但是,我正在寻找一个脱离上下文的示例,说明如何以最简单的方式完成此操作。
有谁知道如何做到这一点或可以提出 "better" 方法。为了避免主观性,我在架构方面将更好定义为结构更好。 (例如,单个手势处理程序中的多个 if 语句似乎是执行此操作的错误方法。)
根据我得到的各种帮助和想法,我找到了解决我的问题的有效方法,但是我仍然非常愿意接受其他解决方案。
这个问题提出的主要问题是如何从 spritenode 引用回实体。
通过阅读 SKSpriteNode 的文档,我发现它的父 class SKNode 有一个 userData attribute,它允许您在该节点中存储数据。
将实体实例附加到需要在 SpriteComponent 中发生的节点,因为这是构造节点的地方,但是它不能发生在构造函数中,所以它必须在 SpriteComponent 中的函数中。
func addToNodeKey() {
self.node.userData = NSMutableDictionary()
self.node.userData?.setObject(self.entity!, forKey: "entity")
}
然后在实体class构造中将组件添加到自身后调用该函数。
addComponent(spriteComponent)
spriteComponent.addToNodeKey()
现在可以从触摸事件访问 Enity 实例,我需要一种在该实例上执行功能的方法,但是您不知道该实例是否是 GKEntity 的子class 或不是,也不是什么类型。
因此,我又创建了一个组件TouchableSpriteComponent。经过一番尝试,init 函数将单个函数作为其参数,然后从场景触摸事件中调用该函数,这允许创建 TouchableSpriteComponent 的实体定义其处理事件的方式。
我创建了一个 gist for this solution,因为这里可能有太多代码无法放置。这是一个许可链接。
我真的很想知道这是否是一个 "good" 解决方案,或者是否有更清晰的路线会产生相同的效果(无需遍历所有实体或节点)。
如果我理解得很好,你应该有这样的东西:
func entityTouched(touches: Set<UITouch>, withEvent event: UIEvent?)
在您的 GKEntity 子类中。
我在游戏中这样做:
class Square: MainEntity {
override func entityTouched(touches: Set<UITouch>, withEvent event: UIEvent?) {
//DO something
}
}
游戏场景:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
super.touchesBegan(touches, withEvent: event)
let touch = touches.first!
let viewTouchLocation = touch.locationInView(self.view)
let sceneTouchPoint = self.convertPointFromView(viewTouchLocation)
let touchedNode = self.nodeAtPoint(sceneTouchPoint)
let touchedEntity = (touchedNode as? EntityNode)?.entity
if let myVC = touchedEntity as? MainEntity {
myVC.entityTouched(touches, withEvent: event)
}
其中:
实体节点:
class EntityNode: SKSpriteNode {
// MARK: Properties
weak var entity: GKEntity!
}
精灵组件:
class SpriteComponent: GKComponent {
let node : EntityNode
init(entity: GKEntity, texture: SKTexture, size: CGSize) {
node = EntityNode(texture: texture, color: SKColor.whiteColor(), size: size)
node.entity = entity
}
}
主要实体:
class MainEntity: GKEntity {
var entityManager : EntityManager!
var node : SKSpriteNode!
//MARK: INITIALIZE
init(position:CGPoint, entityManager: EntityManager) {
super.init()
self.entityManager = entityManager
let texture = SKTexture(imageNamed: "some image")
let spriteComponent = SpriteComponent(entity: self, texture: texture, size: texture.size())
node = spriteComponent.node
addComponent(spriteComponent)
}
func entityTouched (touches: Set<UITouch>, withEvent event: UIEvent?) {}
}
让我知道您是否正在寻找。
我正在使用 swift 为 ios 创建游戏。我已经从 Apples GameplayKit 中实现了组件实体系统,与 this tutorial.
中所示的非常相似我添加了一个正方形网格,我想对点击手势做出不同的响应。当点击 UI 元素时,我将使用状态机更改游戏状态,但我还想更改每个方块对点击手势的反应。根据我目前有限的理解,最好的方法是更改点击手势委托。但是,我一直找不到任何简单的例子来说明如何做到这一点。正方形是 SKSpriteNodes.
代码可应要求提供;但是,我正在寻找一个脱离上下文的示例,说明如何以最简单的方式完成此操作。
有谁知道如何做到这一点或可以提出 "better" 方法。为了避免主观性,我在架构方面将更好定义为结构更好。 (例如,单个手势处理程序中的多个 if 语句似乎是执行此操作的错误方法。)
根据我得到的各种帮助和想法,我找到了解决我的问题的有效方法,但是我仍然非常愿意接受其他解决方案。
这个问题提出的主要问题是如何从 spritenode 引用回实体。 通过阅读 SKSpriteNode 的文档,我发现它的父 class SKNode 有一个 userData attribute,它允许您在该节点中存储数据。
将实体实例附加到需要在 SpriteComponent 中发生的节点,因为这是构造节点的地方,但是它不能发生在构造函数中,所以它必须在 SpriteComponent 中的函数中。
func addToNodeKey() {
self.node.userData = NSMutableDictionary()
self.node.userData?.setObject(self.entity!, forKey: "entity")
}
然后在实体class构造中将组件添加到自身后调用该函数。
addComponent(spriteComponent)
spriteComponent.addToNodeKey()
现在可以从触摸事件访问 Enity 实例,我需要一种在该实例上执行功能的方法,但是您不知道该实例是否是 GKEntity 的子class 或不是,也不是什么类型。
因此,我又创建了一个组件TouchableSpriteComponent。经过一番尝试,init 函数将单个函数作为其参数,然后从场景触摸事件中调用该函数,这允许创建 TouchableSpriteComponent 的实体定义其处理事件的方式。
我创建了一个 gist for this solution,因为这里可能有太多代码无法放置。这是一个许可链接。
我真的很想知道这是否是一个 "good" 解决方案,或者是否有更清晰的路线会产生相同的效果(无需遍历所有实体或节点)。
如果我理解得很好,你应该有这样的东西:
func entityTouched(touches: Set<UITouch>, withEvent event: UIEvent?)
在您的 GKEntity 子类中。
我在游戏中这样做:
class Square: MainEntity {
override func entityTouched(touches: Set<UITouch>, withEvent event: UIEvent?) {
//DO something
}
}
游戏场景:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
super.touchesBegan(touches, withEvent: event)
let touch = touches.first!
let viewTouchLocation = touch.locationInView(self.view)
let sceneTouchPoint = self.convertPointFromView(viewTouchLocation)
let touchedNode = self.nodeAtPoint(sceneTouchPoint)
let touchedEntity = (touchedNode as? EntityNode)?.entity
if let myVC = touchedEntity as? MainEntity {
myVC.entityTouched(touches, withEvent: event)
}
其中:
实体节点:
class EntityNode: SKSpriteNode {
// MARK: Properties
weak var entity: GKEntity!
}
精灵组件:
class SpriteComponent: GKComponent {
let node : EntityNode
init(entity: GKEntity, texture: SKTexture, size: CGSize) {
node = EntityNode(texture: texture, color: SKColor.whiteColor(), size: size)
node.entity = entity
}
}
主要实体:
class MainEntity: GKEntity {
var entityManager : EntityManager!
var node : SKSpriteNode!
//MARK: INITIALIZE
init(position:CGPoint, entityManager: EntityManager) {
super.init()
self.entityManager = entityManager
let texture = SKTexture(imageNamed: "some image")
let spriteComponent = SpriteComponent(entity: self, texture: texture, size: texture.size())
node = spriteComponent.node
addComponent(spriteComponent)
}
func entityTouched (touches: Set<UITouch>, withEvent event: UIEvent?) {}
}
让我知道您是否正在寻找。