Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

JMonkey Engine 3.0: giochi 3D per java (e android)

Breve presentazione dell'engine 3d JMonkey, pensato per applicazioni desktop e... android.
Breve presentazione dell'engine 3d JMonkey, pensato per applicazioni desktop e... android.
Link copiato negli appunti

Con questo articolo introduciamo Jmonkey: un'interessante framework opnesource per la realizzazione di giochi 3D con il linguaggio Java. Il framework utilizza una licenza BSD, ed è liberamente utilizzabile per hobby, fini educazionali o commerciali. L'aspetto particolarmente interessante è quello di poter realizzare giochi non soltanto per piattaforme desktop, ma anche per il web (pensiamo alla crescente richiesta di giochi per le piattaforme "social", come facebook) o per i dispositivi Android.

JMonkeyEngine è un engine ad alte performance scritto in Java e che utilizza LWJGL per l'accesso ad OpenGL. LWJGL (Lightweight Java Game Library) è la libreria Java che permette agli sviluppatori l'accesso a librerie quali OpenGL (Open Graphics Library), OpenCL (Open Computing Language), OpenAL (Open Audio Library).

La libreria è disponibile per Windows, Linux e Mac. I requisiti hardware sono i seguenti:

Sistemi operativi Mac OS X, Windows, Linux, or Solaris
Memoria (JVM heap size) > 40 MB + memory for assets
CPU 1 GHz
Scheda grafica ATI Radeon 9500, NVIDIA GeForce 5 FX, Intel GMA 4500, o superiori supporto OpenGL 2.0 (ultimo driver raccomandato)
Java Development Kit JDK 6

Vogliamo fornire un assaggio di questo motore 3D vedendo l'esecuzione di una applicazione base che visualizzerà una scena 3D di una piccola cittadina. Proviamo il tutto sotto Windows: scarichiamo ed installiamo la platform di sviluppo dall'url:

http://jmonkeyengine.org/downloads/

Una volta completata l'installazione lanciamo l'ambiente.Dovremmo trovarci di fronte ad una schermata simile alla seguente:

Figura 1. schermata inziale applicazione
(clic per ingrandire)


schermata inziale applicazione

Il progetto Basic Game

É il momento di creare il primo progetto, che chiameremo per semplicità BasicGame:

Figura 2. creazione del progetto BasicGame
(clic per ingrandire)


creazione del progetto BasicGame

A questo punto, nel package mygame creato automaticamente definiamo una classe con il nome HelloCollision

public class HelloCollision
	extends SimpleApplication
	implements ActionListener {
    // ...
}

Iniziamo con l'aggiungere le seguenti variabili di istanza che utilizzeremo successivamente:

private BulletAppState bulletAppState;
private Spatial sceneModel;
private RigidBodyControl landscape;
private CharacterControl player;
private Vector3f walkDirection = new Vector3f();
private boolean left = false, right = false, up = false, down = false;

L'esempio fa uso di quella che viene chiamata game physics (l'implementazione della fisica nel gioco, insomma); ne abbiamo bisogno per simulare massa, gravità, collisioni: pensiamo ad esempio ai fenomeni fisici nel gioco del biliardo o nei giochi che simulano corse di auto. Per utilizzarla abbiamo bisogno di un oggetto BulletAppState

bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
definiamo all'interno della classe il metodo
public void simpleInitApp() {
     bulletAppState = new BulletAppState();
     stateManager.attach(bulletAppState);
	// ...
}

e cominciamo con l'inserire al suo interno le righe di codice appena descritte. La variabile stateManager SimpleApplication

Dopo aver inizializzato le funzionalità di game physics

public void simpleInitApp() {
	bulletAppState = new BulletAppState();
	stateManager.attach(bulletAppState);
	viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
	flyCam.setMoveSpeed(100);
}

Anche viewPort è ereditata dalla classe Application flyCam (anch'essa nella classe Application estensione della Camera di default SimpleApplication flyCam

Interazione con l'utente

Per completare la configurazione del movimento all'interno dell'ambiente, definiamo il seguente metodo che invochiamo subito dopo l'istruzione relativa a flyCam:

private void setUpKeys() {
	inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A));
	inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D));
	inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_W));
	inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_S));
	inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE));
	inputManager.addListener(this, "Left");
	inputManager.addListener(this, "Right");
	inputManager.addListener(this, "Up");
	inputManager.addListener(this, "Down");
	inputManager.addListener(this, "Jump");
}

L'interazione con l'utente avviene attraverso la tastiera, il mouse, il joystick, per gestire questi dispositivi si fa uso dell'oggetto inputManager ereditato dalla classe SimpleApplication.

Attraverso il metodo addMapping definiamo dei trigger che si attivano per determinate azioni. Ad esempio Left, Right, Up, Down rappresentano le azioni di movimento verso sinistra, destra, in alto, in basso. Nel metodo addMapping le specifichiamo attraverso il primo parametro, mentre con il secondo indichiamo,nel nostro caso, quale tasto premuto le attiva : KeInput.KEY_A tasto con lettera A, KeyInput.KEY_B tasto con lettera B e cosi via. Il metodo addListener serve per impostare l'ascoltatore per le azioni-evento.

Il metodo simpletInitApp diventa:

public void simpleInitApp() {
	bulletAppState = new BulletAppState();
	stateManager.attach(bulletAppState);
	viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
	flyCam.setMoveSpeed(100);
	setupKeys();
}

gestione della luce e delle ombre

Il prossimo aspetto da considerare e la gestione delle luci e delle ombre: ad ogni oggetto visibile dovrà avere associata una sorgente di luce con una locazione e direzione.

In JMonkey abbiamo a disposizione differenti tipi di sorgenti di luce. Quelle che utilizziamo in questo esempio sono DirectionalLight e AmbientLight. DirectionalLight è caratterizzata dal non avere posizione ma solo direzione, è considerata infinita, tipicamente usata per simulare la luce del sole.

AmbientLight viene utilizzata per influenzare la luminosità della scena globale, non ha direzione ne posizione e non comporta nessuna ombra. Inizializziamo queste sorgenti di luce all'interno del seguente metodo:

private void setUpLight() {
	AmbientLight al = new AmbientLight();
	al.setColor(ColorRGBA.White.mult(1.3f));
	rootNode.addLight(al);

	DirectionalLight dl = new DirectionalLight();
	dl.setColor(ColorRGBA.White);
	dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal());
	rootNode.addLight(dl);
}

che invochiamo subito dopo setupKeys all'interno del metodo simpleInitApp:

public void simpleInitApp() {
	bulletAppState = new BulletAppState();
	stateManager.attach(bulletAppState);
	viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
	flyCam.setMoveSpeed(100);
	setupKeys();
	setupLight();
}

configurazione della scena

A questo punto continuiamo caricando tutto l'ambiente all'interno del quale ci muoveremo, definito in termini di risorse immagini, font, suoni, nel file town.zip. Il codice da aggiungere dopo setupLight è il seguente:

assetManager.registerLocator("town.zip", ZipLocator.class.getName());
sceneModel = assetManager.loadModel("main.scene");
sceneModel.setLocalScale(2f);

assetManager è ereditata dalla classe Application estesa da SimpleApplication, mentre sceneModel è stata dichiarata come variabile di istanza precedentemente. Il codice del metodo si completa con la gestione delle collisioni tra l'ambiente ed il giocatore che si muove in esso:

CollisionShape sceneShape =
CollisionShapeFactory.createMeshShape((Node) sceneModel);
landscape = new RigidBodyControl(sceneShape, 0);
sceneModel.addControl(landscape);

CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1);
player = new CharacterControl(capsuleShape, 0.05f);
player.setJumpSpeed(20);
player.setFallSpeed(30);
player.setGravity(30);
player.setPhysicsLocation(new Vector3f(0, 10, 0));

le seguenti ultime righe di codice completano la configurazione della scena simpleInitApp

rootNode.attachChild(sceneModel);
bulletAppState.getPhysicsSpace().add(landscape);
bulletAppState.getPhysicsSpace().add(player);

La classe HelloCollision com.jme3.input.controls.ActionListener HelloCollision

public void onAction(String binding, boolean value, float tpf) {
	if (binding.equals("Left")) {
		if (value) { left = true; } else { left = false; }
	} else if (binding.equals("Right")) {
		if (value) { right = true; } else { right = false; }
	} else if (binding.equals("Up")) {
		if (value) { up = true; } else { up = false; }
	} else if (binding.equals("Down")) {
		if (value) { down = true; } else { down = false; }
	} else if (binding.equals("Jump")) {
		player.jump();
	}
}

il codice all'interno del metodo non effettua nessun movimento in una determinata direzione ma ne mantiene solo traccia. La classe SimpleApplication

public void simpleUpdate(float tpf)

la cui implementazione è vuota. Dobbiamo fare override di questo metodo in HelloCollision

@Override
public void simpleUpdate(float tpf) {
	Vector3f camDir = cam.getDirection().clone().multLocal(0.6f);
	Vector3f camLeft = cam.getLeft().clone().multLocal(0.4f);
	walkDirection.set(0, 0, 0);
	if (left)  { walkDirection.addLocal(camLeft); }
	if (right) { walkDirection.addLocal(camLeft.negate()); }
	if (up)    { walkDirection.addLocal(camDir); }
	if (down)  { walkDirection.addLocal(camDir.negate()); }
	player.setWalkDirection(walkDirection);
	cam.setLocation(player.getPhysicsLocation());
}

Attraverso questo metodo viene ripetutamente controllata la posizione della camera. Grazie alla direzione forward(camDir) left(leftDir) setWalkDirection() HelloCollision physics-controlled object

L'applicazione demo è praticamente conclusa, dobbiamo aggiungere in HelloCollision il metodo main di lancio:

public static void main(String[] args) {
	HelloCollision app = new HelloCollision();
	app.start();
}

Infine copiamo all'interno del cartella del progetto il file town.zip fornito in allegato con l'articolo. Questo file contiene tutto ciò che riguarda la grafica dell'ambiente. Siamo pronti per compilare e lanciare l'applicativo HelloCollision. La prima schermata che viene visualizzata è quella di lancio:

Figura 3. jmonkey: schermata di lancio dell'applicazione, con selezione del tipo di visualizzazione
(clic per ingrandire)


jmonkey: schermata di lancio dell'applicazione

Facendo click su ok

Figura 4. jmonkey: l'ambiente 3D di prova
(clic per ingrandire)


jmonkey: l'ambiente 3D di prova

Conclusioni

Abbiamo introdotto velocemente il software senza soffermarci sugli aspetti realizzativi e concetti matematici 3D, necessari per poter comprendere i codice scritto, e poter effettivamente sfruttare la libreria partendo da un livello principiante. Potete trovare questo ed altri tutorial al seguente link:

http://jmonkeyengine.org/wiki/doku.php/jme3:beginner

Nei prossimi articoli vedremo in dettaglio le caratteristiche fondamentali degli strumenti messi a disposizione, concetti matematici alla base del loro utilizzo e come costruire oggetti ed ambienti.

Ti consigliamo anche