Andrea "Kiraya"Magini

IT Professional Master

Single post

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:
[cce lang=”objc”]
//
// 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
[/cce]
E questa la sua implementazione:
[cce lang=”objc”]
//
// 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
[/cce]
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)
[cce lang=”objc”]
//
// KeyboardControlHandler.h
// KingdomUndead
//
// Created by Andrea Magini on 04/04/12.
// Copyright (c) 2012 metalide. All rights reserved.
//
#import
#import
//per gestire il controllo sui vari ccnode e layers in modo da abilitare e disabilitare il controller
@protocol KeyboardControlHandler
@required
-(void) handleKeyUp:(NSEvent *)event;
@end
[/cce]
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:
[cce lang=”objc”]
@interface HudNode : CCNode{
}
[/cce]
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
[cce lang=”objc”]
[self addChild:hudNode];
[self setKeyboardDelegate:hudNode];
[/cce]
e poi nel CCNode che implementa l’hud, implemento il metodo del Protocol KeyboardControlHandler
[cce lang=”objc”]
-(void) handleKeyUp:(NSEvent *)event{
CCLOG(@”key up: %@”, [event characters] );
UInt16 keyCode = [event keyCode];
if (keyCode == kVK_Space) {
//fai qualcosa 🙂
}
}
[/cce]
Spero sia chiaro 🙂