miércoles, 10 de agosto de 2011

Tutorial Cocos2D: Juego completo (parte 3)

Y ahora, el tutorial está llegando a su fin, esta es la tercera parte de un total de cuatro partes, y en esta en concreto, explicaré la lógica de juego, la detección de toques en la pantalla, el "montaje" del escenario, barras de progreso (CCProgressTimer) y como crear unas partículas en Cocos2D.

Como de costumbre, escribiré aquí la cabecera de la clase "JuegoLayer" la cual contendrá información sobre todo lo relativo al juego, como monstruos, animaciones y puntuaciones.





#import "cocos2d.h"
#import "Monstruo.h"
#import "MenuScene.h"
#import "Mazo.h"

@interface JuegoLayer : CCLayer{
    CCSpriteBatchNode *graficos;     //Este el el spriteBatchNode donde está todo el escenario y monstruos
    CCSpriteBatchNode *graficosMazo; //Con este spriteBatchNode, tenemos el mazo
    CCSprite *fondo;                 //El sprite que contiene el fondo
    NSMutableArray *hoyos;           //Array que guarda los 6 hoyos
    NSMutableArray *monstruos;       //Array que guarda los 6 monstruos
    Mazo *mazo;                      //Array que guarda el mazo creado
    CCProgressTimer *tiempo;         //Barra de progreso que muestra cuando acabará el juego
    int entrePuntuaciones;           //
    int multiplicador;               // Variables relacionadas
    int score;                       // con las puntuaciones
    CCLabelTTF *etiquetaPuntuacion;  //
}

+(CCScene *) scene;

@end

Definida la cabecera, debemos crear ahora los métodos y procedimientos que harán uso de estas variables. Metodos que debemos implementar... Podrían ser algunos para crear el escenario, otro para controlar los toques, otros para la puntuación, otros para detectar la "colisión", etc..

Aquí va la implementación:

#import "JuegoLayer.h"

@implementation JuegoLayer

//Aquí creamos un monstruo en cierta posición con cierta escala, para facilitar la tarea de crear 6 monstruos
-(void) creaMonstruo:(NSString*) tipo Posicion: (CGPoint) pos Escala: (float) escala{
    Monstruo *monstruo = [Monstruo spriteWithSpriteFrameName:tipo];
    monstruo.position = pos;
    monstruo.scale = escala;
    [monstruos addObject:monstruo];
    [graficos addChild:monstruo];
    [monstruo marcaOrigen];
}

//Creamos la porción de tierra que va a tapar al monstruo cuando se esconde en el hoyo
-(void) creaHoyo:(NSString*) tipo Posicion: (CGPoint) pos {
    CCSprite *hoyo = [CCSprite spriteWithSpriteFrameName:tipo];
    hoyo.position = pos;
    [hoyos addObject:hoyo];
    [graficos addChild:hoyo];
}


//Montaje del escenario
-(void) montaEscenario{
    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:[[NSBundle mainBundle] pathForResource:@"Sprites" ofType:@"plist"]];
    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:[[NSBundle mainBundle] pathForResource:@"Mazo" ofType:@"plist"]];
    
    graficos = [CCSpriteBatchNode batchNodeWithFile:[[NSBundle mainBundle] pathForResource:@"Sprites" ofType:@"png"]];
    graficosMazo = [CCSpriteBatchNode batchNodeWithFile:[[NSBundle mainBundle] pathForResource:@"Mazo" ofType:@"png"]];

    [self addChild: graficos];
    [self addChild: graficosMazo];
    
    fondo = [CCSprite spriteWithSpriteFrameName:@"Escenario.png"];
    fondo.position = ccp(240,160);
    [graficos addChild:fondo];
    
    [self schedule:@selector(update:) interval:1.0f/30.0f];
    
    [self creaMonstruo:@"Naranja.png" Posicion:ccp(97.8,145) Escala:0.8f];
    [self creaMonstruo:@"Azul.png" Posicion:ccp(249,145) Escala:0.8f];
    [self creaMonstruo:@"Verde.png" Posicion:ccp(397.0,145) Escala:0.8f];
    [self creaHoyo:@"Hoyo-1.png" Posicion:ccp(97.8,150)];
    [self creaHoyo:@"Hoyo-2.png" Posicion:ccp(249,150)];
    [self creaHoyo:@"Hoyo-3.png" Posicion:ccp(397.0,150)];
    [self creaMonstruo:@"Rosa.png" Posicion:ccp(97.25,30) Escala:0.9f];
    [self creaMonstruo:@"Naranja.png" Posicion:ccp(248,30) Escala:0.9f];
    [self creaMonstruo:@"Azul.png" Posicion:ccp(398.8,30) Escala:0.9f];
    [self creaHoyo:@"Hoyo-4.png" Posicion:ccp(97.25,43.5)];
    [self creaHoyo:@"Hoyo-5.png" Posicion:ccp(248,43)];
    [self creaHoyo:@"Hoyo-6.png" Posicion:ccp(398.8,43)];
    
    CCParticleSnow *particulas = [[CCParticleSnow alloc] initWithTotalParticles:150];
    particulas.tag = 1337;
    particulas.autoRemoveOnFinish = YES;
    
    particulas.position = ccp(240,330);
    particulas.speed = 55;
    particulas.life = 8;
    particulas.lifeVar = 0;

    particulas.texture = [[CCTextureCache sharedTextureCache] addImage:[[NSBundle mainBundle] pathForResource:@"particle-stars" ofType:@"png"]];
    [self addChild:particulas];
    
    tiempo = [CCProgressTimer progressWithFile:[[NSBundle mainBundle] pathForResource:@"Progreso" ofType:@"png"]];
    tiempo.position = ccp(240, 300);
    tiempo.type = kCCProgressTimerTypeHorizontalBarLR;
    tiempo.percentage = 100;
    [self addChild:tiempo];
    
    etiquetaPuntuacion = [CCLabelTTF labelWithString:@"0" fontName:@"Arial" fontSize:32];
    etiquetaPuntuacion.position = ccp(450,30);
    etiquetaPuntuacion.anchorPoint = ccp(etiquetaPuntuacion.anchorPoint.x*2,etiquetaPuntuacion.anchorPoint.y);
    [self addChild:etiquetaPuntuacion];
    
}

//Actualizar puntuacion tras acabar la partida, creando un valor en el diccionario
-(void) actualizaPuntuacion{
    int puntuacionAnterior=0;
    if([[NSUserDefaults standardUserDefaults] valueForKey:@"Score"] != nil) {
        // Si la entrada existe, entonces actualizamos el valor
        puntuacionAnterior = [[NSUserDefaults standardUserDefaults] integerForKey:@"Score"];
        if (puntuacionAnterior < score){
            [[NSUserDefaults standardUserDefaults] setInteger:score forKey:@"Score"];
            
            //Tells the userDefaults to update the data base.
            [[NSUserDefaults standardUserDefaults] synchronize];
        }
    }
    else {
        [[NSUserDefaults standardUserDefaults] setInteger:score forKey:@"Score"];
        
        //Tells the userDefaults to update the data base.
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    
}

//En este procedimiento, actualizamos la barra de progreso.
-(void)update:(ccTime)dt
{
    tiempo.percentage = tiempo.percentage - 0.085f;
    entrePuntuaciones = entrePuntuaciones + 1;
    if (entrePuntuaciones > 30){
        entrePuntuaciones = 30;
        multiplicador = 1;
    }
    if (tiempo.percentage <= 0){
        [self actualizaPuntuacion];
        [self unscheduleAllSelectors];
        for (CCNode* nodo in [self children]) {
            [nodo unscheduleAllSelectors];
            [nodo removeFromParentAndCleanup:YES];
        }
        CCTransitionFade *action = [CCTransitionFade transitionWithDuration:2 scene:[MenuScene scene]];
        [[CCDirector sharedDirector] replaceScene:action];
    }
}

+(CCScene *) scene
{
	// 'scene' is an autorelease object.
	CCScene *scene = [CCScene node];
	
	// 'layer' is an autorelease object.
	HelloWorldLayer *layer = [HelloWorldLayer node];
	
	// add layer as a child to scene
	[scene addChild: layer];
	
	// return the scene
	return scene;
}

- (void) cleanupSprite:(CCSprite*)inSprite
{
    [self removeChild:inSprite cleanup:YES];
}

-(void) puntuacion:(int) p Posicion: (CGPoint) pos{
    CCLabelTTF *punt = [CCLabelTTF labelWithString:[NSString stringWithFormat:@"%d",p] fontName:@"Marker Felt" fontSize:22];
    [punt setOpacity:0];
    [punt setPosition:pos];
    // start the destroy process
    id action1 = [CCFadeTo actionWithDuration:0.425 opacity:255];
    id action2 = [CCFadeTo actionWithDuration:0.425 opacity:0]; 
    id action3 = [CCMoveBy actionWithDuration:0.425 position:ccp(0,40)];
    id action5 = [CCMoveBy actionWithDuration:0.425 position:ccp(0,40)];
    id action4 = [CCSpawn actions:action1, action3, nil];
    id action6 = [CCSpawn actions:action2, action5, nil];
    id cleanupAction = [CCCallFuncND actionWithTarget:self selector:@selector(cleanupSprite:) data:punt];
    id seq = [CCSequence actions:action4, action6, cleanupAction, nil];
    [self addChild:punt];
    [punt runAction:seq];
    score = score + p;
    [etiquetaPuntuacion setString:[NSString stringWithFormat:@"%d",score]];
    tiempo.percentage = tiempo.percentage + (p/25);
    
}

// on "init" you need to initialize your instance
-(id) init
{
	// always call "super" init
	// Apple recommends to re-assign "self" with the "super" return value
	if( (self=[super init])) {		
		//Habilitamos la pantalla táctil
        self.isTouchEnabled = YES;   
        monstruos = [[NSMutableArray alloc] init];
        hoyos = [[NSMutableArray alloc] init];
        [self montaEscenario];
	}
	return self;
}

-(bool) compruebaGolpe:(CGPoint) golpe{
    Monstruo* m;
    bool golpeado = false;
    int i;
    if (golpe.y>192){
        for (i = 0; i < 3; i++){
            m = [monstruos objectAtIndex:i];
            if (CGRectContainsPoint([m boundingBox], golpe) && ![m estaMuerto]) {
                [m recibeGolpe];
                golpeado = true;
                [self puntuacion:100*multiplicador-(ccpDistance(golpe, m.position)) Posicion:golpe];
                [m aumentaNivel:score];
            }
        }
    }else if(golpe.y>72){
        for (i = 3; i < 6; i++){
            m = [monstruos objectAtIndex:i];
            if (CGRectContainsPoint([m boundingBox], golpe) && ![m estaMuerto]) {
                [m recibeGolpe];
                golpeado = true;
                [self puntuacion:100*multiplicador-(ccpDistance(golpe, m.position)) Posicion:golpe];
                [m aumentaNivel:score];
            }
        }
    }
    return golpeado;
}

//Comprobamos los toques que se realizan en la pantalla.
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSSet *allTouches = [event allTouches];
	for (UITouch *touch in allTouches) {
        CGPoint location = [touch locationInView:[touch view]];
        location = [[CCDirector sharedDirector] convertToGL:location];
        
        mazo = [Mazo animacion];
        [graficosMazo addChild: mazo];
        mazo.position = ccpAdd(location,ccp(-15,50));
        if ([self compruebaGolpe: location]){
            multiplicador++;
            entrePuntuaciones = 0;
        }
        else{
            tiempo.percentage = tiempo.percentage - 3;
            multiplicador = 0;
            entrePuntuaciones = 30;
        }
	}
    [self reorderChild:[self getChildByTag:1337] z:1000];
}



-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

}

-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {    
    
    
}

// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
	// in case you have something to dealloc, do it in this method
	// in this particular example nothing needs to be released.
	// cocos2d will automatically release all the children (Label)
	
	// don't forget to call "super dealloc"
    [[self getChildByTag:1337] dealloc];
    [monstruos dealloc];
    [hoyos dealloc];
    [super dealloc];
}
@end
Continúa leyendo la cuarta parte del Tutorial Cocos2D en Español

No hay comentarios:

Publicar un comentario