Создание игры на движке Sprite Kit (Часть 1)

С появлением IOS 7 мир узрел новый игровой движок от Apple — SpriteKit. В свете того, что он появился совсем недавно об этом движке еще мало что написано, конечно в сети можно найти несколько tutorial -ов по нему, но в основном все они на Английском языке. И по этому я задалась целью написать подробный Туториал об этом замечательном движке. SpriteKit — это 2D движок, оптимизированный для создание игр для устройств от компании Apple. В его основе лежит популярный физический движок Box 2D. Поскольку разработчики создавали его заточенным специально для устройств Apple он существенно выигрывает в скорости у остальных движков.В SpriteKit всю роль по оптимизации и рисованию графики берет на себя OpenGl, это все происходит на низком уровне и по этому вы можете сосредоточить свои усилия на решении проблем более высокого уровня и создание больших 2D игр. Для создание игр на SpriteKit используется язык Objective-c, но с выходом IOS 8 и нового языка Swift, игры также можно создавать и на нем.От себя хотела бы добавить, что в некотором роде на Swift писать даже легче, так что если вы только начинаете и думаете какой язык выбрать то советую выбрать Swift.Ниже, я предоставила видео с демонстрацией игрового процесса SpriteKit, если вам стало интересно то милости прошу.

[embedded content]

И так, давайте начнем, откройте Xcode.Создайте новый проект, когда вам предложат выбрать Application template выберите тип Game.11822cc78699970bb88a56363c63c761.png

Далее после ввода данных вам предложат выбрать язык: это либо Objective-c, либо совсем новый Swift.Можете выбрать любой, в этой статье примеры будут на обоих.Дальше в пункте Game Tehnology выбираем SpriteKit.Также не забудьте выбрать устройство для которого собираетесь писать, в нашем случае это Iphone.

344c006d69b315ca97aff1d819418a35.png

И так, мы создали наш проект, слева мы видим наши файлы для Objective-C это:

Objective-c 917c9e5bc9a5f10aec8501415a46fd04.png Для Swift: Swift d0d3e717b136548f5f063bc6e611aabe.png Как вы уже успели заметить, в проекте со Swift файлов в двое меньше.Слева мы видим:1) AppDelegate — делегат нашего проекта.2) GameViewController — контроллер наше проекта.3) GameScene — основная сцена нашей игры.4) GameScene.sks — это визуальный конструктор нашей сцены, его добавили с выходом Ios 8, служит для визуального добавление некоторых элементов. Давайте заглянем в некоторые файлы и посмотрим что у них внутри.GameViewController GameViewController — он отвечает за создание и инициализацию нашей сцены. Все начальные настройки служащие для отображение нашей сцены нужно проводить здесь.В целом все что, происходит в GameViewController одинаково для обоих языков: В самом начале вызывается метод или функция viewDidLoad.В этом методе или функции происходит: создание и настройка нашей сцены и некоторых параметров ее отображения.

Objective-c  — (void)viewDidLoad { [super viewDidLoad];

// Configure the view. SKView * skView = (SKView *)self.view; // Создается указатель на объект SKView и ему присваивается текущий View. skView.showsFPS = YES; // Разрешить отображать частоту обновлений нашей сцены skView.showsNodeCount = YES; // Разрешить показывать число Node (Объектов на нашей сцене). /* Sprite Kit applies additional optimizations to improve rendering performance */ skView.ignoresSiblingOrder = YES;// Разрешить применять дополнительную оптимизацию для улучшения производительности рендеринга // Create and configure the scene. GameScene *scene = [GameScene unarchiveFromFile:@«GameScene»]; // Создаем и инициализируем объект нашей сцены. scene.scaleMode = SKSceneScaleModeAspectFill; // Присвоить свойству ScaleMode объекта Scene тип SKSceneScaleModeAspectFill. // Present the scene. // Передаем методу presentScene, объекта skView в качестве параметра объект нашей сцены и этим отображаем наше сцену [skView presentScene: scene]; } Swift override func viewDidLoad () { super.viewDidLoad () // if let scene = GameScene.unarchiveFromFile («GameScene») as? GameScene //Проверяем принадлежит ли наш объект классу GameScene { // Configure the view. let skView = self.view as SKView // константе SKView присваивается текущий UIView skView.showsFPS = true // Разрешить отображать частоту обновлений нашей сцены skView.showsNodeCount = true // Разрешить показывать число Node (Объектов на нашей сцене). /* Sprite Kit applies additional optimizations to improve rendering performance */ skView.ignoresSiblingOrder = true // Разрешить применять дополнительную оптимизацию для улучшения производительности рендеринга /* Set the scale mode to scale to fit the window */ scene.scaleMode = .AspectFill // Присвоить свойству ScaleMode объекта Scene тип AspectFill. // Передаем функции presentScene, объекта skView в качестве параметра объект нашей сцены и этим отображаем наше сцену skView.presentScene (scene) } } В самом начале, в этом методе или функции создается указатель или константа на объект типа SKView и ему присваивается текущий View.

SKView — это наследник UIView, он служит для отображение нашей сцены.

Далее идет настройка основных свойств нашего SKView:

showFPS — это свойство отображает частоту обновлений нашей сцены.showsNodeCount — показывает число Node (Объектов на нашей сцене).ignoressSiblingOrder — применяет дополнительную оптимизацию для улучшения производительности рендеринга.Кроме перечисленных, у SKView есть еще много прочих полезных свойств, посмотрите и поэкспериментируйте с ними! Далее идет создание Объекта нашей сцены — GameScene. В случае со Swift он уже был создан до конфигурации нашего View.По умолчанию объект нашей сцены инициализируется с вызова метода или функции:

Objective-c

+ (instancetype)unarchiveFromFile:(NSString *)file { /* Retrieve scene file path from the application bundle */ NSString *nodePath = [[NSBundle mainBundle] pathForResource: file ofType:@«sks»]; /* Unarchive the file to an SKScene object */ NSData *data = [NSData dataWithContentsOfFile: nodePath options: NSDataReadingMappedIfSafe error: nil]; NSKeyedUnarchiver *arch = [[NSKeyedUnarchiver alloc] initForReadingWithData: data]; [arch setClass: self forClassName:@«SKScene»]; SKScene *scene = [arch decodeObjectForKey: NSKeyedArchiveRootObjectKey]; [arch finishDecoding]; return scene; } Swift class func unarchiveFromFile (file: NSString) → SKNode? { let path = NSBundle.mainBundle ().pathForResource (file, ofType: «sks») var sceneData = NSData.dataWithContentsOfFile (path, options: .DataReadingMappedIfSafe, error: nil) var archiver = NSKeyedUnarchiver (forReadingWithData: sceneData) archiver.setClass (self.classForKeyedUnarchiver (), forClassName: «SKScene») let scene = archiver.decodeObjectForKey (NSKeyedArchiveRootObjectKey) as GameScene archiver.finishDecoding () return scene } Что происходит при его вызове, он находит файл нашего визуального конструктора GameScene.sks затем разархивирует его, а после возвращает объект типа SKScene для последующий инициализации нашей сцены.Обратите внимание что, у объекта нашей сцены, есть свойства: scaleMode как можно догадаться из название, это свойство выполняет растяжку сцены по экрану, поэкспериментируйте с этим свойством! После того, как мы настроили наш SKView и создали объект нашей сцены, теперь можно ее отобразить. Делается это очень просто, мы вызываем функцию или метод класса SKView:

Objective-c  — (void)presentScene:(SKScene *)scene transition:(SKTransition *)transition; Swift func presentScene (scene: SKScene!, transition: SKTransition!) , а затем передаем в качестве параметра объект нашей сцены, теперь скомпилируем и «вуаля» наша сцена готова! Ниже я привела полный код GameViewController.21ce033d1aa6c2b25caf21e104db8977.png

Objective-c #import «GameViewController.h» #import «GameScene.h»

@implementation SKScene (Unarchive)

+ (instancetype)unarchiveFromFile:(NSString *)file { /* Retrieve scene file path from the application bundle */ NSString *nodePath = [[NSBundle mainBundle] pathForResource: file ofType:@«sks»]; /* Unarchive the file to an SKScene object */ NSData *data = [NSData dataWithContentsOfFile: nodePath options: NSDataReadingMappedIfSafe error: nil]; NSKeyedUnarchiver *arch = [[NSKeyedUnarchiver alloc] initForReadingWithData: data]; [arch setClass: self forClassName:@«SKScene»]; SKScene *scene = [arch decodeObjectForKey: NSKeyedArchiveRootObjectKey]; [arch finishDecoding]; return scene; }

@end

@implementation GameViewController

— (void)viewDidLoad { [super viewDidLoad];

// Configure the view. SKView * skView = (SKView *)self.view; // skView.showsFPS = YES; skView.showsNodeCount = YES; /* Sprite Kit applies additional optimizations to improve rendering performance */ skView.ignoresSiblingOrder = YES; // Create and configure the scene. GameScene *scene = [GameScene unarchiveFromFile:@«GameScene»]; scene.scaleMode = SKSceneScaleModeAspectFill; // Present the scene. [skView presentScene: scene]; }

— (BOOL)shouldAutorotate { return YES; }

— (NSUInteger)supportedInterfaceOrientations { if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { return UIInterfaceOrientationMaskAllButUpsideDown; } else { return UIInterfaceOrientationMaskAll; } }

— (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren’t in use. }

@end Swift import UIKit import SpriteKit

extension SKNode { class func unarchiveFromFile (file: NSString) → SKNode? { let path = NSBundle.mainBundle ().pathForResource (file, ofType: «sks») var sceneData = NSData.dataWithContentsOfFile (path, options: .DataReadingMappedIfSafe, error: nil) var archiver = NSKeyedUnarchiver (forReadingWithData: sceneData) archiver.setClass (self.classForKeyedUnarchiver (), forClassName: «SKScene») let scene = archiver.decodeObjectForKey (NSKeyedArchiveRootObjectKey) as GameScene archiver.finishDecoding () return scene } }

class GameViewController: UIViewController {

override func viewDidLoad () { super.viewDidLoad ()

if let scene = GameScene.unarchiveFromFile («GameScene») as? GameScene { // Configure the view. let skView = self.view as SKView skView.showsFPS = true skView.showsNodeCount = true /* Sprite Kit applies additional optimizations to improve rendering performance */ skView.ignoresSiblingOrder = true /* Set the scale mode to scale to fit the window */ scene.scaleMode = .AspectFill skView.presentScene (scene) } }

override func shouldAutorotate () → Bool { return true }

override func supportedInterfaceOrientations () → Int { if UIDevice.currentDevice ().userInterfaceIdiom == .Phone { return Int (UIInterfaceOrientationMask.AllButUpsideDown.toRaw ()) } else { return Int (UIInterfaceOrientationMask.All.toRaw ()) } }

override func didReceiveMemoryWarning () { super.didReceiveMemoryWarning () // Release any cached data, images, etc that aren’t in use. } } GameScene Ну что же, после того как мы настроили нашу сцену, она готова к боевым действиям и тут друзья мои начинается все самое интересное! Как вы уже успели заметить, по умолчанию у нас запуститься сцена с некоторыми уже добавленными объектами.Удалите все в GameScene так, что бы она соответствовала коду ниже:

Objective-c #import «GameScene.h»

@implementation GameScene

-(void)didMoveToView:(SKView *)view { }

@end

Swift import SpriteKit

class GameScene: SKScene { override func didMoveToView (view: SKView) { } }

И теперь скомпилируем наш проект и мы увидим: e6a046847702354fe289ce1cca62a2c2.png

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

Что бы понять как наша сцена работает, нам сначала нужно понять ее основные методы или функции, ниже я приведу основные, остальные вы можете посмотреть и сами в .h файле.

Основные свойства:

1) size — Определяет размер нашей сцены.2) scaleMode — Определяет отображение нашей сцены.3) backgroundColor — Определяет цвет нашей сцены по умолчание серый (как мы и успели заметить выше).4) anchorPoint — Определяет начальную точку нашей сцены.5) view — Наш исходный View.6) physicsWorld — Это очень важное свойства, которое отвечает за физику сцены (Гравитация, скорость) мы подробно поговорим о нем позже. Основные методы или функции1) didMoveToView: — Вызывается, после того как наша сцена отобразилась.2) willMoveFromView: — Вызывается, после того как наша сцена была удалена.3) didChangeSize: — Вызывается, при изменение размера нашей сцены.4) convertPointToView: — Служит для конвертирование координат5) convertPointFromView: — Служит для конвертирование координат6) initWithSize: — Вызывается при инициализации нашей сцены. Основные события нашей сценыСобытия нужны для написание основной логики нашей игры, Они вызываются именно в том порядке в котором я написала!1) Update: — Здесь реализуется основная логика нашей игры.2) didEvaluateActions — Служит для расчетов наших Action — действий.3) didSimulatePhysics — Служит для расчетов физических событий.4) didApplyConstriants — Служит для расчетов ограничений.5) didFinishUpdate — Вызывается, после того как все выше перечисленные события выполнились. И так друзья, теперь когда мы видели основные методы или функции, Свойства и события нашей сцены, мы можем немного изменить наш код. Давайте попробуем изменить цвет нашей сцены, для этого обратимся к свойству backgroundColor и покрасим нашу сцену в оранжевый цвет. Как мы уже видели выше, при инициализации сцены первым должен вызваться метод или функция initWithSize:, а после того как наша сцена уже отобразилась, вызывается didMoveToView:. В нашем случае, сцена инициализируется с вызова метода или функции unarchiveFromFile и поэтому мы уже не можем повторно написать метод инициализации. И поэтому, нам остается определить наши начальные настройки в didMoveToView:.Objective-c

#import «GameScene.h»

@implementation GameScene

-(void)didMoveToView:(SKView *)view { [self SceneSetting]; // вызываем метод SceneSetting }

-(void)SceneSetting { self.backgroundColor = [SKColor orangeColor]; // изменяем цвет сцены на оранжевый }

@end Swift import SpriteKit

class GameScene: SKScene { override func didMoveToView (view: SKView) { SceneSetting () // вызываем функцию SceneSetting } func SceneSetting () { self.backgroundColor = SKColor.orangeColor () // изменяем цвет сцены на оранжевый } } Как видно из примеров выше, сначала вызывается метод или функция didMoveToView, далее в нем (ей) вызывается метод или функцию SceneSetting, а уже после изменяется цвет нашей сцены. Обратите внимание, что при изменение цвета мы не обращаемся к объекту UIColor как мы привыкли, мы обращаемся к SKColor, по сути это define UIColor и поэтому вы можете писать и так и так, ошибкой это не будет. Вы наверно спросите, для чего я вынесла настройки в отдельный метод или функцию. Я это сделала для удобство, в больших проектах порой бывает очень трудно ориентироваться, и нам будет очень удобно, если мы в самом начале все будем делать аккуратно.

И так, что у нас получилась вы видите на изображение снизу.68b0074ec80f0288489583b81d1968ba.png

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

SKNode Ну что, друзья, как видите мы изменили цвет нашей сцены и вы наверно задались вопросом, и все? и ради этого мы зашли сюда? Друзья, к сожаление я не могу продемонстрировать вам всю мощь, какую имеет наша сцена, для этого нам нужно изучить еще один очень важный пункт это — SKNode.

SKNode — это важнейший элемент. В SpriteKit он считается основным, от него наследуются все остальные элементы.Даже наша сцена по сути является его наследником и обладает всеми его свойствами.

Давайте посмотрим на Свойство, Методы или Функции, нашего SKNode.

Свойство

1) frame — Определяет форму нашего Node.2) position — Определяет позицию нашего Node.3) zPosition — Определяет положение нашего Node относительно оси Z.4) zRotation — Определяет поворот нашего Node в углах Эйлера.5) xScale — Определяет масштаб нашего Node по оси x.6) yScale — Определяет масштаб нашего Node по оси y.7) speed — Определяет скорость нашего Node.8) alpha — Определяет Альфа компоненту нашего Node.9) paused — Возвращает Yes, если наш Node не выполняет Actions — действий.10) hidden — Возвращает Yes, если наш Node спрятан.11) isUserInteractionEnabled — Возвращает Yes, если наш Node принимает касание.12) parent — Возвращает, родительский Node.(Если возвращает nil, то он сам является родительским Node)13) children — Возвращает всех потомков нашего Node.14) name — Определяет имя нашего Node. (Очень важное свойство)15) scene — Сцена на которой в данный момент находится наш Node.16) physicsBody — Физическое Тело Нашего Node.(Очень важное свойство о котором подробнее узнаем чуть позже)17) userData — Определяет место куда можно записывать полезную информацию нашего Node.18) reachConstraints — Определяет степень свободы в IK (Inverse Kinematics) — Action действиях.19) constraints — Определяет список Ограничений. Методы или Функции

1) setScale — Задать масштаб.(равномерно по X & Y)2) addChild — Добавить потомка.(Добавить один Node на другого)3) insertChild — Изъять потомка.4) removeChildrenInArray — Удалить потомков по списку.5) removeAllChildren — Удалить всех потомков. 6) removeFromParent — Удалить родительский Node.7) childNodeWithName — Возвращает потомка по имени.8) enumerateChildNodesWithName — Пересчитать всех потомков по определенному имени.9) inParentHierarchy — Вернет Yes, если наш Node является членом Иерархии10) runAction — Выполнить Action — действие.11) runAction — completion — Выполнить Action — действие, после завершение вызывает блок Completion.12) runAction — withKey — Выполнить Action — действие, с заданным ключом.13) hasAction — Возвращает Yes, если наш Node выполняет Action — действие14) actionForKey — Возвращает Action — действие, с заданным ключом.15) removeActionForKey — Удалить Action — действие с заданным ключом.16) removeAllActions — Удалить все Action — действие нашего Node.17) containsPoint — Возвращает Yes, если наша точка лежит внутри нашего Node/18) nodeAtPoint — Возвращает объект типа SKNode, находящийся в этой точки.19) nodesAtPoint — Возвращает список объектов типа SKNode находящихся в этой точки.20) convertPoint — fromNode — Конвертирует и возвращает координаты для нашей системы координат.21) convertPoint — toNode — Конвертирует и возвращает координаты для НЕ нашей системы координат.22) intersectsNode — Возвращает Yes, если наш Node пересекается с границей другого Node23) calculateAccumulatedFrame — Возвращает координаты границ, включая потомков. 24) locationInNode — Возвращает координаты Node, которого мы коснулись.25) previousLocationInNode — Возвращает координаты Node, которого мы коснулись до этого. И так, мы почти закончили, друзья потерпите еще чуть-чуть. Как мы видим, чуть выше, SKNode не такой уж и сложный в своем строении! Да и вообще, сам SpriteKit не сложный, просто нужно немного терпение и все! Продолжим, от SKNode наследуются несколько основных Объектов, давайте по быстрому на них посмотрим:

1) SKSpriteNode — Это стандартный Спрайт.2) SKShapeNode — Это составной Спрайт — объект, который может принимать практически любую форму.3) SKFieldNode — Это поля с воздействием физических сил на другие тела.4) SKEmitterNode — Это специальный Node (particle), это особые частицы из которых можно создавать крутые эффекты.5) SKLabelNode — Это Node, который выводит текст с различными опциями.6) SKEffectNode — Это Node который добавляет специальные эффекты для его потомков. 7) SKLightNode — Это Node, добавляет свет и тени к нашей Сцене, появился с выходом Ios 8.8) SKVideoNode — Это Node, который позволяет отображать видео в нашей сцене.9) SKCropNode — Это Node, который позволяет изменять текстуру объекта определенной формы.10) SK3DNode — Как видно из название, это Node, который позволяет добавлять 3D объекты.Все выше перечисленные элементы — это самые используемые объекты, они служат основой в создании игр на SpriteKit.И так, настало то время, когда мы сможем посмотреть на наши Node в живую. Я специально начала эту статью с небольшого теоретического материала, чтобы вы имели небольшое представление о самом движке и о его огромных возможностях. Теперь давайте на примерах посмотрим, что делают некоторые из них, пойдем по порядку и начнем с SKSpriteNode.

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

Objective-c

scene.scaleMode = SKSceneScaleModeResizeFill;  — (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskLandscape; } Swift

scene.scaleMode = .ResizeFill override func supportedInterfaceOrientations () → Int { return Int (UIInterfaceOrientationMask.Landscape.toRaw ()) } SKSpriteNode SKSpriteNode — это стандартный спрайт, который отображает Текстуры (Графические изображение).Давайте посмотрим на него вблизи, на изображение ниже мы видим три объекта (Спрайта): Синий квадрат, Спрайт с изображение дощечки, и Спрайт заднего фона.Я специально создала 3 объекта типа SKSpriteNode, что бы вы увидели различия в их создании.

57d0671d4d1816a28ed6d797d06eec1f.png

Для начала откройте Xcode и в нашем проекте создайте новую папку и назовите ее SpriteKitImage (Можете назвать как хотите)Далее скачайте отсюда архив с изображениями, после распакуйте его и добавьте эти изображение в нашу только что созданную папку.

Весь код с описанием процесса создание находится чуть ниже, здесь я объясню некоторые моменты.

Первый спрайт имеет имя BackgroundSprite, перед его созданием, мы создаем объект типа SKTexture, и в него в качестве параметра передаем имя нашего изображения. Зачем нужен этот объект? Текстуры, очень полезны для работы с изображениями еще до создание нами самих спрайтов, с их помощь можно экономно управлять ресурсами, один и тот-же объект может быть использован несколькими спрайтами.

Далее мы задаем размер и позицию. Несколько слов о позиции, в SKSpriteNode ее мы отсчитываем от середины нашего объекта, то есть когда говорят мы сдвинули такой то спрайт на 100 px, это значит мы сдвинули его центральную точку на 100 px.После того, как мы задали размер и позицию, мы изменяем свойство anchorPoint. Его изменять не обязательно, я это сделала для того, чтобы было удобнее подогнать наше изображение под весь экран. Сейчас вы все поймете! Как вы уже знаете, anchorPoint — это точка отсчета, и как я уже писала выше, позицию нашего Спрайта определяет точка по середине, так вот anchorPoint ее изменяет. Что бы лучше понять давайте рассмотрим картинку ниже:

48c3119204bc4e43437eaf78bac45d0a.png

Как видно на изображение нарисованы декартовы координаты. По умолчанию объекты SKSpriteNode имеют anchorPoint равный (0.5, 0.5), то есть по центру. В примере я изменила это свойство и задала его равным (0, 0), если мы опять посмотрим на изображение то увидим, что это точка находится в самом нижнем левом углу, а это значит что теперь наша начальная точка уже будет не посередине, а снизу слева. И теперь если скажут, что мы сдвинули такой то спрайт на 100 px, это значит мы сдвинули его самую нижнею и самую левую точку на 100 px.

Далее мы задаем имя, это тоже очень важное свойство, его в данным случае писать было не обязательно, так как у нас пока что не происходит никаких действий.Зачем нужно имя? По нему мы будем находить, определять и различать наши объекты. Будьте осторожны с выбором имени!.

После того, как мы задали необходимые нам свойства, мы обращаемся к нашей сцене и вызываем у нее метод или функцию:

addChild — Добавить потомка.(Добавить один Node на другого), который (-ая) добавляет наш объект на сцену. Как я уже писала выше, наша сцена тоже является наследником от SKNode и поэтому мы добавляем один Node на другого.Этот метод или функция работает так же, если вы захотите, скажем добавить один спрайт на другой.Второй Спрайт с именем SimpleSprite, при его создании мы передаем два параметра это: Цвет и размер.В качестве цвета мы передаем объект типа UIColor, как я уже писала выше мы можем передать и SKColor, это не будет ошибкой.Еще один момент, это zPosition, как вы уже знаете zPosition — Определяет положение нашего Node относительно оси Z.По умолчанию это свойство равно 0. Когда я создавала наши объекты, почему то объект с именем SimpleSprite — второй объект, находился под остальными, видимо из-за особенностей его инициализации и по этому я присвоила этому спрайту свойство zPosition равному 1.Еще одно очень важное замечание: Node не находящиеся на одной плоскости не могут взаимодействовать! То есть, если у одного zPosition равен 0, а у другого 1 то они не будут контактировать!

Третий Спрайт, с именем ImageSprite, при его инициализации мы ему в качестве параметра передали имя нашей картинки.Этот способ, конечно отличается от первого, где мы создавали объект типа SKTexture, но для обычной инициализации весьма подходит.

Objective-c

Objective-C #import «GameScene.h»

@implementation GameScene

-(void)didMoveToView:(SKView *)view { [self SceneSetting]; [self SKSpriteNodeDemo]; // Вызываем только что созданный нами метод }

-(void)SceneSetting { self.backgroundColor = [SKColor orangeColor]; }

-(void)SKSpriteNodeDemo { // Создаем указатель на объект типа SKTexture и инициализируем его. В качестве параметра передаем имя нашего изображение. SKTexture *Texture = [SKTexture textureWithImageNamed:@«desert_BG»]; //Создаем наш SKSpriteNode и инициализируем его. В качестве параметра передаем объект типа SKTexture, который мы создали выше. SKSpriteNode *BackgroundSprite = [SKSpriteNode spriteNodeWithTexture: Texture]; BackgroundSprite.size = CGSizeMake (640, 320); // Задаем размер. BackgroundSprite.position = CGPointMake (0, 0); // задаем позицию. BackgroundSprite.anchorPoint = CGPointMake (0, 0); //задаем начальную точку. BackgroundSprite.name = @«BackgroundSprite»;// задаем имя. [self addChild: BackgroundSprite];//добавляем наш объект на нашу сцену. //Создаем наш SKSpriteNode и инициализируем его. В качестве параметров передаем цвет и размер. SKSpriteNode *SimpleSprite = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size: CGSizeMake (50, 50)]; SimpleSprite.position = CGPointMake (200, 150);// задаем позицию. SimpleSprite.zPosition = 1;// задаем положение нашего объекта относительно оси Z. SimpleSprite.name = @«SimpleSprite»;// задаем имя. [self addChild: SimpleSprite];//добавляем наш объект на нашу сцену.

//Создаем наш SKSpriteNode и инициализируем его. В качестве параметра передаем имя нашего изображение. SKSpriteNode *ImageSprite = [SKSpriteNode spriteNodeWithImageNamed:@«DerevoOpora»]; ImageSprite.position = CGPointMake (250, 50);// задаем позицию. ImageSprite.size = CGSizeMake (100, 15);// Задаем размер. ImageSprite.name = @«ImageSprite»;// задаем имя. [self addChild: ImageSprite];//добавляем наш объект на нашу сцену. }

@end

Swift

Swift import SpriteKit

class GameScene: SKScene { override func didMoveToView (view: SKView) { SceneSetting () SKSpriteNodeDemo () //Вызываем только что созданную нами функцию. } func SceneSetting () { self.backgroundColor = SKColor.orangeColor () } func SKSpriteNodeDemo () { //Создаем переменную Texture и ей присваиваем объект типа SKTexture. В качестве параметра передаем имя нашего изображение var Texture = SKTexture (imageNamed: «desert_BG»)

//Создаем переменную BackgroundSprite и ей присваиваем объект типа SKSpriteNode. // В качестве параметра передаем объект типа SKTexture созданный нами выше. var BackgroundSprite = SKSpriteNode (texture: Texture) BackgroundSprite.size = CGSizeMake (640, 320) //задаем размер. BackgroundSprite.position = CGPointMake (0, 0) //задаем позицию. BackgroundSprite.anchorPoint = CGPointMake (0, 0) //задаем начальную точку. BackgroundSprite.name = «BackgroundSprite» // задаем имя. self.addChild (BackgroundSprite) //добавляем наш объект на нашу сцену. //Создаем переменную SimpleSprite и ей присваиваем объект типа SKSpriteNode. // В качестве параметров передаем цвет и размер. var SimpleSprite = SKSpriteNode (color: UIColor.blueColor (), size: CGSizeMake (50, 50)) SimpleSprite.position = CGPointMake (200, 150) //задаем позицию. SimpleSprite.zPosition = 1; // задаем положение нашего объекта относительно оси Z. SimpleSprite.name = «SimpleSprite» // задаем имя. self.addChild (SimpleSprite) //добавляем наш объект на нашу сцену. //Создаем переменную ImageSprite и ей присваиваем объект типа SKSpriteNode. // В качестве параметров передаем имя нашего изображение. var ImageSprite = SKSpriteNode (imageNamed: «DerevoOpora») ImageSprite.position = CGPointMake (250, 50) //задаем позицию. ImageSprite.size = CGSizeMake (100, 15) //задаем размер. ImageSprite.name = «ImageSprite» // задаем имя. self.addChild (ImageSprite) //добавляем наш объект на нашу сцену. } } Ну что же, вы увидели визуально SKSpriteNode и увидели простейшие формы его инициализации, пока что этого хватит, давайте пойдем дальше и посмотрим еще один тип Node — это SKShapeNode.SKShapeNode SKShapeNode — Это составной Спрайт — объект, который может принимать практически любую форму. То есть он может быть почти любой геометрической фигурой: Окружность, Квадрат, Треугольник, Эллипс.В строение он немного сложнее, чем SKSpriteNode так как здесь вся форма составная. Но он незаменим в построении сложных форм, без него очень тяжело управится.Ладно довольно слов перейдем к делу!

888606d8c31521560735ea0060f2b872.png

Давайте рассмотрим метод или функцию в которой (-ом) реализованы фигуры выше, полный код вы найдете ниже.И так, для удобства я закомvентировала предыдущий метод или функцию, так что не пугайтесь, если вдруг не увидите предыдущих объектов.

Objective-c

Objective-c -(void)SKShapeNodeDemo { //Создаем наш SKShapeNode и инициализируем его. В качестве параметра передаем радиус. SKShapeNode *Circle = [SKShapeNode shapeNodeWithCircleOfRadius:20]; Circle.position = CGPointMake (50, 200); // задаем позицию. Circle.lineWidth = 10; // задаем ширину линий. Circle.strokeColor = [SKColor blueColor]; // задаем цвет контура. Circle.fillColor = [SKColor redColor]; // задаем цвет внутренности. Circle.name = @«Circle»; // задаем имя. [self addChild: Circle]; // добавляем наш объект на нашу сцену. //Создаем наш SKShapeNode и инициализируем его. В качестве параметра передаем координаты и размер прямоугольника (CGRectMake). SKShapeNode *Quad = [SKShapeNode shapeNodeWithRect: CGRectMake (0, 0, 50, 50)]; Quad.position = CGPointMake (100, 200); // задаем позицию. Quad.lineWidth = 4; // задаем ширину линий. Quad.strokeColor = [SKColor whiteColor]; // задаем цвет контура. Quad.fillColor = [SKColor blackColor]; // задаем цвет внутренности. Quad.name = @«Quad»; // задаем имя. [self addChild: Quad]; // добавляем наш объект на нашу сцену. // Создаем наш SKShapeNode и инициализируем его. В качестве параметра передаем координаты и размер прямоугольника (CGRectMake). // В данном случае форма эллипса будет создана внутри прямоугольника в соответствии с его размерами. SKShapeNode *Ellips = [SKShapeNode shapeNodeWithEllipseInRect: CGRectMake (0, 0, 50, 90)]; Ellips.position = CGPointMake (200, 200); // задаем позицию. Ellips.lineWidth = 2; // задаем ширину линий. Ellips.strokeColor = [SKColor greenColor]; // задаем цвет контура. Ellips.fillColor = [SKColor purpleColor]; // задаем цвет внутренности. Ellips.glowWidth = 5; // задаем эффект свечение контура. Ellips.name = @«Ellips»; // задаем имя. [self addChild: Ellips]; // добавляем наш объект на нашу сцену. // Создаем и инициализируем объект типа UIBezierPath. В качестве параметра передаем координаты и размер прямоугольника (CGRectMake), //, а также радиус округление углов. UIBezierPath *RoundedRectPath = [UIBezierPath bezierPathWithRoundedRect: CGRectMake (0, 0, 50, 50) cornerRadius:12];

// Создаем наш SKShapeNode и инициализируем его. В качестве параметра передаем объект созданный нами выше и булева значение. // обратите внимание на то, что к объекту передаваемому в первом параметре добавляется свойство CGPath. SKShapeNode *RoundedRect = [ SKShapeNode shapeNodeWithPath: RoundedRectPath.CGPath centered: YES]; RoundedRect.position = CGPointMake (50, 100); // задаем позицию. RoundedRect.lineWidth = 2; // задаем ширину линий. RoundedRect.strokeColor = [SKColor blueColor]; // задаем цвет контура. RoundedRect.fillColor = [SKColor redColor]; // задаем цвет внутренности. RoundedRect.name = @«RoundedRect»; // задаем имя. [self addChild: RoundedRect]; // добавляем наш объект на нашу сцену. UIBezierPath *TrianglePath = [UIBezierPath bezierPath]; // Создаем и инициализируем объект типа UIBezierPath. [TrianglePath moveToPoint: CGPointMake (0, 0)]; // переходим на точку с заданными координатами. [TrianglePath addLineToPoint: CGPointMake (-25, -50)]; // добавляем линию к заданной точке. [TrianglePath addLineToPoint: CGPointMake (25, -50)]; // добавляем линию к заданной точке. [TrianglePath addLineToPoint: CGPointMake (0, 0)]; // добавляем линию к заданной точке. // Создаем наш SKShapeNode и инициализируем его. В качестве параметра передаем объект созданный нами выше и булева значение. // обратите внимание на то, что к объекту передаваемому в первом параметре добавляется свойство CGPath. SKShapeNode *Triangle = [SKShapeNode shapeNodeWithPath: TrianglePath.CGPath centered: YES]; Triangle.position = CGPointMake (200, 70); // задаем позицию. Triangle.lineWidth = 2; // задаем ширину линий. Triangle.strokeColor = [SKColor blackColor]; // задаем цвет контура. Triangle.fillColor = [SKColor blueColor]; // задаем цвет внутренности. Triangle.name = @«Triangle»; // задаем имя. [self addChild: Triangle]; // добавляем наш объект на нашу сцену. } SwiftSwift func SKShapeNodeDemo () { // Создаем переменную Circle и ей присваиваем объект типа SKShapeNode. в качестве параметра передаем радиус. var Circle = SKShapeNode (circleOfRadius: 20) Circle.position = CGPointMake (50, 200) // задаем позицию. Circle.lineWidth = 10 // задаем размер линий. Circle.strokeColor = SKColor.blueColor () // задаем цвет контура. Circle.fillColor = SKColor.redColor () // задаем цвет внутренности. Circle.name = «Circle» // задаем имя. self.addChild (Circle) // добавляем наш объект на нашу сцену. // Создаем переменную Quad и ей присваиваем объект типа SKShapeNode. // В качестве параметра передаем координаты и размер прямоугольника (CGRectMake). var Quad = SKShapeNode (rect: CGRectMake (0, 0, 50, 50)) Quad.position = CGPointMake (100, 200) // задаем позицию. Quad.lineWidth = 4 // задаем размер линий. Quad.strokeColor = SKColor.whiteColor () // задаем цвет контура. Quad.fillColor = SKColor.blackColor () // задаем цвет внутренности. Quad.name = «Quad» // задаем имя. self.addChild (Quad) // добавляем наш объект на нашу сцену. // Создаем переменную Ellips и ей присваиваем объект типа SKShapeNode. // В данном случае форма эллипса будет создана внутри прямоугольника в соответствии с его размерами. var Ellips = SKShapeNode (ellipseInRect: CGRectMake (0, 0, 50, 90)) Ellips.position = CGPointMake (200, 200) // задаем позицию. Ellips.lineWidth = 2 // задаем размер линий. Ellips.strokeColor = SKColor.greenColor () // задаем цвет контура. Ellips.fillColor = SKColor.purpleColor () // задаем цвет внутренности. Ellips.glowWidth = 5 // задаем эффект свечение контура. Ellips.name = «Ellips» // задаем имя. self.addChild (Ellips) // добавляем наш объект на нашу сцену. // Создаем переменную RoundedRectPath и ей присваиваем объект типа UIBezierPath. // В качестве параметра передаем координаты и размер прямоугольника (CGRectMake), а также радиус округление углов. var RoundedRectPath = UIBezierPath (roundedRect: CGRectMake (0, 0, 50, 50), cornerRadius: 12) // Создаем переменную RoundedRect и ей присваиваем объект типа SKShapeNode. // В качестве параметра передаем объект созданный нами выше и булева значение. // обратите внимание на то, что к объекту передаваемому в первом параметре добавляется свойство CGPath. var RoundedRect = SKShapeNode (path: RoundedRectPath.CGPath, centered: true) RoundedRect.position = CGPointMake (50, 100) // задаем позицию. RoundedRect.lineWidth = 2 // задаем размер линий. RoundedRect.strokeColor = SKColor.blueColor () // задаем цвет контура. RoundedRect.fillColor = SKColor.redColor () // задаем цвет внутренности. RoundedRect.name = «RoundedRect» // задаем имя. self.addChild (RoundedRect) // добавляем наш объект на нашу сцену. var TrianglePath = UIBezierPath () // Создаем и инициализируем объект типа UIBezierPath. TrianglePath.moveToPoint (CGPointMake (0, 0)) // переходим на точку с заданными координатами. TrianglePath.addLineToPoint (CGPointMake (-25, -50)) // добавляем линию к заданной точке. TrianglePath.addLineToPoint (CGPointMake (25, -50)) // добавляем линию к заданной точке. TrianglePath.addLineToPoint (CGPointMake (0, 0)) // добавляем линию к заданной точке. // Создаем переменную Triangle и ей присваиваем объект типа SKShapeNode. // В качестве параметра передаем объект созданный нами выше и булева значение. // обратите внимание на то, что к объекту передаваемому в первом параметре добавляется свойство CGPath. var Triangle = SKShapeNode (path: TrianglePath.CGPath, centered: true) Triangle.position = CGPointMake (200, 70) // задаем позицию. Triangle.lineWidth = 2 // задаем размер линий. Triangle.strokeColor = SKColor.blackColor () // задаем цвет контура. Triangle.fillColor = SKColor.blueColor () // задаем цвет внутренности. Triangle.name = «Triangle» // задаем имя. self.addChild (Triangle) // добавляем наш объект на нашу сцену. } У SKShapeNode есть несколько способов инициализации, их можно разделить на две группы: Стандартная инициализация или инициализация с помощью объекта UIBezierPath.Рассмотрим их по отдельности!

Стандартная инициализация

• В первую группу попадают объекты с простой инициализацией. Что это значит? Это например объекты при инициализации которых форма уже создана, и вам остается только задать ее параметры. Сейчас вы все поймете! Circle Давайте рассмотрим наш первый объект, это Circle. Как можно заметить, при его создании мы вызываем метод shapeNodeWithCircleOfRadius или функцию circleOfRadius и в него (-нее) в качестве параметра передаем радиус.Objective-c

//Создаем наш SKShapeNode и инициализируем его. В качестве параметра передаем радиус. SKShapeNode *Circle = [SKShapeNode shapeNodeWithCircleOfRadius:20]; Circle.position = CGPointMake (50, 200); // задаем позицию. Circle.lineWidth = 10; // задаем ширину линий. Circle.strokeColor = [SKColor blueColor]; // задаем цвет контура. Circle.fillColor = [SKColor redColor]; // задаем цвет внутренности. Circle.name = @«Circle»; // задаем имя. [self addChild: Circle]; // добавляем наш объект на нашу сцену. Swift // Создаем переменную Circle и ей присваиваем объект типа SKShapeNode. в качестве параметра передаем радиус. var Circle = SKShapeNode (circleOfRadius: 20) Circle.position = CGPointMake (50, 200) // задаем позицию. Circle.lineWidth = 10 // задаем размер линий. Circle.strokeColor = SKColor.blueColor () // задаем цвет контура. Circle.fillColor = SKColor.redColor () // задаем цвет внутренности. Circle.name = «Circle» // задаем имя. self.addChild (Circle) // добавляем наш объект на нашу сцену. Видите, форма уже готова и нам остается просто передать параметр по которому и будет создан наш объект, в данном случае это радиус.Что происходит дальше, а далее мы задаем позицию нашего объекта, я думаю с этим проблем не будет.После мы задаем свойство lineWidth, оно отвечает за ширину контура (Линий), чем больше число, тем шире контур.

Дальше задаем два цветовых свойство: strokeColor и fillColor.

• strokeColor — Задает цвет контура (цвет линий формы).• fillColor — задает цвет внутренности формы.

С первым свойством все понятно, со вторым небольшая загвоздка.

Как наверно вы успели заметить, на изображение 5 фигур — объектов, но почему же на сцене пишется 10 nodes? Дело в том, что свойство fillColor наша сцена считает тоже за объект, и поэтому она отображает 10 nodes, если вы обратите внимание я каждой фигуре задала это свойство. Его можно и не задавать, тогда число объектов уменьшится. После того, как мы настроили свойство цвета, мы задаем имя и после добавляем наш объект на нашу сцену. Quad Objective-c //Создаем наш SKShapeNode и инициализируем его. В качестве параметра передаем к

© Habrahabr.ru