Ответ 1
Основные сведения о обнаружении столкновений в SceneKit:
- он основан на бит-масках, которые вместе образуют таблицу.
- контактный делегат - это то, как вы реагируете на столкновение.
Приведение объектов в столкновение
Например, вы можете указать немного игрового дизайна на простом английском языке:
Астероиды ударяют друг друга (и делают меньшие астероиды). Ракеты должны проходить друг через друга, но уничтожать ракеты и астероиды. Ракеты не должны делать ничего с ракетами (только наоборот), но если вы слишком близко приближаетесь к другому или к астероиду, у вас плохая проблема, и вы сегодня не пойдете в космос.
Первый шаг к пониманию того, что с обнаружением столкновения - это кодировать эту конструкцию, в которой взаимодействуют пары. Вы можете сделать это со следующей таблицей:
| Missile | Rocket | Asteroid
--------------------------------------
Missile | No | Yes | Yes
Rocket | No | Yes | Yes
Asteroid | No | No | Yes
Затем вы можете превратить заголовки таблицы в набор констант категории для использования в вашем коде.
typedef NS_OPTIONS(NSUInteger, CollisionCategory) {
CollisionCategoryMissile = 1 << 0,
CollisionCategoryRocket = 1 << 1,
CollisionCategoryAsteroid = 1 << 2,
};
missile.physicsBody.categoryBitMask = CollisionCategoryMissile;
rocket.physicsBody.categoryBitMask = CollisionCategoryRocket;
asteroid.physicsBody.categoryBitMask = CollisionCategoryAsteroid;
Используйте побитовое ИЛИ для этих констант для создания значений collisionBitMask
, которые заполняют таблицу.
missile.physicsBody.collisionBitMask =
CollisionCategoryRocket | CollisionCategoryAsteroid;
rocket.physicsBody.collisionBitMask =
CollisionCategoryRocket | CollisionCategoryAsteroid;
asteroid.physicsBody.collisionBitMask = CollisionCategoryAsteroid;
Это все, что вам нужно, чтобы заставить SceneKit разрешать конфликты для вас (то есть отбрасывать объекты друг от друга).
Реакция на столкновение
Если вы также хотите, чтобы вас уведомляли о столкновениях (чтобы вы могли заставить ракеты взорваться и запустить свой корабль в конце астероида в игре), вам нужно установить связаться с делегатом в мире физики вашей сцены и реализовать один или несколько из методов делегирования контактов, которые вызываются, когда контакт происходит.
В вашем методе делегирования контактов (скажем, physicsWorld:didBeginContact:
) вам нужно будет выяснить, какие категории тел были задействованы в контакт, и который был таким, чтобы вы могли получить свой код, который делает все, что ваша игра делает для столкновения:
- (void)physicsWorld:(SCNPhysicsWorld *)world didBeginContact:(SCNPhysicsContact *)contact
{
CollisionCategory contactMask =
contact.nodeA.physicsBody.categoryBitMask | contact.nodeB.physicsBody.categoryBitMask;
// first, sort out what kind of collision
if (contactMask == (CollisionCategoryMissile | CollisionCategoryRocket)) {
// next, sort out which body is the missile and which is the rocket
// and do something about it
if (contact.nodeA.physicsBody.categoryBitMask == CollisionCategoryMissile) {
[self hitRocket:contact.nodeB withMissile:contact.nodeA];
} else {
[self hitRocket:contact.nodeA withMissile:contact.nodeB];
}
} else if (contactMask == (CollisionCategoryMissile | CollisionCategoryAsteroid)) {
// ... and so on ...
}
}
Поместите этот код в один из ваших классов (контроллер просмотра, может быть - везде, где вы держите свою логику игры хорошо), и сделайте этот класс объявленным соглашением SCNPhysicsContactDelegate
.
@interface ViewController: UIViewController <SCNPhysicsContactDelegate>
Затем назначьте этот объект в мир физики сцены как делегат-контакт:
// in initial setup, where presumably you already have a reference to your scene
scene.physicsWorld.contactDelegate = self
Узнать больше
Немного о разрешении конфликтов в справочной документации SCNPhysicsBody. И у Apple есть пример кода, который использует обнаружение конфликтов - это часть smorgasbord демонстраций в WWDC слайды и demo примеры приложений, а также в автомобильной физике.
Кроме того, модель обработки столкновений SceneKit почти такая же, как у SpriteKit, поэтому почти все в руководстве по программированию SpriteKit также полезно для понимания тот же материал в SceneKit.