Вопрос был:
Как вернуть ответ от асинхронного вызова?
, который может быть интерпретирован как:
Как сделать синхронный асинхронный код синхронным?
Решение будет состоять в том, чтобы избежать обратных вызовов и использовать комбинацию 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")
Основные сведения о обнаружении столкновений в SceneKit:
Например, вы можете указать немного игрового дизайна в простой английский:
Астероиды ударяют друг друга (и делают меньшие астероиды). Ракеты должны проходить друг через друга, но уничтожать ракеты и астероиды. Ракеты не должны делать ничего с ракетами (только наоборот), но если вы слишком близко приближаетесь к другому или к астероиду, у вас плохая проблема, и сегодня вы не пойдете в космос.
blockquote >Первый шаг к пониманию того, что при обнаружении столкновений необходимо кодифицировать этот дизайн, с точки зрения которого взаимодействуют пары. Вы можете сделать это со следующей таблицей:
| 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.