Статьи

Спрайт Кит против Cocos2D

Sprite Kit — одна из самых захватывающих новых технологий, доступных с iOS 7 SDK и Xcode 5, но как она соотносится с установленным игровым движком, таким как Cocos2D? В этом руководстве будет дано краткое введение в Sprite Kit, а затем будет подробно рассказано, как он сочетается с Cocos2D.


Из всех доступных игр в App Store многие из самых скачиваемых и наиболее прибыльных — это 2D-игры. Некоторые знаковые названия в этой категории включают Angry Birds , Tiny Wings и Cut the Rope . У успеха этих игр есть несколько общих характеристик: красивая графика, эффекты частиц, физический движок, плавная анимация и убедительные звуковые эффекты.

До выпуска iOS 7 SDK создание подобных игр было возможно только с использованием сторонних фреймворков и движков. Теперь, с появлением Sprite Kit, разработчикам не нужно искать ничего, кроме родного SDK, чтобы найти все, что им нужно для создания великолепных игр 2D и 2.5D. Функциональные возможности, предоставляемые набором Sprite, включают в себя спрайты, формы, частицы (например, огонь, дым и т. Д.), Анимацию, физическое моделирование, аудио, видео и визуальные эффекты. Xcode 5 теперь также предоставляет поддержку пакетов текстур и дизайна частиц.

Набор Sprite может быть логически разделен на следующие три части:

  • Сцены — Как и в Cocos2D, Сцены являются визуальным слоем игры. Здесь вы управляете фоном, объектами (такими как деревья, автомобили, самолеты, аватары и т. Д.).
  • Действия — Плавная анимация является важной частью любой игры. Apple разработала систему действий интуитивно понятным способом, и она позволяет вам делать практически все, что угодно. Некоторые из наиболее распространенных представленных действий: перемещение, исчезновение, масштабирование, изменение размера, вращение, анимация с текстурами и групповые действия. Кроме того, если конкретное действие не определено, вы всегда можете создать собственный блок кода, чтобы сформировать собственное действие и управлять этим объектом.
  • Физика. Если вы хотите реалистичную игру, вам нужно добавить физический движок. Вам не нужна пуля, которая не следует определенной траектории, шар, который не прыгает при падении на землю, и другие подобные любительские эффекты. К счастью, в Sprite Kit встроен физический движок.

Apple предоставляет 2D-и 2,5-мерную игровую платформу для очень серьезных преимуществ. Рассмотрим следующие моменты:

Нативная разработка и нативные инструменты — все о производительности.

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

Как упоминалось выше, Sprite Kit и Xcode 5 сочетают в себе многие важные компоненты для создания отличных игр. Это означает, что разработка может быть более упорядоченной, а инструменты будут более надежными и эффективными.

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

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

С набором Sprite Apple предоставила набор инструментов, обеспечивающих беспроблемную работу игрового кода на всех совместимых устройствах. Обратите внимание, что Sprite Kit — это не просто платформа iOS. Разработчики могут также начать создавать игры Sprite Kit для OS X, и вполне вероятно, что игры Sprite Kit будут работать и на любых будущих устройствах iOS.

Простота использования была основным фактором успеха игровых движков, таких как Cocos2D. Вообще говоря, разработчики обнаружили, что Cocos2D гораздо проще реализовать, чем другие нативные альтернативы, такие как OpenGL ES. С Cocos2D все вызовы API низкого уровня были преобразованы в простые методы.

Sprite Kit следует этому подходу и предлагает сотни методов, которые значительно облегчают процесс разработки игр. Sprite Kit также дружелюбен. Он имеет пользовательский, хорошо разработанный Apple API и поставляется с полной структурированной документацией. Apple проделала выдающуюся работу по оттачиванию этого инструмента для сторонних разработчиков. Самым большим преимуществом является то, что он полностью загружен каждым ресурсом, необходимым для создания игры. Физика, звуковые эффекты, эффекты частиц, текстуры, управление сценами — все включено в один пакет.

Обратите внимание, что на первоначальной презентации Sprite Kit Рикардо Кесада , ведущий разработчик Cocos2D, сказал в Twitter следующее:

Sprite Kit очень хорош. С меньшим количеством функций, чем у Cocos2D, но лучше. Мне нравится физическая интеграция.

Это высокая похвала от одного из ведущих умов Cocos2D!


Особенность Sprite Kit Cocos2D
Открытый источник нет да
Собственная поддержка Objective-C да да
Графический движок да да
Анимации да да
Физика симуляция Да (интегрированный) Нет (требуется Box2D или Бурундук)
Эффекты частиц да да
Собственная интеграция XCode да нет
Автоматическое создание атласа да нет
Встроенный редактор частиц да нет
шейдеры нет да
камера нет да

Итак, как же на самом деле выглядят проекты с каждым игровым движком? Чтобы ответить на этот вопрос, авторы включили полный исходный код как для Sprite Kit, так и для проекта Cocos2D . Вы можете использовать эти проекты в качестве высокоуровневого сравнения каждого игрового движка.


В этом разделе мы разберем общие задачи и концепции, показывая, как их реализовать в Cocos2D и Sprite Kit.

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

Переход между сценами в Cocos2D осуществляется с помощью следующих шагов:

1
2
GameScene* gameScene = [[GameScene alloc] init];
[[CCDirector sharedDirector] replaceScene:gameScene];

Обратите внимание, что файл GameScene.h должен относиться к категории CCLayer и иметь определенный доступный инициализатор.

1
2
@interface GameScene : CCLayer {}
+(CCScene *) scene;

В GameScene.m начальная реализация:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
+(CCScene *)scene
{
    CCScene *scene = [CCScene node];
     
    GameScene *layer = [GameScene node];
     
    [scene addChild: layer];
 
    return scene;
}
 
-(id) init{
    if( (self=[super init] )) {
        // Your code here
    }
    return self;
}

В Sprite Kit переход аналогичен:

1
2
3
GameScene* gameScene = [[GameScene alloc] initWithSize:CGSizeMake(1024, 768)];
[self.scene.view presentScene:gameScene];
}

GameScene должен относиться к категории SKScene , а -(id)initWithSize:(CGSize)size является пользовательским инициализатором. Простой пример:

1
2
3
4
5
6
7
8
-(id)initWithSize:(CGSize)size
{
    if (self = [super initWithSize:size])
    {
        // Your code
    }
    return self;
}

Объекты Sprite обычно используются для отображения какого-либо изображения. Он может иметь несколько свойств, таких как: вращение, масштаб, положение, кадры, идентификаторы и многое другое. Реализация как Cocos2D, так и Sprite Kit схожи. Реализация Cocos2D:

1
2
3
4
5
CCSprite* aSprite;
aSprite = [CCSprite spriteWithFile:@»player.png»];
aSprite.scale = .5;
aSprite.position = ccp(_size.width/1.30, _size.height/1.25);
[self addChild:aSprite];

В то время как в Sprite Kit реализация:

1
2
3
4
SKSpriteNode* planeShadow = [SKSpriteNode spriteNodeWithImageNamed:@»player.png»];
planeShadow.scale = 0.5;
planeShadow.position = CGPointMake(CGRectGetMidX(self.frame)+100,CGRectGetMidY(self.frame)+200);
[self addChild:planeShadow];

Объекты меток используются для отображения текста. Он может иметь несколько свойств, включая текст, размер текста, цвет текста, положение и многие другие. Реализация как Cocos2D, так и Sprite Kit схожи. Реализация Cocos2D:

1
2
3
4
5
CCLabelTTF *label = [CCLabelTTF labelWithString:@»Hello World» fontName:@»Marker Felt» fontSize:64];
// ask director for the window size
CGSize size = [[CCDirector sharedDirector] winSize];
label.position = ccp( size.width /2 , size.height/2 );
[self addChild: label];

Реализация набора Sprite:

1
2
3
4
5
SKLabelNode* gameScene = [SKLabelNode labelNodeWithFontNamed:@»Chalkduster»];
[gameScene setText:@»New Game»];
[gameScene setFontSize:18];
gameScene setPosition:CGPointMake(CGRectGetMidX(self.frame)+5,CGRectGetMidY(self.frame)-40)];
[self addChild:gameScene];

В Cocos2D меню создаются с использованием двух объектов: CCMenu и CCMenuItem . В следующем примере представлено меню с двумя опциями в Cocos2D:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
CGSize size = [[CCDirector sharedDirector] winSize];
     
[CCMenuItemFont setFontSize:28];
 
CCMenuItem *itemNewGame = [CCMenuItemFont itemWithString:@»New Game» block:^(id sender) {
    // Your code
}];
         
CCMenuItem *itemOptions = [CCMenuItemFont itemWithString:@»Options» block:^(id sender) {
    NSLog(@»Second item»);
}];
             
CCMenu *menu = [CCMenu menuWithItems:itemNewGame, itemOptions, nil];
[menu alignItemsHorizontallyWithPadding:20];
[menu setPosition:ccp( size.width/2, size.height/2 — 50)];
[self addChild:menu];

SpiteKit не включает в себя какой-либо конкретный объект меню. Вам необходимо создать обработчик событий для конкретного объекта, чтобы активировать его для пользовательского ввода. Итак, чтобы «создать» меню, вы должны использовать объект UIKit или объект Sprite Kit.

В следующем примере SKLabelNode используется в качестве элемента меню. Сначала мы определим SKLabelNode :

1
2
3
4
5
SKLabelNode* gameScene = [SKLabelNode labelNodeWithFontNamed:@»Chalkduster»];
[gameScene setText:@»New Game»];
[gameScene setFontSize:18];
[gameScene setPosition:CGPointMake(CGRectGetMidX(self.frame)+5,CGRectGetMidY(self.frame)-40)];
[self addChild:gameScene];

Внутри -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event мы создадим обработчик события, который будет перехватывать событие касания:

01
02
03
04
05
06
07
08
09
10
11
12
13
for (UITouch *touch in touches)
{
    CGPoint location = [touch locationInNode:self];
         
    if ([gameScene containsPoint:location]) {
        // Scene Transition Animation
        SKTransition* reveal = [SKTransition revealWithDirection:SKTransitionDirectionDown duration:1];
        GameScene* gameScene = [[GameScene alloc] initWithSize:CGSizeMake(1024, 768)];
        [self.scene.view presentScene:gameScene transition:reveal];
             
        NSLog(@»Touched gameScene!!!!»);
    }
}

Вышеупомянутый код делает несколько вещей:

  1. Активирует сенсорные события.
  2. Преобразует местоположение крана во внутреннее местоположение.
  3. Проверяет, находится ли местоположение крана внутри объекта gameScene SKLabelNode .
  4. Создает анимацию перехода.
  5. Меняет сцену.

Основное различие между Action и SKAction заключается в том, что SKAction является сложным объектом с несколькими свойствами. Действие в Cocos2D — это только действие, которое программист должен определить, вызвать и обработать.

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

Мы сосредоточимся на действиях движения.

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

1
[self schedule:@selector(addSprite:) interval:1];

А затем определите пользовательский метод для создания пользовательской анимации.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
— (void) addSprite:(ccTime)dt
{
     
    CCSprite* aMovableSprite = [CCSprite spriteWithFile:@»frankenstein.png»];
    aMovableSprite.scale = .8;
    [self addChild:aMovableSprite];
     
    CGSize winSize = [CCDirector sharedDirector].winSize;
    int minX = aMovableSprite.contentSize.width / 2;
    int maxX = winSize.width — aMovableSprite.contentSize.width/2;
    int rangeX = maxX — minX;
    int actualY = (arc4random() % rangeX) + minX;
 
    CCCallBlockN * actionMoveDone = [CCCallBlockN actionWithBlock:^(CCNode *node) {
        NSLog(@»Sprite free!»);
    }];
     
    NSMutableArray *arrayBezier = [[NSMutableArray alloc] init];
    ccBezierConfig bezier;
    id bezierAction1;
    float splitDuration = 6 / 6.0;
    for(int i = 0; i< 6; i++){
         
        if(i % 2 == 0){
            bezier.controlPoint_1 = ccp(actualY+100,winSize.height-(100+(i*200)));
            bezier.controlPoint_2 = ccp(actualY+100,winSize.height-(100+(i*200)));
            bezier.endPosition = ccp(actualY,winSize.height-(200+(i*200)));
            bezierAction1 = [CCBezierTo actionWithDuration:splitDuration bezier:bezier];
        }
        else{
            bezier.controlPoint_1 = ccp(actualY-100,winSize.height-(100+(i*200)));
            bezier.controlPoint_2 = ccp(actualY-100,winSize.height-(100+(i*200)));
            bezier.endPosition = ccp(actualY,winSize.height-(200+(i*200)));
            bezierAction1 = [CCBezierTo actionWithDuration:splitDuration bezier:bezier];
        }
         
        [arrayBezier addObject:bezierAction1];
    }
     
    [arrayBezier addObject:actionMoveDone];
     
    id seq = [CCSequence actionsWithArray:arrayBezier];
     
    [aMovableSprite runAction:seq];
}

В Sprite Kit мы можем использовать SKAction для управления тем, что происходит с объектом в начале и в конце движения. Следующие строки показывают, как перемещать любой объект по прямой линии:

1
2
3
4
5
6
7
SKSpriteNode* playerSprite = [SKSpriteNode spriteNodeWithImageNamed:@»player.png»];
[playerSprite setScale:0.4];
         
SKAction *movement =[SKAction moveTo:CGPointMake(900, 500) duration:5];
SKAction *remove = [SKAction removeFromParent];
[playerSprite runAction:[SKAction sequence:@[movement,remove]]];
[self addChild:playerSprite];

Однако мы можем определить настраиваемое действие и использовать SKAction для его активации. Следующий пример иллюстрирует движение Безье (аналогично версии Cocos2D Action). Обратите внимание, что мы должны определить планировщик для вызова пользовательского метода.

1
2
3
4
5
6
7
SKAction *wait = [SKAction waitForDuration:1];
SKAction *callEnemies = [SKAction runBlock:^{
    [self sendNewSKSpriteNode];
}];
         
SKAction *updateSKSpriteNodeOnScreen = [SKAction sequence:@[wait,callEnemies]];
[self runAction:[SKAction repeatActionForever:updateSKSpriteNodeOnScreen]];

Метод sendNewSKSpriteNode будет обрабатывать перемещение пользовательских объектов.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
-(void) sendNewSKSpriteNode{
    CGRect screenRect = [[UIScreen mainScreen] bounds];
     
    // Custom SKAction
    SKSpriteNode* enemy = [SKSpriteNode spriteNodeWithImageNamed:@»frankenstein.png»];
    enemy.scale = 0.6;
     
    CGMutablePathRef cgpath = CGPathCreateMutable();
     
    //random values
    float xStart = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.width ];
    float xEnd = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.width ];
     
    //ControlPoint1
    float cp1X = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.width ];
    float cp1Y = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.height ];
     
    //ControlPoint2
    float cp2X = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.width ];
    float cp2Y = [self getRandomNumberBetween:0 to:cp1Y];
     
    CGPoint s = CGPointMake(xStart, 1024.0);
    CGPoint e = CGPointMake(xEnd, -100.0);
    CGPoint cp1 = CGPointMake(cp1X, cp1Y);
    CGPoint cp2 = CGPointMake(cp2X, cp2Y);
    CGPathMoveToPoint(cgpath,NULL, sx, sy);
    CGPathAddCurveToPoint(cgpath, NULL, cp1.x, cp1.y, cp2.x, cp2.y, ex, ey);
     
    SKAction *planeDestroy = [SKAction followPath:cgpath asOffset:NO orientToPath:YES duration:5];
    [self addChild:enemy];
     
    SKAction *remove2 = [SKAction removeFromParent];
    [enemy runAction:[SKAction sequence:@[planeDestroy,remove2]]];
     
    CGPathRelease(cgpath);
}

Cocos2D не имеет какого-либо редактора частиц. Нужно использовать внешнее приложение для создания частицы, а затем использовать определенные свойства CCParticleExplosion чтобы изменить ее поведение. После того, как у вас есть частица в вашем проекте Xcode, вы можете вызвать ее, используя

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
CCParticleExplosion* _particleExplosion;
particleExplosion = [[CCParticleExplosion alloc] initWithTotalParticles:800];
particleExplosion.texture = [[CCTextureCache sharedTextureCache] addImage:@»texture.png»];
particleExplosion.life = 0.0f;
particleExplosion.lifeVar = 0.708f;
particleExplosion.startSize = 40;
particleExplosion.startSizeVar = 38;
particleExplosion.endSize = 14;
particleExplosion.endSizeVar = 0;
particleExplosion.angle = 360;
particleExplosion.angleVar = 360;
particleExplosion.speed = 243;
particleExplosion.speedVar = 1;
 
CGPoint g = CGPointMake(1.15, 1.58);
particleExplosion.gravity = g;
ccColor4F startC = {0.89f, 0.56f, 0.36f, 1.0f};
particleExplosion.startColor = startC;
ccColor4F endC = {1.0f,0.0f,0.0f,1.0f};
particleExplosion.endColor = endC;
     
[self addChild:_particleExplosion];
particleExplosion.position = ccp(_size.width/5, _size.height/5);
[particleExplosion resetSystem];

Излучатели используются в Sprite Kit для генерации частиц. Чтобы использовать их, вам нужно добавить частицу в ваш проект. Перейдите в New -> File -> Resource -> Sprite Kit Particle File . Затем вы должны назвать его и выбрать любой тип частиц (огонь, магия, дым, снег, среди прочих). Теперь вы увидите, что в вашем проекте XCode появятся два новых файла. Вы реализуете их с помощью:

1
2
3
4
5
SKEmitterNode* smokeTrail;
NSString *smokePath = [[NSBundle mainBundle] pathForResource:@»MyParticle» ofType:@»sks»];
smokeTrail = [NSKeyedUnarchiver unarchiveObjectWithFile:smokePath];
smokeTrail.position = CGPointMake(CGRectGetMidX(self.frame)+40,CGRectGetMidY(self.frame)-100);
[self addChild:smokeTrail];

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

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

1
#import «SimpleAudioEngine.h»

Затем вы используете следующие строки для вызова музыкального файла внутри нашего проекта:

1
2
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@»sound.caf» loop:YES];
[[SimpleAudioEngine sharedEngine] setEffectsVolume:0.4f];

Иногда XCode автоматически не включает музыкальный файл в «Копирование ресурсов». Если это произойдет, вы должны добавить его вручную.

С набором Sprite включение звуков является простым:

1
2
SKAction* soundAction = [SKAction playSoundFileNamed:@»preview.mp3″ waitForCompletion:NO];
[self runAction:soundAction];

Обратите внимание, что для достижения этого с помощью Sprite Kit вы снова использовали объект SKAction.


Как видно из приведенного выше анализа, Cocos2D и Sprite Kit имеют много общего. Cocos2D использует несколько слоев для каждого объекта, тогда как Sprite Kit инкапсулирует больше объектов и использует суперкласс NSObject для достижения определенных целей (таких как кнопки или меню).

С точки зрения удобства для пользователя, Sprite Kit действительно сияет, когда вы хотите использовать систему Particle или Action action. Однако при работе с более общими объектами обе платформы находятся примерно на одном уровне сложности.

Тем не менее, создание игры с использованием Sprite Kit дает много ключевых преимуществ, включая полностью интегрированный физический движок, оптимизированные инструменты рабочего процесса в Xcode 5, совместимость с iOS и OS X и официальное обслуживание Apple.

Вопрос в том, что вы будете использовать для своего следующего проекта 2D-игры? Дайте нам знать об этом в комментариях.