Entity-компонент в Swift

Я пытаюсь создать простую игру для iOS, используя архитектуру компонентов-сущностей, аналогичную описанной здесь.

Чего я хотел бы добиться в своей игре, так это того, что когда пользователь касается экрана, определяет, где произошло касание, и перемещает все объекты одного типа в определенном направлении (направление зависит от того, где пользователь коснулся, справа от экрана = вверх, слева от экран = вниз).

Пока что игра действительно простая и я только начинаю, но я застрял в этом простом функционале:

Моя проблема в том, что SKAction должен работать на всех объектах типа, но происходит вообще.

До того, как я переделал свою игру в соответствии с подходом ECS, это работало нормально.

Вот подкласс GKEntity, который я объявил в Lines.swift:

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 я вызываю функцию Move(XAxisPoint: t.location(in: self)), которая объявлена ​​в GameScene, и вот что делает 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, но компилятор не выдает никаких ошибок, и я не уверен, где моя ошибка.

Любая помощь/руководство будет принята с благодарностью!


person FrankVIII    schedule 15.07.2018    source источник


Ответы (1)


Проблема заключается в следующей строке в MoveUpOrDown и StopMoving

let Line = Lines()

Он создает новый объект Lines, а затем говорит ему запустить действие. Поскольку он новый, он не был добавлен в сцену, поэтому он не рисуется и не обрабатывается.

Вы должны получить существующий объект Lines и изменить его вместо создания нового.


В качестве примечания: общепринятым соглашением для именования методов и переменных является использование camelCase, что означает, что MoveUpOrDown должно быть moveUpOrDown. С другой стороны, SnakeCase используется для структур классов и протоколов, поэтому SpriteComponent является текущим. Это позволяет вам сразу узнать, работаете ли вы с типом или переменной.

person Craig Siemens    schedule 15.07.2018
comment
Спасибо @CleverError за вашу помощь! Похоже, я создавал несколько объектов Lines вместо ссылки на ранее созданный объект Lines, поэтому действия выполнялись для другого объекта. Я буду внимательнее относиться к соглашениям об именах, еще раз спасибо! - person FrankVIII; 15.07.2018