Refactored subsystems for cleaner modularity.
This commit is contained in:
@@ -10,6 +10,7 @@ import javax.swing.JOptionPane;
|
||||
import mightypork.rogue.display.DisplaySystem;
|
||||
import mightypork.rogue.display.Screen;
|
||||
import mightypork.rogue.display.ScreenTestAnimations;
|
||||
import mightypork.rogue.display.events.UpdateEvent;
|
||||
import mightypork.rogue.input.InputSystem;
|
||||
import mightypork.rogue.input.KeyStroke;
|
||||
import mightypork.rogue.sounds.SoundSystem;
|
||||
@@ -20,12 +21,11 @@ import mightypork.utils.logging.LogInstance;
|
||||
import mightypork.utils.patterns.Destroyable;
|
||||
import mightypork.utils.patterns.subscription.MessageBus;
|
||||
import mightypork.utils.time.TimerDelta;
|
||||
import mightypork.utils.time.TimerInterpolating;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
|
||||
public class App implements Destroyable {
|
||||
public class App implements Destroyable, AppAccess {
|
||||
|
||||
/** instance pointer */
|
||||
private static App inst;
|
||||
@@ -42,17 +42,6 @@ public class App implements Destroyable {
|
||||
private boolean scheduledScreenshot = false;
|
||||
|
||||
|
||||
/**
|
||||
* Get the instance
|
||||
*
|
||||
* @return instance of App
|
||||
*/
|
||||
public static App inst()
|
||||
{
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param args
|
||||
*/
|
||||
@@ -80,7 +69,7 @@ public class App implements Destroyable {
|
||||
{
|
||||
Log.e("The game has crashed.", error);
|
||||
|
||||
inst.exit();
|
||||
if (inst != null) inst.exit();
|
||||
}
|
||||
|
||||
|
||||
@@ -95,17 +84,6 @@ public class App implements Destroyable {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get current screen
|
||||
*
|
||||
* @return screen
|
||||
*/
|
||||
public Screen getCurrentScreen()
|
||||
{
|
||||
return screen;
|
||||
}
|
||||
|
||||
|
||||
public void initialize()
|
||||
{
|
||||
Log.i("Initializing subsystems");
|
||||
@@ -188,6 +166,8 @@ public class App implements Destroyable {
|
||||
{
|
||||
events = new MessageBus();
|
||||
events.addSubscriber(this);
|
||||
|
||||
events.createChannel(UpdateEvent.class, UpdateEvent.Listener.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -196,7 +176,7 @@ public class App implements Destroyable {
|
||||
*/
|
||||
private void initSound()
|
||||
{
|
||||
sounds = new SoundSystem();
|
||||
sounds = new SoundSystem(this);
|
||||
sounds.setMasterVolume(1);
|
||||
}
|
||||
|
||||
@@ -206,7 +186,7 @@ public class App implements Destroyable {
|
||||
*/
|
||||
private void initInput()
|
||||
{
|
||||
input = new InputSystem();
|
||||
input = new InputSystem(this);
|
||||
|
||||
input.bindKeyStroke(new KeyStroke(Keyboard.KEY_F2), new Runnable() {
|
||||
|
||||
@@ -245,7 +225,7 @@ public class App implements Destroyable {
|
||||
*/
|
||||
private void initDisplay()
|
||||
{
|
||||
display = new DisplaySystem();
|
||||
display = new DisplaySystem(this);
|
||||
display.createMainWindow(Const.WINDOW_W, Const.WINDOW_H, true, Config.START_IN_FS, Const.TITLEBAR);
|
||||
display.setTargetFps(Const.FPS_RENDER);
|
||||
}
|
||||
@@ -275,8 +255,7 @@ public class App implements Destroyable {
|
||||
|
||||
private void mainLoop()
|
||||
{
|
||||
screen = new ScreenTestAnimations();
|
||||
|
||||
screen = new ScreenTestAnimations(this);
|
||||
screen.setActive(true);
|
||||
|
||||
timerRender = new TimerDelta();
|
||||
@@ -284,14 +263,7 @@ public class App implements Destroyable {
|
||||
while (!display.isCloseRequested()) {
|
||||
display.beginFrame();
|
||||
|
||||
input.poll();
|
||||
|
||||
double delta = timerRender.getDelta();
|
||||
|
||||
sounds.update(delta);
|
||||
|
||||
// Screen
|
||||
screen.update(delta);
|
||||
events.broadcast(new UpdateEvent(timerRender.getDelta()));
|
||||
|
||||
if (scheduledScreenshot) {
|
||||
takeScreenshot();
|
||||
@@ -309,7 +281,7 @@ public class App implements Destroyable {
|
||||
public void takeScreenshot()
|
||||
{
|
||||
sounds.getEffect("gui.shutter").play(1);
|
||||
Utils.runAsThread(new TaskTakeScreenshot());
|
||||
Utils.runAsThread(new TaskTakeScreenshot(display));
|
||||
}
|
||||
|
||||
|
||||
@@ -320,53 +292,40 @@ public class App implements Destroyable {
|
||||
/**
|
||||
* @return sound system of the running instance
|
||||
*/
|
||||
public static SoundSystem soundsys()
|
||||
@Override
|
||||
public SoundSystem soundsys()
|
||||
{
|
||||
return inst.sounds;
|
||||
return sounds;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return input system of the running instance
|
||||
*/
|
||||
public static InputSystem input()
|
||||
@Override
|
||||
public InputSystem input()
|
||||
{
|
||||
return inst.input;
|
||||
return input;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return display system of the running instance
|
||||
*/
|
||||
public static DisplaySystem disp()
|
||||
@Override
|
||||
public DisplaySystem disp()
|
||||
{
|
||||
return inst.display;
|
||||
return display;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return event bus of the running instance
|
||||
* @return event bus
|
||||
*/
|
||||
public static MessageBus msgbus()
|
||||
@Override
|
||||
public MessageBus msgbus()
|
||||
{
|
||||
return inst.events;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return screen of the running instance
|
||||
*/
|
||||
public static Screen screen()
|
||||
{
|
||||
return inst.getCurrentScreen();
|
||||
}
|
||||
|
||||
|
||||
public static boolean broadcast(Object message)
|
||||
{
|
||||
boolean was = msgbus().broadcast(message);
|
||||
if (!was) Log.w("Message not accepted by any channel: " + message);
|
||||
return was;
|
||||
return events;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package mightypork.rogue;
|
||||
|
||||
|
||||
import mightypork.rogue.display.DisplaySystem;
|
||||
import mightypork.rogue.input.InputSystem;
|
||||
import mightypork.rogue.sounds.SoundSystem;
|
||||
import mightypork.utils.patterns.subscription.MessageBus;
|
||||
|
||||
|
||||
/**
|
||||
* App interface visible to subsystems
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public interface AppAccess {
|
||||
|
||||
/**
|
||||
* @return sound system
|
||||
*/
|
||||
abstract SoundSystem soundsys();
|
||||
|
||||
|
||||
/**
|
||||
* @return input system
|
||||
*/
|
||||
abstract InputSystem input();
|
||||
|
||||
|
||||
/**
|
||||
* @return display system
|
||||
*/
|
||||
abstract DisplaySystem disp();
|
||||
|
||||
|
||||
/**
|
||||
* @return event bus
|
||||
*/
|
||||
abstract MessageBus msgbus();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
package mightypork.rogue;
|
||||
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import mightypork.rogue.display.DisplaySystem;
|
||||
import mightypork.rogue.display.events.UpdateEvent;
|
||||
import mightypork.rogue.input.InputSystem;
|
||||
import mightypork.rogue.sounds.SoundSystem;
|
||||
import mightypork.utils.logging.Log;
|
||||
import mightypork.utils.patterns.Destroyable;
|
||||
import mightypork.utils.patterns.subscription.MessageBus;
|
||||
import mightypork.utils.time.Updateable;
|
||||
|
||||
|
||||
public abstract class AppSubsystem implements AppAccess, UpdateEvent.Listener, Updateable, Destroyable {
|
||||
|
||||
private AppAccess app;
|
||||
private boolean wantUpdates;
|
||||
private boolean destroyed = false;
|
||||
|
||||
/** Subsystem children subscribing to MessageBus */
|
||||
private Set<Object> childSubscribers = new HashSet<Object>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a subsystem
|
||||
*
|
||||
* @param app app instance access
|
||||
* @param joinBus whether to initially join msgbus
|
||||
*/
|
||||
public AppSubsystem(AppAccess app, boolean joinBus) {
|
||||
this.app = app;
|
||||
|
||||
// add to subscriber group
|
||||
childSubscribers.add(this);
|
||||
|
||||
enableEvents(joinBus);
|
||||
|
||||
enableUpdates(true);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set whether events should be received.<br>
|
||||
* This includes {@link UpdateEvent}, so disabling events also disables
|
||||
* updates.
|
||||
*
|
||||
* @param enable
|
||||
*/
|
||||
protected final void enableEvents(boolean enable)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
// this & child subscribers
|
||||
for (Object o : childSubscribers) {
|
||||
if (enable) {
|
||||
app.msgbus().addSubscriber(o);
|
||||
} else {
|
||||
app.msgbus().removeSubscriber(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to receive {@link UpdateEvent}s (delta timing, one each
|
||||
* frame).<br>
|
||||
*
|
||||
* @param enable
|
||||
*/
|
||||
protected final void enableUpdates(boolean enable)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
wantUpdates = enable;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void receive(UpdateEvent event)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
if (wantUpdates) update(event.getDeltaTime());
|
||||
}
|
||||
|
||||
|
||||
// /**
|
||||
// * @return app instance
|
||||
// */
|
||||
// protected AppAccess app()
|
||||
// {
|
||||
// assertLive();
|
||||
//
|
||||
// return app;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
Log.w("Subsystem " + getClass().getSimpleName() + " receives updates, but does not override the update() method.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the subsystem<br>
|
||||
* (called during construction)
|
||||
*/
|
||||
protected abstract void init();
|
||||
|
||||
|
||||
/**
|
||||
* Deinitialize the subsystem<br>
|
||||
* (called during destruction)<br>
|
||||
* <br>
|
||||
* All child eventbus subscribers will be removed from the eventbus.
|
||||
*/
|
||||
protected abstract void deinit();
|
||||
|
||||
|
||||
/**
|
||||
* Add a child subscriber to the {@link MessageBus}.<br>
|
||||
* Child subscribers are removed when subsystem is destroyed, and can be
|
||||
* connected/disconnected using the <code>enableEvents()</code> method.
|
||||
*
|
||||
* @param client
|
||||
* @return true on success
|
||||
*/
|
||||
public final boolean addChildSubscriber(Object client)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
if (client == null) return false;
|
||||
|
||||
msgbus().addSubscriber(client);
|
||||
childSubscribers.add(client);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public final void removeChildSubscriber(Object client)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
childSubscribers.remove(client);
|
||||
msgbus().removeSubscriber(client);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void destroy()
|
||||
{
|
||||
assertLive();
|
||||
|
||||
deinit();
|
||||
|
||||
enableEvents(false); // remove all subscribers from bus
|
||||
app = null;
|
||||
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MessageBus msgbus()
|
||||
{
|
||||
assertLive();
|
||||
|
||||
return app.msgbus();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SoundSystem soundsys()
|
||||
{
|
||||
assertLive();
|
||||
|
||||
return app.soundsys();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public InputSystem input()
|
||||
{
|
||||
assertLive();
|
||||
|
||||
return app.input();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DisplaySystem disp()
|
||||
{
|
||||
assertLive();
|
||||
|
||||
return app.disp();
|
||||
}
|
||||
|
||||
|
||||
private void assertLive()
|
||||
{
|
||||
if (destroyed) throw new IllegalStateException("Subsystem already destroyed.");
|
||||
}
|
||||
}
|
||||
@@ -6,12 +6,13 @@ import static org.lwjgl.opengl.GL11.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import mightypork.rogue.App;
|
||||
import mightypork.rogue.AppAccess;
|
||||
import mightypork.rogue.AppSubsystem;
|
||||
import mightypork.rogue.display.constraints.ConstraintContext;
|
||||
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.math.coord.Rect;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.LWJGLException;
|
||||
@@ -19,27 +20,29 @@ import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.opengl.DisplayMode;
|
||||
|
||||
|
||||
public class DisplaySystem implements Initializable, Destroyable {
|
||||
|
||||
private boolean initialized;
|
||||
public class DisplaySystem extends AppSubsystem implements ConstraintContext {
|
||||
|
||||
private DisplayMode windowDisplayMode;
|
||||
private int targetFps;
|
||||
|
||||
|
||||
public DisplaySystem() {
|
||||
initialize();
|
||||
public DisplaySystem(AppAccess app) {
|
||||
super(app, true);
|
||||
enableUpdates(false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize()
|
||||
protected void init()
|
||||
{
|
||||
if (initialized) return;
|
||||
|
||||
initChannels();
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
|
||||
@Override
|
||||
public void deinit()
|
||||
{
|
||||
Display.destroy();
|
||||
}
|
||||
|
||||
|
||||
@@ -48,14 +51,7 @@ public class DisplaySystem implements Initializable, Destroyable {
|
||||
*/
|
||||
private void initChannels()
|
||||
{
|
||||
App.msgbus().registerMessageType(ScreenChangeEvent.class, ScreenChangeEvent.Listener.class);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
Display.destroy();
|
||||
msgbus().createChannel(ScreenChangeEvent.class, ScreenChangeEvent.Listener.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +101,7 @@ public class DisplaySystem implements Initializable, Destroyable {
|
||||
Display.update();
|
||||
}
|
||||
|
||||
App.broadcast(new ScreenChangeEvent(true, Display.isFullscreen(), getSize()));
|
||||
msgbus().broadcast(new ScreenChangeEvent(true, Display.isFullscreen(), getSize()));
|
||||
|
||||
} catch (Throwable t) {
|
||||
Log.e("Failed to toggle fullscreen mode.", t);
|
||||
@@ -182,7 +178,7 @@ public class DisplaySystem implements Initializable, Destroyable {
|
||||
public void beginFrame()
|
||||
{
|
||||
if (Display.wasResized()) {
|
||||
App.broadcast(new ScreenChangeEvent(false, Display.isFullscreen(), getSize()));
|
||||
msgbus().broadcast(new ScreenChangeEvent(false, Display.isFullscreen(), getSize()));
|
||||
}
|
||||
|
||||
glLoadIdentity();
|
||||
@@ -198,4 +194,11 @@ public class DisplaySystem implements Initializable, Destroyable {
|
||||
Display.update(false); // don't poll input devices
|
||||
Display.sync(targetFps);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Rect getRect()
|
||||
{
|
||||
return new Rect(getSize());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,15 @@ package mightypork.rogue.display;
|
||||
|
||||
|
||||
import static org.lwjgl.opengl.GL11.*;
|
||||
import mightypork.rogue.App;
|
||||
import mightypork.rogue.AppAccess;
|
||||
import mightypork.rogue.AppSubsystem;
|
||||
import mightypork.rogue.display.constraints.ConstraintContext;
|
||||
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.MouseButtonEvent;
|
||||
import mightypork.rogue.input.events.MouseMotionEvent;
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
import mightypork.utils.patterns.Initializable;
|
||||
import mightypork.utils.time.Updateable;
|
||||
import mightypork.utils.math.coord.Rect;
|
||||
|
||||
|
||||
/**
|
||||
@@ -22,27 +20,27 @@ import mightypork.utils.time.Updateable;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public abstract class Screen implements KeyBinder, Updateable, Initializable, KeyboardEvent.Listener, MouseMotionEvent.Listener, MouseButtonEvent.Listener, ScreenChangeEvent.Listener {
|
||||
public abstract class Screen extends AppSubsystem implements KeyBinder, ConstraintContext, ScreenChangeEvent.Listener {
|
||||
|
||||
private KeyBindingPool keybindings = new KeyBindingPool();
|
||||
private KeyBindingPool keybindings;
|
||||
|
||||
private boolean active;
|
||||
|
||||
|
||||
public Screen() {
|
||||
initialize();
|
||||
public Screen(AppAccess app) {
|
||||
super(app, false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void bindKeyStroke(KeyStroke stroke, Runnable task)
|
||||
public final void bindKeyStroke(KeyStroke stroke, Runnable task)
|
||||
{
|
||||
keybindings.bindKeyStroke(stroke, task);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void unbindKeyStroke(KeyStroke stroke)
|
||||
public final void unbindKeyStroke(KeyStroke stroke)
|
||||
{
|
||||
keybindings.unbindKeyStroke(stroke);
|
||||
}
|
||||
@@ -59,13 +57,19 @@ public abstract class Screen implements KeyBinder, Updateable, Initializable, Ke
|
||||
active = true;
|
||||
setupGraphics();
|
||||
setupViewport();
|
||||
onSizeChanged(App.disp().getSize());
|
||||
onEnter();
|
||||
App.msgbus().addSubscriber(this);
|
||||
onSizeChanged(getRect().getSize());
|
||||
onScreenEnter();
|
||||
|
||||
// subscribe to event bus
|
||||
enableEvents(true);
|
||||
|
||||
} else {
|
||||
onScreenLeave();
|
||||
|
||||
active = false;
|
||||
onLeave();
|
||||
App.msgbus().removeSubscriber(this);
|
||||
|
||||
// unsusbcribe from event bus
|
||||
enableEvents(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +103,7 @@ public abstract class Screen implements KeyBinder, Updateable, Initializable, Ke
|
||||
// fix projection for changed size
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Coord s = App.disp().getSize();
|
||||
Coord s = disp().getSize();
|
||||
glViewport(0, 0, s.xi(), s.yi());
|
||||
glOrtho(0, s.x, 0, s.y, -1000, 1000);
|
||||
|
||||
@@ -108,25 +112,47 @@ public abstract class Screen implements KeyBinder, Updateable, Initializable, Ke
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected final void init()
|
||||
{
|
||||
keybindings = new KeyBindingPool();
|
||||
|
||||
addChildSubscriber(keybindings);
|
||||
|
||||
initScreen();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected final void deinit()
|
||||
{
|
||||
deinitScreen();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize screen layout and key bindings.<br>
|
||||
* Called when the screen is created, not when it comes to front. For that,
|
||||
* use onEnter().
|
||||
* Called during screen construction.
|
||||
*/
|
||||
@Override
|
||||
public abstract void initialize();
|
||||
protected abstract void initScreen();
|
||||
|
||||
|
||||
/**
|
||||
* Clean up before screen is destroyed.
|
||||
*/
|
||||
protected abstract void deinitScreen();
|
||||
|
||||
|
||||
/**
|
||||
* Called when the screen becomes active
|
||||
*/
|
||||
protected abstract void onEnter();
|
||||
protected abstract void onScreenEnter();
|
||||
|
||||
|
||||
/**
|
||||
* Called when the screen is no longer active
|
||||
*/
|
||||
protected abstract void onLeave();
|
||||
protected abstract void onScreenLeave();
|
||||
|
||||
|
||||
/**
|
||||
@@ -134,7 +160,10 @@ public abstract class Screen implements KeyBinder, Updateable, Initializable, Ke
|
||||
*
|
||||
* @param size screen size
|
||||
*/
|
||||
protected abstract void onSizeChanged(Coord size);
|
||||
protected void onSizeChanged(Coord size)
|
||||
{
|
||||
// no impl
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -154,7 +183,7 @@ public abstract class Screen implements KeyBinder, Updateable, Initializable, Ke
|
||||
/**
|
||||
* Render screen
|
||||
*/
|
||||
private final void renderBegin()
|
||||
private void renderBegin()
|
||||
{
|
||||
glPushAttrib(GL_ENABLE_BIT);
|
||||
glPushMatrix();
|
||||
@@ -164,32 +193,17 @@ public abstract class Screen implements KeyBinder, Updateable, Initializable, Ke
|
||||
/**
|
||||
* Render screen
|
||||
*/
|
||||
private final void renderEnd()
|
||||
private void renderEnd()
|
||||
{
|
||||
glPopAttrib();
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update and render the screen
|
||||
*/
|
||||
@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()
|
||||
public final boolean isActive()
|
||||
{
|
||||
return active;
|
||||
}
|
||||
@@ -206,11 +220,24 @@ public abstract class Screen implements KeyBinder, Updateable, Initializable, Ke
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update and render the screen
|
||||
*/
|
||||
@Override
|
||||
public final void receive(KeyboardEvent event)
|
||||
public final void update(double delta)
|
||||
{
|
||||
if (!isActive()) return;
|
||||
keybindings.receive(event);
|
||||
updateScreen(delta);
|
||||
|
||||
renderBegin();
|
||||
renderScreen();
|
||||
renderEnd();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final Rect getRect()
|
||||
{
|
||||
return disp().getRect();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,10 +3,9 @@ package mightypork.rogue.display;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import mightypork.rogue.App;
|
||||
import mightypork.rogue.AppAccess;
|
||||
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;
|
||||
@@ -19,8 +18,12 @@ import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.opengl.Display;
|
||||
|
||||
|
||||
public class ScreenTestAnimations extends Screen {
|
||||
|
||||
public class ScreenTestAnimations extends Screen implements MouseButtonEvent.Listener {
|
||||
|
||||
public ScreenTestAnimations(AppAccess app) {
|
||||
super(app);
|
||||
}
|
||||
|
||||
private Random rand = new Random();
|
||||
|
||||
private AnimDoubleDeg degAnim = new AnimDoubleDeg(0, Easing.ELASTIC_OUT);
|
||||
@@ -94,7 +97,7 @@ public class ScreenTestAnimations extends Screen {
|
||||
//@formatter:on
|
||||
|
||||
@Override
|
||||
public void initialize()
|
||||
public void initScreen()
|
||||
{
|
||||
bindKeyStroke(new KeyStroke(Keyboard.KEY_RIGHT), new Runnable() {
|
||||
|
||||
@@ -102,7 +105,7 @@ public class ScreenTestAnimations extends Screen {
|
||||
public void run()
|
||||
{
|
||||
for (AnimDouble a : anims) {
|
||||
a.animate(0, 1, 1+rand.nextDouble()*1);
|
||||
a.animate(0, 1, 1 + rand.nextDouble() * 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -113,13 +116,45 @@ public class ScreenTestAnimations extends Screen {
|
||||
public void run()
|
||||
{
|
||||
for (AnimDouble a : anims) {
|
||||
a.animate(1, 0, 1+rand.nextDouble()*1);
|
||||
a.animate(1, 0, 1 + rand.nextDouble() * 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void deinitScreen()
|
||||
{
|
||||
// no impl
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onScreenEnter()
|
||||
{
|
||||
// no impl
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onScreenLeave()
|
||||
{
|
||||
// no impl
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void updateScreen(double delta)
|
||||
{
|
||||
degAnim.update(delta);
|
||||
|
||||
for (AnimDouble a : anims) {
|
||||
a.update(delta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void renderScreen()
|
||||
{
|
||||
@@ -143,18 +178,11 @@ public class ScreenTestAnimations extends Screen {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void receive(MouseMotionEvent event)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void receive(MouseButtonEvent event)
|
||||
{
|
||||
if (event.isDown()) {
|
||||
Coord vec = App.disp().getSize().half().vecTo(event.getPos());
|
||||
Coord vec = disp().getSize().half().vecTo(event.getPos());
|
||||
|
||||
Polar p = Polar.fromCoord(vec);
|
||||
|
||||
@@ -162,39 +190,4 @@ public class ScreenTestAnimations extends Screen {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,7 +4,15 @@ package mightypork.rogue.display.constraints;
|
||||
import mightypork.utils.math.coord.Rect;
|
||||
|
||||
|
||||
/**
|
||||
* Constraints can be based on this
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public interface ConstraintContext {
|
||||
|
||||
/**
|
||||
* @return bounding rectangle
|
||||
*/
|
||||
public Rect getRect();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package mightypork.rogue.display.events;
|
||||
|
||||
|
||||
import mightypork.utils.patterns.subscription.Handleable;
|
||||
|
||||
|
||||
public class UpdateEvent implements Handleable<UpdateEvent.Listener> {
|
||||
|
||||
private final double deltaTime;
|
||||
|
||||
|
||||
public UpdateEvent(double deltaTime) {
|
||||
this.deltaTime = deltaTime;
|
||||
}
|
||||
|
||||
|
||||
public double getDeltaTime()
|
||||
{
|
||||
return deltaTime;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handleBy(Listener handler)
|
||||
{
|
||||
handler.receive(this);
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
|
||||
public void receive(UpdateEvent event);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ package mightypork.rogue.fonts;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
@SuppressWarnings("javadoc")
|
||||
public class Align {
|
||||
|
||||
public static final int LEFT = -1;
|
||||
|
||||
@@ -11,7 +11,6 @@ import mightypork.utils.logging.Log;
|
||||
*
|
||||
* @author Rapus
|
||||
*/
|
||||
@SuppressWarnings("javadoc")
|
||||
public class Fonts {
|
||||
|
||||
public static LoadedFont splash_info;
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package mightypork.rogue.input;
|
||||
|
||||
|
||||
import mightypork.rogue.App;
|
||||
import mightypork.rogue.AppAccess;
|
||||
import mightypork.rogue.AppSubsystem;
|
||||
import mightypork.rogue.input.events.KeyboardEvent;
|
||||
import mightypork.rogue.input.events.MouseButtonEvent;
|
||||
import mightypork.rogue.input.events.MouseMotionEvent;
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
import mightypork.utils.patterns.Destroyable;
|
||||
import mightypork.utils.patterns.Initializable;
|
||||
|
||||
import org.lwjgl.LWJGLException;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
@@ -15,31 +14,35 @@ import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.Display;
|
||||
|
||||
|
||||
public class InputSystem implements KeyBinder, Destroyable, Initializable {
|
||||
|
||||
private boolean initialized;
|
||||
public class InputSystem extends AppSubsystem implements KeyBinder {
|
||||
|
||||
// listeners
|
||||
private KeyBindingPool keybindings;
|
||||
|
||||
|
||||
public InputSystem() {
|
||||
initialize();
|
||||
public InputSystem(AppAccess app) {
|
||||
super(app, true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize()
|
||||
protected void init()
|
||||
{
|
||||
if (initialized) return;
|
||||
|
||||
initDevices();
|
||||
|
||||
initChannels();
|
||||
|
||||
// global keybindings
|
||||
keybindings = new KeyBindingPool();
|
||||
addChildSubscriber(keybindings);
|
||||
}
|
||||
|
||||
App.msgbus().addSubscriber(keybindings);
|
||||
|
||||
@Override
|
||||
public void deinit()
|
||||
{
|
||||
Mouse.destroy();
|
||||
Keyboard.destroy();
|
||||
}
|
||||
|
||||
|
||||
@@ -57,17 +60,9 @@ public class InputSystem implements KeyBinder, Destroyable, Initializable {
|
||||
|
||||
private void initChannels()
|
||||
{
|
||||
App.msgbus().registerMessageType(KeyboardEvent.class, KeyboardEvent.Listener.class);
|
||||
App.msgbus().registerMessageType(MouseMotionEvent.class, MouseMotionEvent.Listener.class);
|
||||
App.msgbus().registerMessageType(MouseButtonEvent.class, MouseButtonEvent.Listener.class);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
Mouse.destroy();
|
||||
Keyboard.destroy();
|
||||
msgbus().createChannel(KeyboardEvent.class, KeyboardEvent.Listener.class);
|
||||
msgbus().createChannel(MouseMotionEvent.class, MouseMotionEvent.Listener.class);
|
||||
msgbus().createChannel(MouseButtonEvent.class, MouseButtonEvent.Listener.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,14 +80,32 @@ public class InputSystem implements KeyBinder, Destroyable, Initializable {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update inputs
|
||||
*/
|
||||
public final void poll()
|
||||
private void onMouseEvent()
|
||||
{
|
||||
int button = Mouse.getEventButton();
|
||||
boolean down = Mouse.getEventButtonState();
|
||||
Coord pos = new Coord(Mouse.getEventX(), Mouse.getEventY());
|
||||
Coord move = new Coord(Mouse.getEventDX(), Mouse.getEventDY());
|
||||
int wheeld = Mouse.getEventDWheel();
|
||||
|
||||
if (button != -1 || wheeld != 0) msgbus().broadcast(new MouseButtonEvent(pos, button, down, wheeld));
|
||||
if (!move.isZero()) msgbus().broadcast(new MouseMotionEvent(pos, move));
|
||||
}
|
||||
|
||||
|
||||
private void onKeyEvent()
|
||||
{
|
||||
int key = Keyboard.getEventKey();
|
||||
boolean down = Keyboard.getEventKeyState();
|
||||
char c = Keyboard.getEventCharacter();
|
||||
msgbus().broadcast(new KeyboardEvent(key, c, down));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
Display.processMessages(); // redundant if Display.update() is called in main loop
|
||||
Mouse.poll();
|
||||
Keyboard.poll();
|
||||
|
||||
while (Mouse.next()) {
|
||||
onMouseEvent();
|
||||
@@ -102,26 +115,4 @@ public class InputSystem implements KeyBinder, Destroyable, Initializable {
|
||||
onKeyEvent();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void onMouseEvent()
|
||||
{
|
||||
int button = Mouse.getEventButton();
|
||||
boolean down = Mouse.getEventButtonState();
|
||||
Coord pos = new Coord(Mouse.getEventX(), Mouse.getEventY());
|
||||
Coord move = new Coord(Mouse.getEventDX(), Mouse.getEventDY());
|
||||
int wheeld = Mouse.getEventDWheel();
|
||||
|
||||
if (button != -1 || wheeld != 0) App.broadcast(new MouseButtonEvent(pos, button, down, wheeld));
|
||||
if (!move.isZero()) App.broadcast(new MouseMotionEvent(pos, move));
|
||||
}
|
||||
|
||||
|
||||
private void onKeyEvent()
|
||||
{
|
||||
int key = Keyboard.getEventKey();
|
||||
boolean down = Keyboard.getEventKeyState();
|
||||
char c = Keyboard.getEventCharacter();
|
||||
App.broadcast(new KeyboardEvent(key, c, down));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ public abstract class BaseAudioPlayer {
|
||||
this.baseGain = baseGain;
|
||||
this.basePitch = basePitch;
|
||||
|
||||
if (gainMultiplier == null) gainMultiplier = new Mutable<Double>(1D);
|
||||
|
||||
this.gainMultiplier = gainMultiplier;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package mightypork.rogue.sounds;
|
||||
|
||||
|
||||
public class NullAudio extends AudioX {
|
||||
|
||||
public NullAudio() {
|
||||
super("");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean load()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,11 +7,12 @@ import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import mightypork.rogue.AppAccess;
|
||||
import mightypork.rogue.AppSubsystem;
|
||||
import mightypork.utils.logging.Log;
|
||||
import mightypork.utils.math.Calc.Buffers;
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
import mightypork.utils.objects.Mutable;
|
||||
import mightypork.utils.patterns.Destroyable;
|
||||
import mightypork.utils.time.Updateable;
|
||||
|
||||
import org.lwjgl.openal.AL;
|
||||
import org.lwjgl.openal.AL10;
|
||||
@@ -24,13 +25,13 @@ import org.newdawn.slick.openal.SoundStore;
|
||||
* @author MightyPork
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// needed for JointVolume
|
||||
public class SoundSystem implements Updateable, Destroyable {
|
||||
|
||||
// static
|
||||
public class SoundSystem extends AppSubsystem {
|
||||
|
||||
private static final Coord INITIAL_LISTENER_POS = new Coord(0, 0, 0);
|
||||
private static final int MAX_SOURCES = 256;
|
||||
private static final AudioX NO_SOUND = new NullAudio();
|
||||
private static final LoopPlayer NULL_LOOP = new LoopPlayer(NO_SOUND, 0, 0, null);
|
||||
private static final EffectPlayer NULL_EFFECT = new EffectPlayer(NO_SOUND, 0, 0, null);
|
||||
|
||||
private static Coord listener = new Coord();
|
||||
|
||||
@@ -65,13 +66,7 @@ public class SoundSystem implements Updateable, Destroyable {
|
||||
buf3 = buf6 = null;
|
||||
}
|
||||
|
||||
|
||||
public static Coord getListener()
|
||||
{
|
||||
return listener;
|
||||
}
|
||||
|
||||
// instance
|
||||
// -- instance --
|
||||
|
||||
public Mutable<Double> masterVolume = new Mutable<Double>(1D);
|
||||
public Mutable<Double> effectsVolume = new JointVolume(masterVolume);
|
||||
@@ -82,6 +77,45 @@ public class SoundSystem implements Updateable, Destroyable {
|
||||
private Set<AudioX> resources = new HashSet<AudioX>();
|
||||
|
||||
|
||||
public SoundSystem(AppAccess app) {
|
||||
super(app, true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void init()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void deinit()
|
||||
{
|
||||
for (AudioX r : resources) {
|
||||
r.destroy();
|
||||
}
|
||||
|
||||
SoundStore.get().clear();
|
||||
AL.destroy();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
for (LoopPlayer lp : loops.values()) {
|
||||
lp.update(delta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Coord getListener()
|
||||
{
|
||||
return listener;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register effect resource
|
||||
*
|
||||
@@ -141,7 +175,8 @@ public class SoundSystem implements Updateable, Destroyable {
|
||||
{
|
||||
LoopPlayer p = loops.get(key);
|
||||
if (p == null) {
|
||||
throw new IllegalArgumentException("Requesting unknown sound loop \"" + key + "\".");
|
||||
Log.w("Requesting unknown sound loop \"" + key + "\".");
|
||||
return NULL_LOOP;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
@@ -157,7 +192,8 @@ public class SoundSystem implements Updateable, Destroyable {
|
||||
{
|
||||
EffectPlayer p = effects.get(key);
|
||||
if (p == null) {
|
||||
throw new IllegalArgumentException("Requesting unknown sound effect \"" + key + "\".");
|
||||
Log.w("Requesting unknown sound effect \"" + key + "\".");
|
||||
return NULL_EFFECT;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
@@ -253,15 +289,6 @@ public class SoundSystem implements Updateable, Destroyable {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
for (LoopPlayer lp : loops.values()) {
|
||||
lp.update(delta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set level of master volume
|
||||
*
|
||||
@@ -293,17 +320,4 @@ public class SoundSystem implements Updateable, Destroyable {
|
||||
{
|
||||
loopsVolume.set(d);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
for (AudioX r : resources) {
|
||||
r.destroy();
|
||||
}
|
||||
|
||||
SoundStore.get().clear();
|
||||
AL.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ import java.util.Date;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import mightypork.rogue.App;
|
||||
import mightypork.rogue.Paths;
|
||||
import mightypork.rogue.display.DisplaySystem;
|
||||
import mightypork.utils.logging.Log;
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ public class TaskTakeScreenshot implements Runnable {
|
||||
private BufferedImage image;
|
||||
|
||||
|
||||
public TaskTakeScreenshot() {
|
||||
this.image = App.disp().takeScreenshot();
|
||||
public TaskTakeScreenshot(DisplaySystem disp) {
|
||||
this.image = disp.takeScreenshot();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11,8 +11,6 @@ import org.newdawn.slick.opengl.Texture;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
@SuppressWarnings("javadoc")
|
||||
// unrelevant
|
||||
public class Textures {
|
||||
|
||||
protected static Texture buttons_menu;
|
||||
|
||||
@@ -6,7 +6,6 @@ package mightypork.rogue.textures;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
@SuppressWarnings("javadoc")
|
||||
public class Tx {
|
||||
|
||||
// logo
|
||||
|
||||
Reference in New Issue
Block a user