Removed junk & added Easing, Event system and others
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
package mightypork.rogue.display;
|
||||
|
||||
|
||||
import static org.lwjgl.opengl.GL11.*;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.LWJGLException;
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.opengl.DisplayMode;
|
||||
|
||||
import mightypork.rogue.App;
|
||||
import mightypork.rogue.Const;
|
||||
import mightypork.rogue.display.events.ScreenChangeEvent;
|
||||
import mightypork.utils.logging.Log;
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
import mightypork.utils.patterns.Destroyable;
|
||||
import mightypork.utils.patterns.Initializable;
|
||||
import mightypork.utils.time.Updateable;
|
||||
|
||||
|
||||
public class DisplaySystem implements Initializable, Destroyable {
|
||||
|
||||
private boolean initialized;
|
||||
|
||||
private DisplayMode windowDisplayMode;
|
||||
private int targetFps;
|
||||
|
||||
|
||||
public DisplaySystem() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize()
|
||||
{
|
||||
if(initialized) return;
|
||||
|
||||
initChannels();
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize event channels
|
||||
*/
|
||||
private void initChannels()
|
||||
{
|
||||
App.msgbus().registerMessageType(ScreenChangeEvent.class, ScreenChangeEvent.Listener.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
Display.destroy();
|
||||
}
|
||||
|
||||
|
||||
public void setTargetFps(int fps)
|
||||
{
|
||||
this.targetFps = fps;
|
||||
}
|
||||
|
||||
|
||||
public void createMainWindow(int width, int height, boolean resizable, boolean fullscreen, String title)
|
||||
{
|
||||
try {
|
||||
Display.setDisplayMode(windowDisplayMode = new DisplayMode(width, height));
|
||||
Display.setResizable(resizable);
|
||||
Display.setVSyncEnabled(true);
|
||||
Display.setTitle(title);
|
||||
Display.create();
|
||||
|
||||
if (fullscreen) {
|
||||
switchFullscreen();
|
||||
Display.update();
|
||||
}
|
||||
} catch (LWJGLException e) {
|
||||
throw new RuntimeException("Could not initialize screen", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Toggle FS if possible
|
||||
*/
|
||||
public void switchFullscreen()
|
||||
{
|
||||
try {
|
||||
|
||||
if (!Display.isFullscreen()) {
|
||||
Log.f3("Entering fullscreen.");
|
||||
// save window resize
|
||||
windowDisplayMode = new DisplayMode(Display.getWidth(), Display.getHeight());
|
||||
|
||||
Display.setDisplayMode(Display.getDesktopDisplayMode());
|
||||
Display.setFullscreen(true);
|
||||
Display.update();
|
||||
} else {
|
||||
Log.f3("Leaving fullscreen.");
|
||||
Display.setDisplayMode(windowDisplayMode);
|
||||
Display.update();
|
||||
}
|
||||
|
||||
App.broadcast(new ScreenChangeEvent(true, Display.isFullscreen(), getSize()));
|
||||
|
||||
} catch (Throwable t) {
|
||||
Log.e("Failed to toggle fullscreen mode.", t);
|
||||
try {
|
||||
Display.setDisplayMode(windowDisplayMode);
|
||||
Display.update();
|
||||
} catch (Throwable t1) {
|
||||
throw new RuntimeException("Failed to revert failed fullscreen toggle.", t1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public BufferedImage takeScreenshot()
|
||||
{
|
||||
glReadBuffer(GL_FRONT);
|
||||
int width = Display.getDisplayMode().getWidth();
|
||||
int height = Display.getDisplayMode().getHeight();
|
||||
int bpp = 4; // Assuming a 32-bit display with a byte each for red, green, blue, and alpha.
|
||||
ByteBuffer buffer = BufferUtils.createByteBuffer(width * height * bpp);
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
||||
|
||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
// convert to a buffered image
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
int i = (x + (width * y)) * bpp;
|
||||
int r = buffer.get(i) & 0xFF;
|
||||
int g = buffer.get(i + 1) & 0xFF;
|
||||
int b = buffer.get(i + 2) & 0xFF;
|
||||
image.setRGB(x, height - (y + 1), (0xFF << 24) | (r << 16) | (g << 8) | b);
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true if close was requested (i.e. click on cross)
|
||||
*/
|
||||
public boolean isCloseRequested()
|
||||
{
|
||||
return Display.isCloseRequested();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get fullscreen state
|
||||
*
|
||||
* @return is fullscreen
|
||||
*/
|
||||
public boolean isFullscreen()
|
||||
{
|
||||
return Display.isFullscreen();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get screen size
|
||||
*
|
||||
* @return size
|
||||
*/
|
||||
public Coord getSize()
|
||||
{
|
||||
return new Coord(Display.getWidth(), Display.getHeight());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start a OpenGL frame
|
||||
*/
|
||||
public void beginFrame()
|
||||
{
|
||||
if(Display.wasResized()) {
|
||||
App.broadcast(new ScreenChangeEvent(false, Display.isFullscreen(), getSize()));
|
||||
}
|
||||
|
||||
glLoadIdentity();
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* End an OpenGL frame, flip buffers, sync to fps.
|
||||
*/
|
||||
public void endFrame()
|
||||
{
|
||||
Display.update(false); // don't poll input devices
|
||||
Display.sync(targetFps);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
package mightypork.rogue.display;
|
||||
|
||||
|
||||
import static org.lwjgl.opengl.GL11.*;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import mightypork.rogue.App;
|
||||
import mightypork.rogue.display.events.ScreenChangeEvent;
|
||||
import mightypork.rogue.input.KeyBinder;
|
||||
import mightypork.rogue.input.KeyBindingPool;
|
||||
import mightypork.rogue.input.KeyStroke;
|
||||
import mightypork.rogue.input.events.KeyboardEvent;
|
||||
import mightypork.rogue.input.events.MouseMotionEvent;
|
||||
import mightypork.rogue.input.events.MouseButtonEvent;
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
import mightypork.utils.patterns.Destroyable;
|
||||
import mightypork.utils.patterns.Initializable;
|
||||
import mightypork.utils.time.Updateable;
|
||||
|
||||
|
||||
/**
|
||||
* Screen class.<br>
|
||||
* Screen animates 3D world, while contained panels render 2D overlays, process
|
||||
* inputs and run the game logic.
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public abstract class Screen implements KeyBinder, Updateable, Initializable, KeyboardEvent.Listener, MouseMotionEvent.Listener, MouseButtonEvent.Listener, ScreenChangeEvent.Listener {
|
||||
|
||||
private KeyBindingPool keybindings = new KeyBindingPool();
|
||||
|
||||
private boolean active;
|
||||
|
||||
|
||||
public Screen() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void bindKeyStroke(KeyStroke stroke, Runnable task)
|
||||
{
|
||||
keybindings.bindKeyStroke(stroke, task);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void unbindKeyStroke(KeyStroke stroke)
|
||||
{
|
||||
keybindings.unbindKeyStroke(stroke);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prepare for being shown
|
||||
* @param shown true to show, false to hide
|
||||
*/
|
||||
public final void setActive(boolean shown)
|
||||
{
|
||||
if (shown) {
|
||||
active = true;
|
||||
setupGraphics();
|
||||
setupViewport();
|
||||
onSizeChanged(App.disp().getSize());
|
||||
onEnter();
|
||||
App.msgbus().addSubscriber(this);
|
||||
} else {
|
||||
active = false;
|
||||
onLeave();
|
||||
App.msgbus().removeSubscriber(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setupGraphics()
|
||||
{
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
glClearDepth(1f);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
glEnable(GL_NORMALIZE);
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
setupViewport();
|
||||
}
|
||||
|
||||
|
||||
private void setupViewport()
|
||||
{
|
||||
// fix projection for changed size
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Coord s = App.disp().getSize();
|
||||
glViewport(0, 0, s.xi(), s.yi());
|
||||
glOrtho(0, s.x, 0, s.y, -1000, 1000);
|
||||
|
||||
// back to modelview
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize screen layout and key bindings.<br>
|
||||
* Called when the screen is created, not when it comes to front. For that, use onEnter().
|
||||
*/
|
||||
@Override
|
||||
public abstract void initialize();
|
||||
|
||||
/**
|
||||
* Called when the screen becomes active
|
||||
*/
|
||||
protected abstract void onEnter();
|
||||
|
||||
|
||||
/**
|
||||
* Called when the screen is no longer active
|
||||
*/
|
||||
protected abstract void onLeave();
|
||||
|
||||
|
||||
/**
|
||||
* Update GUI for new screen size
|
||||
*
|
||||
* @param size screen size
|
||||
*/
|
||||
protected abstract void onSizeChanged(Coord size);
|
||||
|
||||
|
||||
/**
|
||||
* Render screen contents (context is ready for 2D rendering)
|
||||
*/
|
||||
protected abstract void renderScreen();
|
||||
|
||||
|
||||
/**
|
||||
* Update animations and timing
|
||||
*
|
||||
* @param delta time elapsed
|
||||
*/
|
||||
protected abstract void updateScreen(double delta);
|
||||
|
||||
|
||||
/**
|
||||
* Render screen
|
||||
*/
|
||||
private final void renderBegin()
|
||||
{
|
||||
glPushAttrib(GL_ENABLE_BIT);
|
||||
glPushMatrix();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render screen
|
||||
*/
|
||||
private final void renderEnd()
|
||||
{
|
||||
glPopAttrib();
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void update(double delta)
|
||||
{
|
||||
if (!isActive()) return;
|
||||
|
||||
updateScreen(delta);
|
||||
renderBegin();
|
||||
renderScreen();
|
||||
renderEnd();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return true if screen is the curretn screen
|
||||
*/
|
||||
protected final boolean isActive()
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void receive(ScreenChangeEvent event)
|
||||
{
|
||||
if (!isActive()) return;
|
||||
|
||||
setupViewport();
|
||||
|
||||
onSizeChanged(event.getScreenSize());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void receive(KeyboardEvent event)
|
||||
{
|
||||
if (!isActive()) return;
|
||||
keybindings.receive(event);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package mightypork.rogue.display;
|
||||
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.Display;
|
||||
|
||||
import mightypork.rogue.App;
|
||||
import mightypork.rogue.input.KeyStroke;
|
||||
import mightypork.rogue.input.events.MouseButtonEvent;
|
||||
import mightypork.rogue.input.events.MouseMotionEvent;
|
||||
import mightypork.rogue.util.RenderUtils;
|
||||
import mightypork.utils.math.Polar;
|
||||
import mightypork.utils.math.color.RGB;
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
import mightypork.utils.math.easing.Easing;
|
||||
import mightypork.utils.time.AnimDouble;
|
||||
import mightypork.utils.time.AnimDoubleDeg;
|
||||
|
||||
|
||||
public class ScreenSplash extends Screen {
|
||||
|
||||
private AnimDoubleDeg degAnim = new AnimDoubleDeg(0, Easing.SINE);
|
||||
|
||||
//@formatter:off
|
||||
private AnimDouble[] anims = new AnimDouble[] {
|
||||
new AnimDouble(0, Easing.NONE),
|
||||
new AnimDouble(0, Easing.LINEAR),
|
||||
|
||||
new AnimDouble(0, Easing.QUADRATIC_IN),
|
||||
new AnimDouble(0, Easing.QUADRATIC_OUT),
|
||||
new AnimDouble(0, Easing.QUADRATIC),
|
||||
|
||||
new AnimDouble(0, Easing.CUBIC_IN),
|
||||
new AnimDouble(0, Easing.CUBIC_OUT),
|
||||
new AnimDouble(0, Easing.CUBIC),
|
||||
|
||||
new AnimDouble(0, Easing.QUADRATIC_IN),
|
||||
new AnimDouble(0, Easing.QUADRATIC_OUT),
|
||||
new AnimDouble(0, Easing.QUADRATIC),
|
||||
|
||||
new AnimDouble(0, Easing.QUINTIC_IN),
|
||||
new AnimDouble(0, Easing.QUINTIC_OUT),
|
||||
new AnimDouble(0, Easing.QUINTIC_IN_OUT),
|
||||
|
||||
new AnimDouble(0, Easing.EXPO_IN),
|
||||
new AnimDouble(0, Easing.EXPO_OUT),
|
||||
new AnimDouble(0, Easing.EXPO),
|
||||
|
||||
new AnimDouble(0, Easing.SINE_IN),
|
||||
new AnimDouble(0, Easing.SINE_OUT),
|
||||
new AnimDouble(0, Easing.SINE),
|
||||
|
||||
new AnimDouble(0, Easing.CIRC_IN),
|
||||
new AnimDouble(0, Easing.CIRC_OUT),
|
||||
new AnimDouble(0, Easing.CIRC),
|
||||
};
|
||||
//@formatter:on
|
||||
|
||||
@Override
|
||||
public void initialize()
|
||||
{
|
||||
bindKeyStroke(new KeyStroke(Keyboard.KEY_RIGHT), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
for (AnimDouble a : anims) {
|
||||
a.animate(0, 1, 3);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
bindKeyStroke(new KeyStroke(Keyboard.KEY_LEFT), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
for (AnimDouble a : anims) {
|
||||
a.animate(1, 0, 3);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void renderScreen()
|
||||
{
|
||||
double screenH = Display.getHeight();
|
||||
double screenW = Display.getWidth();
|
||||
double perBoxH = screenH / anims.length;
|
||||
double padding = perBoxH*0.1;
|
||||
double boxSide = perBoxH-padding*2;
|
||||
|
||||
for (int i = 0; i < anims.length; i++) {
|
||||
AnimDouble a = anims[i];
|
||||
|
||||
RenderUtils.setColor(i%3==0?RGB.GREEN:RGB.BLUE);
|
||||
RenderUtils.quadSize(
|
||||
padding + a.getCurrentValue() * (screenW - perBoxH - padding*2),
|
||||
screenH - perBoxH * i - perBoxH + padding,
|
||||
boxSide,
|
||||
boxSide
|
||||
);
|
||||
}
|
||||
|
||||
RenderUtils.setColor(RGB.YELLOW);
|
||||
RenderUtils.translate(new Coord(Display.getWidth() / 2, Display.getHeight() / 2));
|
||||
RenderUtils.rotateZ(degAnim.getCurrentValue());
|
||||
RenderUtils.quadSize(-10, -10, 20, 200);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void receive(MouseMotionEvent event)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void receive(MouseButtonEvent event)
|
||||
{
|
||||
if(event.isDown()) {
|
||||
Coord vec = App.disp().getSize().half().vecTo(event.getPos());
|
||||
|
||||
Polar p = Polar.fromCoord(vec);
|
||||
|
||||
degAnim.fadeTo(p.getAngleDeg() - 90, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onEnter()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onLeave()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(Coord size)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void updateScreen(double delta)
|
||||
{
|
||||
degAnim.update(delta);
|
||||
|
||||
for (AnimDouble a : anims) {
|
||||
a.update(delta);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package mightypork.rogue.display.events;
|
||||
|
||||
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
import mightypork.utils.patterns.subscription.Handleable;
|
||||
|
||||
|
||||
public class ScreenChangeEvent implements Handleable<ScreenChangeEvent.Listener> {
|
||||
|
||||
private boolean fullscreen;
|
||||
private Coord screenSize;
|
||||
private boolean fsChanged;
|
||||
|
||||
|
||||
public ScreenChangeEvent(boolean fsChanged, boolean fullscreen, Coord size) {
|
||||
this.fullscreen = fullscreen;
|
||||
this.screenSize = size;
|
||||
this.fsChanged = fsChanged;
|
||||
}
|
||||
|
||||
|
||||
public boolean isFullscreen()
|
||||
{
|
||||
return fullscreen;
|
||||
}
|
||||
|
||||
|
||||
public boolean fullscreenChanged()
|
||||
{
|
||||
return fsChanged;
|
||||
}
|
||||
|
||||
|
||||
public Coord getScreenSize()
|
||||
{
|
||||
return screenSize;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handleBy(Listener handler)
|
||||
{
|
||||
handler.receive(this);
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
|
||||
public void receive(ScreenChangeEvent event);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user