diff --git a/src/mightypork/rogue/App.java b/src/mightypork/rogue/App.java index ba6fe05..4a1c8df 100644 --- a/src/mightypork/rogue/App.java +++ b/src/mightypork/rogue/App.java @@ -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() - { - return inst.display; - } - - - /** - * @return event bus of the running instance - */ - public static MessageBus msgbus() + @Override + public DisplaySystem disp() { - return inst.events; + return display; } /** - * @return screen of the running instance + * @return event bus */ - public static Screen screen() - { - return inst.getCurrentScreen(); - } - - - public static boolean broadcast(Object message) + @Override + public MessageBus msgbus() { - boolean was = msgbus().broadcast(message); - if (!was) Log.w("Message not accepted by any channel: " + message); - return was; + return events; } } diff --git a/src/mightypork/rogue/AppAccess.java b/src/mightypork/rogue/AppAccess.java new file mode 100644 index 0000000..c2776d2 --- /dev/null +++ b/src/mightypork/rogue/AppAccess.java @@ -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(); + +} diff --git a/src/mightypork/rogue/AppSubsystem.java b/src/mightypork/rogue/AppSubsystem.java new file mode 100644 index 0000000..0625cd1 --- /dev/null +++ b/src/mightypork/rogue/AppSubsystem.java @@ -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 childSubscribers = new HashSet(); + + + /** + * 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.
+ * 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).
+ * + * @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
+ * (called during construction) + */ + protected abstract void init(); + + + /** + * Deinitialize the subsystem
+ * (called during destruction)
+ *
+ * All child eventbus subscribers will be removed from the eventbus. + */ + protected abstract void deinit(); + + + /** + * Add a child subscriber to the {@link MessageBus}.
+ * Child subscribers are removed when subsystem is destroyed, and can be + * connected/disconnected using the enableEvents() 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."); + } +} diff --git a/src/mightypork/rogue/display/DisplaySystem.java b/src/mightypork/rogue/display/DisplaySystem.java index 7bbb5ea..0510543 100644 --- a/src/mightypork/rogue/display/DisplaySystem.java +++ b/src/mightypork/rogue/display/DisplaySystem.java @@ -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()); + } } diff --git a/src/mightypork/rogue/display/Screen.java b/src/mightypork/rogue/display/Screen.java index 01b8022..c651849 100644 --- a/src/mightypork/rogue/display/Screen.java +++ b/src/mightypork/rogue/display/Screen.java @@ -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.
- * 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 update(double delta) + { + updateScreen(delta); + + renderBegin(); + renderScreen(); + renderEnd(); + } + + @Override - public final void receive(KeyboardEvent event) + public final Rect getRect() { - if (!isActive()) return; - keybindings.receive(event); + return disp().getRect(); } } diff --git a/src/mightypork/rogue/display/ScreenTestAnimations.java b/src/mightypork/rogue/display/ScreenTestAnimations.java index d4da94d..99bd5f3 100644 --- a/src/mightypork/rogue/display/ScreenTestAnimations.java +++ b/src/mightypork/rogue/display/ScreenTestAnimations.java @@ -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,7 +116,7 @@ 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); } } }); @@ -121,79 +124,69 @@ public class ScreenTestAnimations extends Screen { @Override - protected void renderScreen() + protected void deinitScreen() { - 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(RGB.GREEN); - RenderUtils.quadSize(padding + a.getCurrentValue() * (screenW - perBoxH), 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); + // no impl } @Override - public void receive(MouseMotionEvent event) + protected void onScreenEnter() { - // + // no impl } @Override - public void receive(MouseButtonEvent event) + protected void onScreenLeave() { - if (event.isDown()) { - Coord vec = App.disp().getSize().half().vecTo(event.getPos()); - - Polar p = Polar.fromCoord(vec); - - degAnim.fadeTo(p.getAngleDeg() - 90, 1.5); - } + // no impl } @Override - protected void onEnter() + protected void updateScreen(double delta) { - // TODO Auto-generated method stub + degAnim.update(delta); + for (AnimDouble a : anims) { + a.update(delta); + } } @Override - protected void onLeave() + protected void renderScreen() { - // TODO Auto-generated method stub - - } + 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]; - @Override - protected void onSizeChanged(Coord size) - { - // TODO Auto-generated method stub + RenderUtils.setColor(RGB.GREEN); + RenderUtils.quadSize(padding + a.getCurrentValue() * (screenW - perBoxH), 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 - protected void updateScreen(double delta) + public void receive(MouseButtonEvent event) { - degAnim.update(delta); + if (event.isDown()) { + Coord vec = disp().getSize().half().vecTo(event.getPos()); - for (AnimDouble a : anims) { - a.update(delta); + Polar p = Polar.fromCoord(vec); + + degAnim.fadeTo(p.getAngleDeg() - 90, 1.5); } } diff --git a/src/mightypork/rogue/display/constraints/ConstraintContext.java b/src/mightypork/rogue/display/constraints/ConstraintContext.java index fe33008..aa5b86a 100644 --- a/src/mightypork/rogue/display/constraints/ConstraintContext.java +++ b/src/mightypork/rogue/display/constraints/ConstraintContext.java @@ -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(); } diff --git a/src/mightypork/rogue/display/events/UpdateEvent.java b/src/mightypork/rogue/display/events/UpdateEvent.java new file mode 100644 index 0000000..3852170 --- /dev/null +++ b/src/mightypork/rogue/display/events/UpdateEvent.java @@ -0,0 +1,33 @@ +package mightypork.rogue.display.events; + + +import mightypork.utils.patterns.subscription.Handleable; + + +public class UpdateEvent implements Handleable { + + 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); + } +} diff --git a/src/mightypork/rogue/fonts/Align.java b/src/mightypork/rogue/fonts/Align.java index 171e620..e9ff742 100644 --- a/src/mightypork/rogue/fonts/Align.java +++ b/src/mightypork/rogue/fonts/Align.java @@ -6,7 +6,6 @@ package mightypork.rogue.fonts; * * @author MightyPork */ -@SuppressWarnings("javadoc") public class Align { public static final int LEFT = -1; diff --git a/src/mightypork/rogue/fonts/Fonts.java b/src/mightypork/rogue/fonts/Fonts.java index 69b0a0f..cd9ceeb 100644 --- a/src/mightypork/rogue/fonts/Fonts.java +++ b/src/mightypork/rogue/fonts/Fonts.java @@ -11,7 +11,6 @@ import mightypork.utils.logging.Log; * * @author Rapus */ -@SuppressWarnings("javadoc") public class Fonts { public static LoadedFont splash_info; diff --git a/src/mightypork/rogue/input/InputSystem.java b/src/mightypork/rogue/input/InputSystem.java index 97d1143..2b6af67 100644 --- a/src/mightypork/rogue/input/InputSystem.java +++ b/src/mightypork/rogue/input/InputSystem.java @@ -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,25 +80,6 @@ public class InputSystem implements KeyBinder, Destroyable, Initializable { } - /** - * Update inputs - */ - public final void poll() - { - Display.processMessages(); // redundant if Display.update() is called in main loop - Mouse.poll(); - Keyboard.poll(); - - while (Mouse.next()) { - onMouseEvent(); - } - - while (Keyboard.next()) { - onKeyEvent(); - } - } - - private void onMouseEvent() { int button = Mouse.getEventButton(); @@ -112,8 +88,8 @@ public class InputSystem implements KeyBinder, Destroyable, Initializable { 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)); + if (button != -1 || wheeld != 0) msgbus().broadcast(new MouseButtonEvent(pos, button, down, wheeld)); + if (!move.isZero()) msgbus().broadcast(new MouseMotionEvent(pos, move)); } @@ -122,6 +98,21 @@ public class InputSystem implements KeyBinder, Destroyable, Initializable { int key = Keyboard.getEventKey(); boolean down = Keyboard.getEventKeyState(); char c = Keyboard.getEventCharacter(); - App.broadcast(new KeyboardEvent(key, c, down)); + msgbus().broadcast(new KeyboardEvent(key, c, down)); + } + + + @Override + public void update(double delta) + { + Display.processMessages(); // redundant if Display.update() is called in main loop + + while (Mouse.next()) { + onMouseEvent(); + } + + while (Keyboard.next()) { + onKeyEvent(); + } } } diff --git a/src/mightypork/rogue/sounds/BaseAudioPlayer.java b/src/mightypork/rogue/sounds/BaseAudioPlayer.java index 067041c..f4d81e2 100644 --- a/src/mightypork/rogue/sounds/BaseAudioPlayer.java +++ b/src/mightypork/rogue/sounds/BaseAudioPlayer.java @@ -30,6 +30,8 @@ public abstract class BaseAudioPlayer { this.baseGain = baseGain; this.basePitch = basePitch; + if (gainMultiplier == null) gainMultiplier = new Mutable(1D); + this.gainMultiplier = gainMultiplier; } diff --git a/src/mightypork/rogue/sounds/NullAudio.java b/src/mightypork/rogue/sounds/NullAudio.java new file mode 100644 index 0000000..e3417ff --- /dev/null +++ b/src/mightypork/rogue/sounds/NullAudio.java @@ -0,0 +1,17 @@ +package mightypork.rogue.sounds; + + +public class NullAudio extends AudioX { + + public NullAudio() { + super(""); + } + + + @Override + public boolean load() + { + return false; + } + +} diff --git a/src/mightypork/rogue/sounds/SoundSystem.java b/src/mightypork/rogue/sounds/SoundSystem.java index b0094e5..4ca9811 100644 --- a/src/mightypork/rogue/sounds/SoundSystem.java +++ b/src/mightypork/rogue/sounds/SoundSystem.java @@ -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 masterVolume = new Mutable(1D); public Mutable effectsVolume = new JointVolume(masterVolume); @@ -82,6 +77,45 @@ public class SoundSystem implements Updateable, Destroyable { private Set resources = new HashSet(); + 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(); - } - } diff --git a/src/mightypork/rogue/tasks/TaskTakeScreenshot.java b/src/mightypork/rogue/tasks/TaskTakeScreenshot.java index dde9961..1932574 100644 --- a/src/mightypork/rogue/tasks/TaskTakeScreenshot.java +++ b/src/mightypork/rogue/tasks/TaskTakeScreenshot.java @@ -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(); } diff --git a/src/mightypork/rogue/textures/Textures.java b/src/mightypork/rogue/textures/Textures.java index a8711e8..e6fc1c9 100644 --- a/src/mightypork/rogue/textures/Textures.java +++ b/src/mightypork/rogue/textures/Textures.java @@ -11,8 +11,6 @@ import org.newdawn.slick.opengl.Texture; * * @author MightyPork */ -@SuppressWarnings("javadoc") -// unrelevant public class Textures { protected static Texture buttons_menu; diff --git a/src/mightypork/rogue/textures/Tx.java b/src/mightypork/rogue/textures/Tx.java index a31f356..7715824 100644 --- a/src/mightypork/rogue/textures/Tx.java +++ b/src/mightypork/rogue/textures/Tx.java @@ -6,7 +6,6 @@ package mightypork.rogue.textures; * * @author MightyPork */ -@SuppressWarnings("javadoc") public class Tx { // logo diff --git a/src/mightypork/utils/objects/VarargsParser.java b/src/mightypork/utils/objects/VarargsParser.java index 23c1e3f..a9bfcfa 100644 --- a/src/mightypork/utils/objects/VarargsParser.java +++ b/src/mightypork/utils/objects/VarargsParser.java @@ -16,6 +16,8 @@ import java.util.Map; * * * + * + * * Object[] array = { "one", 1, "two", 4, "three", 9, "four", 16 }; * Map<String, Integer> args = new VarargsParser<String, Integer>().parse(array); * diff --git a/src/mightypork/utils/patterns/Initializable.java b/src/mightypork/utils/patterns/Initializable.java deleted file mode 100644 index 31a7ba7..0000000 --- a/src/mightypork/utils/patterns/Initializable.java +++ /dev/null @@ -1,15 +0,0 @@ -package mightypork.utils.patterns; - - -/** - * Object that can be initialized - * - * @author MightyPork - */ -public interface Initializable { - - /** - * Initialize if not initialized yet - */ - public void initialize(); -} diff --git a/src/mightypork/utils/patterns/subscription/MessageBus.java b/src/mightypork/utils/patterns/subscription/MessageBus.java index 30ca56a..1333b00 100644 --- a/src/mightypork/utils/patterns/subscription/MessageBus.java +++ b/src/mightypork/utils/patterns/subscription/MessageBus.java @@ -16,6 +16,7 @@ public class MessageBus implements Subscribable { private Set> channels = new LinkedHashSet>(); private Set clients = new LinkedHashSet(); + private boolean warn_unsent = true; /** @@ -72,6 +73,8 @@ public class MessageBus implements Subscribable { for (MessageChannel b : channels) { sent |= b.broadcast(message); } + if (!sent && warn_unsent) Log.w("Message not accepted by any channel: " + message); + return sent; } @@ -80,11 +83,13 @@ public class MessageBus implements Subscribable { * Subscribe a client to the bus. The client will be connected to all * current and future channels, until removed from the bus. * - * @return true + * @return true on success */ @Override public boolean addSubscriber(Object client) { + if (client == null) return false; + for (MessageChannel b : channels) { b.addSubscriber(client); } @@ -106,6 +111,17 @@ public class MessageBus implements Subscribable { } + /** + * Enable logging of unsent messages + * + * @param enable + */ + public void enableLoggingUnsent(boolean enable) + { + this.warn_unsent = enable; + } + + /** * Add a channel for given message and client type. * @@ -113,7 +129,7 @@ public class MessageBus implements Subscribable { * @param clientClass client type * @return the created channel instance */ - public , F_CLIENT> MessageChannel registerMessageType(Class messageClass, Class clientClass) + public , F_CLIENT> MessageChannel createChannel(Class messageClass, Class clientClass) { MessageChannel bc = new MessageChannel(messageClass, clientClass); return addChannel(bc);