Статьи

iOS SDK: создание игры с фактами — настройка проекта

Из этого туториала вы узнаете, как использовать среду Sprite Kit для создания игры с фактами на основе вопросов. Он предназначен как для начинающих, так и для опытных пользователей. По пути вы будете применять ядро ​​Sprite Kit. Серия Facts Game состоит из трех учебных пособий, чтобы полностью охватить каждую тему.


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

В конце этого урока результат будет выглядеть так:

image0
Законченная Игра Фактов

Запустите новый проект SpriteKit Xcode и назовите его Facts . Информация о развертывании, используемая в трех частях:

  • Цель развертывания: 7
  • Устройства: iPad
  • Ориентация устройства: портрет
  • Скрыть стиль строки состояния

Обратите внимание, что следующие четыре фреймворка автоматически включаются в проект: CoreGraphics , UIKit , SpriteKit и Foundation . Вы увидите три класса, изображение ( Spaceship.png ) и файл Main.storyboard . Вы можете удалить изображение, так как вы не будете его использовать.

Теперь откройте Myscene.m и закомментируйте все -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event метода -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event . Вам не нужно создавать жест касания в этой сцене, потому что вы будете использовать несколько UIKit UIButtons для взаимодействия с пользователем.


Начните с изменения цвета фона SKScene, изменив свойства self.backgroundColor . Обратите внимание, что он использует объект SKColor с тремя свойствами для красного, синего и зеленого компонентов. Теперь измените текст myLabel на «Факты !!» или к любому другому названию вашего интереса.

Следующим шагом является добавление необходимых ресурсов в ваш проект; найдите их в папке «Ресурсы». Несмотря на то, что вы не будете сейчас использовать все ресурсы, вам следует добавить их все. Поскольку вы будете использовать инфраструктуру UIKit, добавьте специальный метод -(void) didMoveToView:(SKView *)view которое определяет, произошел ли переход сцены без проблем. Если проблем не возникает, приложение загружает ресурсы на экран. Добавьте этот метод в свой код. Внутри вы объявите три кнопки: одну для запуска игры, одну для опций и последнюю для выхода из приложения.

Добавьте три UIButtons на свой MyScene.m . Это будет выглядеть так:

1
2
3
4
5
@implementation MyScene {
    UIButton *startButton;
    UIButton *optionsButton;
    UIButton *exitButton;
}

Каждая кнопка имеет определенные конфигурации, касающиеся расположения и размера рамки, цвета фона и фонового изображения. Вы должны попытаться создать UIButton и добавить его в вид сцены. Кнопки должны выглядеть следующим образом:

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
-(void) didMoveToView:(SKView *)view{
 
    startButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    startButton.frame = CGRectMake(CGRectGetMidX(self.frame)-100, CGRectGetMidY(self.frame), 200, 70.0);
    startButton.backgroundColor = [UIColor clearColor];
    [startButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal ];
    UIImage *buttonImageNormal = [UIImage imageNamed:@»StartBtn.png»];
    UIImage *strechableButtonImageNormal = [buttonImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
    [startButton setBackgroundImage:strechableButtonImageNormal forState:UIControlStateNormal];
    [self.view addSubview:startButton];
 
    optionsButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    optionsButton.frame = CGRectMake(CGRectGetMidX(self.frame)-100, CGRectGetMidY(self.frame)+90, 200, 70.0);
    optionsButton.backgroundColor = [UIColor clearColor];
    [optionsButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal ];
    UIImage *buttonOptionsImageNormal = [UIImage imageNamed:@»OptionsBtn.png»];
    UIImage *strechableButtonOptionsImageNormal = [buttonOptionsImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
    [optionsButton setBackgroundImage:strechableButtonOptionsImageNormal forState:UIControlStateNormal];
    [self.view addSubview:optionsButton];
 
    exitButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    exitButton.frame = CGRectMake(CGRectGetMidX(self.frame)-100, CGRectGetMidY(self.frame)+180, 200, 70.0);
    exitButton.backgroundColor = [UIColor clearColor];
    [exitButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal ];
    UIImage *buttonExitImageNormal = [UIImage imageNamed:@»ExitBtn.png»];
    UIImage *strechableButtonExitImageNormal = [buttonExitImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
    [exitButton setBackgroundImage:strechableButtonExitImageNormal forState:UIControlStateNormal];
    [self.view addSubview:exitButton];
 
}

Run проект и увидите новый корневой интерфейс. Если вы хотите, вы можете настроить местоположение, размер и положение объектов интерфейса. Если вы хотите узнать больше о SKLabelNode или UIButton , я советую вам поиграть с этими классами немного больше. Интерфейс должен выглядеть примерно так:

Изображение1
Корневой интерфейс

Настало время добавить больше классов в ваш проект.


Поскольку вы добавили несколько кнопок, теперь пришло время использовать их для перенаправления пользователя на другой интерфейс. Добавьте два новых класса. Выберите « Файл»> «Создать»> «Файл» и класс Objective-C . Назовите классы FactsScene и OptionsScene . Обратите внимание, что оба будут суперклассом SKScene .

В вашем проекте доступны четыре новых файла: FactsScene.h , FactsScene.m , OptionsScene.h и OptionsScene.m . Обратите внимание, что файлы реализации обоих классов практически пусты. Следовательно, вы должны добавить инициализаторы класса. Для обоих классов используйте -initWithSize: метод. Попробуйте и добавьте это самостоятельно. Если у вас возникли проблемы, вам поможет следующий фрагмент кода:

1
2
3
4
5
6
-(id)initWithSize:(CGSize)size{
    if (self = [super initWithSize:size]) {
        NSLog(@»Opstions Scene»);
    }
    return self;
}

Еще раз вы должны применить его для обоих классов. Теперь, когда у вас есть инициализаторы классов, пришло время изменить код UIButton с последнего шага для переключения между классами. Вернитесь на MyScene.m и импортируйте оба класса в разделе импорта:

1
2
#import «OptionsScene.h»
#import «FactsScene.h»

Теперь в startButton , optionsButton и exitButton вам нужно добавить пользовательское действие. На каждую кнопку добавьте соответствующую строку кода.

1
2
3
[startButton addTarget:self action:@selector(moveToGame) forControlEvents:UIControlEventTouchUpInside];
[optionsButton addTarget:self action:@selector(moveToOptions) forControlEvents:UIControlEventTouchUpInside];
[exitButton addTarget:self action:@selector(endApplication) forControlEvents:UIControlEventTouchUpInside];

Вы должны увидеть три предупреждения («необъявленный селектор»). Не волнуйся! Настало время добавить эти методы в ваш класс.

1
2
3
-(void) moveToGame {}
-(void) moveToOptions {}
-(void) endApplication {}

Каждый отвечает за определенное действие, а название каждого метода говорит само за себя. -(void) moveToGame и -(void) moveToOptions похожи, поскольку оба используются для создания перехода из этого SKScene в другой. В каждом методе вы должны создать целевой объект SKScene и объект перехода и представить новую сцену. Обратите внимание, что, поскольку вы используете объекты UIKit, вам также необходимо удалить их со сцены при переходах SKScene . Если у вас возникли проблемы с этими шагами, вам помогут следующие фрагменты:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
-(void) moveToGame{
    NSLog(@»moveToGame»);
    FactsScene* factsScene = [[FactsScene alloc] initWithSize:CGSizeMake(CGRectGetMaxX(self.frame), CGRectGetMaxY(self.frame))];
    SKTransition* transition = [SKTransition revealWithDirection:SKTransitionDirectionUp duration:1];
    [startButton removeFromSuperview];
    [optionsButton removeFromSuperview];
    [exitButton removeFromSuperview];
    [self.scene.view presentScene:factsScene transition:transition];
}
 
-(void) moveToOptions{
    NSLog(@»moveToOptions»);
    OptionsScene* optionsScene = [[OptionsScene alloc] initWithSize:CGSizeMake(CGRectGetMaxX(self.frame), CGRectGetMaxY(self.frame))];
    SKTransition* transition = [SKTransition revealWithDirection:SKTransitionDirectionLeft duration:1];
    [startButton removeFromSuperview];
    [optionsButton removeFromSuperview];
    [exitButton removeFromSuperview];
    [self.scene.view presentScene:optionsScene transition:transition];
}

Последний метод -(void) endApplication — проще, поскольку он используется только для завершения приложения.

1
2
3
4
5
6
-(void) endApplication{
    [startButton removeFromSuperview];
    [optionsButton removeFromSuperview];
    [exitButton removeFromSuperview];
    exit(0);
}

Настало время Run код и протестировать новые функции. Если все в порядке, вы сможете изменить вид по умолчанию на представление « New Game и « Options . Однако вы не можете вернуться в главное меню. Давайте изменим это прямо сейчас.

Следующие шаги — добавить кнопку UIB в сцену Options , запрограммировать ее для перехода обратно в главное меню и выбрать создание эффекта перехода (или нет). Для этого необходимо выполнить несколько шагов:

  • Добавьте -(void) didMoveToView:(SKView *)view метод представления
  • Добавить объект UIButton
  • Настройте UIButton
  • Добавьте метод @selector
  • Импортируйте MyScene.h

Сначала перейдите в OptionsScene.h и добавьте:

1
@property (nonatomic, retain) UIButton* backButton;

Теперь переключите ваше внимание на OptionsScene.m . didMoveToView псевдокода должны добавить метод didMoveToView, UIButton и конфигурацию кнопки.

01
02
03
04
05
06
07
08
09
10
11
-(void) didMoveToView:(SKView *)view{
  _backButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
  _backButton.frame = CGRectMake(CGRectGetMidX(self.frame)-100, CGRectGetMidY(self.frame)+180, 200, 70.0);
  _backButton.backgroundColor = [UIColor clearColor];
  [_backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal ];
  UIImage *buttonExitImageNormal = [UIImage imageNamed:@»ExitBtn.png»];
  UIImage *strechableButtonExitImageNormal = [buttonExitImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
  [_backButton setBackgroundImage:strechableButtonExitImageNormal forState:UIControlStateNormal];
  [_backButton addTarget:self action:@selector(moveToHome) forControlEvents:UIControlEventTouchUpInside];
  [self.view addSubview:_backButton];
  }

Затем добавьте метод @selector .

1
2
3
4
5
-(void) moveToHome{
  MyScene* myScene = [[MyScene alloc] initWithSize:CGSizeMake(CGRectGetMaxX(self.frame), CGRectGetMaxY(self.frame))];
  [_backButton removeFromSuperview];
  [self.scene.view presentScene:myScene];
}

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


Опции игры — это то, где пользователь может изменить настройки игры. На данный момент вы сосредоточитесь только на двух вариантах: музыка и звук. Вам нужно добавить SKLabelNode , UISwitch и объект OptionsScene.h в OptionsScene.h :

1
2
3
4
@property (nonatomic, retain) IBOutlet UISwitch *musicSwitch;
@property (nonatomic, retain) IBOutlet UISwitch *soundSwitch;
@property (nonatomic, retain) SKLabelNode* soundTitle;
@property (nonatomic, retain) SKLabelNode* musicTitle;

Затем на OptionsScene.m внутри метода didMoveToView выделите объекты как:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
_soundSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.frame)+50, CGRectGetMidY(self.frame)-26, 100, 100)];[_soundSwitch addTarget: self action: @selector(flipMusicAndSound:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview: _soundSwitch];
 
_musicSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.frame)+50, CGRectGetMidY(self.frame)+50, 100, 100)];
[_musicSwitch addTarget: self action: @selector(flipMusicAndSound:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview: _musicSwitch];
 
_soundTitle = [SKLabelNode labelNodeWithFontNamed:@»Chalkduster»];
[_soundTitle setText:@»Sound»];
[_soundTitle setFontSize:40];
[_soundTitle setPosition:CGPointMake(CGRectGetMidX(self.frame)-80, CGRectGetMidY(self.frame))];
[self addChild:_soundTitle];
 
_musicTitle = [SKLabelNode labelNodeWithFontNamed:@»Chalkduster»];
[_musicTitle setText:@»Music»];
[_musicTitle setFontSize:40];
[_musicTitle setPosition:CGPointMake(CGRectGetMidX(self.frame)-80, CGRectGetMidY(self.frame)-80)];
[self addChild:_musicTitle];

Вы получите предупреждение. Чтобы исправить это, добавьте метод flipMusicAndSound . Этот метод проверяет состояние _soundSwitch и _musicSwitch UISwitches и устанавливает ключ по умолчанию для каждого свойства, используя NSUserDefaults . Прежде чем завершить метод, вы должны добавить объект NSUserDefaults в класс.

1
2
3
@implementation OptionsScene{
    NSUserDefaults* defaults;
}

Затем вы должны выделить его в методе initWithSize следующим образом:

1
defaults = [NSUserDefaults standardUserDefaults];

Теперь вы готовы использовать преимущества NSUserDefaults . Вы будете использовать его для хранения состояния звука и музыкальных свойств во всем приложении. Вы можете написать и заполнить метод flipMusicAndSound . Вы будете использовать integer значение 1, чтобы включить звук и музыку, и 0 в противном случае. flipMusicAndSound находится ниже.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
— (IBAction)flipMusicAndSound:(id)sender {
    if (_musicSwitch.on) {
        [defaults setInteger:1 forKey:@»music»];
    }
    else {
        [defaults setInteger:0 forKey:@»music»];
    }
 
    if (_soundSwitch.on) {
        [defaults setInteger:1 forKey:@»sound»];
    }
    else {
        [defaults setInteger:0 forKey:@»sound»];
    }
}

Если вы Run проект и OptionsScene с обоими переключателями, вы увидите, что каждый раз, когда вы переходите к OptionsScene оба переключателя имеют состояние по умолчанию, а не последнее определенное состояние. Чтобы изменить это, мы должны прочитать объект didMoveToView методе didMoveToView .

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
long soundDefaults = [defaults integerForKey:@»sound»];
long musicDefaults = [defaults integerForKey:@»music»];
 
if (soundDefaults == 1) {
  [_soundSwitch setOn:YES animated:YES];
}
else {
  [_soundSwitch setOn:FALSE animated:YES];
}
 
if (musicDefaults == 1) {
  [_musicSwitch setOn:YES animated:YES];
} else{
  [_musicSwitch setOn:FALSE animated:YES];
}

Последний шаг в файле OptionsScene.m — удаление элементов UISwitch из суперпредставления каждый раз, когда пользователь нажимает кнопку «Назад»:

1
2
[_soundSwitch removeFromSuperview];
[_musicSwitch removeFromSuperview];

Вот иллюстрация интерфейса параметров:

Image2
Варианты интерфейса

Перейти на FactsScene.m . Теперь мы можем добавить элементы звука и музыки. Как и в случае с OptionsScene , нам нужно использовать NSUserDefaults чтобы получить значение для музыки и звука. Нам также понадобится объект для хранения музыкального пути, а другой — для музыкального проигрывателя iOS. Таким образом, мы объявим их как:

1
2
3
4
@implementation FactsScene{
    NSUserDefaults* defaults;
    NSString* musicPath;
}

Также в FactsScene.h :

1
@property (nonatomic, strong) AVAudioPlayer* musicPlayer;

Вы должны объявить (как вы сделали с последним классом) метод -(void) didMoveToView:(SKView *)view . Внутри вы должны проверить, включены ли музыкальные и звуковые настройки, и выделить музыкальные предпочтения. Оба могут быть достигнуты через:

01
02
03
04
05
06
07
08
09
10
11
musicPath = [[NSBundle mainBundle] pathForResource:@»music» ofType:@»mp3″];
_musicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:musicPath] error:NULL];
_musicPlayer.numberOfLoops = -1;
_musicPlayer.volume = 0.7;
 
long musicFlag = [defaults integerForKey:@»music»];
if (musicFlag == 1){
  [_musicPlayer play];
} else {
  [_musicPlayer stop];
}

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

Вы помните — -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event из MyScene.m реализации MyScene.m ? Вы определите это и будете использовать его здесь.

1
2
3
4
5
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    for (UITouch *touch in touches) {
        [self touchWillProduceASound:@»False»];
    }
}

Обратите внимание, что -(void) touchWillProduceASound:(NSString*)answer еще не объявлен. Объявите это. Он используется для проверки того, является ли данное касание «правильным» или «неправильным» (об этом будет больше в следующем уроке). Он анализирует (NSString*)answer и издает звук в соответствии с содержимым этой NSString.

Звук создается с SKAction объекта SKAction . Создает звуковой объект и воспроизводит определенный звук. Еще раз, это происходит, только если свойство звука (заданное NSUserDefaults ) NSUserDefaults .

01
02
03
04
05
06
07
08
09
10
11
12
-(void) touchWillProduceASound:(NSString*)answer{
    long soundFlag = [defaults integerForKey:@»sound»];
 
    if (soundFlag == 1){
        SKAction* sound;
        if ([answer isEqualToString:@»False»]) {
            sound = [SKAction playSoundFileNamed:@»beep.mp3″ waitForCompletion:YES];
            NSLog(@»inside»);
        }
        [self runAction:sound];
    }
}

Запустите проект и протестируйте новые музыкальные и звуковые взаимодействия. Активируйте и деактивируйте звуковые и музыкальные переключатели UIS и перейдите на новую игровую сцену, чтобы проверить их правильность.


Это конец первого урока! На этом этапе вы можете инициировать и настраивать проект SpriteKit, добавлять и инициализировать объекты SKScene , перемещаться между объектами SKScene , взаимодействовать между средами SpriteKit и UIKit, а также добавлять и удалять звуки и музыку. В следующих уроках вы будете иметь дело с созданием интерфейса и игровой логикой.