Как сделать игру как Fruit Ninja с Box2D и Cocos2D - Часть 1

  1. Демо-версия игры
  2. Начало работы: настройка проекта
  3. Ресурсный комплект
  4. Рисование текстурированных полигонов с помощью PRKit
  5. Планирование наших фруктов
  6. Создание первого фрукта
  7. Добавление фруктов на сцену
  8. Куда пойти отсюда?

Это сообщение от iOS Tutorial Team Аллен Тан , iOS разработчик и соучредитель в Белый Виджет , Вы также можете найти его на Google+ а также щебет ,

В этом уроке вы узнаете, как сделать спрайт-игру для iPhone, похожую на Фруктовый ниндзя от Студии Halfbrick использование мощных библиотек Cocos2D и Box2D вместе с некоторыми готовыми инструментами.

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

Но этот урок продемонстрирует еще более прохладную технику. Наши фрукты могут быть нарезаны несколько раз, и они будут разделены динамически на основе точных линий разреза!

Как вы можете себе представить, это продвинутый метод, так что это руководство предназначено для опытных разработчиков Cocos2D и Box2D. Если вы новичок в Cocos2D или Box2D, вы должны пройти (по крайней мере) введение в Cocos2D а также введение в Box2D учебники, прежде чем приступить к этому учебнику.

Этот урок разделен на три части:

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

Я хотел бы выразить особую благодарность Рик Смравски для создания основы для проекта, на котором основан этот учебник. Он был ответственным за портирование этого демонстрация слайсинга на основе flash в Cocos2D, а также для портирования CCBlade и PRKit на Cocos2D 2.0.

Продолжайте читать, чтобы посмотреть видео о том, что вы будете делать, и начать изучать новые классные приемы!

Демо-версия игры

Вот демонстрационное видео, показывающее, что вы будете делать в этой серии уроков:

Как я уже говорил, вы увидите, что эффект нарезки фруктов действительно динамичен. Фрукты нарезаются динамически в зависимости от того, где вы нарезаете, и, поскольку вы можете нарезать объекты несколько раз, вы можете порезать их!

Вы также можете реализовать крутой эффект среза, некоторые системы частиц, логику геймплея и звуки, чтобы оживить обстановку.

Есть много чего, так что давайте начнем!

Начало работы: настройка проекта

В этом проекте вы собираетесь использовать Cocos2D 2.X, так что загрузить если у вас его еще нет Обратите внимание, что вы можете использовать Cocos2D 1.X вместо 2.X. С 1.X вы можете пропустить части о преобразовании PRKit и CCBlade в Cocos2D 2.X, но не забудьте обратить внимание на другие небольшие изменения, которые вы вносите в эти классы.

После загрузки дважды щелкните по tar, чтобы разархивировать его, затем установите шаблоны с помощью следующих команд в Терминале:

cd ~ / Загрузки / cocos2d-iphone-2.0-beta ./install-templates.sh -f -u

Запустите Xcode и создайте новый проект с iOS \ cocos2d v2.x \ cocos2d iOS с шаблоном Box2d и назовите его CutCutCut.

Ваш новый проект должен выглядеть примерно так:

Перво-наперво - вы должны немного очистить шаблон, чтобы получить хорошую отправную точку.

Откройте HelloWorldLayer.h и удалите следующую строку:

CCTexture2D * spriteTexture _; // слабая ссылка

Переключитесь на HelloWorldLayer.mm и внесите следующие изменения

// Удалить эту строку сверху #import "PhysicsSprite.h" // Заменить метод init следующим - (id) init {if ((self = [super init])) {// включить события self.isTouchEnabled = YES ; self.isAccelerometerEnabled = YES; CGSize s = [CCDirector sharedDirector] .winSize; // init физика [self initPhysics]; [self scheduleUpdate]; } вернуть себя; } // Удалить эти два метода - (void) createMenu {// все содержимое} - (void) addNewSpriteAtPosition: (CGPoint) p методы {// все содержимое} // Удалить эту строку из ccTouchesEnded [self addNewSpriteAtPosition: location];

На данный момент вы удалили все ссылки на PhysicsSprite из HelloWorldLayer, но пока не удаляете файлы из проекта. Позже вам нужно будет скопировать метод, который PhysicsSprite.mm содержит где-то еще, так что оставьте его отложенным.

Нажмите Ctrl + R, чтобы скомпилировать и запустить ваш проект, и вы должны увидеть пустой экран с зеленой рамкой вокруг него:

Оставшийся код шаблона настроил отладочный чертеж Box2D, который рисует границы вокруг тел Box2D на экране. Видите тонкие зеленые линии, нарисованные вокруг экрана? Это стены, сгенерированные стандартным методом initPhysics, который поставляется с шаблоном.

Взгляните на оставшийся код шаблона, чтобы убедиться, что вы понимаете, что происходит до сих пор - он инициализирует мир Box2D, устанавливает основание (зеленые границы), настраивает отладочный чертеж и т. Д. Это довольно неплохой «почти пустой» отправная точка с Box2D мы можем продолжить отсюда.

Ресурсный комплект

Затем загрузите ресурсы для этого проекта и разархивируйте файл.

Пока не добавляйте все в проект; некоторые файлы на самом деле являются необязательными. Держите папку под рукой, хотя - по мере прохождения учебника время от времени я буду просить вас добавить некоторые из этих файлов в проект.

Вот что вы найдете внутри:

  • Фоновое изображение и куча фруктов, сделанные Vicki и другие разные изображения в папке «Изображения»
  • Фоновый звуковой микс сделан с использованием gomix.it в папке Sounds
  • Звуковые эффекты сделаны с использованием bfxr или скачано с Freesound в папке Sounds
  • Все системы частиц, созданные с Конструктор частиц в папке Particles
  • Файл PLIST, сгенерированный PhysicsEditor содержащий информацию о вершинах для классов Fruits & Bomb в папке Misc
  • Классы "Фрукты и бомбы" в папке "Классы"
  • Версии PRKIt а также CCBlade вы будете использовать в учебнике в папке Classes
  • Список атрибуции для ресурсов, которые находятся под лицензией Attribution в папке Misc

Рисование текстурированных полигонов с помощью PRKit

Наша цель - разрезать спрайты на несколько частей. Типичный CCSprite содержит текстуру и ограничивающую рамку независимо от формы изображения. Это не подходит для нашей игры, так как знание реальных форм на изображениях является критически важным шагом для создания спрайтов, которые можно вырезать, разрезать и разделять.

Вам нужно создать текстурированные полигоны, которые:

  • Создать соответствие между многоугольником / формой и изображением (Texture Mapping)
  • Отображать только те части изображения, которые находятся в границах многоугольника (заполнение текстурой)

Ни в Cocos2D, ни в Box2D нет встроенного класса, который обрабатывает нужные вам функции, и обычно для этого требуется некоторая триангуляция в сочетании с пользовательским кодом рисования OpenGL.

Звучит сложно, правда?

К счастью, все сложные вычисления и код рисования, необходимые для достижения этой цели, уже написаны хорошими людьми в Предварительные исследования , Они создали дополнение к библиотеке Cocos2D под названием PRKit, которая обрабатывает наложение текстур и заливку.

Чтобы начать работу с текстурированными полигонами, скачать PRKit , распакуйте его и перетащите папку PRKit в ваш проект. Убедитесь, что установлен флажок «Копировать элементы в папку целевой группы» и выбран «Создать группы для любых добавленных папок».

Обратите внимание, что PRKit поддерживается Precognitive Research, поэтому он может своевременно обновляться. Чтобы избежать путаницы, наш набор ресурсов также содержит точную версию PRKit, которую я использовал при создании этого урока.

Ваш проект должен теперь включать эти файлы:

Ваш проект должен теперь включать эти файлы:

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

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

Ошибки появляются, потому что PRKit был сделан для Cocos2D 1.X, который использует OpenGL ES 1.1, тогда как вы используете Cocos2D 2.X, который использует OpenGL ES 2.0, и между ними есть существенные различия.

Чтобы это исправить, откройте PRFilledPolygon.m и внесите следующие изменения:

// Добавить внутрь initWithPoints: andTexture: usingTriangulator: method self.shaderProgram = [[CCShaderCache sharedShaderCache] programForKey: kCCShader_PositionTexture]; // Замените метод CalculayTextureCoordinates на этот - (void) ); textureCoordinates [j] .y = 1 - textureCoordinates [j] .y; }} // Заменим метод рисования этим - (void) draw {CC_NODE_DRAW_SETUP (); ccGLBindTexture2D (self.texture.name); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); ccGLBlendFunc (blendFunc.src, blendFunc.dst); ccGLEnableVertexAttribs (kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords); glVertexAttribPointer (kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, areaTrianglePoints); glVertexAttribPointer (kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates); glDrawArrays (GL_TRIANGLES, 0, areaTrianglePointCount); }

Давайте рассмотрим эти изменения по крупицам.

Во-первых, в Cocos2D к каждому CCNode прикреплена шейдерная программа OpenGL ES 2.0. Чтобы нарисовать PRFilledPolygon, вам нужно подать в суд на встроенный шейдер "Position / Texture", который вы назначаете в методе init.

Далее вам нужно установить правильные координаты текстуры для каждой точки в многоугольнике. Для этого вам нужно внести два изменения в метод calcTextureCoordinates:

  • Масштаб : так как этот класс выполняет свои собственные вычисления по координатам своей текстуры, он автоматически не обрабатывает отображение сетчатки. Чтобы это исправить, вы просто умножаете texture.pixelsWide на CC_CONTENT_SCALE_FACTOR - удобное значение множителя, предоставляемое Cocos2D для преобразования значений между обычными эквивалентами и эквивалентами сетчатки.
  • Отразить Y : По какой-то причине PRFIlledPolygon рисует текстуры вверх ногами, поэтому вы просто переворачиваете значение y здесь.

Наконец, код чертежа обновляется до OpenGL ES 2.0, аналогично тому, как чертеж CCSprite изменился с Cocos2D 1.X на Cocos2D 2.X:

  • Начните с вызова CC_NODE_DRAW_SETUP (), чтобы подготовить узел к рисованию.
  • Вызовы glDisableClientState () и glEnableClientState () устарели и отбрасываются.
  • Команды glVertexPointer () и glTexCoordPointer () заменены на glVertexAttribPointer (), который теперь принимает положение вершины или координату текстуры в качестве первого параметра.
  • Настройка glTexEnvf (), которая отвечала за повторение спрайта в случае, если многоугольник был больше текстуры, заменяется вызовами glTexParameteri ().

Если вас что-то смущает, вы можете проверить наши OpenGL ES 2.0 для iPhone а также Пользовательские шейдеры Cocos2D 2.X учебники для получения дополнительной справочной информации. Но вам не нужно слишком беспокоиться об этом, потому что на данный момент все, что мы делаем, это переносим класс для работы в Cocos2D 2.X:]

Скомпилируйте и запустите, и все ошибки PRKit должны исчезнуть!

Пришло время привести PRKit в действие. Вы будете подклассифицировать класс PRFilledPolygon PRKit, чтобы создать базовый класс PolygonSprite, который будет приносить наши плоды.

PolygonSprite основывается на PRFilledPolygon, прикрепляя тело Box2D к спрайту, и он также будет содержать другие пользовательские переменные и методы для плодов в нашей игровой реализации.

Давайте доберемся до этого. Нажмите Ctrl + N и создайте новый файл с помощью шаблона класса iOS \ cocos2d v2.x \ CCNode. Сделайте его подклассом PRFilledPolygon и назовите его PolygonSprite.m .

Переключитесь на PolygonSprite.h и внесите следующие изменения:

// Добавить в начало файла #import "Box2D.h" #import "PRFilledPolygon.h" #define PTM_RATIO 32 // Добавить внутрь @interface b2Body * _body; BOOL _original; b2Vec2 _centroid; // Добавить после @interface @property (nonatomic, assign) b2Body * body; @property (nonatomic, readwrite) BOOL оригинал; @property (nonatomic, readwrite) b2Vec2 centroid; // Добавить перед текстурой @end - (id) initWithTexture: (CCTexture2D *) тело: (b2Body *) тело original: (BOOL) original; - (id) initWithFile: (NSString *) тело файла: (b2Body *) тело оригинала: (BOOL) оригинал; + (id) spriteWithFile: (NSString *) тело файла: (b2Body *) тело оригинала: (BOOL) оригинал; + (id) spriteWithTexture: (CCTexture2D *) тело текстуры: (b2Body *) тело оригинала: (BOOL) оригинал; - (ID) initWithWorld: (b2World *) мир; + (Идентификатор) spriteWithWorld: (b2World *) мир; - (b2Body *) createBodyForWorld: (b2World *) положение в мире: (b2Vec2) вращение позиции: (float) вершины вращения: (b2Vec2 *) вершины vertexCount: (int32) плотность счета: (float) трение плотности: (float) восстановление трения : (с плавающей точкой) реституция; - (пустоты) activateCollisions; - (пустоты) deactivateCollisions;

Приведенный выше код объявляет базовые переменные и методы, необходимые для создания PolygonSprite. Это:

  • body : это тело Box2D, которое прикреплено к нашему спрайту. Это необходимо для моделирования физики.
  • оригинал : полные и нарезанные спрайты будут использовать один и тот же класс PolygonSprite, поэтому различия между ними будут важны. Если это ДА, это означает, что это неразрезанный или оригинальный объект, который вы создали, в противном случае это просто часть целого.
  • Центр тяжести : центр многоугольника на изображении не всегда совпадает с центром изображения, поэтому полезно сохранить это значение.
  • Свойства : Предоставьте доступ ко всем переменным, используя свойства, чтобы другие классы могли получить к ним свободный доступ.
  • init / spriteWith * : наши основные методы init следуют тем же правилам именования, что и Cocos2D.
  • другие методы : это методы создания и работы с прикрепленным телом Box2D и его свойствами.
  • PTM_RATIO : отношение пикселей к метрам. Box2D нуждается в этом значении конверсии, потому что он имеет дело с метрами вместо пикселей.

Быстро переключитесь на PolygonSprite.m и переименуйте его в PolygonSprite.mm . Все классы, которые смешивают код Objective-C (Cocos2D) и C ++ (Box2D), должны иметь расширение ".mm", чтобы уведомить компилятор о смешанном синтаксисе.

Затем внесите следующие изменения в PolygonSprite.mm :

// Добавить внутрь @implementation @synthesize body = _body; @synthesize original = _original; @synthesize centroid = _centroid; + (id) spriteWithFile: (NSString *) тело файла: (b2Body *) оригинал тела: (BOOL) оригинал {return [[[self alloc] initWithFile: тело файла: оригинал тела: оригинал] autorelease]; } + (id) spriteWithTexture: (CCTexture2D *) тело текстуры: (b2Body *) тело оригинала: (BOOL) оригинал {return [[[self alloc] initWithTexture: тело текста: тело оригинала: оригинал] autorelease]; } + (id) spriteWithWorld: (b2World *) world {return [[self alloc] initWithWorld: world] autorelease]; } - (id) initWithFile: (NSString *) тело файла: (b2Body *) тело оригинала: (BOOL) оригинал {NSAssert (filename! = nil, @ "Неверное имя файла для спрайта"); CCTexture2D * texture = [[CCTextureCache sharedTextureCache] addImage: имя файла]; return [self initWithTexture: текстура тело: тело оригинал: оригинал]; } - (id) initWithTexture: (CCTexture2D *) тело текстуры: (b2Body *) тело original: (BOOL) original {// собрать все вершины из нашей формы Box2D b2Fixture * originalFixture = body-> GetFixtureList (); b2PolygonShape * shape = (b2PolygonShape *) originalFixture-> GetShape (); int vertexCount = shape-> GetVertexCount (); NSMutableArray * points = [NSMutableArray arrayWithCapacity: vertexCount]; for (int i = 0; i <vertexCount; i ++) {CGPoint p = ccp (shape-> GetVertex (i) .x * PTM_RATIO, shape-> GetVertex (i) .y * PTM_RATIO); [points addObject: [NSValue valueWithCGPoint: p]]; } if ((self = [super initWithPoints: points andTexture: texture])) {_body = body; _body-> SetUserData (само); _original = оригинал; // получает центр многоугольника _centroid = self.body-> GetLocalCenter (); // назначить опорную точку на основе центра self.anchorPoint = ccp (_centroid.x * PTM_RATIO / texture.contentSize.width, _centroid.y * PTM_RATIO / texture.contentSize.height); // подробнее об инициализации здесь позже, когда вы раскроете PolygonSprite} return self; } - (id) initWithWorld: (b2World *) world {// здесь нечего делать return nil; }

Как и в Cocos2D, все методы spriteWith * являются просто автоматически выпускаемыми аналогами методов initWith *, в то время как initWithWorld еще не использует этот класс, но вместо этого он будет использоваться подклассами PolygonSprite позже.

Большая часть изменений может быть найдена в методах initWithFile и initWithTexture. Чтобы получить поток вещей, создание фрукта будет вызвано в следующей последовательности:

  • initWithWorld : Это предназначено для подклассов PolygonSprite, поэтому вы ничего не делаете, кроме как возвращаете nil и разбираетесь с этим позже.
  • initWithFile : это добавляет текстуру из нашего файла и передает все в initWithTexture.
  • initWithTexture : наша основная инициализация. PRFilledPolygon нужна текстура и все вершины многоугольника, которые она заполняет. Поскольку предыдущий шаг уже обрабатывал часть текстуры, этот шаг обрабатывает вершины, собирая их из тела Box2D спрайта. После передачи их в PRFilledPolygon, он приступает к инициализации переменных, которые вы ранее объявили.
  • initWithPoints : Все, что это делает, содержится в PRKit, и хорошо, что вам больше не нужно прикасаться к PRKit теперь, когда вы обновили его код.

Еще внутри PolygonSprite.mm , добавьте следующие методы:

- (void) setPosition: (CGPoint) position {[super setPosition: position]; _body-> SetTransform (b2Vec2 (position.x / PTM_RATIO, position.y / PTM_RATIO), _body-> GetAngle ()); } - (b2Body *) createBodyForWorld: (b2World *) положение в мире: (b2Vec2) вращение позиции: (float) вершины вращения: (b2Vec2 *) вершины vertexCount: (int32) плотность счета: (float) плотность трения: (float) трения реституция: (плавание) реституция {b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; bodyDef.position = position; bodyDef.angle = вращение; b2Body * body = world-> CreateBody (& bodyDef); b2FixtureDef fixtureDef; fixtureDef.density = плотность; fixtureDef.friction = трение; fixtureDef.restitution = реституция; fixtureDef.filter.categoryBits = 0; fixtureDef.filter.maskBits = 0; b2PolygonShape shape; shape.Set (вершины, количество); fixtureDef.shape = & shape; объемноцентрированного> CreateFixture (& fixtureDef); возвращение тела; } - (void) activCollisions {b2Fixture * fixture = _body-> GetFixtureList (); b2Filter filter = fixture-> GetFilterData (); filter.categoryBits = 0x0001; filter.maskBits = 0x0001; fixture-> SetFilterData (фильтр); } - (void) deactivateCollisions {b2Fixture * fixture = _body-> GetFixtureList (); b2Filter filter = fixture-> GetFilterData (); filter.categoryBits = 0; filter.maskBits = 0; fixture-> SetFilterData (фильтр); }

В приведенном выше коде вы сначала перегружаете метод setPosition в CCNode, чтобы при обновлении позиции спрайта обновлялась и позиция связанного тела Box2D.

Затем вы создадите удобный метод для создания и определения тела Box2D. Чтобы создать тело, вам нужно определить определение тела, объект тела, форму и определение прибора. Здесь еще не назначены реальные жесткие значения, поскольку этот метод будет использоваться подклассами PolygonSprite в дальнейшем.

Единственное, на что стоит обратить внимание - это биты категорий и биты-маски. Эти два используются для фильтрации столкновений между объектами, так что, если бит категории объекта совпадает с битом маски другого объекта, и наоборот, между этими двумя объектами произойдет столкновение. Сначала вы устанавливаете их на 0, потому что вы не хотите, чтобы при первой инициализации объектов происходили столкновения.

Наконец, вы определяете два метода, которые просто заменяют categoryBits и maskBits, чтобы вы могли активировать и деактивировать столкновения наших PolygonSprites.

Есть еще одна вещь, которую нужно добавить в PolygonSprite.mm :

- (CGAffineTransform) nodeToParentTransform {b2Vec2 pos = _body-> GetPosition (); float x = pos.x * PTM_RATIO; float y = pos.y * PTM_RATIO; if (! isRelativeAnchorPoint_) {x + = anchorPointInPoints_.x; y + = anchorPointInPoints_.y; } // Сделать матрицу с плавающей точкой radians = _body-> GetAngle (); float c = cosf (радианы); float s = sinf (радианы); if (! CGPointEqualToPoint (anchorPointInPoints_, CGPointZero)) {x + = c * -anchorPointInPoints_.x + -s * -anchorPointInPoints_.y; y + = s * -anchorPointInPoints_.x + c * -anchorPointInPoints_.y; } // Rot, Translate Matrix transform_ = CGAffineTransformMake (c, s, -s, c, x, y); вернуть transform_; }

Помните, когда я упоминал, что вам нужно что-то от PhysicsSprite? Ну вот и все. Все, что нужно сделать, это убедиться, что наша форма Box2D и наш спрайт находятся в одинаковом положении при движении. Он подготовлен для нас Cocos2D, и это делает его еще более потрясающим.

После копирования приведенного выше кода вы можете теперь удалить и PhysicsSprite.h, и PhysicsSprite.mm из проекта, так как вы полностью устранили их полезность.

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

Планирование наших фруктов

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

  • Полигоны должны быть выпуклыми , что означает, что внутренний угол не превышает 180.
  • Полигоны не должны превышать 8 вершин .

Вы можете обойти это ограничение, если разрешите каждому телу содержать несколько фигур. Box2D может обрабатывать вогнутые формы, если вы используете метод триангуляции и делаете вогнутые формы из нескольких треугольников, но это выходит за рамки данного руководства.

Для простоты, в этом уроке у вас будет правило 1 Body to 1 Shape.

Примечание: PhysicsEditor, инструмент, который мы рассмотрим позже в этом руководстве, на самом деле содержит код для автоматической триангуляции полигонов, которые вы рисуете в набор выпуклых фигур. Однако, как я уже говорил, мы стараемся упростить ситуацию, поэтому будем рисовать наши фигуры выпуклыми, чтобы у нас была только одна фигура на тело.

Взгляните на эти два фрукта:

Взгляните на эти два фрукта:

Использование банана не очень хорошая идея, потому что он естественно вогнутый. Арбуз, с другой стороны, очень хорош, потому что вы можете определить выпуклый многоугольник, который очень похож на его форму.

Если бы вы определили формы многоугольников, которые следуют правилам Box2D для двух фруктов, вы бы более или менее в итоге получили:

Многоугольник арбуза идеально вписывается в изображение, а многоугольник банана имеет большое пустое пространство, где изображение изгибается внутрь. Box2D будет рассматривать это пространство как часть нашего объекта, и это может заставить банан чувствовать себя неестественно, когда он сталкивается с другими объектами или когда его режут.

Это не означает, что вы не можете использовать банан, а скорее просто не рекомендуется использовать банан. На самом деле, игра, которую вы будете создавать в этом уроке, будет использовать тот же банан.

Создание первого фрукта

Пришло время создать первый фрукт: Арбуз (хотя бы кусочек).

Возвращаясь к процессу инициализации нашего PolygonSprite, вы знаете, что initWithTexture ожидает тело Box2D, но предыдущий шаг initWithFile этого не обеспечивает.

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

Чтобы создать наше тело Box2D, вы должны сначала знать вершины той формы многоугольника, которую вы хотите создать. Есть разные способы сделать это, но для этого урока вы будете использовать отличный инструмент под названием PhysicsEditor. Этот инструмент наполнен функциями, но вы будете использовать его только для того, чтобы направлять нас в получении координат вершин нашего многоугольника.

Если у вас его нет, скачать PhysicsEditor , установите его и запустите. Вы получите пустой проект с 3 панелями / колонками.

Работать с PhysicsEditor довольно просто. Слева вы размещаете все изображения, с которыми хотите работать. В середине вы визуально определяете полигон для вашего изображения. Справа у вас есть параметры для тела.

Справа у вас есть параметры для тела

Возьмите watermelon.png из папки «Изображения» набора ресурсов и перетащите его на левую панель. Теперь вы должны увидеть Арбуз на центральной панели.

Увеличьте увеличение, расположенное внизу этой панели, до комфортного уровня, а затем нажмите кнопку «Пентагон» в верхней части этой панели, чтобы создать 3-стороннюю форму многоугольника.

Щелкните правой кнопкой мыши на многоугольнике и выберите «Добавить вершину», пока у вас не будет 5-8 вершин. Переместите вершины по краям арбуза, убедившись в двух вещах:

  • Полигон, который вы создаете - это выпуклый.
  • Все пиксели Арбуза находятся внутри Полигона.

Примечание. Еще один ярлык для рисования фигур - использование инструмента «Волшебная палочка» от PhysicsEditor. Просто установите высокий допуск (5-8), чтобы в итоге вы получили примерно 5-8 баллов, и откорректируйте баллы оттуда.

Добавьте все остальные фрукты и изображение бомбы из папки «Изображения» в наборе ресурсов и сделайте то же самое для них.

Вы должны определить формы для следующих изображений:

  • banana.png
  • bomb.png
  • grapes.png
  • pineapple.png
  • strawberry.png
  • watermelon.png

Когда вы закончите, в правом верхнем углу измените значение Exporter на «Box2D generic (PLIST)», и у вас должно получиться что-то вроде этого:

Нажмите «Опубликовать» или «Опубликовать как», чтобы экспортировать файл PLIST, содержащий информацию о вершине. Сохраните файл как fruits.plist.

Например, список fruit.plist, который вы использовали для этого урока, находится в папке Misc комплекта ресурсов.

Вам нужно только просмотреть информацию, содержащуюся в файле PLIST, поэтому не добавляйте этот файл в свой проект, а просто откройте файл fruits.plist с помощью Xcode, чтобы просмотреть его содержимое организованным образом.

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

Вам нужно углубиться до самого глубокого уровня, чтобы получить вершины многоугольника Арбуза, например, так:

Разверните арбуз / Светильники / Элемент 0 / полигоны, и теперь вы должны увидеть еще один Элемент 0 Массива Типа под полигонами. Этот последний массив - ваша форма. Если вы правильно определили выпуклую форму с 8 или менее вершинами, вы должны увидеть только один массив под полигонами.

Если вы видите более одного, то есть массива Item 0, массива Item 1 и т. Д., Это означает, что PhysicsEditor создал сложную форму, потому что вы либо определили слишком много вершин, либо сформировали вогнутый многоугольник. Если это произойдет, вернитесь в PhysicsEditor и исправьте свою форму.

Затем разверните элемент 0 типа Array, чтобы увидеть окончательный список элементов. Это ваши вершины, а значение, которое вы видите справа в этом формате {число, число}, - это ваши координаты x & y для каждой вершины.

Теперь, когда у вас есть точные значения для вершин вашего многоугольника, вы можете приступить к созданию класса Арбуз.

В Xcode создайте новый файл с шаблоном iOS \ cocos2d v2.x \ CCNode Class. Сделайте его подклассом PolygonSprite и назовите его «Арбуз». Откройте Watermelon.h и внесите следующие изменения:

// Добавить в начало файла #import "PolygonSprite.h"

Переключитесь на Watermelon.m , переименуйте его в Watermelon.mm и добавьте следующий метод init:

// Добавить внутрь @implementation - (id) initWithWorld: (b2World *) world {int32 count = 7; NSString * file = @ "watermelon.png"; Вершины b2Vec2 [] = {b2Vec2 (5.0 / PTM_RATIO, 15.0 / PTM_RATIO), b2Vec2 (18.0 / PTM_RATIO, 7.0 / PTM_RATIO), b2Vec2 (32.0 / PTM_RATIO, 5.0 / PTM_RATIO), b2_RATIO) (b2VAT2) (b2VAT2) (b2VAT_2), b2VAT2) b2Vec2 (60,0 / PTM_RATIO, 14,0 / PTM_RATIO), b2Vec2 (34,0 / PTM_RATIO, 59,0 / PTM_RATIO), b2Vec2 (28,0 / PTM_RATIO, 59,0 / PTM_RATIO)}; CGSize screen = [[CCDirector sharedDirector] winSize]; b2Body * body = [self createBodyForWorld: мировая позиция: b2Vec2 (screen.width / 2 / PTM_RATIO, screen.height / 2 / PTM_RATIO) вращение: 0 вершин: вершины vertexCount: плотность счета: 5,0 трение: 0,2 восстановление: 0,2]; if ((self = [super initWithFile: тело файла: body original: YES])) {// Здесь мы инициализируем больше значений для фрукта позже} return self; }

В приведенном выше коде вы сначала определяете количество вершин, которое в данном случае равно 7. Затем вы создаете массив вершин, содержащий все координаты, которые вы только что видели в PLIST. Эта информация используется для создания тела с использованием удобного метода, определенного в PolygonSprite.

Вы вносите небольшое трение, чтобы формы не скользили бесконечно, и вы также вносите небольшое восстановление, чтобы фигуры не останавливались, когда они отскакивали друг от друга.

Наконец, вы создаете объект, вызывая инициализацию суперкласса и передавая имя файла изображения, тело Box2D, и заявляете, что это оригинальный фрукт.

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

На панели Project Navigator щелкните правой кнопкой мыши «Ресурсы» и выберите «Добавить файлы в CutCutCut». Добавьте папку «Изображения» из набора ресурсов в проект. Убедитесь, что установлен флажок «Копировать элементы в папку целевой группы» и выбран «Создать группы для любых добавленных папок».

Выполните те же шаги, чтобы создать банан, виноград, ананас, клубнику и бомбу.

Вы только шаг за шагом решали, как создать первый фрукт, так как это процесс промывки и повторения каждого фрукта. Набор ресурсов содержит готовые классы фруктов и бомб в папке «Классы», на которые вы можете посмотреть, если вам все еще нужны рекомендации, или вы можете добавить их все в свой проект, если хотите пропустить этот шаг.

Скомпилируйте и запустите, и убедитесь, что все в порядке.

Добавление фруктов на сцену

Пока на экране ничего не происходит, и вам явно не терпится увидеть плоды своего труда - каламбур! :]

Переключитесь на HelloWorldLayer.h и внесите следующие изменения:

// Добавить в начало файла #import "PolygonSprite.h" // Добавить внутри @interface CCArray * _cache; // Добавить после @interface @property (nonatomic, retain) CCArray * cache;

Вернитесь к HelloWorldLayer.mm и внесите следующие изменения:

// Добавить в начало файла #import "Watermelon.h" // Добавить внутри @implementation @synthesize cache = _cache; // Добавить внутри метода init, ниже [self initPhysics] [self initSprites]; // Добавить внутри метода dealloc перед вызовом [super dealloc] [_cache release]; _cache = ноль; // Добавить в любом месте внутри @implementation и перед @end - (void) initSprites {_cache = [[CCArray alloc] initWithCapacity: 53]; // Просто создайте один спрайт. Весь этот метод будет заменен позже. PolygonSprite * sprite = [[Распределение арбуза] initWithWorld: world]; [self addChild: sprite z: 1]; [sprite activCollisions]; [_cache addObject: sprite]; }

Вы объявляете массив кеша, который будет содержать все плоды и бомбы, которые вы создадите в будущем. Далее вы создаете 1 арбуз и добавляете его на сцену. Вы вызываете activCollisions, чтобы Арбуз не проходил сквозь стены.

Скомпилируйте и запустите, и вы увидите арбуз, падающий из центральной части экрана, и приземлитесь внизу, как показано ниже.

Вы можете заметить, что Арбуз не совсем в центре. Причина этого в том, что вы разместили объект на основе его тела Box2D, а источник нашего тела Box2D находится в нижнем левом углу объекта. Тонкий контур вокруг Арбуза виден, потому что режим отладочного рисования все еще включен.

Куда пойти отсюда?

Вот пример проекта со всем кодом из приведенного выше учебника.

Вот и все для первой части серии. Пока что у вас есть текстурированный полигон с арбузом, который просто падает на нижнюю часть экрана.

Но вместо того, чтобы рисовать прямоугольный спрайт с прозрачным пространством, как вы обычно видите в уроках Box2D, он использует PRKit для рисования только тех частей текстуры, которые соответствуют вершинам тела Box2D. Это скоро пригодится!

Теперь вы готовы к Часть 2 из учебника, где вы добавляете возможность нарезать фрукты!

А пока, если у вас есть какие-либо вопросы или комментарии по поводу этой части, присоединяйтесь к обсуждению на форуме ниже!

Это сообщение от iOS Tutorial Team   Аллен Тан   , iOS разработчик и соучредитель в   Белый Виджет   ,   Google+   а также   щебет   ,
Это сообщение от iOS Tutorial Team Аллен Тан , iOS разработчик и соучредитель в Белый Виджет , Google+ а также щебет ,

Похожие

Как успокоить ребенка мгновенно
... сть надежный способ почти мгновенно успокоить ребенка. YouTube В следующий раз, когда вы опаздываете с плачущим младенцем, может быть простой и надежный способ успокоить их. Это называется " Трюм "И это было усовершенствовано Доктор Роберт Гамильтон из Тихоокеанская педиатрия в Санта-Монике,
Веб-программирования. Что такое кроссбраузерность?
Для просмотра интернет-сайтов пользователи сети Интернет используют специальные программы - браузеры. Еще несколько лет назад посетителям интернета были известны лишь один-два разные браузеры, то теперь число таких программ исчисляется десятками, особенно, если учитывать, что каждая из них имеет несколько версий, отличающихся по функциональности. В связи с этим появилось понятие кроссбраузерности
Как перейти с одного аккаунта Google на другой?
В настоящее время учетная запись Google - это не только почта Gmail, но и видео YouTube, история разговоров в чате, учетная запись Google+, контакты, сохраненные события в календаре и т. Д. После нескольких лет интенсивного использования наша база данных, безусловно, впечатляет, и трудно просто оставить все это, а затем создать новую, совершенно новую и пустую учетную запись. Иногда изменение адреса электронной почты - это не просто прихоть, а требование, вызванное сменой должности, имени
Список прокси-серверов Германии
... как номер порта прокси, страна происхождения прокси и уровень анонимности прокси. Примечание . Если вы не знаете, что означает любое из этих чисел или как вообще использовать прокси-серверы, прокрутите страницу вниз. Уровни анонимности прокси Более подробное объяснение специфики можно найти на нашем объясненные уровни прокси страница, но
Инструменты, которые помогут вам администрировать службы Microsoft Online / Office 365, часть 1
... d, Excel, PowerPoint, OneNote, Publisher Office Online - приложения Office, доступные через веб-браузер Офисный пакет для мобильных телефонов Управление Microsoft Online доступно как через веб-браузер - с помощью панели администрирования, так и с помощью консоли PowerShell. Документация, размещенная на веб-сайтах Microsoft, в частности на Technet, описывающая, как настроить службы, является исчерпывающей. Тем не менее, он предполагает правильную
Модульные наборы кухонной мебели - все, что нам нужно знать, часть. II
... редней полки» - как изготавливаются модули"> Кухонная мебель из «средней полки» - как изготавливаются модули? или модульные наборы кухонной мебели всегда должно быть хуже, чем то, что мы будем делать по размеру? Так не должно быть. Среди доступных коллекций
Антивирусные приложения для Android бесполезны - вот что нужно сделать вместо этого - ExtremeTech
Этот сайт может зарабатывать партнерские комиссии по ссылкам на этой странице. Условия эксплуатации , Android вырос, чтобы стать крупнейшей вычислительной платформой на планете, и это делает его целью. Вы не можете проводить много времени в интернете, не услышав о какой-то новой Android вредоносная программа, которая определенно разрушит ваш телефон. Эти отчеты всегда
Windows предлагает несколько встроенных инструментов для удаленной помощи через Интернет. Эти инстр...
Windows предлагает несколько встроенных инструментов для удаленной помощи через Интернет. Эти инструменты позволяют вам дистанционно управлять компьютером другого человека, чтобы вы могли помочь ему устранить его, пока вы разговариваете
FireWire
... как можно получить полностью работающую настройку FireWire, используя либо одну приставку, либо несколько блоков с последовательным подключением. Стеки Firewire, старые против новых Существует два стека FireWire. Более старый стек "ieee1394", а более новый - "juju". В зависимости от используемого дистрибутива Linux и его версии, вы можете использовать один или другой стек. Не рекомендуется использовать оба стека одновременно. Вы можете подтвердить, что используете
... ds/2019/12/ru-zapret-na-ispolzovanie-mobilnyh-telefonov-na-rabote-mozet-povysit-bezopasnost-truda-posmotrite-kak-eto-sdelat-1.png"...
... ds/2019/12/ru-zapret-na-ispolzovanie-mobilnyh-telefonov-na-rabote-mozet-povysit-bezopasnost-truda-posmotrite-kak-eto-sdelat-1.png" alt="Опрос SRP © был проведен в апреле и мае 2018 года компанией Marketing Relacji Sp"> Опрос SRP © был проведен в апреле и мае 2018 года компанией Marketing Relacji Sp. z o. o. среди клиентов четырех сайтов « Знания и практика» : www.portalfk.pl, www.portalkadrowy.pl, www.portalbhp.pl и www.portaloswiatowy.pl. Интервьюеры задали вопрос
... пециалиста для создания своего интернет-магазина? Если вы не программист и обладаете ограниченными тех...
... пециалиста для создания своего интернет-магазина? Если вы не программист и обладаете ограниченными техническими знаниями, трудоустройство может вызвать проблемы. Мы здесь, чтобы помочь вам! Чтобы помочь вам принять лучшее решение, мы составили список из 10 вопросов к задаче, прежде чем создать программист электронной коммерции для создания интернет-магазина. Убедитесь, что вы знаете ответы на эти вопросы, прежде чем тратить время и тратить деньги.

Комментарии

Как безопасно оплатить онлайн?
Как безопасно оплатить онлайн? PayPal и Allegro вернут деньги PayPal предлагает так называемые программа защиты покупателя. Если товары, за которые мы заплатили с помощью системы PayPal, не доходят до нас, компания возместит деньги вместе со стоимостью доставки. Вы также можете рассчитывать на возврат, если отправленный товар значительно отличается от описания на странице, например, мы заказали новый продукт, привыкли, он должен был быть оригинальным, а поддельный или поврежденный был
4. Как мы будем связываться друг с другом?
4. Как мы будем связываться друг с другом? Этот вопрос часто упускается из виду, но очень важно установить средства коммуникации в процессе создания вашего сайта. Вы хотите участвовать во всем процессе, а не только когда он завершен. Решите, будете ли вы использовать Skype, Google Hangout или MSN для регулярных разговоров. Я определенно рекомендую использовать инструмент управления проектами, такой как асана или Basecamp
Как люди с таким именем жили в прошлом, и что это имя будет значить для будущего вашего ребенка?
Как люди с таким именем жили в прошлом, и что это имя будет значить для будущего вашего ребенка? Johnson's Baby, DM9DBB и UNIT9 создали инструмент, который отвечает на эти вопросы. Здравствуйте, My Name Means собирает данные в режиме реального времени с ведущих в мире сайтов социальных сетей, чтобы предсказать будущее имени ребенка. «Hello, My Name Means» - это микросайт HTML5, использующий преимущества сложных API для компиляции и анализа больших наборов данных из 5 независимых источников.
Но как насчет внутренних ценностей?
Но как насчет внутренних ценностей? Huawei снова полагается на восьмиъядерный процессор HiSilicon Kirin 930 в P8. Собственный процессор состоит из четырех быстрых ядер - два гигагерца и четырех медленных ядер - 1,5 ГГц. При размере трех гигабайт памяти достаточно большой. Тем не менее, внутренняя память, вероятно, будет немного больше - всего 16 ГБ измеряет это (модель на 64 ГБ все еще будет следовать). Из них пользователю по-прежнему доступно чуть более 9 ГБ. Для компенсации память может быть
Но то, что вы действительно хотите знать, это как видео, верно?
Но то, что вы действительно хотите знать, это как видео, верно? Выше приведен пример видео, снятого на Hero4 Black, отредактированный и экспортированный с помощью бесплатного программного обеспечения GoPro Studio компании. (Примечание: звук не воспроизводится до последних 25 секунд видео.) Качество фантастическое, а сюжеты при слабом освещении и ночные особенно хороши, учитывая размер камеры и ее сенсора. Вы можете выбрать их дизайн, время автономной работы и функции, но видео выглядит
Q: Как я могу стать Золотым Участником?
Q: Как я могу стать Золотым Участником? Если вы решите подписаться или продолжить подписку на Star Trek Online, вы автоматически станете золотым участником. Если вы являетесь пожизненным подписчиком, вас также считают золотым участником. Если вы не являетесь золотым участником, но хотели бы стать им, вы можете подписаться через страницы управления учетной записью на этом официальном веб-сайте. В: В настоящее время я постоянный или пожизненный подписчик Star Trek
Что такое сетевой комплект Powerline?
Что такое сетевой комплект Powerline? Для тех, кто не знаком с этой технологией, сеть Powerline Network использует имеющиеся в вашем доме силовые провода в качестве проводной сети. Один адаптер подключится к сетевой розетке рядом с маршрутизатором, и вы подключите адаптер к маршрутизатору с помощью кабеля Ethernet. Затем подключите другой адаптер к электрической розетке в любой комнате и подключите его к оборудованию в этой комнате с помощью другого кабеля Ethernet. Провода питания
А как насчет других цветов?
А как насчет других цветов? ЗЕЛЕНЫЙ и ЖЕЛТЫЙ они также имеют значение! Кислородная диета Мы заботимся о том, чтобы научить вас новым, здоровым привычкам питания и осознанно выбирать лучшие продукты для вашего тела. Все меню и диеты, разработанные OXY, основаны на высококачественных, необработанных
Как они поддерживают эту теорию?
Как они поддерживают эту теорию? На рисунке ниже показаны как макро, так и микропробелы на старой странице новостного сайта BBC. Зеркальные бумажные газеты, новостные сайты, как правило, редко используют пустое пространство. Вместо этого они показывают свои правдоподобие через это большое количество контента на странице. Они отражают, как «происходит» наш мир!
Но с другой стороны, когда я должен загружать эти часы, как не ночью ?
Но с другой стороны, когда я должен загружать эти часы, как не ночью ?! Ведь я не буду делать это днем, потому что проверил, что такой цикл зарядки длится от полутора до двух часов. Я не буду просыпаться ночью, чтобы вытащить его из зарядного устройства. Тем более, что с этого момента до утра я бы наверняка потерял несколько процентов батареи, о чем свидетельствует тот факт, что устройство ест батарею даже лежа и ничего не делая (за 14 часов оно потеряло 17% батареи, что дает примерно один процент
Как начать бизнес веб-хостинга?
Как начать бизнес веб-хостинга? Трудно начать бизнес веб-хостинга, если у вас нет денег, чтобы открыть центр обработки данных. Тем не менее, вы можете перепродать веб-хостинг с планом посредника с более крупным поставщиком. Читайте наш лучший реселлер хостинга руководство, чтобы узнать больше. Что такое пропускная способность в веб-хостинге? Пропускная способность -

Видите тонкие зеленые линии, нарисованные вокруг экрана?
Звучит сложно, правда?
Куда пойти отсюда?
Что такое кроссбраузерность?
?редней полки» - как изготавливаются модули"> Кухонная мебель из «средней полки» - как изготавливаются модули?
Или модульные наборы кухонной мебели всегда должно быть хуже, чем то, что мы будем делать по размеру?
?пециалиста для создания своего интернет-магазина?
?пециалиста для создания своего интернет-магазина?
Как безопасно оплатить онлайн?
4. Как мы будем связываться друг с другом?