queremos que o método removeMe: seja invocado depois de a animação terminar.
- (void)removeMe:(id)sender
{
116
Casa do Código
Capítulo 7. Detectando colisões, pontuando e criando efeitos
// Quando o Meteoro é removido, limpa a memória utilizada pelo mesmo
[self removeFromParentAndCleanup:YES];
}
Animando o tiro
Utilizaremos o mesmo pensamento para animar o tiro quando colidir com um
meteoro. Para isso, criaremos o método explode na classe Shoot, alterando ape-
nas alguns parâmetros.
Esse método terá que executar algumas ações:
Parar o agendamento da movimentação do meteoro
Animar a explosão do meteoro
Limpar o objeto da memória
Vamos declarar o método na Meteor.h:
- (void)explode;
Agora implemente o método na Meteor.m:
- (void)explode
{
// Para o agendamento
[self unscheduleUpdate];
// Cria efeitos
float dt = 0.2f;
CCScaleBy *a1 = [CCScaleBy actionWithDuration:dt scale:2.0f];
CCFadeOut *a2 = [CCFadeOut actionWithDuration:dt];
CCSpawn *s1 = [CCSpawn actionWithArray:
[NSArray arrayWithObjects:a1, a2, nil]];
// Método a ser executado após efeito
CCCallFunc *c1 = [CCCallFunc actionWithTarget:self
selector:@selector(removeMe:)];
// Executa efeito
[self runAction:[CCSequence actionWithArray:
[NSArray arrayWithObjects:s1, c1, nil]]];
}
117
7.2. Efeitos
Casa do Código
Para limpar o objeto da memória, chamaremos novamente o método do Co-
cos2D chamado removeFromParentAndCleanup:.
- (void)removeMe:(id)sender
{
// Quando o Tiro é removido, limpa a memória utilizada pelo mesmo
[self removeFromParentAndCleanup:YES];
}
Já temos o código que o meteoro deve executar quando uma co-
lisão for detectada.
Agora precisamos fazer a chamada a ele nos mo-
mento de colisão.
Voltando à classe
GameScene
temos o método
checkRadiusHitsOfArray:againstArray:withSender:andCallbackMethod:,
que percorre dois arrays e verifica intersecções.
Nesse método, quando dois objetos estiverem colidindo, algo deve ser feito. Essa
é uma parte importante do jogo e precisa de muito cuidado. Repare que o nosso
método de detecção é genérico, ou seja, ele recebe dois arrays de objetos e analisa se ocorre colisão entre eles. No momento que essa colisão é detectada, ele precisará executar algo que pode ser a explosão da nave ou a explosão de um meteoro.
É importante perceber que a decisão de qual método rodar após detectada a co-
lisão é em tempo de execução, e precisaremos invocá-lo via performSelector:.
No
arquivo
GameScene.m
altere
o
método
checkRadiusHitsOfArray:againstArray:withSender:andCallbackMethod:.
//...
// Verifica colisão
if (CGRectIntersectsRect(rect1, rect2)) {
NSLog(@"Colisão Detectada: %@",
NSStringFromSelector(callbackMethod));
result = YES;
// Se o sender possui o método indicado na chamada do método,
// executa o mesmo com os objetos encontrados nos arrays
if ([sender respondsToSelector:callbackMethod]) {
[sender performSelector:callbackMethod
withObject:[array1 objectAtIndex:i]
withObject:[array2 objectAtIndex:j]];
}
// Se encontrou uma colisão, sai dos 2 loops
118
Casa do Código
Capítulo 7. Detectando colisões, pontuando e criando efeitos
i = [array1 count] + 1;
j = [array2 count] + 1;
}
A partir daqui, basta fazer as chamadas aos métodos gotShot e explode. Na
GameScene.m adicione o método meteorHit:withShoot::
- (void)meteorHit:(id)meteor withShoot:(id)shoot
{
// Quando houve uma colisão entre Meteoro e Tiro, indica que
// o Meteoro foi atingido e que o Tiro deve explodir
if ([meteor isKindOfClass:[Meteor class]]) {
[(Meteor *)meteor gotShot];
}
if ([shoot isKindOfClass:[Shoot class]]) {
[(Shoot *)shoot explode];
}
}
Rode o projeto e teste o que fizemos até aqui!
Removendo objetos
Precisamos lembrar que embora os objetos não estejam mais aparecendo na tela
eles continuam alocados na memória, ou seja, ainda não foram removidos. Cria-
remos agora o código que eliminará os objetos dos arrays após colisão entre tiro e meteoro.
Primeiramente, vamos criar um delegate para nossa classe Meteor para que ela
avise quando deverá ser removida. Declare o protocolo e delegate na Meteor.h:
@protocol MeteorDelegate;
@interface Meteor : CCSprite
@property (nonatomic, assign) float positionX;
@property (nonatomic, assign) float positionY;
@property (nonatomic, assign) id<MeteorDelegate>delegate;
+ (Meteor *)meteorWithImage:(NSString *)image;
119
7.2. Efeitos
Casa do Código
- (void)start;
- (void)gotShot;
@end
@protocol MeteorDelegate <NSObject>
- (void)meteorWillBeRemoved:(Meteor *)meteor;
@end
Altere o método gotShot para que o meteoro notifique seu delegate de que ele
será removido:
- (void)gotShot
{
//...
// Notifica delegate
if ([self.delegate respondsToSelector:
@selector(meteorWillBeRemoved:)])
{
[self.delegate meteorWillBeRemoved:self];
}
}
Faremos a mesma coisa para a classe Shoot. Declare o protocolo e delegate na
Shoot.h:
@protocol ShootDelegate;
@interface Shoot : CCSprite
@property (nonatomic, assign) id<ShootDelegate>delegate;