Archivi tag: CCLayer

Kingdom:Undead Control Handlers

Nel disegno del codice, mi sono accorto di una cosa che a tendere rendeva illeggibile e poco gestibile il codice, la gestione degli eventi mouse, touch e keyboard da parte dei CCLayer di cocos2d.

Dovendo mostrare diversi CCNode contenenti UI realizzate con cocos, come ad esempio la scheda del giocatore, piuttosto che un menu di scelta, una popup modale magari realizzata con texture fatte adhoc, la gestione degli eventi rimaneva tutta comunque nell’implementazione del cclayer contenente tutta la parte principale del gioco.

Così ho deciso di estendere il cclayer, aggiungendo la possibilità di fornire gli eventi a dei delegati. Questo mi permette di “responsabilizzare” il codice al meglio, lasciando ad esempio la gestione del click su un certo pulsante solo nel ccnode che lo contiene.

Questo e’ un esempio di come estendere il CCLayer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//
// CCLayerControlServer.h
// KingdomUndead
//
// Created by Andrea Magini on 04/04/12.
// Copyright (c) 2012 metalide. All rights reserved.
//

#import
#import "cocos2d.h"
#import "KeyboardControlHandler.h"
#import "MouseControlHandler.h"

@interface CCLayerControlServer : CCLayer{
@private

idkeyboardDelegate;
id mouseDelegate;
}
@property (nonatomic,retain)id keyboardDelegate;
@property (nonatomic,retain)id mouseDelegate;

@end

E questa la sua implementazione:

1
2
3
4
5
6
7
8
9
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
//
// CCLayerControlServer.m
// KingdomUndead
//
// Created by Andrea Magini on 04/04/12.
// Copyright (c) 2012 metalide. All rights reserved.
//

#import "CCLayerControlServer.h"

@implementation CCLayerControlServer
@synthesize keyboardDelegate;
@synthesize mouseDelegate;
-(id) init
{
if( (self=[super init])) {
self.isMouseEnabled = YES;
self.isKeyboardEnabled = YES;
}
return self;
}

-(BOOL) ccKeyUp:(NSEvent *)event
{

[keyboardDelegate handleKeyUp:event];
return NO;
}

-(BOOL) ccMouseUp:(NSEvent *)event{
[mouseDelegate handleMouseUp:event];
return YES;
}

-(BOOL) ccMouseDragged:(NSEvent *)event{
[mouseDelegate handleMouseDragged:event];
return YES;
}

-(void)dealloc{
[keyboardDelegate release];
[mouseDelegate release];
[super dealloc];
}
@end

In questo modo tutti gli eventi intercettati dal layer vengono passati di volta in volta ai delegati registrati.
In ogni momento posso ad esempio deregistrare il layer come delegato per gli eventi e registrare un particolare CCNODE che gestisce una popup che si e’ appena mostrata a video.

I delegati devono avere un particolare Protocol per rispondere agli eventi mouse, o tastiera (o touch su iOS)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//
//  KeyboardControlHandler.h
//  KingdomUndead
//
//  Created by Andrea Magini on 04/04/12.
//  Copyright (c) 2012 metalide. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <Carbon/Carbon.h>

//per gestire il controllo sui vari ccnode e layers in modo da abilitare e disabilitare il controller

@protocol KeyboardControlHandler <NSObject>
@required
-(void) handleKeyUp:(NSEvent *)event;
@end

Questo permette di snellire il codice del CCLayer evitando di mettere tonnellate di if nei vari mousebuttonup, down, keyup etc e andando invece a gestire gli eventi
in maniera opportuna nei vari ccnode contenuti nella scena principale. Un esempio pratico è quello per la gestione degli eventi sull’HUD , lasciandoli gestire direttamente al CCNODE in questione, separandolo dagli eventi di gioco.

Come registrare un delegato:

1
2
3
@interface HudNode : CCNode<KeyboardControlHandler>{

}

Nel codice del CCLayer principale, durante l’init registro il CCNode dell’hud, e poi lo imposto come delegato per la gestione degli eventi tastiera

1
2
   [self addChild:hudNode];
   [self setKeyboardDelegate:hudNode];

e poi nel CCNode che implementa l’hud, implemento il metodo del Protocol KeyboardControlHandler

1
2
3
4
5
6
7
-(void) handleKeyUp:(NSEvent *)event{
    CCLOG(@"key up: %@", [event characters] );
    UInt16 keyCode = [event keyCode];
    if (keyCode == kVK_Space) {
       //fai qualcosa :)
    }
}

Spero sia chiaro 🙂