/*
* Copyright (C) 2014 MillerV
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package aspect.core;
import aspect.entity.Entity;
import aspect.entity.behavior.Behavior;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.Display.*;
import static aspect.core.AspectRenderer.*;
import aspect.event.KeyEvent;
import aspect.event.MouseEvent;
import aspect.physics.Time;
import aspect.render.shader.Shader;
import aspect.render.shader.Shader;
import aspect.render.shader.ShaderProgram;
import aspect.util.Matrix4x4;
import aspect.util.Vector3;
import aspect.world.World;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Container;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.File;
import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.opengl.PixelFormat;
/**
* A utility class containing methods for creating and animating the game
* window.
*
* @author MillerV
*/
public class AspectLauncher {
private static int frames = 0;
private static final Timer fpsTimer = new Timer();
private static final LinkedList<Behavior> keyListeners = new LinkedList<>();
private static final LinkedList<Behavior> mouseListeners = new LinkedList<>();
public static void main(String[] args) {
run(800, 600, false, 60, new Behavior());
}
/**
* Run the animation in full screen, calling appropriate event methods in
* the control Component. Remember that the actual FPS may drop below the
* specified value.
*
* @param fps the desired frame rate (negative value means don't cap)
* @param control the main event listener
*/
public static void createAnimation(int fps, Behavior control) {
run(0, 0, true, fps, control);
}
public static void createAnimation(Canvas canvas, final int fps, final Behavior control) {
try {
run(canvas.getWidth(), canvas.getHeight(), false, fps, control);
setParent(canvas);
setResizable(true);
canvas.setIgnoreRepaint(true);
} catch (LWJGLException ex) {
Logger.getLogger(AspectLauncher.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* Run the animation, calling appropriate event methods in the control
* Component. Remember that the actual FPS may drop below the specified
* value.
*
*
* @param width the window width
* @param height the window height
* @param fullscreen whether the window should be full screen
* @param fps the desired frame rate (negative value means don't cap)
* @param control the main event listener
* @see #printFPS(int)
*/
public static void run(final int width, final int height, final boolean fullscreen, final int fps, final Behavior control) {
System.setProperty("org.lwjgl.librarypath", new File("native").getAbsolutePath());
new Thread() {
@Override
public void run() {
try {
if (fullscreen) {
setFullscreen(true);
setVSyncEnabled(true);
} else {
setDisplayMode(new DisplayMode(width, height));
}
create(new PixelFormat(8, 8, 8));
AspectRenderer.FBO_ENABLED = GLContext.getCapabilities().GL_EXT_framebuffer_object;
ShaderProgram.BLINN_PHONG = ShaderProgram.loadPrebuilt("blinn-phong");
//ShaderProgram.PHONG = ShaderProgram.loadPrebuilt("phong");
ShaderProgram.COLOR = ShaderProgram.loadPrebuilt("color");
ShaderProgram.TEXTURE = ShaderProgram.loadPrebuilt("texture");
} catch (LWJGLException ex) {
Logger.getLogger(AspectLauncher.class.getName()).log(Level.SEVERE, null, ex);
}
Time.tick();
control.onAdd();
while (!isCloseRequested()) {
Time.tick();
setRenderMode(RenderMode.PERSPECTIVE);
clearRenderer();
if (mouseListeners.size() > 0) {
while (Mouse.next()) {
int button = Mouse.getEventButton();
int x = Mouse.getEventX();
int y = Mouse.getEventY();
int dx = Mouse.getEventDX();
int dy = Mouse.getEventDY();
int w = Mouse.getEventDWheel();
boolean state = Mouse.getEventButtonState();
for (Behavior c : mouseListeners) {
c.mouseEvent(new MouseEvent(button, x, y, dx, dy, w, state));
}
}
}
if (keyListeners.size() > 0) {
while (Keyboard.next()) {
char ch = Keyboard.getEventCharacter();
int key = Keyboard.getEventKey();
boolean state = Keyboard.getEventKeyState();
for (Behavior c : keyListeners) {
c.keyEvent(new KeyEvent(key, ch, state));
}
}
}
control.updateBehavior();
World.main.update();
clearRenderer();
if (skybox != null) {
loadIdentity();
Matrix4x4 m = camera.getCamMatrix();
skybox.transform.global.forward = m.transformVector(Vector3.zAxis().negate());
skybox.transform.global.up = m.transformVector(Vector3.yAxis());
skybox.render();
clearDepthBuffer();
camera.transformCamera();
}
control.render();
World.main.draw();
while (popMatrix()) {
Logger.getLogger(AspectLauncher.class.getName()).log(Level.WARNING, "Unpopped matrix (did you forget to pop it?)");
}
update();
if (fps > 0) {
sync(fps);
}
frames++;
}
control.onRemove();
Display.destroy();
fpsTimer.cancel();
System.exit(0);
}
}.start();
}
public static void addKeyListener(Behavior c) {
if (!keyListeners.contains(c)) {
keyListeners.add(c);
}
}
public static void addMouseListener(Behavior c) {
if (!mouseListeners.contains(c)) {
mouseListeners.add(c);
}
}
/**
* Print out the measured frame rate at the specified interval.
*
* @param interval the interval in milliseconds
*/
public static void printFPS(final int interval) {
fpsTimer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("FPS: " + ((frames * 1000) / interval));
frames = 0;
}
}, interval, interval);
}
}