Archives for July 2009
Using LWJGL with Griffon
LWJGL (Light-weight Java Game Library) is a game library that is the basis for many graphics libraries including jMonkeyEngine. You might be wondering why I'm covering LWJGL in a separate post when it is used in jMonkeyEngine which I covered several weeks ago. Though there is some overlap, each fits a specific need.
I'd describe the relationship like this: OpenGL/JOGL is a bicycle, LWJGL is a Vespa, and jME is a Harley. OpenGL is great if you want to touch the bare metal, LWJGL if you want to tweak and customize, jME if you singular goal is to make a game.
Getting started
- Download LWJGL and drop the lwjgl.jar in your lib directory.
- Find the native files for your operating system and extract them into lib/native
- Download jME 2.0 Distribution. We aren't doing that much advanced stuff so we only need jme.jar, jinput.jar, and jme-awt.jar. Drop these into your lib directory.
- Modify your Config.groovy file to contain the following:
griffon { app { javaOpts = ["-Djava.library.path=${basedir}/lib/native"] } }
Linking our model and view
Our model and view are going to be fairly basic and initiate a model property called canvas that is added to the view. We don't need to do anything in our controller.
SimpleLWJGLModel.groovy
import groovy.beans.Bindable
class SimpleLWJGLModel {
@Bindable canvas = new SimpleCanvas()
}
SimpleLWJGLView.groovy
application(title:'SimpleLWJGL',
size:[300,300],
resizable:false,
locationByPlatform:true,
iconImage: imageIcon('/griffon-icon-48x48.png').image,
iconImages: [imageIcon('/griffon-icon-48x48.png').image,
imageIcon('/griffon-icon-32x32.png').image,
imageIcon('/griffon-icon-16x16.png').image]
) {
widget(model.canvas)
}
Drawing on our canvas
Here we draw a rotating quad.
import org.lwjgl.LWJGLException
import org.lwjgl.opengl.AWTGLCanvas
import org.lwjgl.opengl.Display
import org.lwjgl.opengl.GL11
public class SimpleCanvas extends AWTGLCanvas {
float angle = 0
public SimpleCanvas() throws LWJGLException {
// Launch a thread to repaint the canvas 60 fps
Thread.start{
while (true) {
if (isVisible()) {
repaint()
}
Display.sync(60)
}
}
}
public void paintGL() {
GL11.with {
glClear(GL_COLOR_BUFFER_BIT)
glMatrixMode(GL_PROJECTION_MATRIX)
glLoadIdentity()
glOrtho(0, 640, 0, 480, 1, -1)
glMatrixMode(GL_MODELVIEW_MATRIX)
glPushMatrix()
glTranslatef(320, 240, 0.0f)
glRotatef(angle, 0, 0, 1.0f)
glBegin(GL_QUADS)
glVertex2i(-50, -50)
glVertex2i(50, -50)
glVertex2i(50, 50)
glVertex2i(-50, 50)
glEnd()
glPopMatrix()
}
angle += 1
try {
swapBuffers()
} catch (Exception e) { }
}
}
One thing you might notice is that LWJGL requires a lot less setup than jME. Download the source here.
Griffon at The Strange Loop
I'm happy to report that my session entitled, "Griffon: Swing just got fun again" was accepted at The Strange Loop.
The Strange Loop is a developer conference taking place in St. Louis October 22nd and 23rd. The sessions are a nice mix of different technologies so it won't be hard to find something that interests you. Register by August 14th for half($75) of what it would you pay at the door.
Fellow Groovyists Hamley D'Arcy, Guillaume Laforge, and Jeff Brown will be presenting "Groovy Compiler Metaprogramming for Fun and Profit," "Groovy, to infinity and beyond!," and "Polyglot Web Development with Grails," respectively.
You can follow announcements from the conference on Twitter @strangeloop_stl or or on the website http://thestrangeloop.com.
Using jMonkeyEngine with Griffon
jMonkeyEngine is a scenegraph game engine with a vibrant community. It supports OpenGL functionality via LWJGL, sound via OpenAL, and keyboard/mouse/controller interactivity using JInput. In this post, we are going to embed a jME canvas in Griffon and draw a textured cube.
Getting started
- Download LWJGL and drop the lwjgl.jar in your lib directory.
- Find the native files for your operating system and extract them into lib/native
- Download jME 2.0 Distribution. We aren't doing that much advanced stuff so we only need jme.jar, jinput.jar, and jme-awt.jar. Drop these into your lib directory.
- Modify your Config.groovy file to contain the following:
griffon { app { javaOpts = ["-Djava.library.path=${basedir}/lib/native"] } extensions { jarUrls = [] jnlpUrls = ["lwjgl.jnlp"] } } - Add this jnlp file to griffon-app/conf/webstart: lwjgl.jnlp.
- Switch the order in Application.groovy to the following:
mvcGroups { '<Your app name>' { model = 'YOURAPP-Model' controller = 'YOURAPP-Controller' view = 'YOURAPP-View' } }It's important that the controller be initialized before the view because the controller will initialize our canvas.
Linking our model and view
JmeSwingModel.groovy
import groovy.beans.Bindable
class JmeSwingModel {
@Bindable canvas
@Bindable impl
@Bindable display
int height = 640
int width = 480
}
JmeSwingView.groovy
application(title:'Griffon jME Swing',
pack:true,
resizable:false,
//location:[50,50],
locationByPlatform:true,
iconImage: imageIcon('/griffon-icon-48x48.png').image,
iconImages: [imageIcon('/griffon-icon-48x48.png').image,
imageIcon('/griffon-icon-32x32.png').image,
imageIcon('/griffon-icon-16x16.png').image]
) {
widget(model.canvas)
}
Initializing our canvas
JmeSwingController.groovy
import com.jme.input.KeyInput
import java.awt.event.KeyListener
import com.jme.input.InputHandler
import com.jme.system.DisplaySystem
import com.jmex.awt.lwjgl.LWJGLCanvas
import com.jme.system.canvas.JMECanvas
import java.awt.event.ComponentListener
import com.jmex.awt.input.AWTMouseInput
import com.jme.system.lwjgl.LWJGLSystemProvider
import com.jme.system.canvas.JMECanvasImplementor
import com.jmex.awt.lwjgl.LWJGLAWTCanvasConstructor
class JmeSwingController {
// these will be injected by Griffon
def model
def view
void mvcGroupInit(Map args) {
// make the canvas:
model.display = DisplaySystem.getDisplaySystem(LWJGLSystemProvider.LWJGL_SYSTEM_IDENTIFIER);
model.display.registerCanvasConstructor("AWT", LWJGLAWTCanvasConstructor.class);
model.canvas = (LWJGLCanvas)model.display.createCanvas(model.width, model.height);
model.canvas.setUpdateInput(true);
model.canvas.setTargetRate(60);
// Setup key and mouse input
KeyInput.setProvider(KeyInput.INPUT_AWT);
KeyListener kl = (KeyListener) KeyInput.get();
model.canvas.addKeyListener(kl);
AWTMouseInput.setup(model.canvas, false);
// Important! Here is where we add the guts to the panel:
model.impl = new MyImplementor(model.width, model.height);
model.canvas.setImplementor(model.impl);
model.canvas.setBounds(0, 0, model.width, model.height);
}
}
Drawing on our canvas
MyImplementor is bit of code that draws our world.
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.InputHandler;
import com.jme.input.KeyInput;
import com.jme.input.action.InputAction;
import com.jme.input.action.InputActionEvent;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.Renderer;
import com.jme.scene.shape.Box;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.system.canvas.JMECanvas;
import com.jme.system.canvas.JMECanvasImplementor;
import com.jme.system.canvas.SimpleCanvasImpl;
import com.jme.system.lwjgl.LWJGLSystemProvider;
import com.jme.util.GameTaskQueueManager;
import com.jme.util.TextureManager;
import com.jmex.awt.input.AWTMouseInput;
import com.jmex.awt.lwjgl.LWJGLAWTCanvasConstructor;
import com.jmex.awt.lwjgl.LWJGLCanvas;
public class MyImplementor extends SimpleCanvasImpl {
private Quaternion rotQuat;
private float angle = 0;
private Vector3f axis;
private Box box;
private InputHandler input;
public MyImplementor(int width, int height) {
super(width, height);
}
public void simpleSetup() {
// Normal Scene setup stuff...
rotQuat = new Quaternion();
axis = new Vector3f(1, 1, 0.5f);
axis.normalizeLocal();
Vector3f max = new Vector3f(5, 5, 5);
Vector3f min = new Vector3f(-5, -5, -5);
box = new Box("Box", min, max);
box.setModelBound(new BoundingBox());
box.updateModelBound();
box.setLocalTranslation(new Vector3f(0, 0, -10));
box.setRenderQueueMode(Renderer.QUEUE_SKIP);
rootNode.attachChild(box);
box.setRandomColors();
TextureState ts = renderer.createTextureState();
ts.setEnabled(true);
ts.setTexture(TextureManager.loadTexture(this.getClass().getClassLoader().getResource(
"Monkey.jpg"),
Texture.MinificationFilter.BilinearNearestMipMap,
Texture.MagnificationFilter.Bilinear));
rootNode.setRenderState(ts);
input = new InputHandler();
}
public void simpleUpdate() {
input.update(tpf);
// Code for rotating the box... no surprises here.
if (tpf < 1) {
angle = angle + (tpf * 25);
if (angle > 360) {
angle = 0;
}
}
rotQuat.fromAngleNormalAxis(angle * FastMath.DEG_TO_RAD, axis);
box.setLocalRotation(rotQuat);
}
}
Download the source here

Using Processing with Griffon
Processing is a great graphics language that reminds me alot of old-school BASIC/turtle graphics. It's built on top of Java so it's only natural that we'd eventually try it with Griffon.
Getting Started
- Download processing from http://processing.org/download.
- Regardless of your operating system, grab the Windows version WITHOUT Java.
- Find the core.jar file and drop it in the lib directory of your project.
Extend PApplet
The following is a slightly tweaked example from processingjs.org
import processing.core.*;
public class Embedded extends PApplet {
// Global variables
float radius = 50.0f;
int X, Y;
int nX, nY;
int delay = 16;
// Setup the Processing Canvas
void setup() {
size(400, 400);
strokeWeight(10);
frameRate(15);
X = width / 2;
Y = width / 2;
nX = X;
nY = Y;
}
// Main draw loop
void draw() {
radius = radius + sin((float) (frameCount / 4));
// Track circle to new destination
X += (nX - X) / delay;
Y += (nY - Y) / delay;
// Fill canvas grey
background(100);
// Set fill-color to blue
fill(0, 121, 184);
// Set stroke-color white
stroke(255);
// Draw circle
ellipse(X, Y, radius, radius);
}
// Set circle's next destination
void mouseMoved() {
nX = mouseX;
nY = mouseY;
}
}
Linking your view and model to Processing
Proce55ingModel.groovy
import groovy.beans.Bindable
import processing.core.PApplet
class Proce55ingModel {
@Bindable pApplet = new Embedded()
}
Proce55ingView.groovy
application(title:'Proce55ing',
size:[400,400],
//location:[50,50],
locationByPlatform:true,
iconImage: imageIcon('/griffon-icon-48x48.png').image,
iconImages: [imageIcon('/griffon-icon-48x48.png').image,
imageIcon('/griffon-icon-32x32.png').image,
imageIcon('/griffon-icon-16x16.png').image]
) {
widget(model.pApplet)
}
Final touches
Proce55ingController.groovy
class Proce55ingController {
// these will be injected by Griffon
def model
def view
void mvcGroupInit(Map args) {
// ensures animation is started and that vars properly set
model.pApplet.init()
}
/*
def action = { evt = null ->
}
*/
}

Because it is very procedural like OpenGL, a builder might be improbable.
Groovy's duck-typing and the fact that Processing uses floats for its non-integral numeric type means that some values will need to be cast. With a few casts, you can use any of the examples on processingjs.org
Download the source code here.