same code running in a Applet and JFrame

Started by athanazio, November 23, 2006, 12:12:41 PM

Previous topic - Next topic

athanazio

-- warning long message -- (sorry for this)

In my studies yesterday I got a result that I liked, and want to share with the other JPCT learners :D

I separated a class to represent the game, and used in a Applet and in a JFrame, I didn't use the OGL rendering just the software rendering, but I dont have parameters to say if the performance was good or not, follow some comments and the code - note that the game is a cut and paste of Car example, changing just some details to see how it looks :)

One detail that is important to comment is about the PathBuilder interface, this one allows both (Applet and JFrame) to pass its instance as parameter to the game class, and when the game needs any external resources as models, textures can delegate to the caller the job of find out where the resources are, by using the method createPath()

As the Game class extends JComponent, I only to override the paintComponent() method, allowing for example the use of the game component within other Swing components in the interface.

The Applet

import java.io.InputStream;
import java.net.URL;

import javax.swing.JApplet;

public class Load3DSApplet extends JApplet implements Runnable, Pathbuilder {

private static final long serialVersionUID = 1L;

private Load3DSGame game = null;

public void start() {
try {
game = new Load3DSGame(this, this);
game.finishOnESC(false);
getContentPane().add(game);

Thread gamethread = new Thread(this);
gamethread.start();
} catch (Exception e) {
System.err.println("Initialization failed");
e.printStackTrace();
}
}

public void run() {
game.play();
}

public InputStream createPath(String fileName) throws Exception {
System.out.println("createPath() filename=" + fileName);
URL url = new URL(getDocumentBase(), fileName);
InputStream in = url.openStream();
return in;
}

public void destroy() {
game.exit();
}

public void stop() {
game.exit();
}

}


The JFrame


import java.awt.BorderLayout;
import java.awt.Label;
import java.io.FileInputStream;
import java.io.InputStream;

import javax.swing.JFrame;

public class Load3DSFrame extends JFrame implements Pathbuilder, Runnable {

private static final long serialVersionUID = 1L;

private Load3DSGame game;

public static void main(String[] args) throws Exception {
Load3DSFrame frame = new Load3DSFrame();
frame.setVisible(true);
}

public Load3DSFrame() throws Exception {
game = new Load3DSGame(this, this);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Game Frame");
setSize(800, 600);
setResizable(false);
setLocationRelativeTo(null);

getContentPane().add(game, BorderLayout.CENTER);
getContentPane().add(new Label("this is a label"), BorderLayout.SOUTH);

Thread gamethread = new Thread(this);
gamethread.start();

}

public InputStream createPath(String fileName) throws Exception {
System.out.println("createPath() filename=" + fileName);
FileInputStream in = new FileInputStream(fileName);
return in;
}

public void run() {
game.play();
}

}


The game class

import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.KeyEvent;

import javax.swing.JComponent;

import com.threed.jpct.Camera;
import com.threed.jpct.Config;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.IRenderer;
import com.threed.jpct.Lights;
import com.threed.jpct.Loader;
import com.threed.jpct.Matrix;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.KeyMapper;
import com.threed.jpct.util.KeyState;

public class Load3DSGame extends JComponent {

private static final long serialVersionUID = 1L;

private FrameBuffer buffer = null;

private World world = null;

private Camera camera = null;

private Object3D box = null;

private TextureManager textureManager = null;

private static final float ROTATE_ANGLE = (float) Math.toRadians(20.0);

private static final float SPEED = 6.0f;

private static boolean left = false;

private static boolean right = false;

private static boolean up = false;

private static boolean down = false;

private boolean exit = false;

private int titleBarHeight = 0;

private int leftBorderWidth = 0;

private KeyMapper keyMapper;

private Pathbuilder builder;

private Component owner;

private boolean finishOnESC = true;

/**
* @throws Exception
*/
public Load3DSGame(Component owner, Pathbuilder builder) throws Exception {
this.owner = owner;
this.builder = builder;
add3DStuff();
}

public void play() {
World.setDefaultThread(Thread.currentThread());

// wait until Swing determine the dimension of the component
while ((getWidth() == 0 || getHeight() == 0) && !exit) {
Thread.yield();

try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}

if (getWidth() > 0 && getHeight() > 0) {
buffer = new FrameBuffer(getWidth(), getHeight(),
FrameBuffer.SAMPLINGMODE_NORMAL);
buffer.enableRenderer(IRenderer.RENDERER_SOFTWARE);
}

while (!exit) {
buffer.clear();
moveTheCube();

world.renderScene(buffer);
world.draw(buffer);
buffer.update();

// poll the keyboard
poll();

// force the refresh of the component
repaint();
Thread.yield();

try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}

buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
}

protected void paintComponent(Graphics g) {
if (buffer != null) {
buffer.display(g, leftBorderWidth, titleBarHeight);
}
super.paintComponent(g);
}

private void add3DStuff() throws Exception {
keyMapper = new KeyMapper(owner);
Config.maxPolysVisible = 10000;
Config.farPlane = 1200;

SimpleVector middle = new SimpleVector(0, 0, 0);
world = new World();
textureManager = TextureManager.getInstance();

box = Primitives.getBox(10, 1);
box.setOrigin(middle);

Texture rocks = new Texture(builder.createPath("textures/rocks.jpg"));
textureManager.addTexture("rocks", rocks);

Object3D terrain = null;
Object3D[] foo = Loader.load3DS(builder
.createPath("models/terascene.3ds"), 400);
if (foo.length > 0) {
terrain = foo[0];
}

if (terrain != null) {
terrain.setTexture("rocks");
terrain.build();
SimpleVector pos = terrain.getCenter();
pos.scalarMul(-1f);
terrain.translate(pos);
terrain.rotateX((float) Math.toRadians(-90));
terrain.translateMesh();
terrain.rotateMesh();
terrain.setTranslationMatrix(new Matrix());
terrain.setRotationMatrix(new Matrix());
terrain.enableLazyTransformations();
world.addObject(terrain);
}

world.addObject(box);
world.buildAllObjects();
/**
* Place the camera at the starting position.
*/
setCamera(box);
setLight();
Config.tuneForOutdoor();
}

private void setCamera(Object3D box) {
camera = world.getCamera();
camera.setPosition(0, -200, 200);
camera.lookAt(box.getTransformedCenter());
}

private void setLight() {
Config.fadeoutLight = false;
world.getLights().setOverbrightLighting(
Lights.OVERBRIGHT_LIGHTING_DISABLED);
world.getLights().setRGBScale(Lights.RGB_SCALE_2X);
world.setAmbientLight(25, 3, 3);

world.addLight(new SimpleVector(0, -150, 0), 25, 25, 3);
world.addLight(new SimpleVector(-100, -150, 100), 22, 15, 4);
world.addLight(new SimpleVector(100, -150, -100), 4, 2, 22);

world.setFogging(World.FOGGING_ENABLED);
world.setFogParameters(1200, 0, 0, 0);

}

/**
* Use the KeyMapper to poll the keyboard
*/
private void poll() {
KeyState state = null;
do {
state = keyMapper.poll();
if (state != KeyState.NONE) {
keyAffected(state);
}
} while (state != KeyState.NONE);
}

private void keyAffected(KeyState state) {
int code = state.getKeyCode();
boolean event = state.getState();

switch (code) {
case (KeyEvent.VK_ESCAPE): {
if (finishOnESC)
exit = event;
break;
}
case (KeyEvent.VK_UP): {
up = event;
break;
}
case (KeyEvent.VK_DOWN): {
down = event;
break;
}
case (KeyEvent.VK_LEFT): {
left = event;
break;
}
case (KeyEvent.VK_RIGHT): {
right = event;
break;
}
}
}

// TODO Understand how to move the camera to follow the car ...
private void moveTheCamera() {
camera.lookAt(box.getTransformedCenter());
// SimpleVector a = camera.getPosition();
// a.scalarMul(SPEED);
// camera.setPosition(a);
}

private void moveTheCube() {

if (up) {
SimpleVector a = box.getZAxis();
a.scalarMul(SPEED);
box.translate(a);
moveTheCamera();
}

if (down) {
SimpleVector a = box.getZAxis();
a.scalarMul(-SPEED);
box.translate(a);
moveTheCamera();
}

if (left) {
box.rotateY(ROTATE_ANGLE);
}

if (right) {
box.rotateY(-ROTATE_ANGLE);
}

}

public void exit() {
exit = true;
}

public void finishOnESC(boolean b) {
this.finishOnESC = b;
}

// my component does not care about overlapping
public boolean isOptimizedDrawingEnabled() {
return true;
}
}

athanazio

I forget this one ... the interface


import java.io.InputStream;

public interface Pathbuilder {
public InputStream  createPath(String filename) throws Exception ;
}

cyberkilla

Thanks for that. I forgot about rotateMesh
Danke;)
http://futurerp.net - Text Based MMORPG
http://beta.rpwar.com - 3D Isometric MMORPG