2016-01-26 4 views
2

Я создаю игру для ios, используя быстрый. Я реализовал систему компонентов компонента из Apples GameplayKit, очень похожую на то, как показано в this tutorial.Как я могу передать событие touchsbegan в компонент сущностей с помощью swift?

Я добавил сетку квадратов, которые я хочу по-разному реагировать на жесты касания. Я изменю состояние игры, используя конечный автомат, когда элемент пользовательского интерфейса будет прослушиваться, но я также хочу изменить, как каждый квадрат реагирует на жест нажатия. Из моего нынешнего ограниченного понимания лучший способ сделать это - изменить делегат жесты нажатия. Однако я не смог найти простых примеров того, как это можно сделать. Sqaures - это SKSpriteNodes.

Код можно получить по запросу; однако я ищу неконкурентный пример того, как это можно было бы сделать самым простым способом.

Кто-нибудь знает, как это можно сделать или может предложить «лучший» способ. Чтобы избежать субъективности, я лучше определяю структуру с точки зрения архитектуры. (Например, несколько операторов if в одном дескрипторе жестов выглядят как неправильный способ сделать это.)

+0

Если каждый квадрат является подклассом 'SKSpriteNode', вы можете установить его свойство' userInteractionEnabled' 'true' и переопределить его методы' touchhesBegan/Moved/Ended' для получения событий касания. Затем вы можете реализовать квадратные эффекты (поворот, масштабирование и т. Д.) В подклассе. – 0x141E

+0

Спасибо. Я отдам это. Каждый квадрат, который я вижу на экране, является SKSpriteNode. Я могу получить доступ к узлу через созданный мной компонент спрайта. – Relequestual

+0

Я предлагаю вам сделать ваши квадраты подклассом «SKSpriteNode», чтобы вы могли анимировать квадрат при касании, а затем вызвать метод в сцене, чтобы обработать прикосновение на более высоком уровне, если это необходимо. – 0x141E

ответ

1

Я нашел рабочее решение для своей проблемы, основанное на различных кусках помощи и идей, которые у меня были, однако я Все еще очень открыты для альтернативных решений.

Основная проблема, связанная с этой проблемой, заключается в том, как ссылаться на объект из спрайта. Прочитав документацию по SKSpriteNode, я обнаружил, что это родительский класс SKNode имеет userData attribute, что позволяет хранить данные в этом узле.

Прикрепление экземпляра сущности к узлу, который должен произойти в SpriteComponent, поскольку именно здесь сконструирован узел, однако он не может произойти в конструкторе, поэтому он должен быть в функции в SpriteComponent.

func addToNodeKey() { 
    self.node.userData = NSMutableDictionary() 
    self.node.userData?.setObject(self.entity!, forKey: "entity") 
    } 

Затем функция вызывается в конструкции класса Enity после добавления compoennt к себе.

addComponent(spriteComponent) 
spriteComponent.addToNodeKey() 

Теперь экземпляр Enity можно получить с помощью сенсорного случае, мне нужен способ, чтобы выполнить функцию на этом случае, однако, вы не знаете, если экземпляр будет подклассом GKEntity или нет, ни какого вида.

Поэтому я создал еще один компонент TouchableSpriteComponent. После некоторых попыток функция init приняла в качестве аргумента одну функцию, которая затем вызывается из эпизода touch event, которая позволяет сущности, которая создала TouchableSpriteComponent, определить, как она обрабатывает событие.

Я создал gist for this solution, так как здесь, вероятно, слишком много кода. Это permilink.

Мне очень хотелось бы знать, является ли это «хорошим» решением, или если есть гораздо более четкий маршрут, который будет иметь тот же эффект (без прокрутки всех объектов или узлов).

+0

Я понимаю, что код, содержащийся в gist, не идеален с точки зрения развернутых и развернутых переменных. Я все еще учился =] – Relequestual

+2

Просто FYI, все SKNodes (включая SKSpriteNode) уже имеют свойство «entity», которое вы можете установить без необходимости погружения в словарь userData. (В идеале, загрузка GKScene заполнила бы это, но это, к сожалению, не так, поэтому вам нужно сделать это вручную в коде.) –

+0

О, мужчина. Хорошо, спасибо. Я дам это в следующий раз, когда я буду работать над проектом =] – Relequestual

1

Если я understod хорошо, вы должны иметь что-то вроде:

func entityTouched(touches: Set<UITouch>, withEvent event: UIEvent?)

в вашем GKEntity подкласса.

Я делаю это в моей игре:

class Square: MainEntity { 
    override func entityTouched(touches: Set<UITouch>, withEvent event: UIEvent?) { 
     //DO something 
    } 
} 

GameScene:

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) 
    } 

где:

EntityNode:

class EntityNode: SKSpriteNode { 
    // MARK: Properties 
    weak var entity: GKEntity! 
} 

SpriteComponent:

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 
    } 
} 

MainEntity:

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?) {} 
} 

Позвольте мне знать, если было то, что вы ищете.

+0

Я не рассматривал подкласс SKSpriteNode, чтобы разрешить строение объекта, но я думаю, что это действительно имеет смысл. Есть ли какое-либо преимущество для этой реализации по сравнению с моим использованием атрибута userData для узлов? – Relequestual

+0

Я не думаю, что хранить класс в словаре - лучший способ сделать это. Где хранятся данные userData? Но я вполне уверен в этом решении, потому что Apple в DemoBoat использует этот подход, чтобы наблюдать, что узел ведьмы сталкивается. Я думаю, что разработчики яблока лучше меня! :) –

+0

Я посмотрю, где DemoBots делает это таким же образом. Я посмотрел DemoBots. Он делает более продвинутые вещи, чем я думаю, что мне нужно для некоторых вещей. – Relequestual