Swift 中的实体组件
Entity-Component in Swift
我正在尝试使用与 here.
所述类似的实体组件架构来构建一个简单的 iOS 游戏
我想在我的游戏中实现的是当用户触摸屏幕时,检测触摸发生的位置并将一种类型的所有实体移向特定方向(方向取决于用户触摸的位置,屏幕右侧= 向上,屏幕左侧 = 向下)。
到目前为止,游戏真的很简单,我才刚刚开始,但我被困在这个简单的功能中:
我的问题是 SKAction
应该 运行 在一个类型的所有实体上,但实际上确实发生了。
在我将我的游戏重新设计为 ECS 方法之前,它运行良好。
这是我在 Lines.swift 中声明的 GKEntity
子类:
class Lines: GKEntity {
override init() {
super.init()
let LineSprite = SpriteComponent(color: UIColor.white, size: CGSize(width: 10.0, height: 300))
addComponent(LineSprite)
// Set physics body
if let sprite = component(ofType: SpriteComponent.self)?.node {
sprite.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: sprite.size.width, height: sprite.size.height))
sprite.physicsBody?.isDynamic = false
sprite.physicsBody?.restitution = 1.0
sprite.physicsBody?.friction = 0.0
sprite.physicsBody?.linearDamping = 0.0
sprite.physicsBody?.angularDamping = 0.0
sprite.physicsBody?.mass = 0.00
sprite.physicsBody?.affectedByGravity = false
sprite.physicsBody?.usesPreciseCollisionDetection = true
sprite.physicsBody?.categoryBitMask = 0b1
sprite.zPosition = 10
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
在 TouchesBegan
中,我正在调用在 GameScene
中声明的函数 Move(XAxisPoint: t.location(in: self))
,这是 Move()
所做的:
///Determines direction of movement based on touch location, calls MoveUpOrDown for movement
func move(XAxisPoint: CGPoint){
let Direction: SKAction
let Key: String
if XAxisPoint.x >= 0 {
Direction = SKAction.moveBy(x: 0, y: 3, duration: 0.01)
Key = "MovingUp"
} else {
Direction = SKAction.moveBy(x: 0, y: -3, duration: 0.01)
Key = "MovingDown"
}
moveUpOrDown(ActionDirection: Direction, ActionKey: Key)
}
///Moves sprite on touch
func moveUpOrDown(ActionDirection: SKAction, ActionKey: String) {
let Line = Lines()
if let sprite = Line.component(ofType: SpriteComponent.self)?.node {
if sprite.action(forKey: ActionKey) == nil {
stopMoving()
let repeatAction = SKAction.repeatForever(ActionDirection)
sprite.run(repeatAction, withKey: ActionKey)
}
}
}
///Stops movement
func stopMoving() {
let Line = Lines()
if let sprite = Line.component(ofType: SpriteComponent.self)?.node {
sprite.removeAllActions()
}
}
我猜这行代码有问题 Line.component(ofType: SpriteComponent.self)?.node
但编译器没有抛出任何错误,我不确定我的错误在哪里。
任何 help/guidance 将不胜感激!
问题出在 MoveUpOrDown
和 StopMoving
中的以下行
let Line = Lines()
它正在创建一个新的 Lines
对象,然后告诉它 运行 一个动作。因为它是新的,所以它还没有被添加到场景中,所以它没有被绘制或作用。
您应该获取一个现有的 Lines
对象并对其进行修改,而不是创建一个新对象。
作为旁注,命名方法和变量的通用约定是使用 camelCase
,这意味着 MoveUpOrDown
应该是 moveUpOrDown
。另一方面,SnakeCase
用于 类 结构和协议,因此 SpriteComponent
是最新的。这使您一眼就能知道您使用的是类型还是变量。
我正在尝试使用与 here.
所述类似的实体组件架构来构建一个简单的 iOS 游戏我想在我的游戏中实现的是当用户触摸屏幕时,检测触摸发生的位置并将一种类型的所有实体移向特定方向(方向取决于用户触摸的位置,屏幕右侧= 向上,屏幕左侧 = 向下)。
到目前为止,游戏真的很简单,我才刚刚开始,但我被困在这个简单的功能中:
我的问题是 SKAction
应该 运行 在一个类型的所有实体上,但实际上确实发生了。
在我将我的游戏重新设计为 ECS 方法之前,它运行良好。
这是我在 Lines.swift 中声明的 GKEntity
子类:
class Lines: GKEntity {
override init() {
super.init()
let LineSprite = SpriteComponent(color: UIColor.white, size: CGSize(width: 10.0, height: 300))
addComponent(LineSprite)
// Set physics body
if let sprite = component(ofType: SpriteComponent.self)?.node {
sprite.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: sprite.size.width, height: sprite.size.height))
sprite.physicsBody?.isDynamic = false
sprite.physicsBody?.restitution = 1.0
sprite.physicsBody?.friction = 0.0
sprite.physicsBody?.linearDamping = 0.0
sprite.physicsBody?.angularDamping = 0.0
sprite.physicsBody?.mass = 0.00
sprite.physicsBody?.affectedByGravity = false
sprite.physicsBody?.usesPreciseCollisionDetection = true
sprite.physicsBody?.categoryBitMask = 0b1
sprite.zPosition = 10
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
在 TouchesBegan
中,我正在调用在 GameScene
中声明的函数 Move(XAxisPoint: t.location(in: self))
,这是 Move()
所做的:
///Determines direction of movement based on touch location, calls MoveUpOrDown for movement
func move(XAxisPoint: CGPoint){
let Direction: SKAction
let Key: String
if XAxisPoint.x >= 0 {
Direction = SKAction.moveBy(x: 0, y: 3, duration: 0.01)
Key = "MovingUp"
} else {
Direction = SKAction.moveBy(x: 0, y: -3, duration: 0.01)
Key = "MovingDown"
}
moveUpOrDown(ActionDirection: Direction, ActionKey: Key)
}
///Moves sprite on touch
func moveUpOrDown(ActionDirection: SKAction, ActionKey: String) {
let Line = Lines()
if let sprite = Line.component(ofType: SpriteComponent.self)?.node {
if sprite.action(forKey: ActionKey) == nil {
stopMoving()
let repeatAction = SKAction.repeatForever(ActionDirection)
sprite.run(repeatAction, withKey: ActionKey)
}
}
}
///Stops movement
func stopMoving() {
let Line = Lines()
if let sprite = Line.component(ofType: SpriteComponent.self)?.node {
sprite.removeAllActions()
}
}
我猜这行代码有问题 Line.component(ofType: SpriteComponent.self)?.node
但编译器没有抛出任何错误,我不确定我的错误在哪里。
任何 help/guidance 将不胜感激!
问题出在 MoveUpOrDown
和 StopMoving
let Line = Lines()
它正在创建一个新的 Lines
对象,然后告诉它 运行 一个动作。因为它是新的,所以它还没有被添加到场景中,所以它没有被绘制或作用。
您应该获取一个现有的 Lines
对象并对其进行修改,而不是创建一个新对象。
作为旁注,命名方法和变量的通用约定是使用 camelCase
,这意味着 MoveUpOrDown
应该是 moveUpOrDown
。另一方面,SnakeCase
用于 类 结构和协议,因此 SpriteComponent
是最新的。这使您一眼就能知道您使用的是类型还是变量。