Как определить два столкновений SCNNodes? [Дубликат]

Вопрос был:

Как вернуть ответ от асинхронного вызова?

, который может быть интерпретирован как:

Как сделать синхронный асинхронный код синхронным?

Решение будет состоять в том, чтобы избежать обратных вызовов и использовать комбинацию Promises и async / await.

Я хотел бы привести пример для запроса Ajax.

(Хотя он может быть записан в Javascript, я предпочитаю писать его на Python и компилировать его в Javascript, используя Transcrypt . Это будет достаточно ясно.)

Позволяет сначала включить использование JQuery, чтобы $ был доступен как S:

__pragma__ ('alias', 'S', '$')

Определить функцию, которая возвращает Promise, в этом случае вызов Ajax:

def read(url: str):
    deferred = S.Deferred()
    S.ajax({'type': "POST", 'url': url, 'data': { },
        'success': lambda d: deferred.resolve(d),
        'error': lambda e: deferred.reject(e)
    })
    return deferred.promise()

Использовать асинхронный код, как если бы он был синхронным:

async def readALot():
    try:
        result1 = await read("url_1")
        result2 = await read("url_2")
    except Exception:
        console.warn("Reading a lot failed")

12
задан rickster 10 December 2014 в 19:27
поделиться

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

Pu t этот код в одном из ваших классов (контроллер просмотра, может быть - везде, где вы держите свою логику игры хорошо), и сделайте этот класс объявленным соглашением с протоколом 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.

28
ответ дан rickster 26 August 2018 в 19:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: