Archivi tag: Tutorial

JBoss As 7 e HSQLDB

Rieccoci al lavoro anche se per un brevissimo periodo di tempo con Java, e le applicazioni J2EE..
Per un prototipo ho bisogno di un DB veloce e semplice da installare, magari residente in memoria.
Dopo qualche prova fallimentare con Derby e con H2 (causa mie lacune), decido di testare il famoso HyperSQL DB, HSQLDB.
http://hsqldb.org/

Dovendo utilizzare un datasource configurato tramite JNDI, e quindi rendere residente su Application Server il mio db, ho dovuto configurare in maniera opportuna JBOSS..

Per prima cosa dobbiamo inserire un “MODULE” dentro l’installazione di jboss dove andare a mettere il jar del database in questione.
quindi dentro la cartella Modules, nella cartella org, creiamo una cartella hsqldb e al suo interno una cartella main.

Se non sappiamo bene come fare o abbiamo paura di sbagliare, possiamo prendere spunto da come è configurato h2 su jboss, partendo dalla cartella com/h2database.

Dopo aver creato la cartella main al suo interno dobbiamo mettere il file hsqldb.jar (io sto usando la versione 2.2.8) che potete scaricare dal sito ufficiale, poi creiamo un file module.xml e mettiamo questo contenuto:

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
<?xml version="1.0" encoding="UTF-8"?>

<!--
 ~ JBoss, Home of Professional Open Source.
 ~ Copyright 2010, Red Hat, Inc., and individual contributors
 ~ as indicated by the @author tags. See the copyright.txt file in the
 ~ distribution for a full listing of individual contributors.
 ~
 ~ This is free software; you can redistribute it and/or modify it
 ~ under the terms of the GNU Lesser General Public License as
 ~ published by the Free Software Foundation; either version 2.1 of
 ~ the License, or (at your option) any later version.
 ~
 ~ This software is distributed in the hope that it will be useful,
 ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
 ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 ~ Lesser General Public License for more details.
 ~
 ~ You should have received a copy of the GNU Lesser General Public
 ~ License along with this software; if not, write to the Free
 ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 -->

<module xmlns="urn:jboss:module:1.1" name="org.hsqldb">

    <resources>
        <resource-root path="hsqldb.jar"/>
    </resources>
    <dependencies>  
    <module name="javax.api"/>  
    <module name="javax.transaction.api"/>  
  </dependencies>  
</module>

Fatto questo apriamo la configurazione di jboss che andremo ad usare (nel mio caso la standalone, e quindi il file standalone.xml contenuto dentro la cartella jboss/standalone/configuration) e modifichiamo la parte inerente i datasources e i drivers:
dentro la voce profiles/subsystem ( ) troveremo un datasource di test per il db H2 e il suo relativo driver configurato. Aggiungiamo un nostro datasource per il nostro prototipo di applicazione e il driver hsqldb appena configurato nel module:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<subsystem xmlns="urn:jboss:domain:datasources:1.0">
            <datasources>            
                <datasource jta="true" jndi-name="java:/jboss/datasources/testAppDB" pool-name="TESTAPPDS" enabled="true" use-java-context="true" use-ccm="true">
                    <connection-url>jdbc:hsqldb:mem:testAppDB;hsqldb.write_delay=false;shutdown=true</connection-url>
                    <driver>hsqldb</driver>
                    <pool>
                        <prefill>false</prefill>
                        <use-strict-min>false</use-strict-min>
                        <flush-strategy>FailingConnectionOnly</flush-strategy>
                    </pool>
                    <security>
                        <user-name>sa</user-name>
                    </security>
                </datasource>
                <drivers>
                    <driver name="hsqldb" module="org.hsqldb"/>
                </drivers>
            </datasources>
        </subsystem>

Il gioco è fatto. Così facendo ora potremo reperire una connessione tramite lookup Jndi e ottenere così una connessione (jta compatibile) per la prototipazione delle nostre applicazioni.

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 🙂

Kingdom:Undead sketch e idee

Iniziamo oggi una serie di articoli/appunti/idee sullo sviluppo di un prototipo di gioco per mac osx, iphone e ipad.

Il gioco è un incrocio tra un tower defence e un rpg, in cui si deve gestire il Kingdom, il “regno” di un manipolo di sopravvissuti all’infezione zombie.

Il tutto sarà incentrato nella gestione e nella crescita di questo Kingdom, un insieme di bunker e container che vengono assemblati man mano che si acquisiscono le materie prime.

Lo sviluppo per ora è su XCode 4.2 utilizzando obiective-c e la libreria Cocos2d .

Per semplificare il disegno, sto iniziando a definire tutti i modelli grafici abbozzandoli a matita, e poi scannerizzandoli e scontornandoli a mano.
Consiglio l’uso di PixelMator per questo tipo di attività. E’ un software dal costo moderato e dalle grandi potenzialità. Quando il gioco si troverà ad uno stadio abbastanza maturo, e avrò finito di definire con esattezza la dimensione di ogni singolo asset di gioco, allora passerò il lavoro a uno o più grafici 2d per ridisegnare il tutto.

Non conoscendo bene objective-c e cocos2d, inizio per gradi facendo direttamente training on the job, molte cose quindi magari ovvie a chi conosce meglio questo linguaggio, a primo acchitto potrebbero sfuggirmi. Già nella situazione attuale, iniziata oramai da 2 settimane, mi sono accorto di carenze nel disegno delle classi e ho iniziato a utilizzare funzionalità non previste inizialmente, come CoreData, il NotificationCenter , i Protocolli, e tante altre cose.

Alcuni ignobili schizzi da me eseguiti:

 

Che trasformati, diventeranno la base dei nostri spritesheet dove mettere tutte le animazioni per i sopravvissuti e per gli zombie, e i tileset per la nostra mappa.

Per la creazione del Kingdom invece sto utilizzando una CCTMXTiledMap composta da due righe, una per il piano base e una per il piano superiore, composta da 3 strati di layer, il primo che contiene lo sfondo di ogni cella, il secondo che contiene il centro della cella, con i mobili e soprammobili, il terzo strato che contiene le immagini frontali, le cornici dei bunker. i personaggi si troveranno tra lo sfondo e il layer centrale. Questo permetterà di avere una mappa modulare in cui andare a mischiare diversi background, foreground e middle per ottenere un numero maggiore di personalizzazioni della mappa.

Una prima bozza dopo una settimana di lavoro inizia a prendere forma:

Ci sono già diverse scene per l’implementazione dei credits iniziali, del menu di gioco e della schermata principale, basata su uno sfondo con scrolling in parallasse e la nostra mappa di bunker al centro.

Per poter lavorare al meglio, ho esteso la CCTXMTiledMap, per aggiungere tutte quelle proprietà e metodi che dovranno snellire e semplificare lo sviluppo e la gestione della mappa.

ecco un esempio della sua interfaccia:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#import "cocos2d.h"
#import "CCTMXTiledMap.h"

@interface BunkerMap : CCTMXTiledMap
{
CCTMXLayer *_baseLayer;
int _homeBunkerPosition;
int _lastSelectedBunkerId;
CCSprite* _lastSelectedBunker;
}

@property(nonatomic,retain)CCTMXLayer *baseLayer;
@property(nonatomic,readwrite)int homeBunkerPosition;
@property(nonatomic,readonly)int lastSelectedBunkerId;
//TODO: convertire il lastSelectedBunker da sprite a oggetto Bunker
@property(nonatomic,readonly)CCSprite *lastSelectedBunker;
-(void)selectBunker:(int)bunkerNumber;

-(void)centerToBunkerNumber:(int)bunkerNumber select:(BOOL)flag;
-(int)centerToBunkerPosition:(CGPoint)location select:(BOOL)flag;

-(int) findBunkerByPosition:(CGPoint)location;
@end

ed un esempio di implementazione della funzione per capire su che bunker ho selezionato (per poterlo centrare ad esempio o visualizzarne la sua scheda):

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
-(int) findBunkerByPosition:(CGPoint)location{
   
    CGSize s = [self.baseLayer layerSize];
    for( int x=0; x<s.width;x++) {
        for( int y=0; y< s.height; y++ ) {
            CCTMXLayer *l;
            CCARRAY_FOREACH(self.children, l) {
                if([l isKindOfClass:[CCTMXLayer class]]){
                    CCSprite *tile = [l tileAt:ccp(x,y)];
                   
                    if (CGRectContainsPoint([tile boundingBox],[self convertToNodeSpace:location])){
                        // NSLog(@"TILE:%@",[tile position]);
                        return x;
                    }
                }
               
            }
           
           
            //  unsigned int tmpgid =[layer tileGIDAt:ccp(x,y)];
           
           
        }
    }
   
    return -1;
}