package engine;
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
import engine.hierarchy.Scene;
import engine.hierarchy.Stage;
import engine.implementation.SimpleClock;
import engine.implementation.SimpleImage;
import engine.implementation.SimpleKeyboard;
import engine.implementation.SimpleMouse;
import engine.implementation.SimpleRenderTarget;
import engine.interfaces.Clock;
import engine.interfaces.Library;
import engine.interfaces.RenderTarget;
import game.console.Console;
import game.scenes.DebugOverlay;
import game.scenes.MainMenuScene;
public final class Engine extends Applet implements Runnable, Stage {
/** Auto generated serial version UID */
private static final long serialVersionUID = -517727537873772926L;
/** The width of the game in pixels */
public static final int WIDTH = 640;
/** The height of the game in pixels */
public static final int HEIGHT = 480;
/** The number of buffers for the main canvas */
public static final int NUM_BUFFERS = 2;
private transient Thread thread;
private Canvas canvas;
private transient BufferStrategy bufferStrategy;
private transient RenderTarget screen;
private transient SimpleMouse mouse;
private transient SimpleKeyboard keyboard;
private transient Clock clock;
private Stack<Scene> sceneStack;
private transient Library library;
private transient Console console;
private boolean running;
public Engine() {
bufferStrategy = null;
screen = null;
mouse = null;
keyboard = null;
clock = null;
canvas = null;
sceneStack = null;
console = null;
}
private void loadLibrary() {
library = new MyLibrary();
}
@Override
public void init() {
if (thread != null) {
destroy();
}
thread = new Thread(this);
thread.start();
}
@Override
public void destroy() {
running = false;
while (thread.isAlive()) {
continue;
}
thread = null;
}
@Override
public void run() {
running = true;
begin();
console = new MyConsole(this);
// parseCommands();
loadLibrary();
sceneStack = new Stack<Scene>();
pushScene(new MainMenuScene());
pushScene(new DebugOverlay());
clock = new SimpleClock();
while (running) {
beginStep();
// Get a copy of the scene stack
Scene[] array = new Scene[sceneStack.size()];
sceneStack.copyInto(array);
// Update all scenes
for (Scene s : array) {
s.update();
}
for (Scene s : array) {
s.beforeMove(keyboard, mouse, clock);
}
for (Scene s : array) {
s.move();
}
for (Scene s : array) {
s.afterMove();
}
// Draw all scenes
for (Scene s : array) {
s.draw(screen);
}
endStep();
clock.nextFrame();
}
while (!sceneStack.isEmpty()) {
popScene();
}
library.findMusic("Background Music").stop();
clock = null;
end();
}
// private void parseCommands() {
// try {
// InputStream is = new FileInputStream("config/config.txt");
// console.executeStream(is);
// is.close();
// } catch (FileNotFoundException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }
@Override
public Library getLibrary() {
return library;
}
@Override
public Console getConsole() {
return console;
}
private void add(Scene scene) {
System.out.println("+++ " + scene + " added to Engine");
scene.add(this);
scene.update();
}
private void remove(Scene scene) {
System.out.println("--- " + scene + " removed from Engine");
scene.remove();
scene.update();
}
@Override
public Scene pushScene(final Scene scene) {
sceneStack.push(scene);
add(scene);
return scene;
}
@Override
public Scene popScene() {
Scene scene = sceneStack.pop();
remove(scene);
return scene;
}
@Override
public Scene peekScene() {
return sceneStack.peek();
}
@Override
public Scene insertSceneAbove(final Scene scene, final Scene reference) {
int index = sceneStack.indexOf(reference) + 1;
sceneStack.insertElementAt(scene, index);
add(scene);
return scene;
}
@Override
public Scene insertSceneBelow(final Scene scene, final Scene reference) {
int index = sceneStack.indexOf(reference);
sceneStack.insertElementAt(scene, index);
add(scene);
return scene;
}
@Override
public Scene removeSceneAboveScene(final Scene reference) {
int index = sceneStack.indexOf(reference) + 1;
Scene scene = sceneStack.remove(index);
remove(scene);
return scene;
}
@Override
public Scene removeSceneBelow(final Scene reference) {
int index = sceneStack.indexOf(reference) - 1;
Scene scene = sceneStack.remove(index);
remove(scene);
return scene;
}
@Override
public Scene removeScene(final Scene scene) {
sceneStack.remove(scene);
remove(scene);
return scene;
}
@Override
public Scene getSceneAbove(final Scene reference) {
int index = sceneStack.indexOf(reference) + 1;
try {
return sceneStack.get(index);
} catch (ArrayIndexOutOfBoundsException e) {
return null;
}
}
@Override
public Scene getSceneBelow(final Scene reference) {
int index = sceneStack.indexOf(reference) - 1;
try {
return sceneStack.get(index);
} catch (ArrayIndexOutOfBoundsException e) {
return null;
}
}
@Override
public List<Scene> getScenes() {
return new LinkedList<Scene>(sceneStack);
}
/** Called once when the page containing the game is entered. */
public void begin() {
setSize(WIDTH, HEIGHT);
setLayout(new BorderLayout());
setIgnoreRepaint(true);
canvas = new Canvas();
add(canvas);
canvas.setSize(WIDTH, HEIGHT);
canvas.setIgnoreRepaint(true);
canvas.createBufferStrategy(NUM_BUFFERS);
bufferStrategy = canvas.getBufferStrategy();
keyboard = new SimpleKeyboard();
canvas.addKeyListener(keyboard);
mouse = new SimpleMouse();
canvas.addMouseListener(mouse);
canvas.addMouseMotionListener(mouse);
SimpleImage.setGraphicsConfiguration(canvas.getGraphicsConfiguration());
canvas.requestFocusInWindow();
}
/** Called once when the page containing the game is exited. */
public void end() {
canvas.removeMouseMotionListener(mouse);
canvas.removeMouseListener(mouse);
mouse = null;
canvas.removeKeyListener(keyboard);
keyboard = null;
bufferStrategy = null;
remove(canvas);
canvas = null;
setLayout(null);
}
/** Called every step before anything else. */
private void beginStep() {
screen = new SimpleRenderTarget((Graphics2D) bufferStrategy.getDrawGraphics());
keyboard.poll();
mouse.poll();
}
/** Called every step after everything else. */
private void endStep() {
screen.destroy();
screen = null;
bufferStrategy.show();
}
}