В этом руководстве представлен обзор новых функций платформы SpriteKit, представленных в iOS 8. Новые функции призваны упростить поддержку расширенных игровых эффектов и включают поддержку пользовательских шейдеров фрагментов OpenGL ES, освещения, теней, новых расширенных возможностей. физические эффекты и анимация, а также интеграция со SceneKit. В этом руководстве вы узнаете, как реализовать эти новые функции.
Прежде чем приступить к обучению , я хотел бы поблагодарить Мелоди Дешанс ( Wicked Cat ) за предоставление нам игрового искусства, использованного в этой серии.
Предпосылки
В этом руководстве предполагается, что вы знакомы как с Spr IteKit, так и с Objective-C. Чтобы взаимодействовать с шейдером и редактором сцены без задержки ввода, я рекомендую вам загрузить и установить Xcode 6.1 или более позднюю версию. Загрузите проект Xcode с GitHub , если хотите подписаться.
Формат серии
Эта серия разделена на два руководства и охватывает самые важные новые функции платформы SpriteKit. В первой части мы рассмотрим шейдеры, освещение и тени. Во второй части я расскажу об интеграции физики и SceneKit.
В то время как каждая часть этой серии стоит отдельно, я рекомендую следовать шаг за шагом, чтобы правильно понять новые возможности платформы SpriteKit. Прочитав обе части, вы сможете создавать как простые, так и более сложные игры, используя новые функции платформы SpriteKit.
1. Введение
SpriteKit предоставляет конвейер рендеринга, который можно использовать для анимации спрайтов. Конвейер рендеринга содержит цикл рендеринга, который чередуется между определением содержимого и фреймами рендеринга. Разработчик определяет содержимое каждого фрейма и то, как он изменяется. SpriteKit использует графический процессор устройства для эффективной визуализации каждого кадра.
Платформа SpriteKit доступна как для iOS, так и для OS X, и поддерживает множество различных видов контента, включая спрайты, текст, фигуры и видео.
Новые функции SpriteKit, представленные в iOS 8:
-
Шейдеры: шейдеры настраивают способ рисования объектов на экране. Они полезны для добавления или изменения эффектов. Шейдеры основаны на фрагментном шейдере OpenGL ES. Каждый эффект применяется для каждого пикселя. Вы используете C-подобный язык программирования для программирования шейдера, и его можно развернуть как на iOS, так и на OS X. Шейдер можно применить к сцене или поддерживаемым классам,
SKSpriteNode
,SKShapeNode
,SKEmitterNode
,SKEffectNode
иSKScene
.
- Освещение и тени: Освещение используется для освещения сцены или спрайта. Каждый источник света поддерживает цвет, тени и конфигурации с падением. Вы можете иметь до восьми различных источников света на спрайт.
- Физика. Физика используется для придания реалистичности играм. SpriteKit представляет четыре новых типа физических свойств: физику на пиксель, ограничения, обратную кинематику и физические поля. Свойства для каждого пикселя обеспечивают точное представление взаимодействия объекта. Благодаря множеству предопределенных ограничений, шаблон кода может быть удален в обновлениях сцены. Обратная кинематика используется для представления соединений с использованием спрайтов (опорные точки, отношения родитель-ребенок, максимальное и минимальное вращение и т. Д.). Наконец, вы можете создавать физические поля для имитации гравитации, сопротивления и электромагнитных сил. Эти новые физические функции значительно упрощают реализацию сложных симуляций.
- Интеграция с SceneKit: С помощью SceneKit вы можете включать 3D-контент в приложения SpriteKit и управлять ими, как обычные экземпляры
SKNode
. Он визуализирует 3D-контент непосредственно внутри конвейера рендеринга SpriteKit. Вы можете импортировать существующие файлыSKScene
или .abc вSKScene
.
2. Обзор проекта
Я создал проект XCode, чтобы начать нас. Это позволяет нам немедленно начать использовать новые функции SpriteKit. Однако есть несколько вещей, о которых нужно знать.
- В проекте используется Objective-C, ориентированный только на устройства iPhone с iOS 8.1. Тем не менее, вы можете изменить целевое устройство, если хотите.
- В разделе Ресурсы > Редактор вы найдете три файла сцены SpriteKit (.sks). В этой серии вы добавите четвертый файл сцены SpriteKit. Каждый файл сцены отвечает за определенный учебный раздел.
- Шейдер может быть инициализирован одним из двух способов. Первый использует традиционный метод, в то время как второй использует новый метод сцены SpriteKit. Цель состоит в том, чтобы вы узнали о различиях и в будущих проектах выбрали тот, который соответствует вашим потребностям.
- Если вы создаете экземпляр объекта
SKScene
с использованием файла сцены SpriteKit, вы всегда будете использовать методunarchiveFromFile:
. Однако обязательно добавьте для каждого файла сценыSKScene
соответствующий классSKScene
. - Если вы создаете экземпляр объекта
SKScene
без использования файла сцены SpriteKit, вам следует использовать методinitWithSize:
который вы использовали в предыдущих версиях iOS. -
GameViewController
иGameScene
содержат метод с именемunarchiveFromFile:
Этот метод преобразует графические объекты, определенные в сцене SpriteKit, и превращает их в объектSKScene
. Метод использует ключевое словоinstancetype
, так как он возвращает экземпляр класса, который он вызывает, в данном случае классSKScene
.
Загрузите проект и найдите время, чтобы просмотреть его папки, классы и ресурсы. Создайте и запустите проект на физическом устройстве или в симуляторе iOS. Если приложение работает без проблем, то пришло время начать исследовать новые функции iOS 8 SpriteKit.
3. Шейдеры
Шаг 1. Создание сцены SpriteKit
В проекте Xcode добавьте новый файл сцены SpriteKit . Выберите « Файл» > « Создать» > « Файл …» и в разделе « Ресурсы » выберите « SpriteKit Scene» . Назовите его ShaderSceneEditor
и нажмите « Создать» . Должен появиться серый интерфейс.
Шаг 2: Настройка сцены SpriteKit
В SKNode Inspector справа вы должны увидеть два свойства: Размер и Гравитация . Установите свойство Size с учетом разрешения экрана вашего устройства и установите Gravity на 0.0
.
Вы заметите, что размер желтого прямоугольника меняется, чтобы отразить сделанные вами изменения. Желтый прямоугольник — это интерфейс вашего виртуального устройства. Он показывает вам, как объекты отображаются на вашем устройстве.
Шаг 3: Добавьте Цветной Спрайт
Внутри библиотеки объектов справа выберите Color Sprite и перетащите его в желтый прямоугольник.
Выберите цветной спрайт и откройте SKNode Inspector справа, чтобы увидеть его свойства.
Вы можете взаимодействовать с объектом в режиме реального времени. Любые сделанные вами изменения отображаются в редакторе. Вы можете играть с Позицией , Размером , Цветом или Масштабом , но то, что вы действительно хотите, это опция Custom Shader . Однако вы заметите, что шейдеров пока нет.
Шаг 4: Добавьте пользовательский шейдер: метод 1
Добавьте новый пустой исходный файл (« Файл» > «Создать»> « Файл …» ), выберите « Другой» > «Пустой» в разделе iOS и назовите его Shader01.fsh . Добавьте следующий код в файл, который вы только что создали.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
void main()
{
float currTime = u_time;
vec2 uv = v_tex_coord;
vec2 circleCenter = vec2(0.5, 0.5);
vec3 circleColor = vec3(0.8, 0.5, 0.7);
vec3 posColor = vec3(uv, 0.5 + 0.5 * sin(currTime)) * circleColor;
float illu = pow(1. — distance(uv, circleCenter), 4.) * 1.2;
illu *= (2. + abs(0.4 + cos(currTime * -20. + 50. * distance(uv, circleCenter)) / 1.5));
gl_FragColor = vec4(posColor * illu * 2., illu * 2.) * v_color_mix.a;
}
|
Приведенный выше кодовый блок генерирует сочетание цветов с учетом центра круга и его края. Apple показала этот шейдер в своей сессии SpriteKit во время WWDC 2014 .
Вернитесь в редактор, выберите объект цветового спрайта и в пользовательском шейдере выберите только что созданный шейдер. Теперь вы должны увидеть шейдер в действии.
Шаг 5: Обратная связь в реальном времени
Программирование шейдеров с использованием Xcode и SpriteKit легко, потому что вы получаете обратную связь в реальном времени. Откройте редактор Assistant и настройте его так, чтобы он отображал как сцену SpriteKit, так и только что созданный вами шейдер.
Посмотрим, как это работает. Введите ошибку времени выполнения в шейдер, например, изменив имя переменной и сохраните изменения, чтобы увидеть результат.
Как вы можете видеть, Xcode предоставляет быстрый и простой способ предупредить разработчика о возможных ошибках шейдеров. Преимущество заключается в том, что вам не нужно создавать или развертывать приложение на своем устройстве или в iOS Simulator, чтобы посмотреть, все ли работает нормально.
Пришло время добавить еще один шейдер и запрограммировать его вручную.
Шаг 6: Добавьте пользовательский шейдер: метод 2
На этом этапе вы узнаете, как:
- вызвать шейдер вручную
- назначить шейдер объекту SpriteKit
- создавать и отправлять свойства в шейдер
На этом шаге вы добавите пользовательский SKSpriteNode
в положение касания пользователя, а затем будете использовать шейдер для изменения цвета текстуры SKSpriteNode
.
Первый шаг — добавить еще один шейдер. Назовите новый шейдер shader02.fsh и добавьте следующий блок кода в файл шейдера:
1
2
3
4
|
void main()
{
gl_FragColor = texture2D(myTexture,v_tex_coord) * vec4(1, 0.2, 0.2, 1);
}
|
Откройте файл ShaderScene
класса ShaderScene
. Первым шагом является определение, коснулся ли пользователь экрана, и определение местоположения касания. Для этого нам нужно реализовать метод touchesBegan:withEvent:
Внутри этого метода добавьте экземпляр SKSpriteNode
в месте крана. Вы можете использовать любой спрайт, который вам нравится. Я использовал Spaceship.png , который уже включен в проект.
01
02
03
04
05
06
07
08
09
10
|
— (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches){
CGPoint location = [touch locationInNode:self];
// Create the node
SKSpriteNode *space = [SKSpriteNode spriteNodeWithImageNamed:@»Spaceship.png»];
space.position = CGPointMake(location.x, location.y);
[self addChild:space];
}
}
|
Затем мы создаем объект SKShader
и инициализируем его с помощью файла shader02.fsh :
1
|
SKShader *shader = [SKShader shaderWithFileNamed:@»shader02.fsh»];
|
Возможно, вы заметили, что исходный файл шейдера ссылается на объект myTexture
. Это не предопределенное свойство шейдера, но ссылка, которую ваше приложение должно передать шейдеру. Следующий фрагмент кода иллюстрирует, как это сделать.
1
|
shader.uniforms = @[ [SKUniform uniformWithName:@»myTexture» texture:[SKTexture textureWithImageNamed:@»Spaceship.png»]] ];
|
Затем мы добавляем шейдер в объект SKSpriteNode
.
1
|
space.shader = shader;
|
Вот как должен выглядеть метод touchesBegan:withEvent:
::
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
— (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches){
CGPoint location = [touch locationInNode:self];
// Create the node
SKSpriteNode *space = [SKSpriteNode spriteNodeWithImageNamed:@»Spaceship.png»];
space.position = CGPointMake(location.x, location.y);
[self addChild:space];
SKShader *shader = [SKShader shaderWithFileNamed:@»shader02.fsh»];
shader.uniforms = @[ [SKUniform uniformWithName:@»myTexture» texture:[SKTexture textureWithImageNamed:@»Spaceship.png»]] ];
space.shader = shader;
}
}
|
Создайте и запустите свой проект. Нажмите кнопку Shaders (initWithSize) и коснитесь экрана. Каждый раз, когда вы нажимаете на экран, спрайт космического корабля добавляется с измененной текстурой.
Используя эту опцию, вы видите, что первый шейдер не представлен на экране. Это происходит потому, что этот шейдер был создан и настроен в редакторе сцен SpriteKit. Чтобы увидеть это, вам нужно инициализировать класс ShaderScene
используя метод ShaderScene
unarchiveFromFile:
.
В GameScene.m вы должны увидеть раздел, который обнаруживает и анализирует нажатия пользователя в touchesBegan:withEvent:
Во втором предложении if
мы инициализируем экземпляр ShaderScene
как показано ниже.
1
2
3
4
|
if ([node.name isEqualToString:@»buttonShaderCoder»]) {
ShaderScene *scene = [ShaderScene unarchiveFromFile:@»ShaderSceneEditor»];
[self.scene.view presentScene:scene];
}
|
Создайте и запустите свой проект снова, нажмите кнопку Shaders (initWithCoder) и коснитесь экрана. Оба шейдера теперь активны в одной сцене SpriteKit.
4. Освещение и тени
Освещение и тени — это два свойства, которые играют вместе. Цель этого раздела — добавить несколько легких узлов и спрайтов и поиграть с их свойствами.
Шаг 1: Добавьте свет
Откройте LightingSceneEditor.sks и просмотрите объекты внутри библиотеки мультимедиа справа. В библиотеке мультимедиа вы можете увидеть ресурсы, включенные в проект.
Выберите и перетащите background.jpg к желтому прямоугольнику. Если вы не изменили разрешение сцены по умолчанию, изображение должно поместиться внутри прямоугольника.
Когда вы выберете спрайт, вы заметите, что он имеет несколько свойств, таких как Положение , Размер , Положение Z , Маска освещения, Маска литья тени , Определение физики и многие другие.
Не стесняйтесь играть с этими свойствами. Однако сейчас важно, чтобы вы оставили свойства по умолчанию. Перетащите объект Light из библиотеки объектов справа на фоновый спрайт. Положение света не важно, но есть и другие свойства света.
Вы можете настроить цвет , тень и цвет окружающей среды, чтобы настроить свет и тень. Z Position — высота узла относительно его родительского узла. Установите его в 1 . Маска освещения определяет, к каким категориям относится этот свет. При визуализации сцены свойство categoryBitMask
источника света сравнивается со свойствами lightingBitMask
, shadowCastBitMask
и shadowCastBitMask
каждого узла спрайта. Если значения совпадают, этот спрайт взаимодействует со светом. Это позволяет вам определять и использовать несколько источников света, которые взаимодействуют с одним или несколькими объектами.
Вы, наверное, заметили, что фон не изменился после добавления света. Это происходит из-за того, что маска освещения и фона различна. Вам нужно установить маску освещения фона на ту, что у источника света, которая в нашем примере равна 1 .
Обновите фон в Инспекторе SKNode и нажмите Enter. Эффект этого изменения является немедленным. Свет теперь освещает фон в зависимости от его положения. Вы можете изменить положение источника света, чтобы видеть взаимодействие между фоном и узлами источника света в режиме реального времени.
Чтобы повысить реалистичность фона или подчеркнуть одну из его особенностей, поиграйте со свойствами плавности и контрастности . Поиграйте со значениями, чтобы увидеть изменения в реальном времени.
Шаг 2: Заполните сцену
Пришло время добавить несколько объектов, которые взаимодействуют с узлом света. В библиотеке мультимедиа найдите спрайты croquette -o.png и croquette-x.png и добавьте их в сцену.
Каждый спрайт должен быть настроен индивидуально. Выберите каждый спрайт и установите маску освещения, маску тени и Положение Z до 1 . Осветительная маска обеспечивает воздействие на спрайт светового узла, в то время как маска отбрасывания теней создает тень в реальном времени на основе положения светового узла. Наконец, установите для параметра « Тип тела» ( определение физики ) значение « Нет» . Сделайте это для обоих спрайтов.
Вы должны были заметить, что даже после настройки свойств освещения и тени вы не можете видеть взаимодействие между светом и узлами. Для этого вам нужно собрать и запустить проект на физическом устройстве или в симуляторе.
Шаг 3: Ручное освещение
Вы уже знаете, как добавить источники света, используя редактор сцен. Давайте посмотрим, как добавить источник света без использования редактора сцены.
Откройте LightingScene.m и внутри didMoveToView:
метод мы создаем объект SKLightNode
объект SKLightNode
.
Для объекта SKSpriteNode
мы используем спрайт Wicked-Cat.png . Положение узла не так важно, но значения zPosition
, shadowCastBitMask
и lightingBitMask
являются. Поскольку SpriteKit анализирует данные последовательно, вам нужно установить zPosition
узла в 1
чтобы этот спрайт был виден поверх фонового спрайта. Мы устанавливаем shadowCastBitMask
и lightingBitMask
в 1
.
Вот как выглядит метод didMoveToView:
:
1
2
3
4
5
6
7
8
9
|
— (void)didMoveToView:(SKView *)view {
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:@»Wicked-Cat.png»];
[sprite setPosition:CGPointMake(self.frame.size.width/2, self.frame.size.height/2)];
[sprite setScale:0.6];
[sprite setZPosition:1];
[sprite setShadowCastBitMask:1];
[sprite setLightingBitMask:1];
[self addChild:sprite];
}
|
Далее давайте добавим объект SKLightNode
. Вы должны обратить особое внимание на свойство categoryBitMask
. Если вы установите его на 1
, этот свет будет взаимодействовать с каждым спрайтом. Назовите его light
и установите zPosition
на 1
.
Полный фрагмент SKLightNode
должен выглядеть следующим образом:
01
02
03
04
05
06
07
08
09
10
|
SKLightNode* light = [[SKLightNode alloc] init];
[light setName:@»light»];
[light setPosition:CGPointMake(100, 100)];
[light setCategoryBitMask:1];
[light setFalloff:1.5];
[light setZPosition:1];
[light setAmbientColor:[UIColor whiteColor]];
[light setLightColor:[[UIColor alloc] initWithRed:1.0 green:0.0 blue:0.0 alpha:.5]];
[light setShadowColor:[[UIColor alloc] initWithRed:0.9 green:0.25 blue:0.0 alpha:.5]];
[self addChild:light];
|
Шаг 4: измените местоположение источника света
На данный момент у вас есть второй свет. Но давайте добавим немного взаимодействия с пользователем. Для этого вам нужно добавить метод touchesMoved:withEvent:
и изменить положение источника света с учетом местоположения касания.
1
2
3
4
5
6
|
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
[self childNodeWithName:@»light»].position = CGPointMake(location.x, location.y);
}
}
|
В заключение, соберите и запустите ваше приложение. Нажмите кнопку « Освещение» , и вы увидите нечто похожее на скриншот ниже:
Вывод
На этом мы завершаем первое руководство из нашей серии из двух частей, посвященное новым функциям платформы SpriteKit, представленным в iOS 8. В этой части вы научились создавать собственные шейдеры и световые эффекты с помощью редактора сцен SpriteKit и с помощью кода. Если у вас есть какие-либо вопросы или комментарии, как всегда, не стесняйтесь оставлять комментарии в комментариях.