import net.sf.jirr.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.*;
/**
*
* @author Matthew Casperson
*
* The EngineManager class is used to initialize, manage and cleanup the underlying
* Irrlicht 3D engine.
*
*/
public class EngineManager extends IEventReceiver
{
static public final int WINDOW_WIDTH = 600;
static public final int WINDOW_HEIGHT = 400;
static protected final int READ_BUFFER_SIZE = 1000;
static protected final double MAX_DT = 0.1;
static protected EngineManager instance = null;
protected IrrlichtDevice device = null;
protected boolean running = true;
protected String filename;
protected long lastFrame = 0;
/** a collection of the BaseObjects */
protected EngineManagerCollection<BaseObject> baseObjects = new EngineManagerCollection<BaseObject>();
/** a collection of 2D game objects */
protected EngineManagerCollection<TwoDGameObject> twoDObjects = new EngineManagerCollection<TwoDGameObject>();
/** a map that defines which 2D game objects will collide */
protected Hashtable<String, ArrayList<String>> collisionMap = new Hashtable<String, ArrayList<String>>();
static public EngineManager getInstance()
{
if (instance == null)
instance = new EngineManager();
return instance;
}
public IrrlichtDevice getDevice()
{
return device;
}
public ISceneManager getSceneManager()
{
return device.getSceneManager();
}
public IVideoDriver getVideoDriver()
{
return device.getVideoDriver();
}
public IGUIEnvironment getGuiEnvironment()
{
return device.getGUIEnvironment();
}
protected EngineManager()
{
}
public boolean OnEvent(SEvent event)
{
if (event.getEventType() == EEVENT_TYPE.EET_KEY_INPUT_EVENT)
{
boolean pressedDown = event.isKeyInputPressedDown();
EKEY_CODE key = event.getKeyInputKey();
for (BaseObject gameObject : baseObjects.getMainCollection())
{
if (gameObject.inUse)
{
if (pressedDown)
gameObject.keyDown(key);
else
gameObject.keyUp(key);
}
}
}
return false;
}
public void startupEngineManager(String caption)
{
// create the Irrlicht device
device = Jirr.createDevice(E_DRIVER_TYPE.EDT_DIRECT3D9, new dimension2di(WINDOW_WIDTH, WINDOW_HEIGHT), 16, false, false, false, this);
// set the window title
device.setWindowCaption(caption);
// add a camera to the scene
device.getSceneManager().addCameraSceneNode(null, new vector3df(0,0,-50), new vector3df(0,0,0));
// load a font and set it as the default
IGUISkin skin = getGuiEnvironment().getSkin();
IGUIFont font = getGuiEnvironment().getFont("fonthaettenschweiler.bmp");
if (font != null)
skin.setFont(font);
loadResources();
lastFrame = System.currentTimeMillis();
}
protected void loadResources()
{
try
{
// The EngineManager assumes that there is a file called media.zip, either in the
// JAR file downloaded via Webstart, or just in the current working directory.
// Webstart doesn't allow you to know the name of the local JAR filename in the cache,
// but we can get access to the media.zip file easily enough with a call to
// getResourceAsStream. Once we get access to that file stream we can copy
// the media.zip file out into a known temporary location and give Irrlicht
// access to it there.
// get the file stream (should be null for a local app, and not null for a webstart app)
InputStream in = this.getClass().getResourceAsStream("media.zip");
if (in != null)
{
// find a unique temporary file name
int i = 0;
String tempDir = System.getProperty("java.io.tmpdir");
File file = null;
do
{
++i;
file = new File(tempDir + "media" + i + ".zip");
} while (file.exists());
// write the output file
filename = file.getPath();
OutputStream out = new FileOutputStream(filename);
int c;
byte[] buffer = new byte[READ_BUFFER_SIZE];
while ((c = in.read(buffer)) != -1)
{
out.write(buffer, 0, c);
}
in.close();
out.close();
System.out.println("addZipFileArchive: " + file);
device.getFileSystem().addZipFileArchive(file.getPath());
}
else
{
// otherwise assume there is a file called media.zip
System.out.println("addZipFileArchive: media.zip");
device.getFileSystem().addZipFileArchive("media.zip");
}
}
catch (Exception ex)
{
}
}
public void shutdown()
{
shutdownAll();
// clean up the Irrlicht engine
device.drop();
device = null;
// clean up the temporary file
if (filename != null)
{
File file = new File(filename);
file.delete();
}
}
public void stopGameLoop()
{
running = false;
}
public void enterGameLoop()
{
while (device.run() && running)
{
baseObjects.sync();
twoDObjects.sync();
// check for collisions between 2D objects
checkCollisions();
// notify all objects that we are starting a new frame
enterFrame();
// begin the scene
device.getVideoDriver().beginScene(true, true, new SColor(255,100,101,140));
// draw any 2D objects
draw2D();
// draw the scene
device.getSceneManager().drawAll();
// draw the GUI
device.getGUIEnvironment().drawAll();
// end the scene
device.getVideoDriver().endScene();
}
}
protected void draw2D()
{
// now allow objects to update themselves
for (BaseObject gameObject : baseObjects.getMainCollection())
if (gameObject.inUse)
gameObject.draw2D();
}
protected void enterFrame()
{
// Calculate the time since the last frame
long thisTick = System.currentTimeMillis();
double seconds = (thisTick - lastFrame) / 1000.0;
lastFrame = thisTick;
if (seconds > MAX_DT) seconds = MAX_DT;
ApplicationManager.getInstance().enterFrame(seconds);
// now allow objects to update themselves
for (BaseObject gameObject : baseObjects.getMainCollection())
if (gameObject.inUse)
gameObject.enterFrame(seconds);
}
public void addBaseObject(BaseObject object)
{
baseObjects.addObject(object);
}
public void removeBaseObject(BaseObject object)
{
baseObjects.removeObject(object);
}
public void addTwoDGameObject(TwoDGameObject object)
{
twoDObjects.addObject(object);
}
public void removeTwoDGameObject(TwoDGameObject object)
{
twoDObjects.removeObject(object);
}
protected void shutdownAll()
{
// don't dispose objects twice
for (BaseObject baseObject : baseObjects.getMainCollection())
{
boolean found = false;
for (BaseObject removedObject : baseObjects.getRemovedCollection())
{
if (removedObject == baseObject)
{
found = true;
break;
}
}
if (!found)
baseObject.shutdown();
}
}
public void addCollidingPair(String collider1, String collider2)
{
if (!collisionMap.containsKey(collider1))
collisionMap.put(collider1, new ArrayList<String>());
if (!collisionMap.containsKey(collider2))
collisionMap.put(collider2, new ArrayList<String>());
collisionMap.get(collider1).add(collider2);
collisionMap.get(collider2).add(collider1);
}
protected void checkCollisions()
{
for (int i = 0; i < twoDObjects.getMainCollection().size(); ++i)
{
TwoDGameObject gameObjectI = twoDObjects.getMainCollection().get(i);
for (int j = i + 1; j < twoDObjects.getMainCollection().size(); ++j)
{
TwoDGameObject gameObjectJ = twoDObjects.getMainCollection().get(j);
// early out for non-colliders
boolean collisionNameNotNothing = !gameObjectI.getCollisionName().equals(CollisionIdentifiers.NONE);
// objects can still exist in the baseObjects collection after being disposed, so check
boolean bothInUse = gameObjectI.getInUse() && gameObjectJ.getInUse();
// make sure we have an entry in the collisionMap
boolean collisionMapEntryExists = collisionMap.containsKey(gameObjectI.getCollisionName());
// make sure the two objects are set to collide
boolean testForCollision = collisionMapEntryExists && collisionMap.get(gameObjectI.getCollisionName()).contains(gameObjectJ.getCollisionName());
if ( collisionNameNotNothing &&
bothInUse &&
collisionMapEntryExists &&
testForCollision)
{
if (gameObjectI.getCollisionArea().isRectCollided(gameObjectJ.getCollisionArea()))
{
gameObjectI.collision(gameObjectJ);
gameObjectJ.collision(gameObjectI);
}
}
}
}
}
}
|