Вскакивание в набор Sprite
Лучший способ изучить Набор Sprite состоит в том, чтобы видеть его в действии. Этот пример создает пару сцен и анимирует содержание в каждом. Путем работы через этот пример Вы изучите некоторые фундаментальные методы для работы с содержанием Набора Sprite, включая:
Используя сцены в Sprite Основанная на наборе игра.
Организация деревьев узла для рисования содержания.
Используя действия для анимации содержания сцены.
Добавление интерактивности к сцене.
Переход между сценами.
Моделирование физики в сцене.
После окончания этого проекта можно использовать его для испытания других понятий Набора Sprite. Некоторые предложения могут быть найдены в конце этого примера.
Необходимо уже быть знакомы с созданием приложений для iOS прежде, чем работать через этот проект. Для получения дополнительной информации посмотрите, Начинают Разрабатывать приложения для iOS Сегодня. Большая часть кода Набора Sprite в этом примере является тем же на OS X.
Начало работы
Этот сквозной контроль требует Xcode 5.0. Создайте новый проект XCode для приложения для iOS с помощью Единственного Шаблона приложений Представления.
Используйте следующие значения при создании проекта:
Название продукта:
SpriteWalkthrough
Префикс класса:
Sprite
Устройства: iPad
Создание первой сцены
Содержание Набора Sprite помещается в окно, точно так же, как другое визуальное содержание. Содержание Набора Sprite представляется SKView
класс. Содержание, что SKView
объектный рендеринг вызывают сценой, которая является SKScene
объект. Сцены участвуют в цепочке респондента и имеют другие функции, делающие их подходящими для игр.
Поскольку содержание Набора Sprite представляется объектом представления, можно объединить это представление с другими представлениями в иерархии представления. Например, можно использовать средства управления стандартной кнопкой и разместить их выше представления Sprite Kit. Или, можно добавить интерактивность к спрайтам для реализации собственных кнопок; выбор ваше дело. Позже в этом примере, Вы будете видеть, как реализовать интерактивность на сцене.
Откройте раскадровку для проекта. Это имеет единственный контроллер представления (
SpriteViewController
). Выберите представление контроллера представления, возражают и изменяют его классSKView
.Добавьте строку импорта к файлу реализации контроллера представления.
#import <SpriteKit/SpriteKit.h>
Реализуйте контроллер представления
viewDidLoad
метод для конфигурирования представления.- (void)viewDidLoad
{
[super viewDidLoad];
SKView *spriteView = (SKView *) self.view;
spriteView.showsDrawCount = YES;
spriteView.showsNodeCount = YES;
spriteView.showsFPS = YES;
}
Код включает диагностическую информацию, описывающую, как сцена представляет представление. Самые важные данные являются частотой кадров (
spriteView.showsFPS
); Вы хотите, чтобы Ваши игры работали в постоянной частоте кадров, когда это возможно. Другие строки показывают подробные данные о том, сколько узлов было выведено на экран в представлении и сколько рисования передач потребовалось для рендеринга содержания (меньше лучше).
Затем, добавьте первую сцену.
Создайте новый названный класс
HelloScene
и сделайте его подклассомSKScene
класс.Заголовочный файл, создаваемый XCode, имеет следующее содержание:
#import <SpriteKit/SpriteKit.h>
@interface HelloScene : SKScene
@end
Вы не должны изменять заголовочный файл.
Импортируйте заголовочный файл сцены в своем файле реализации контроллера представления.
#import "HelloScene.h"
Измените контроллер представления, чтобы создать сцену и представить сцену в представлении.
- (void)viewWillAppear:(BOOL)animated
{
HelloScene* hello = [[HelloScene alloc] initWithSize:CGSizeMake(768,1024)];
SKView *spriteView = (SKView *) self.view;
[spriteView presentScene: hello];
}
Создайте и выполните проект.
Приложение должно запустить и вывести на экран экран, который является пробелом за исключением диагностической информации.
Добавление содержания к сцене
При разработке Sprite Основанная на наборе игра Вы разрабатываете различные классы сцены для каждого главного блока Вашего игрового интерфейса. Например, Вы могли бы создать сцену для главного меню и отдельную сцену для Вашего геймплея. Вы будете следовать подобному проекту здесь. Эта первая сцена выводит на экран традиционное “Привет Мировой” текст.
Чаще всего Вы конфигурируете содержание сцены, когда оно сначала представлено представлением. Это подобно способу, которым контроллеры представления загружают свои представления только когда view
на свойство ссылаются. В этом примере код живет в didMoveToView:
метод, который вызывают каждый раз, когда сцена представлена в представлении.
Добавьте новое свойство к файлу реализации сцены, чтобы отследить, создала ли сцена свое содержание. Ваш файл реализации должен быть похожим на это:
#import "HelloScene.h"
@interface HelloScene ()
@property BOOL contentCreated;
@end
@implementation HelloScene
@end
Информация о дорожках свойства, которая не должна быть представлена клиентам, таким образом, она реализована в объявлении закрытого интерфейса в файле реализации.
Реализуйте сцену
didMoveToView:
метод.- (void)didMoveToView: (SKView *) view
{
if (!self.contentCreated)
{
[self createSceneContents];
self.contentCreated = YES;
}
}
didMoveToView:
метод вызывают каждый раз, когда сцена представлена представлением, но в этом случае, содержание сцены должно только быть сконфигурировано в первый раз, когда сцена представлена. Так, этот код использует ранее определенное свойство (contentCreated
) отслеживать, было ли уже инициализировано содержание сцены.Реализуйте сцену
createSceneContents
метод.- (void)createSceneContents
{
self.backgroundColor = [SKColor blueColor];
self.scaleMode = SKSceneScaleModeAspectFit;
[self addChild: [self newHelloNode]];
}
Сцена красит область представления цветом фона прежде, чем привлечь его дочерние элементы. Отметьте использование
SKColor
класс для создания цветового объекта.Действительно,SKColor
не класс; это - макрос, отображающийся наUIColor
на iOS иNSColor
на OS X. Это существует для создания создающего межплатформенного кода проще.Режим масштаба сцены определяет, как сцена масштабируется для помещений в представление. В этом примере код масштабирует представление так, чтобы Вы видели все содержание сцены, с помощью добавляющий черные полосы сверху и снизу при необходимости.
Реализуйте сцену
newHelloNode
метод.- (SKLabelNode *)newHelloNode
{
SKLabelNode *helloNode = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
helloNode.text = @"Hello, World!";
helloNode.fontSize = 42;
helloNode.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));
return helloNode;
}
В Наборе Sprite Вы никогда не пишете код, явно выполняющий команды рисования, как Вы были бы при использовании OpenGL ES или 2D Кварц. Вместо этого Вы добавляете содержание путем создания объектов узла и добавления их к сцене. Все получение должно быть выполнено классами, предоставленными в Наборе Sprite. Можно настроить поведение тех классов произвести много различных графических эффектов. Однако путем управления всем получением, Набор Sprite может применить много оптимизации к тому, как выполняется получение.
Создайте и выполните проект.
Необходимо видеть «синий» экран с “Привет, Мир!” в нем. Вы теперь изучили основы для рисования содержания Набора Sprite.
Используя действия для анимации сцен
Статический текст хорош, но могло бы быть более интересно, если бы был анимирован текст. Большую часть времени Вы перемещаете вещи вокруг сцены путем выполнения действий. Большинство действий в Наборе Sprite применяет изменения в узле. Вы создаете объект действия для описания изменений, которые Вы хотите, и затем говорите узлу выполнять его. Затем когда сцена представляется, она выполняет действие, анимируя изменения по нескольким кадрам, пока не завершается действие.
Когда пользователь затрагивает в сцене, текст анимирует и затем исчезает.
Добавьте следующий код к
newHelloNode
метод:helloNode.name = @"helloNode";
Все узлы имеют a
name
свойство, которое можно установить для описания узла. Вы называете узел, когда Вы хотите быть в состоянии найти его позже или когда Вы хотите создать поведение, основывающееся на имени узла. Позже, можно искать дерево узлы, соответствующие имя.В этом примере Вы даете метке имя так, чтобы это могло быть обнаружено позже. В фактической игре Вы могли бы дать то же имя к любому узлу, представляющему тот же вид содержания. Например, если Ваша игра представляет каждого монстра как узел, Вы могли бы назвать узел
monster
.Переопределите
touchesBegan:withEvent:
метод на классе сцены. Когда сцена получает сенсорное событие, она считает узел названнымhelloNode
и говорит ему выполнять короткую анимацию.Все объекты узла являются подклассами
UIResponder
на iOS иNSResponder
на OS X. Это означает, что можно создать подклассы классов узла в Наборе Sprite для добавления интерактивности к любому узлу в сцене.- (void)touchesBegan:(NSSet *) touches withEvent:(UIEvent *)event
{
SKNode *helloNode = [self childNodeWithName:@"helloNode"];
if (helloNode != nil)
{
helloNode.name = nil;
SKAction *moveUp = [SKAction moveByX: 0 y: 100.0 duration: 0.5];
SKAction *zoom = [SKAction scaleTo: 2.0 duration: 0.25];
SKAction *pause = [SKAction waitForDuration: 0.5];
SKAction *fadeAway = [SKAction fadeOutWithDuration: 0.25];
SKAction *remove = [SKAction removeFromParent];
SKAction *moveSequence = [SKAction sequence:@[moveUp, zoom, pause, fadeAway, remove]];
[helloNode runAction: moveSequence];
}
}
Чтобы препятствовать тому, чтобы узел ответил на повторные нажатия, код очищает имя узла. Затем это создает объекты действия для выполнения различных действий. После создания всех действий это создает действие последовательности, комбинирующее эти действия вместе; когда последовательность работает, она выполняет каждое из дочерних действий в порядке. Наконец, метод говорит узлу метки выполнять последовательность.
Создайте и выполните проект.
Необходимо видеть текст как прежде. Внизу экрана количество узла должно быть
1
. Теперь, коснитесь в представлении. Необходимо видеть, что текст анимирует и исчезает. После того, как это исчезнет, количество узла должно измениться на0
, потому что узел был удален из родителя.
Переход между сценами
Набор Sprite упрощает переходить между сценами. Можно или иметь в наличии сцены постоянно или избавиться от них, когда Вы переходите между ними. В этом примере Вы создаете второй класс сцены для изучения некоторых других игровых способов поведения. Когда “Привет, Мир!” текст исчезает из экрана, код создает новую сцену и переходы к ней. Привет сцена отбрасывается после перехода.
Создайте новый названный класс
SpaceshipScene
и сделайте его подклассомSKScene
класс.Код реализации для инициализации содержания сцены космического корабля. Код в файле реализации новой сцены подобен коду, который Вы реализовали для
HelloScene
класс.#import "SpaceshipScene.h"
@interface SpaceshipScene ()
@property BOOL contentCreated;
@end
@implementation SpaceshipScene
- (void)didMoveToView:(SKView *)view
{
if (!self.contentCreated)
{
[self createSceneContents];
self.contentCreated = YES;
}
}
- (void)createSceneContents
{
self.backgroundColor = [SKColor blackColor];
self.scaleMode = SKSceneScaleModeAspectFit;
}
@end
Импортируйте
SpaceshipScene.h
заголовок вHelloScene.m
файл.#import "SpaceshipScene.h"
В
HelloScene
классtouchesBegan:withEvent:
метод, замените вызов кrunAction:
с новым вызовом кrunAction:completion:
. Реализуйте обработчик завершения, чтобы создать и представить новую сцену.[helloNode runAction: moveSequence completion:^{
SKScene *spaceshipScene = [[SpaceshipScene alloc] initWithSize:self.size];
SKTransition *doors = [SKTransition doorsOpenVerticalWithDuration:0.5];
[self.view presentScene:spaceshipScene transition:doors];
}];
Создайте и выполните проект.
Когда Вы затрагиваете в сцене, текст постепенно исчезает и затем переходы представления к новой сцене. Необходимо видеть черный экран.
Создание сложного содержания Используя узлы
Новая сцена еще не имеет никакого содержания, таким образом, Вы собираетесь добавить космический корабль к сцене. Для создания космического корабля необходимо использовать многократный SKSpriteNode
объекты создать космический корабль и световые сигналы на его поверхности. Каждый из узлов спрайта собирается выполнить действия.
Узлы Sprite являются наиболее распространенным классом, используемым для создания содержания в приложении Набора Sprite. Они могут или нарисовать нетекстурированные или текстурированные прямоугольники. В этом примере Вы собираетесь использовать нетекстурированные объекты. Позже, эти заполнители могли быть легко заменены текстурированными спрайтами, не изменяя их поведение. В фактической игре Вам, возможно, понадобились бы десятки или сотни узлов для создания визуального содержания игры. Но, существенно, те спрайты собираются использовать те же методы в качестве этого простого примера.
Несмотря на то, что Вы могли добавить все три спрайта непосредственно к сцене, которая не является Набором Sprite путь. Мигающие огни являются частью космического корабля! Если космический корабль перемещается, световые сигналы должны переместиться с ним. Решение состоит в том, чтобы сделать узел космического корабля их родителем, таким же образом что сцена будет родителем космического корабля. Координаты световых сигналов будут указанными относительно позиции родительского узла, которая является в центре изображения спрайта.
В
SpaceshipScene.m
, добавьте код кcreateSceneContents
метод для создания космического корабля.SKSpriteNode *spaceship = [self newSpaceship];
spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)-150);
[self addChild:spaceship];
Реализуйте
newSpaceship
метод.- (SKSpriteNode *)newSpaceship
{
SKSpriteNode *hull = [[SKSpriteNode alloc] initWithColor:[SKColor grayColor] size:CGSizeMake(64,32)];
SKAction *hover = [SKAction sequence:@[
[SKAction waitForDuration:1.0],
[SKAction moveByX:100 y:50.0 duration:1.0],
[SKAction waitForDuration:1.0],
[SKAction moveByX:-100.0 y:-50 duration:1.0]]];
[hull runAction: [SKAction repeatActionForever:hover]];
return hull; }
Этот метод создает оболочку космического корабля и добавляет к ней короткую анимацию. Обратите внимание на то, что новый вид действия был представлен. Повторяющееся действие постоянно повторяет, что действие передало ему. В этом случае последовательность повторяется неопределенно.
Создайте и выполните проект.
Необходимо видеть единственный прямоугольник для оболочки космического корабля.
Добавьте код к
newSpaceship
метод для добавления световых сигналов.Введите следующий код после строки, создающей спрайт оболочки.
SKSpriteNode *light1 = [self newLight];
light1.position = CGPointMake(-28.0, 6.0);
[hull addChild:light1];
SKSpriteNode *light2 = [self newLight];
light2.position = CGPointMake(28.0, 6.0);
[hull addChild:light2];
При создании сложных узлов, имеющих дочерние элементы, это - хорошая идея изолировать код, используемый для создания узла позади способа строительства или даже подкласса. Это упрощает изменять состав спрайта и поведение, не требуя изменений в клиентах, использующих спрайт.
Реализуйте
newLight
метод.- (SKSpriteNode *)newLight
{
SKSpriteNode *light = [[SKSpriteNode alloc] initWithColor:[SKColor yellowColor] size:CGSizeMake(8,8)];
SKAction *blink = [SKAction sequence:@[
[SKAction fadeOutWithDuration:0.25],
[SKAction fadeInWithDuration:0.25]]];
SKAction *blinkForever = [SKAction repeatActionForever:blink];
[light runAction: blinkForever];
return light;
}
Создайте и выполните проект.
Необходимо видеть пару световых сигналов на космическом корабле. Когда космический корабль перемещается, перемещение световых сигналов с ним. Все три узла постоянно анимируются. Вы могли добавить дополнительные действия для перемещения световых сигналов вокруг поставки; они всегда перемещались бы относительно оболочки поставки.
Создание узлов, взаимодействующих друг с другом
В фактической игре Вам обычно нужны узлы для взаимодействия друг с другом. Существует много способов добавить поведение к спрайтам, таким образом, этот пример показывает только одному из них. Вы будете добавлять новые узлы к сцене и использовать подсистему физики для моделирования их перемещения и эффектов коллизии реализации.
Набор Sprite обеспечивает полное моделирование физики, которое можно использовать для добавления автоматических способов поведения к узлам. Т.е. вместо того, чтобы выполнить действия с узлами, физика автоматически моделируется на узле, заставляя его переместиться. Когда это взаимодействует с другими узлами, которые являются частью системы физики, коллизии автоматически вычисляются и выполняются.
Изменитесь
newSpaceship
метод для добавления организации физики к космическому кораблю.hull.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:hull.size];
Создайте и выполните проект.
Космический корабль резко падает через нижнюю часть экрана. Это вызвано тем, что сила тяготения применяется к организации физики космического корабля. Даже при том, что действие перемещения все еще работает, эффекты физики также применяются к космическому кораблю.
Изменитесь
newSpaceship
метод, чтобы препятствовать тому, чтобы космический корабль был затронут взаимодействиями физики.hull.physicsBody.dynamic = NO;
При выполнении его теперь космический корабль больше не затрагивается силой тяжести, таким образом, это работает, как это сделало прежде. Позже, создание организации физики, статичной также, означает, что скорость космического корабля незатронута коллизиями.
Добавьте код к
createSceneContents
метод для порождения скал.SKAction *makeRocks = [SKAction sequence: @[
[SKAction performSelector:@selector(addRock) onTarget:self],
[SKAction waitForDuration:0.10 withRange:0.15]
]];
[self runAction: [SKAction repeatActionForever:makeRocks]];
Сцена является также узлом, таким образом, она может выполнить действия также. В этом случае пользовательское действие вызывает метод на сцене для создания скалы. Последовательность создает скалу, затем ожидает в течение случайного промежутка времени. Путем повторения этого действия сцена постоянно порождает новые скалы.
Реализуйте
addRock
метод.static inline CGFloat skRandf() {
return rand() / (CGFloat) RAND_MAX;
}
static inline CGFloat skRand(CGFloat low, CGFloat high) {
return skRandf() * (high - low) + low;
}
- (void)addRock
{
SKSpriteNode *rock = [[SKSpriteNode alloc] initWithColor:[SKColor brownColor] size:CGSizeMake(8,8)];
rock.position = CGPointMake(skRand(0, self.size.width), self.size.height-50);
rock.name = @"rock";
rock.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:rock.size];
rock.physicsBody.usesPreciseCollisionDetection = YES;
[self addChild:rock];
}
Создайте и выполните проект
Скалы должны теперь упасть от вершины сцены. Когда скала поражает поставку, горные возвраты от поставки. Никакие действия не были добавлены для перемещения скал. Скалы падают и сталкиваются с поставкой полностью вследствие подсистемы физики.
Скалы являются небольшими и перемещаются быстро, таким образом, код указывает точные коллизии, чтобы гарантировать, что обнаруживаются все коллизии.
При разрешении выполнению приложения некоторое время частота кадров начинает отбрасывать, даже при том, что количество узла остается очень низким. Это вызвано тем, что код узла только показывает видимые узлы в сцене. Однако, когда скалы проваливаются нижняя часть сцены, они продолжают существовать в сцене, что означает, что физика все еще моделируется на них. В конечном счете существует столько узлов, обрабатываемых, который замедляет Набор Sprite.
Реализуйте
didSimulatePhysics
метод в сцене, для удаления скал, когда они перемещаются вне экрана.-(void)didSimulatePhysics
{
[self enumerateChildNodesWithName:@"rock" usingBlock:^(SKNode *node, BOOL *stop) {
if (node.position.y < 0)
[node removeFromParent];
}];
}
Каждый раз, когда сцена обрабатывает кадр, она выполняет действия и моделирует физику. Ваша игра может сцепиться в этот процесс для выполнения другого пользовательского кода. Теперь, когда приложение обрабатывает новый кадр анимации, оно обрабатывает физику и затем удаляет любые скалы, отъехавшие нижняя часть экрана. При выполнении приложения частота кадров остается постоянной.
Пред - и последующая обработка в сцене, объединенной с действиями и физикой, места, Вы создаете поведение своей игры.
И вот именно — Ваш первый вкус Набора Sprite! Все остальное - улучшение основных методов, которые Вы видели здесь.
Попробуйте это!
Вот несколько вещей, которые можно попробовать:
Сделайте версию OS X этого примера. Код, который Вы записали в контроллере представления, часто реализуется в делегате приложения на OS X. Также необходимо изменить код респондента, чтобы использовать события от нажатия мыши, вместо того, чтобы коснуться событий. Но остальная часть кода должна быть тем же.
Используйте текстурированные спрайты для представления поставки и скал. (Подсказка: Работа со Спрайтами)
Попытайтесь переместить космический корабль в ответ на сенсорные события. (Подсказка: Добавление Действий к Узлам и Создания Вашей Сцены).
Добавьте другие способы поведения, когда скалы столкнутся с поставкой. Например, заставьте скалы взорваться. (Подсказка: Моделирование Физики)
Добавьте звуковые эффекты. (Подсказка: Используйте a
playSoundFileNamed:waitForCompletion:
действие)Добавьте дополнительные графические эффекты к сцене. (Подсказка: Работа со Спрайтами)