meteor.positionX = arc4random_uniform(SCREEN_WIDTH());
meteor.positionY = SCREEN_HEIGHT();
meteor.position = ccp(meteor.positionX, meteor.positionY);
return meteor;
}
@end
Repare que o objeto meteoro permanece vivo na memória por um bom tempo.
Ele é criado e, a cada frame, renderizado em uma posição diferente, dando a impres-são de movimento.
Aqui mais uma vez o framework nos ajuda. Para que cada frame seja renderizado
durante o jogo, e a posição do objeto mude com o passar do tempo, o Cocos2D
nos permite escolher um método que será invocado de tempo em tempo. Isso será
definido no start, fazendo scheduleUpdate, que invocará o método update.
86
Casa do Código
Capítulo 5. Tela do jogo e objetos inimigos
//...
- (void)start
{
[self scheduleUpdate];
}
- (void)update:(float)dt
{
self.positionY -= 1;
self.position = ccp(self.positionX, self.positionY);
}
Variável dt dos updates
O Cocos2D vai tentar invocar o seu método update de x em x milis-
segundos, isso é, em cada frame. Mas, por uma série de motivos, o pro-
cessador pode estar ocupado com outras coisas, fazendo com que essa
chamada agendada não ocorra quando você queria. Ele pode demorar
mais. Nesse caso, vai dar uma impressão que seu jogo está lento, já que
a tela será renderizada como se só tivesse passado o tempo de um frame,
mas na verdade pode ter passado alguns segundos.
Num jogo profissional, você deve guardar essa informação para deci-
dir corretamente quantos pixels cada objeto deve mudar. No nosso caso,
se o dt for maior que o de 1 frame, deveríamos descer o meteoro mais
que 1 pixel, fazendo a regra de 3.
5.5
Tela do game
Agora que temos nossa classe
Meteor, vamos alterar o protocolo da
MeteorsEngine.h para que passe um objeto meteoro como parâmetro:
# import "Meteor.h"
//...
@protocol MeteorsEngineDelegate <NSObject>
- (void)meteorsEngineDidCreateMeteor:(Meteor *)meteor;
@end
Na MeteorsEngine.m passaremos um novo meteoro como parâmetro para o
delegate:
87
5.5. Tela do game
Casa do Código
- (void)meteorsEngine:(float)dt
{
// sorte: 1 em 30 gera um novo meteoro!
if(arc4random_uniform(30) == 0) {
if ([self.delegate respondsToSelector:
@selector(meteorsEngineDidCreateMeteor:)]){
// Pede para o delegate criar o meteoro
[self.delegate meteorsEngineDidCreateMeteor:
[Meteor meteorWithImage:kMETEOR]];
}
}
}
Para fechar e criar o link entre a classe da tela do jogo, com a engine de meteoros e com os objetos meteoros criados, modificaremos a classe GameScene.
Primeiramente, vamos criar um método que conterá a inicialização dos objetos
de jogo. Crie o método addGameObjects:
- (void)addGameObjects
{
// Inicializa os Arrays
self.meteorsArray = [NSMutableArray array];
// Inicializa a Engine de Meteoros
self.meteorsEngine = [MeteorsEngine meteorEngine];
}
No construtor, criaremos um layer especialmente para os meteoros e adiciona-
remos a tela do jogo via addChild. Declare a propriedade meteorsLayer na
GameScene.h:
//...
// Layers
@property (nonatomic, retain) CCLayer *meteorsLayer;
No init da GameScene.m criaremos a layer de meteoros e invocaremos o
addGameObjetos. Ficará assim:
- (id)init
{
self = [super init];
88
Casa do Código
Capítulo 5. Tela do jogo e objetos inimigos
if (self) {
// Imagem de Background
CCSprite *background = [CCSprite spriteWithFile:kBACKGROUND];
background.position =
ccp(SCREEN_WIDTH() / 2.0f, SCREEN_HEIGHT() / 2.0f);
[self addChild:background];
// CCLayer para os Meteoros
self.meteorsLayer = [CCLayer node];
[self addChild:self.meteorsLayer];
[self addGameObjects];
}
return self;
}
E agora podemos alterar o método meteorsEngineDidCreateMeteor: para
incluir o meteoro na tela e iniciá-lo:
- (void)meteorsEngineDidCreateMeteor:(Meteor *)meteor
{
// A Engine de Meteoros indicou que um novo Meteoro foi criado
[self.meteorsLayer addChild:meteor];
[meteor start];
[self.meteorsArray addObject:meteor];
}
Um
método importante que utilizaremos aqui é o onEnter. Ele é invocado pelo
Cocos2D assim que a tela do game está pronta para orquestrar os objetos do jogo.
Ele será a porta de entrada do jogo. Por enquanto, simplesmente adicionaremos o
meteorsEngine e indicaremos o delegate como self, para sermos avisados
quando novos meteoros forem criados:
//...
- (void)onEnter
{
[super onEnter];
[self startGame];
}
- (void)startGame
89
5.6. Conclusão
Casa do Código
{
[self startEngines];
}
- (void)startEngines
{
[self addChild:self.meteorsEngine];
self.meteorsEngine.delegate = self;
}
5.6
Conclusão
Temos agora a tela de abertura e a tela de jogo (onde o game loop é executado) em funcionamento. Nosso game loop inicializa os inimigos. Precisamos de um player
para jogar contra eles, é o que veremos a seguir!
90
Casa do Código
Capítulo 5. Tela do jogo e objetos inimigos
Figura 5.2: Meteoros inimigos.
91
Capítulo 6
Criando o Player
Tela do jogo preparada e inimigos aparecendo! Cenário perfeito para iniciarmos o
desenvolvimento do player! Essa é uma parte bem interessante no desenvolvimento