Refactoring of subsystems and eventbus
This commit is contained in:
@@ -7,10 +7,10 @@ import java.nio.channels.FileLock;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import mightypork.rogue.bus.events.UpdateEvent;
|
||||
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;
|
||||
@@ -25,6 +25,11 @@ import mightypork.utils.time.TimerDelta;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
|
||||
/**
|
||||
* Main class
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class App implements Destroyable, AppAccess {
|
||||
|
||||
/** instance pointer */
|
||||
@@ -61,7 +66,7 @@ public class App implements Destroyable, AppAccess {
|
||||
|
||||
|
||||
/**
|
||||
* Show crash report dialog with error stack trace.
|
||||
* Handle a crash
|
||||
*
|
||||
* @param error
|
||||
*/
|
||||
@@ -69,15 +74,12 @@ public class App implements Destroyable, AppAccess {
|
||||
{
|
||||
Log.e("The game has crashed.", error);
|
||||
|
||||
if (inst != null) inst.exit();
|
||||
if (inst != null) inst.shutdown();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Quit to OS<br>
|
||||
* Destroy app & exit VM
|
||||
*/
|
||||
public void exit()
|
||||
@Override
|
||||
public void shutdown()
|
||||
{
|
||||
destroy();
|
||||
System.exit(0);
|
||||
@@ -121,7 +123,7 @@ public class App implements Destroyable, AppAccess {
|
||||
);
|
||||
//@formatter:on
|
||||
|
||||
exit();
|
||||
shutdown();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -165,7 +167,7 @@ public class App implements Destroyable, AppAccess {
|
||||
private void initBus()
|
||||
{
|
||||
events = new MessageBus();
|
||||
events.addSubscriber(this);
|
||||
events.subscribe(this);
|
||||
|
||||
events.createChannel(UpdateEvent.class, UpdateEvent.Listener.class);
|
||||
}
|
||||
@@ -214,7 +216,7 @@ public class App implements Destroyable, AppAccess {
|
||||
public void run()
|
||||
{
|
||||
Log.f3("CTRL+Q, shutting down.");
|
||||
exit();
|
||||
shutdown();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -246,7 +248,7 @@ public class App implements Destroyable, AppAccess {
|
||||
{
|
||||
initialize();
|
||||
mainLoop();
|
||||
exit();
|
||||
shutdown();
|
||||
}
|
||||
|
||||
/** timer */
|
||||
@@ -293,7 +295,7 @@ public class App implements Destroyable, AppAccess {
|
||||
* @return sound system of the running instance
|
||||
*/
|
||||
@Override
|
||||
public SoundSystem soundsys()
|
||||
public SoundSystem snd()
|
||||
{
|
||||
return sounds;
|
||||
}
|
||||
@@ -323,7 +325,7 @@ public class App implements Destroyable, AppAccess {
|
||||
* @return event bus
|
||||
*/
|
||||
@Override
|
||||
public MessageBus msgbus()
|
||||
public MessageBus bus()
|
||||
{
|
||||
return events;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public interface AppAccess {
|
||||
/**
|
||||
* @return sound system
|
||||
*/
|
||||
abstract SoundSystem soundsys();
|
||||
abstract SoundSystem snd();
|
||||
|
||||
|
||||
/**
|
||||
@@ -35,6 +35,13 @@ public interface AppAccess {
|
||||
/**
|
||||
* @return event bus
|
||||
*/
|
||||
abstract MessageBus msgbus();
|
||||
abstract MessageBus bus();
|
||||
|
||||
|
||||
/**
|
||||
* Quit to OS<br>
|
||||
* Destroy app & exit VM
|
||||
*/
|
||||
abstract void shutdown();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
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 access adapter
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class AppAdapter implements AppAccess {
|
||||
|
||||
private AppAccess app;
|
||||
|
||||
|
||||
public AppAdapter(AppAccess app) {
|
||||
if (app == null) throw new NullPointerException("AppAccess instance cannot be null.");
|
||||
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final SoundSystem snd()
|
||||
{
|
||||
return app.snd();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final InputSystem input()
|
||||
{
|
||||
return app.input();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final DisplaySystem disp()
|
||||
{
|
||||
return app.disp();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final MessageBus bus()
|
||||
{
|
||||
return app.bus();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void shutdown()
|
||||
{
|
||||
app.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
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.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package mightypork.rogue.bus;
|
||||
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import mightypork.rogue.AppAccess;
|
||||
import mightypork.rogue.AppAdapter;
|
||||
import mightypork.rogue.bus.events.UpdateEvent;
|
||||
import mightypork.utils.logging.Log;
|
||||
import mightypork.utils.patterns.Destroyable;
|
||||
import mightypork.utils.patterns.subscription.MessageBus;
|
||||
import mightypork.utils.patterns.subscription.clients.DelegatingClient;
|
||||
import mightypork.utils.patterns.subscription.clients.ToggleableClient;
|
||||
import mightypork.utils.time.Updateable;
|
||||
|
||||
|
||||
/**
|
||||
* App event bus client, to be used for subsystems, screens and anything that
|
||||
* needs access to the eventbus
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public abstract class DelegatingBusClient extends AppAdapter implements DelegatingClient, ToggleableClient, Destroyable, Updateable, UpdateEvent.Listener {
|
||||
|
||||
/** Subsystem children subscribing to MessageBus */
|
||||
private Set<Object> childSubscribers = new HashSet<Object>();
|
||||
|
||||
private boolean wantUpdates = true;
|
||||
private boolean eventsEnabled = true;
|
||||
|
||||
|
||||
public DelegatingBusClient(AppAccess app, boolean updates) {
|
||||
super(app);
|
||||
|
||||
bus().subscribe(this);
|
||||
|
||||
enableUpdates(updates);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a child subscriber to the {@link MessageBus}.<br>
|
||||
*
|
||||
* @param client
|
||||
* @return true on success
|
||||
*/
|
||||
public final boolean addChildSubscriber(Object client)
|
||||
{
|
||||
if (client == null) return false;
|
||||
|
||||
childSubscribers.add(client);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove a child subscriber
|
||||
*
|
||||
* @param client subscriber to remove
|
||||
*/
|
||||
public final void removeChildSubscriber(Object client)
|
||||
{
|
||||
if (client == null) return;
|
||||
|
||||
childSubscribers.remove(client);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final Collection<Object> getChildClients()
|
||||
{
|
||||
return childSubscribers;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final boolean doesDelegate()
|
||||
{
|
||||
return doesSubscribe();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to receive {@link UpdateEvent}s (delta timing, one each
|
||||
* frame).<br>
|
||||
*
|
||||
* @param enable
|
||||
*/
|
||||
public final void enableUpdates(boolean enable)
|
||||
{
|
||||
wantUpdates = enable;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final boolean doesSubscribe()
|
||||
{
|
||||
return eventsEnabled;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set whether events should be received.
|
||||
*
|
||||
* @param enable
|
||||
*/
|
||||
public final void enableEvents(boolean enable)
|
||||
{
|
||||
this.eventsEnabled = enable;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void receive(UpdateEvent event)
|
||||
{
|
||||
if (wantUpdates) update(event.getDeltaTime());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void destroy()
|
||||
{
|
||||
deinit();
|
||||
|
||||
enableUpdates(false);
|
||||
|
||||
bus().unsubscribe(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
Log.w("Client " + getClass().getSimpleName() + " receives updates, but does not override the update() method.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the subsystem<br>
|
||||
* (called during construction)
|
||||
*/
|
||||
protected void init()
|
||||
{
|
||||
// no impl
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deinitialize the subsystem<br>
|
||||
* (called during destruction)
|
||||
*/
|
||||
protected void deinit()
|
||||
{
|
||||
// no impl
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package mightypork.rogue.bus;
|
||||
|
||||
|
||||
import mightypork.rogue.AppAccess;
|
||||
import mightypork.rogue.AppAdapter;
|
||||
|
||||
|
||||
/**
|
||||
* Simplest event bus client with app access
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class SimpleBusClient extends AppAdapter {
|
||||
|
||||
/**
|
||||
* @param app app access
|
||||
*/
|
||||
public SimpleBusClient(AppAccess app) {
|
||||
super(app);
|
||||
|
||||
bus().subscribe(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package mightypork.rogue.bus;
|
||||
|
||||
|
||||
import mightypork.rogue.AppAccess;
|
||||
import mightypork.rogue.bus.events.UpdateEvent;
|
||||
import mightypork.utils.time.Updateable;
|
||||
|
||||
|
||||
public abstract class UpdateReceiver extends SimpleBusClient implements UpdateEvent.Listener, Updateable {
|
||||
|
||||
public UpdateReceiver(AppAccess app) {
|
||||
super(app);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void receive(UpdateEvent event)
|
||||
{
|
||||
update(event.getDeltaTime());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public abstract void update(double delta);
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package mightypork.rogue.input.events;
|
||||
package mightypork.rogue.bus.events;
|
||||
|
||||
|
||||
import mightypork.utils.patterns.subscription.Handleable;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package mightypork.rogue.input.events;
|
||||
package mightypork.rogue.bus.events;
|
||||
|
||||
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package mightypork.rogue.input.events;
|
||||
package mightypork.rogue.bus.events;
|
||||
|
||||
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package mightypork.rogue.display.events;
|
||||
package mightypork.rogue.bus.events;
|
||||
|
||||
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package mightypork.rogue.display.events;
|
||||
package mightypork.rogue.bus.events;
|
||||
|
||||
|
||||
import mightypork.utils.patterns.subscription.Handleable;
|
||||
@@ -7,9 +7,9 @@ import java.awt.image.BufferedImage;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import mightypork.rogue.AppAccess;
|
||||
import mightypork.rogue.AppSubsystem;
|
||||
import mightypork.rogue.display.constraints.ConstraintContext;
|
||||
import mightypork.rogue.display.events.ScreenChangeEvent;
|
||||
import mightypork.rogue.bus.DelegatingBusClient;
|
||||
import mightypork.rogue.bus.events.ScreenChangeEvent;
|
||||
import mightypork.rogue.display.constraints.Bounding;
|
||||
import mightypork.utils.logging.Log;
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
import mightypork.utils.math.coord.Rect;
|
||||
@@ -20,7 +20,7 @@ import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.opengl.DisplayMode;
|
||||
|
||||
|
||||
public class DisplaySystem extends AppSubsystem implements ConstraintContext {
|
||||
public class DisplaySystem extends DelegatingBusClient implements Bounding {
|
||||
|
||||
private DisplayMode windowDisplayMode;
|
||||
private int targetFps;
|
||||
@@ -51,7 +51,7 @@ public class DisplaySystem extends AppSubsystem implements ConstraintContext {
|
||||
*/
|
||||
private void initChannels()
|
||||
{
|
||||
msgbus().createChannel(ScreenChangeEvent.class, ScreenChangeEvent.Listener.class);
|
||||
bus().createChannel(ScreenChangeEvent.class, ScreenChangeEvent.Listener.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ public class DisplaySystem extends AppSubsystem implements ConstraintContext {
|
||||
Display.update();
|
||||
}
|
||||
|
||||
msgbus().broadcast(new ScreenChangeEvent(true, Display.isFullscreen(), getSize()));
|
||||
bus().broadcast(new ScreenChangeEvent(true, Display.isFullscreen(), getSize()));
|
||||
|
||||
} catch (Throwable t) {
|
||||
Log.e("Failed to toggle fullscreen mode.", t);
|
||||
@@ -178,7 +178,7 @@ public class DisplaySystem extends AppSubsystem implements ConstraintContext {
|
||||
public void beginFrame()
|
||||
{
|
||||
if (Display.wasResized()) {
|
||||
msgbus().broadcast(new ScreenChangeEvent(false, Display.isFullscreen(), getSize()));
|
||||
bus().broadcast(new ScreenChangeEvent(false, Display.isFullscreen(), getSize()));
|
||||
}
|
||||
|
||||
glLoadIdentity();
|
||||
|
||||
@@ -3,9 +3,9 @@ package mightypork.rogue.display;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.*;
|
||||
import mightypork.rogue.AppAccess;
|
||||
import mightypork.rogue.AppSubsystem;
|
||||
import mightypork.rogue.display.constraints.ConstraintContext;
|
||||
import mightypork.rogue.display.events.ScreenChangeEvent;
|
||||
import mightypork.rogue.bus.DelegatingBusClient;
|
||||
import mightypork.rogue.bus.events.ScreenChangeEvent;
|
||||
import mightypork.rogue.display.constraints.Bounding;
|
||||
import mightypork.rogue.input.KeyBinder;
|
||||
import mightypork.rogue.input.KeyBindingPool;
|
||||
import mightypork.rogue.input.KeyStroke;
|
||||
@@ -20,7 +20,7 @@ import mightypork.utils.math.coord.Rect;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public abstract class Screen extends AppSubsystem implements KeyBinder, ConstraintContext, ScreenChangeEvent.Listener {
|
||||
public abstract class Screen extends DelegatingBusClient implements KeyBinder, Bounding, ScreenChangeEvent.Listener {
|
||||
|
||||
private KeyBindingPool keybindings;
|
||||
|
||||
@@ -28,7 +28,10 @@ public abstract class Screen extends AppSubsystem implements KeyBinder, Constrai
|
||||
|
||||
|
||||
public Screen(AppAccess app) {
|
||||
super(app, false);
|
||||
super(app, true);
|
||||
|
||||
// disable events initially
|
||||
enableEvents(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ package mightypork.rogue.display;
|
||||
import java.util.Random;
|
||||
|
||||
import mightypork.rogue.AppAccess;
|
||||
import mightypork.rogue.bus.events.MouseButtonEvent;
|
||||
import mightypork.rogue.input.KeyStroke;
|
||||
import mightypork.rogue.input.events.MouseButtonEvent;
|
||||
import mightypork.rogue.util.RenderUtils;
|
||||
import mightypork.utils.math.Polar;
|
||||
import mightypork.utils.math.color.RGB;
|
||||
|
||||
+2
-2
@@ -5,11 +5,11 @@ import mightypork.utils.math.coord.Rect;
|
||||
|
||||
|
||||
/**
|
||||
* Constraints can be based on this
|
||||
* Bounding box provider - context for {@link Constraint}
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public interface ConstraintContext {
|
||||
public interface Bounding {
|
||||
|
||||
/**
|
||||
* @return bounding rectangle
|
||||
@@ -2,39 +2,58 @@ package mightypork.rogue.display.constraints;
|
||||
|
||||
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
import mightypork.utils.math.coord.Rect;
|
||||
|
||||
|
||||
public abstract class Constraint implements ConstraintContext {
|
||||
public abstract class Constraint implements Bounding {
|
||||
|
||||
protected ConstraintContext context;
|
||||
protected Bounding context;
|
||||
|
||||
|
||||
public Constraint(ConstraintContext context) {
|
||||
public Constraint(Bounding context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
|
||||
public void setContext(ConstraintContext context)
|
||||
/**
|
||||
* Assign a context
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public void setContext(Bounding context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
|
||||
public ConstraintContext getContext()
|
||||
/**
|
||||
* @return context
|
||||
*/
|
||||
public Bounding getContext()
|
||||
{
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return context rect origin
|
||||
*/
|
||||
protected Coord origin()
|
||||
{
|
||||
return context.getRect().getOrigin();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return context rect size
|
||||
*/
|
||||
protected Coord size()
|
||||
{
|
||||
return context.getRect().getSize();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public abstract Rect getRect();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package mightypork.rogue.display.rendering;
|
||||
|
||||
|
||||
public interface Renderable {
|
||||
|
||||
public void render();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package mightypork.rogue.display.rendering;
|
||||
|
||||
|
||||
import mightypork.rogue.AppAccess;
|
||||
import mightypork.rogue.bus.DelegatingBusClient;
|
||||
|
||||
|
||||
public abstract class ScreenLayer extends DelegatingBusClient implements Renderable {
|
||||
|
||||
public ScreenLayer(AppAccess app) {
|
||||
super(app, true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public abstract void render();
|
||||
|
||||
}
|
||||
@@ -2,10 +2,10 @@ package mightypork.rogue.input;
|
||||
|
||||
|
||||
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.rogue.bus.DelegatingBusClient;
|
||||
import mightypork.rogue.bus.events.KeyboardEvent;
|
||||
import mightypork.rogue.bus.events.MouseButtonEvent;
|
||||
import mightypork.rogue.bus.events.MouseMotionEvent;
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
|
||||
import org.lwjgl.LWJGLException;
|
||||
@@ -14,7 +14,7 @@ import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.Display;
|
||||
|
||||
|
||||
public class InputSystem extends AppSubsystem implements KeyBinder {
|
||||
public class InputSystem extends DelegatingBusClient implements KeyBinder {
|
||||
|
||||
// listeners
|
||||
private KeyBindingPool keybindings;
|
||||
@@ -60,9 +60,9 @@ public class InputSystem extends AppSubsystem implements KeyBinder {
|
||||
|
||||
private void initChannels()
|
||||
{
|
||||
msgbus().createChannel(KeyboardEvent.class, KeyboardEvent.Listener.class);
|
||||
msgbus().createChannel(MouseMotionEvent.class, MouseMotionEvent.Listener.class);
|
||||
msgbus().createChannel(MouseButtonEvent.class, MouseButtonEvent.Listener.class);
|
||||
bus().createChannel(KeyboardEvent.class, KeyboardEvent.Listener.class);
|
||||
bus().createChannel(MouseMotionEvent.class, MouseMotionEvent.Listener.class);
|
||||
bus().createChannel(MouseButtonEvent.class, MouseButtonEvent.Listener.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -80,32 +80,10 @@ public class InputSystem extends AppSubsystem implements KeyBinder {
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
Display.processMessages();
|
||||
|
||||
while (Mouse.next()) {
|
||||
onMouseEvent();
|
||||
@@ -115,4 +93,26 @@ public class InputSystem extends AppSubsystem implements KeyBinder {
|
||||
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) bus().broadcast(new MouseButtonEvent(pos, button, down, wheeld));
|
||||
if (!move.isZero()) bus().broadcast(new MouseMotionEvent(pos, move));
|
||||
}
|
||||
|
||||
|
||||
private void onKeyEvent()
|
||||
{
|
||||
int key = Keyboard.getEventKey();
|
||||
boolean down = Keyboard.getEventKeyState();
|
||||
char c = Keyboard.getEventCharacter();
|
||||
bus().broadcast(new KeyboardEvent(key, c, down));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mightypork.rogue.input;
|
||||
|
||||
|
||||
import mightypork.rogue.input.events.KeyboardEvent;
|
||||
import mightypork.rogue.bus.events.KeyboardEvent;
|
||||
|
||||
|
||||
public class KeyBinding implements KeyboardEvent.Listener {
|
||||
|
||||
@@ -5,7 +5,7 @@ import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import mightypork.rogue.input.events.KeyboardEvent;
|
||||
import mightypork.rogue.bus.events.KeyboardEvent;
|
||||
import mightypork.utils.logging.Log;
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import mightypork.rogue.AppAccess;
|
||||
import mightypork.rogue.AppSubsystem;
|
||||
import mightypork.rogue.bus.DelegatingBusClient;
|
||||
import mightypork.utils.logging.Log;
|
||||
import mightypork.utils.math.Calc.Buffers;
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
@@ -25,7 +25,7 @@ import org.newdawn.slick.openal.SoundStore;
|
||||
* @author MightyPork
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class SoundSystem extends AppSubsystem {
|
||||
public class SoundSystem extends DelegatingBusClient {
|
||||
|
||||
private static final Coord INITIAL_LISTENER_POS = new Coord(0, 0, 0);
|
||||
private static final int MAX_SOURCES = 256;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package mightypork.rogue.testing;
|
||||
|
||||
|
||||
import mightypork.rogue.display.constraints.Bounding;
|
||||
import mightypork.rogue.display.constraints.Constraint;
|
||||
import mightypork.rogue.display.constraints.ConstraintContext;
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
import mightypork.utils.math.coord.Rect;
|
||||
|
||||
@@ -11,7 +11,7 @@ public class TestConstraints {
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
ConstraintContext context = new ConstraintContext() {
|
||||
Bounding context = new Bounding() {
|
||||
|
||||
@Override
|
||||
public Rect getRect()
|
||||
@@ -25,7 +25,7 @@ public class TestConstraints {
|
||||
private double height;
|
||||
|
||||
|
||||
public Navbar(ConstraintContext context, double height) {
|
||||
public Navbar(Bounding context, double height) {
|
||||
super(context);
|
||||
this.height = height;
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public class TestConstraints {
|
||||
private int tile;
|
||||
|
||||
|
||||
public TileHorizontal(ConstraintContext context, int tileCount, int aTile) {
|
||||
public TileHorizontal(Bounding context, int tileCount, int aTile) {
|
||||
super(context);
|
||||
this.count = tileCount;
|
||||
setTile(aTile);
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
package mightypork.rogue.testing;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import mightypork.utils.logging.Log;
|
||||
import mightypork.utils.patterns.subscription.Handleable;
|
||||
import mightypork.utils.patterns.subscription.MessageBus;
|
||||
import mightypork.utils.patterns.subscription.clients.DelegatingClient;
|
||||
import mightypork.utils.patterns.subscription.clients.ToggleableClient;
|
||||
|
||||
|
||||
public class TestMsgbus {
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
Log.create("runtime", new File("."), 0);
|
||||
|
||||
MessageBus bus = new MessageBus();
|
||||
|
||||
bus.createChannel(StringMessage.class, StringMessage.Listener.class);
|
||||
bus.createChannel(IntMessage.class, IntMessage.Listener.class);
|
||||
|
||||
Delegator deleg1 = new Delegator("Deleg1");
|
||||
Delegator deleg2 = new Delegator("Deleg2");
|
||||
Toggleable togg1 = new Toggleable("Tog1");
|
||||
Toggleable togg2 = new Toggleable("Tog2");
|
||||
Toggleable plain1 = new Toggleable("Plain1");
|
||||
Toggleable plain2 = new Toggleable("Plain2");
|
||||
Toggleable plain3 = new Toggleable("Plain3");
|
||||
|
||||
PlainInt pint = new PlainInt("Ints");
|
||||
PlainBoth pboth = new PlainBoth("Both");
|
||||
|
||||
bus.subscribe(deleg1);
|
||||
|
||||
deleg1.clients.add(togg1);
|
||||
deleg1.clients.add(plain2);
|
||||
deleg1.clients.add(deleg2);
|
||||
deleg1.clients.add(pint);
|
||||
|
||||
deleg2.clients.add(deleg1);
|
||||
deleg2.clients.add(togg1);
|
||||
deleg2.clients.add(plain3);
|
||||
deleg2.clients.add(pboth);
|
||||
|
||||
bus.subscribe(plain1);
|
||||
|
||||
bus.subscribe(togg2);
|
||||
|
||||
bus.broadcast(new StringMessage("<MSG>"));
|
||||
bus.broadcast(new IntMessage(7));
|
||||
bus.broadcast(new IntMessage(13));
|
||||
|
||||
deleg2.delegating = false;
|
||||
|
||||
bus.broadcast(new IntMessage(44));
|
||||
|
||||
deleg2.delegating = true;
|
||||
|
||||
bus.broadcast(new IntMessage(45));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Delegator extends Plain implements DelegatingClient {
|
||||
|
||||
List<Object> clients = new ArrayList<Object>();
|
||||
boolean delegating = true;
|
||||
|
||||
|
||||
public Delegator(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<Object> getChildClients()
|
||||
{
|
||||
return clients;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean doesDelegate()
|
||||
{
|
||||
return delegating;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Toggleable extends Plain implements ToggleableClient {
|
||||
|
||||
boolean subscribing = true;
|
||||
|
||||
|
||||
public Toggleable(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean doesSubscribe()
|
||||
{
|
||||
return subscribing;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Plain implements StringMessage.Listener {
|
||||
|
||||
String name;
|
||||
|
||||
|
||||
public Plain(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void receive(StringMessage message)
|
||||
{
|
||||
System.out.println(name + " (STR) RECV: " + message.s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PlainInt implements IntMessage.Listener {
|
||||
|
||||
String name;
|
||||
|
||||
|
||||
public PlainInt(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void receive(IntMessage message)
|
||||
{
|
||||
System.out.println(name + " (INT) RECV: " + message.i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PlainBoth implements IntMessage.Listener, StringMessage.Listener {
|
||||
|
||||
String name;
|
||||
|
||||
|
||||
public PlainBoth(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void receive(IntMessage message)
|
||||
{
|
||||
System.out.println(name + " (both-INT) RECV: " + message.i);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void receive(StringMessage message)
|
||||
{
|
||||
System.out.println(name + " (both-STR) RECV: " + message.s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class StringMessage implements Handleable<StringMessage.Listener> {
|
||||
|
||||
String s;
|
||||
|
||||
|
||||
StringMessage(String str) {
|
||||
this.s = str;
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
|
||||
public void receive(StringMessage message);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handleBy(Listener handler)
|
||||
{
|
||||
handler.receive(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class IntMessage implements Handleable<IntMessage.Listener> {
|
||||
|
||||
int i;
|
||||
|
||||
|
||||
IntMessage(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
|
||||
public void receive(IntMessage message);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handleBy(Listener handler)
|
||||
{
|
||||
handler.receive(this);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ import static org.lwjgl.opengl.GL11.*;
|
||||
import org.newdawn.slick.opengl.Texture;
|
||||
|
||||
|
||||
// TODO rewrite to use hashmap with keys
|
||||
|
||||
/**
|
||||
* Texture loading class
|
||||
*
|
||||
@@ -13,62 +15,15 @@ import org.newdawn.slick.opengl.Texture;
|
||||
*/
|
||||
public class Textures {
|
||||
|
||||
protected static Texture buttons_menu;
|
||||
protected static Texture buttons_small;
|
||||
|
||||
// patterns need raw access (are repeated)
|
||||
public static Texture steel_small_dk;
|
||||
public static Texture steel_small_lt;
|
||||
public static Texture steel_big_dk;
|
||||
public static Texture steel_big_lt;
|
||||
public static Texture steel_big_scratched;
|
||||
public static Texture steel_brushed;
|
||||
public static Texture steel_rivet_belts;
|
||||
public static Texture water;
|
||||
|
||||
// particles need direct access
|
||||
public static Texture snow;
|
||||
public static Texture leaves;
|
||||
public static Texture rain;
|
||||
public static Texture circle;
|
||||
|
||||
protected static Texture logo;
|
||||
protected static Texture widgets;
|
||||
public static Texture program;
|
||||
protected static Texture icons;
|
||||
|
||||
public static Texture map_tiles;
|
||||
public static Texture map_shading;
|
||||
|
||||
// spotted
|
||||
public static Texture turtle_blue;
|
||||
public static Texture turtle_green;
|
||||
public static Texture turtle_purple;
|
||||
public static Texture turtle_yellow;
|
||||
|
||||
// misc
|
||||
public static Texture turtle_red;
|
||||
public static Texture turtle_brown_dk;
|
||||
public static Texture turtle_brown_lt;
|
||||
public static Texture turtle_brown_orn;
|
||||
// a shadow sheet
|
||||
public static Texture turtle_shadows;
|
||||
|
||||
public static Texture food;
|
||||
public static Texture food_shadows;
|
||||
|
||||
private static final String GUI = "res/images/gui/";
|
||||
private static final String PATTERNS = "res/images/patterns/";
|
||||
private static final String PROGRAM = "res/images/program/";
|
||||
private static final String TILES = "res/images/tiles/";
|
||||
private static final String SPRITES = "res/images/sprites/";
|
||||
private static final String PARTICLES = "res/images/particles/";
|
||||
|
||||
|
||||
/**
|
||||
* Load what's needed for splash
|
||||
*/
|
||||
public static void loadForSplash()
|
||||
public static void load()
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
@@ -76,63 +31,9 @@ public class Textures {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
logo = TextureManager.load(GUI + "logo.png");
|
||||
steel_small_dk = TextureManager.load(PATTERNS + "steel.png");
|
||||
|
||||
Tx.initForSplash();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load textures
|
||||
*/
|
||||
public static void load()
|
||||
{
|
||||
// gui
|
||||
buttons_menu = TextureManager.load(GUI + "buttons_menu.png");
|
||||
buttons_small = TextureManager.load(GUI + "buttons_small.png");
|
||||
widgets = TextureManager.load(GUI + "widgets.png");
|
||||
icons = TextureManager.load(GUI + "icons.png");
|
||||
|
||||
// patterns
|
||||
|
||||
steel_small_lt = TextureManager.load(PATTERNS + "steel_light.png"); // XXX Unused texture
|
||||
steel_big_dk = TextureManager.load(PATTERNS + "steel_big.png");
|
||||
steel_big_lt = TextureManager.load(PATTERNS + "steel_big_light.png");
|
||||
steel_big_scratched = TextureManager.load(PATTERNS + "steel_big_scratched.png");
|
||||
steel_brushed = TextureManager.load(PATTERNS + "steel_brushed.png");
|
||||
steel_rivet_belts = TextureManager.load(PATTERNS + "rivet_belts.png");
|
||||
water = TextureManager.load(PATTERNS + "water.png");
|
||||
|
||||
// particles
|
||||
snow = TextureManager.load(PARTICLES + "snow.png");
|
||||
leaves = TextureManager.load(PARTICLES + "leaves.png");
|
||||
rain = TextureManager.load(PARTICLES + "rain.png");
|
||||
circle = TextureManager.load(PARTICLES + "circle.png");
|
||||
|
||||
// program tiles
|
||||
program = TextureManager.load(PROGRAM + "program.png");
|
||||
|
||||
// map tiles
|
||||
map_tiles = TextureManager.load(TILES + "tiles.png");
|
||||
map_shading = TextureManager.load(TILES + "shading.png");
|
||||
|
||||
// turtle
|
||||
turtle_blue = TextureManager.load(SPRITES + "HD-blue.png");
|
||||
turtle_yellow = TextureManager.load(SPRITES + "HD-yellow.png");
|
||||
turtle_green = TextureManager.load(SPRITES + "HD-green.png");
|
||||
turtle_purple = TextureManager.load(SPRITES + "HD-purple.png");
|
||||
turtle_red = TextureManager.load(SPRITES + "HD-red.png");
|
||||
|
||||
turtle_brown_dk = TextureManager.load(SPRITES + "HD-brown-dk.png");
|
||||
turtle_brown_lt = TextureManager.load(SPRITES + "HD-brown-lt.png");
|
||||
turtle_brown_orn = TextureManager.load(SPRITES + "HD-brown-ornamental.png");
|
||||
turtle_shadows = TextureManager.load(SPRITES + "HD-shadow.png");
|
||||
|
||||
food = TextureManager.load(SPRITES + "food.png");
|
||||
food_shadows = TextureManager.load(SPRITES + "food-shadow.png");
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
Tx.init();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package mightypork.rogue.textures;
|
||||
|
||||
|
||||
// TODO rewrite
|
||||
|
||||
/**
|
||||
* List of texture quads for GUIs
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user