
My last post I showed you how to import a ship object into your JME game.
This is my sample code that has a bunch of moving Asteroids and a fleet of moving ships from the object that you imported. Below is all of the code for the classes to create the above scenerio. The changes I added from my prior posts are listed below the code. To run this game, you should retrieve the obj file and the images I posted in my prior posts. Below is code up to this point using JME. You also might need to adjust the speed based on the speed of your computer.
You will also need the Asteroid3DStart.java, Movable.java and the MainMenu.java classed from my prior posts to run this game.
Ship.java
package com.guid.asteroid3D;
import java.util.Random;
import com.guid.asteroid3D.Movable;
import com.jme.bounding.BoundingBox;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.scene.TriMesh;
import com.jme.scene.state.TextureState;
public class Ship extends Node implements Movable{
private static final long serialVersionUID = 1L;
private float xlocation=0f;
private float ylocation=0f;
private float zlocation=-4000f;
private Random myRNG=null;
private int worldx=1000;
private int worldy=1000;
private TriMesh mesh=null;
private int speed=0;
public Ship(TriMesh mesh,TextureState ts1)
{ this.mesh=mesh;
this.mesh.setLocalScale(.1f);
this.mesh.setRenderState(ts1);
Quaternion rotQuat = new Quaternion();
Vector3f axis = new Vector3f(0,1,0).normalizeLocal();
float angle = 90; //TBD, prior post should change vector3f to 0,1,0 and angle to 90
rotQuat.fromAngleNormalAxis(angle * FastMath.DEG_TO_RAD, axis);
this.mesh.setLocalRotation(rotQuat);
this.mesh.setModelBound(new BoundingBox());
resetLocation();
}
public float getZLocation()
{
return this.zlocation;
}
public TriMesh getTriMesh()
{
return this.mesh;
}
public void move()
{
zlocation=zlocation+6+speed;
mesh.setLocalTranslation(new Vector3f(xlocation, ylocation,zlocation));
mesh.updateModelBound();
}
public void resetLocation()
{zlocation=-4000f;
myRNG=new Random();
speed=myRNG.nextInt(15);
int x=myRNG.nextInt(worldx);
int y=myRNG.nextInt(worldy);
if(xworldx/2)
{
xlocation=x/2;
}
else
{
xlocation=0;
}
if(yworldy/2)
{
ylocation=y/2;
}
else
{
ylocation=0;
}
mesh.setLocalTranslation(new Vector3f(xlocation, ylocation,zlocation));
mesh.updateModelBound();
}
}
Asteroid.java
package com.guid.asteroid3D;
import java.util.Random;
import com.jme.bounding.BoundingBox;
import com.jme.math.Vector3f;
import com.jme.scene.shape.Sphere;
import com.guid.asteroid3D.Movable;
public class Asteroid extends Sphere implements Movable{
private static final long serialVersionUID=123l;
private float xlocation=1000f;
private float ylocation=0f;
private float zlocation=-8000f;
private Random myRNG=null;
private int worldx=8000;
private int worldy=8000;
private int speed=0;
public Asteroid()
{
super("Asteroid", 30, 30, 25);
this.setModelBound(new BoundingBox());
resetLocation();
}
public float getZLocation()
{
return this.zlocation;
}
public void move()
{
zlocation=zlocation +10 +speed;speed;
this.setLocalTranslation(new Vector3f(xlocation, ylocation,zlocation));
this.updateModelBound();
}
public void resetLocation()
{ zlocation=-8000f;
myRNG=new Random();
speed=myRNG.nextInt(15);
int x=myRNG.nextInt(worldx);
int y=myRNG.nextInt(worldy);
if(xworldx/2)
{
xlocation=x/2;
}
else
{
xlocation=0;
}
if(yworldy/2)
{
ylocation=y/2;
}
else
{
ylocation=0;
}
this.setLocalTranslation(new Vector3f(xlocation, ylocation,zlocation));
this.updateModelBound();
}
}
AsteroidConstants.java
package com.guid.asteroid3D;
public class AsteroidConstants {
public static final String LEFT="LEFT";
public static final String RIGHT="RIGHT";
public static final String UP="UP";
public static final String DOWN="DOWN";
public static final int ADDASTEROID=30;
public static final int ADDSHIP=100;
}
Asteroid3DGame.java
package com.guid.asteroid3D;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import jmetest.TutorialGuide.HelloModelLoading;
import com.jme.app.BaseGame;
import com.jme.image.Texture;
import com.jme.input.FirstPersonHandler;
import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.input.action.InputAction;
import com.jme.input.action.InputActionEvent;
import com.jme.input.action.MouseInputAction;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.lwjgl.LWJGLRenderer;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.TriMesh;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.TextureManager;
import com.jme.util.Timer;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.model.converters.FormatConverter;
import com.jmex.model.converters.ObjToJme;
public class Asteroid3DGame extends BaseGame {
private int width, height, depth, freq;
private boolean fullscreen;
private Camera cam;
protected Timer timer;
private Node scene;
private TextureState ts;
private TextureState ts1;
private float xcameralocation=0.0f;
private float ycameralocation=0.0f;
private float zcameralocation=25.0f;
private int count=0;
private int textureWidth;
private int textureHeight;
protected void initGame() {
scene = new Node("Scene graph node");
ts = display.getRenderer().createTextureState();
ts.setEnabled(true);
ts.setTexture(TextureManager.loadTexture(Asteroid3DGame.class.getClassLoader()
.getResource("jmetest/data/images/Monkey.jpg"),
Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR));
for(int x=0;x<25;x++ )
{
Asteroid asteroid=new Asteroid();
asteroid.setRenderState(ts);
scene.attachChild(asteroid);
}
URL model =
HelloModelLoading.class.getClassLoader().
getResource("images/ship.obj");
FormatConverter converter = new ObjToJme();
ByteArrayOutputStream BO = new ByteArrayOutputStream();
BinaryImporter jbr = new BinaryImporter();
TriMesh ship = null;
ts1 = display.getRenderer().createTextureState();
ts1.setEnabled(true);
ts1.setTexture(TextureManager.loadTexture(Asteroid3DGame.class.getClassLoader()
.getResource("images/lava01.jpg"),
Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR));
for(int x=0;x<15;x++ )
{
try {
converter.convert(model.openStream(), BO);
ship = (TriMesh) jbr.load(new ByteArrayInputStream(BO.toByteArray()));
} catch (IOException e) {
e.printStackTrace();
System.exit(0);
}
Ship newShip=new Ship(ship,ts1);
scene.attachChild(newShip);
scene.attachChild(ship);
}
scene.updateGeometricState(0.0f, true);
scene.updateRenderState();
}
protected void reinit() {
display.recreateWindow(width, height, depth, freq, fullscreen);
}
protected void cleanup() {
ts.deleteAll();
}
private float getUForPixel(int xPixel) {
return (float) xPixel / textureWidth;
}
private float getVForPixel(int yPixel) {
return 1f - (float) yPixel / textureHeight;
}
protected void initSystem() {
width = properties.getWidth();
height = properties.getHeight();
depth = properties.getDepth();
freq = properties.getFreq();
fullscreen = properties.getFullscreen();
try {
display = DisplaySystem.getDisplaySystem(properties.getRenderer());
display.createWindow(width, height, depth, freq, fullscreen);
//***************
LWJGLRenderer renderer=(LWJGLRenderer)display.getRenderer();//TBD
if(renderer==null) //TBD
{
System.out.println("rednderer is null");//TBD
}
cam = renderer.createCamera(width, height);
} catch (JmeException e) {
e.printStackTrace();
System.exit(1);
}
display.getRenderer().setBackgroundColor(ColorRGBA.black);
cam.setFrustumPerspective(45.0f, (float)width / (float)height, 1, 8000);
Vector3f loc = new Vector3f(xcameralocation,ycameralocation,zcameralocation);
Vector3f left = new Vector3f(-1.0f, 0.0f, 0.0f);
Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
Vector3f dir = new Vector3f(0.0f, 0f, -1.0f);
// Move our camera to a correct place and orientation.
cam.setFrame(loc, left, up, dir);
cam.update();
timer = Timer.getTimer();
display.getRenderer().setCamera(cam);
KeyBindingManager.getKeyBindingManager().set("exit",
KeyInput.KEY_ESCAPE);
KeyBindingManager.getKeyBindingManager().set(AsteroidConstants.DOWN,
KeyInput.KEY_DOWN);
KeyBindingManager.getKeyBindingManager().set(AsteroidConstants.LEFT,
KeyInput.KEY_LEFT);
KeyBindingManager.getKeyBindingManager().set(AsteroidConstants.RIGHT,
KeyInput.KEY_RIGHT);
KeyBindingManager.getKeyBindingManager().set(AsteroidConstants.UP,
KeyInput.KEY_UP);
}
private void moveCamera(String direction)
{//TBD increase the camera movement by 5
if(direction.equals(AsteroidConstants.RIGHT))
{
xcameralocation-=7;
Vector3f loc = new Vector3f(xcameralocation,ycameralocation,zcameralocation);
cam.setLocation(loc);
cam.update();
}
if(direction.equals(AsteroidConstants.LEFT))
{
xcameralocation +=7;
Vector3f loc = new Vector3f(xcameralocation,ycameralocation,zcameralocation);
cam.setLocation(loc);
cam.update();
}
if(direction.equals(AsteroidConstants.UP))
{
ycameralocation-=7;
Vector3f loc = new Vector3f(xcameralocation,ycameralocation,zcameralocation);
cam.setLocation(loc);
cam.update();
}
if(direction.equals(AsteroidConstants.DOWN))
{
ycameralocation +=7;
Vector3f loc = new Vector3f(xcameralocation,ycameralocation,zcameralocation);
cam.setLocation(loc);
cam.update();
}
}
protected void update(float interpolation) {
timer.update();
interpolation = timer.getTimePerFrame();
if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit")) {
finished = true;
}
if (KeyBindingManager.getKeyBindingManager().isValidCommand(AsteroidConstants.LEFT)) {
moveCamera(AsteroidConstants.LEFT);
}
if (KeyBindingManager.getKeyBindingManager().isValidCommand(AsteroidConstants.RIGHT)) {
moveCamera(AsteroidConstants.RIGHT);
}
if (KeyBindingManager.getKeyBindingManager().isValidCommand(AsteroidConstants.UP)) {
moveCamera(AsteroidConstants.UP);
}
if (KeyBindingManager.getKeyBindingManager().isValidCommand(AsteroidConstants.DOWN)) {
moveCamera(AsteroidConstants.DOWN);
}
ArrayList<Spatial> childList=scene.getChildren();
if(childList!=null)
{
int size=childList.size();
for(int x=0;x<size;x++ )
{
Spatial spat=childList.get(x);
if(spat instanceof Movable)
{ Movable mov=((Movable) spat);
mov.move();
}
if(spat instanceof Asteroid)
{
Asteroid ast=(Asteroid)(spat);
if(ast.getZLocation()>this.zcameralocation+ 8000)
{
ast.resetLocation();
}
}
if(spat instanceof Ship)
{
Ship ast=(Ship)(spat);
if(ast.getZLocation()>this.zcameralocation+ 8000)
{
ast.resetLocation();
}
}
}
}
count++ ;
if(count%3==0&&count<800)
{
Asteroid asteroid=new Asteroid();
asteroid.setRenderState(ts);
scene.attachChild(asteroid);
scene.updateGeometricState(0.0f, true);
scene.updateRenderState();
}
}
protected void render(float interpolation) {
display.getRenderer().clearBuffers();
display.getRenderer().draw(scene);
}
}
The big change I made since my last post is I created a Ship object to randomize the locations of the TriMesh object in the scene tree. I also added a speed variable to randomize the speed of the objects. I created objects in a loop after importing the TriMesh object. I add the TriMesh object to the scene and the Ship object. The Ship object contains a reference to the TriMesh object so when I move the ship, it will transform the TriMesh object which will change the TriMesh within the scene. When the objects have passed the camera, I reset their location so that they can start over and be placed back in front of the camera. This way we have an endless supply of Asteroids and Ships. So now we have Asteroids and Ships flying towards you at different speeds.
Go To Step 10
Read more...