FInal fields, tweaks to screen system, deferred loading.

v5stable
Ondřej Hruška 10 years ago
parent 53b7b02609
commit f5929f23b1
  1. 64
      src/mightypork/rogue/App.java
  2. 2
      src/mightypork/rogue/AppAccess.java
  3. 2
      src/mightypork/rogue/AppAdapter.java
  4. 24
      src/mightypork/rogue/MainLoop.java
  5. 34
      src/mightypork/rogue/Res.java
  6. 2
      src/mightypork/rogue/bus/ChildClient.java
  7. 16
      src/mightypork/rogue/bus/events/ActionRequest.java
  8. 6
      src/mightypork/rogue/bus/events/KeyboardEvent.java
  9. 38
      src/mightypork/rogue/bus/events/MainLoopTaskRequest.java
  10. 8
      src/mightypork/rogue/bus/events/MouseButtonEvent.java
  11. 4
      src/mightypork/rogue/bus/events/MouseMotionEvent.java
  12. 7
      src/mightypork/rogue/bus/events/RequestType.java
  13. 39
      src/mightypork/rogue/bus/events/ResourceLoadRequest.java
  14. 6
      src/mightypork/rogue/bus/events/ScreenChangeEvent.java
  15. 5
      src/mightypork/rogue/bus/events/ScreenRequestEvent.java
  16. 26
      src/mightypork/rogue/gui/LayeredScreen.java
  17. 29
      src/mightypork/rogue/gui/Screen.java
  18. 23
      src/mightypork/rogue/gui/ScreenLayer.java
  19. 11
      src/mightypork/rogue/gui/ScreenRegistry.java
  20. 45
      src/mightypork/rogue/gui/constraints/ColumnHolder.java
  21. 27
      src/mightypork/rogue/gui/constraints/ElementHolder.java
  22. 45
      src/mightypork/rogue/gui/constraints/RowHolder.java
  23. 70
      src/mightypork/rogue/gui/screens/screenBouncy/ScreenTestAnim.java
  24. 2
      src/mightypork/rogue/gui/screens/test_bouncyboxes/BouncyBox.java
  25. 25
      src/mightypork/rogue/gui/screens/test_bouncyboxes/LayerBouncyBoxes.java
  26. 80
      src/mightypork/rogue/gui/screens/test_bouncyboxes/ScreenTestBouncy.java
  27. 60
      src/mightypork/rogue/gui/screens/test_cat_sound/LayerFlyingCat.java
  28. 73
      src/mightypork/rogue/gui/screens/test_cat_sound/ScreenTestCat.java
  29. 17
      src/mightypork/rogue/input/InputSystem.java
  30. 2
      src/mightypork/rogue/input/KeyBinding.java
  31. 2
      src/mightypork/rogue/input/KeyBindingPool.java
  32. 25
      src/mightypork/rogue/input/KeyStroke.java
  33. 14
      src/mightypork/rogue/render/DisplaySystem.java
  34. 10
      src/mightypork/rogue/render/Render.java
  35. 15
      src/mightypork/rogue/sound/DeferredAudio.java
  36. 4
      src/mightypork/rogue/sound/JointVolume.java
  37. 2
      src/mightypork/rogue/sound/NullAudio.java
  38. 8
      src/mightypork/rogue/sound/SoundBank.java
  39. 17
      src/mightypork/rogue/sound/SoundSystem.java
  40. 16
      src/mightypork/rogue/sound/players/BaseAudioPlayer.java
  41. 3
      src/mightypork/rogue/sound/players/EffectPlayer.java
  42. 5
      src/mightypork/rogue/sound/players/LoopPlayer.java
  43. 102
      src/mightypork/rogue/texture/DeferredLoader.java
  44. 17
      src/mightypork/rogue/texture/DeferredTexture.java
  45. 17
      src/mightypork/rogue/texture/TextureBank.java
  46. 6
      src/mightypork/rogue/texture/TxQuad.java
  47. 38
      src/mightypork/utils/control/bus/EventBus.java
  48. 34
      src/mightypork/utils/control/bus/EventChannel.java
  49. 11
      src/mightypork/utils/control/bus/SingularEvent.java
  50. 5
      src/mightypork/utils/control/bus/events/DestroyEvent.java
  51. 1
      src/mightypork/utils/control/timing/TimerFps.java
  52. 28
      src/mightypork/utils/logging/Log.java
  53. 2
      src/mightypork/utils/math/constraints/ConstraintFactory.java
  54. 8
      src/mightypork/utils/math/coord/Rect.java

@ -8,12 +8,16 @@ import java.util.ArrayList;
import javax.swing.JOptionPane;
import mightypork.rogue.audio.SoundSystem;
import mightypork.rogue.bus.events.*;
import mightypork.rogue.gui.screens.ScreenRegistry;
import mightypork.rogue.bus.events.ActionRequest.RequestType;
import mightypork.rogue.gui.ScreenRegistry;
import mightypork.rogue.gui.screens.test_bouncyboxes.ScreenTestBouncy;
import mightypork.rogue.gui.screens.test_cat_sound.ScreenTestCat;
import mightypork.rogue.input.InputSystem;
import mightypork.rogue.input.KeyStroke;
import mightypork.rogue.render.DisplaySystem;
import mightypork.rogue.sound.SoundSystem;
import mightypork.rogue.texture.DeferredLoader;
import mightypork.utils.control.bus.EventBus;
import mightypork.utils.control.bus.events.DestroyEvent;
import mightypork.utils.control.bus.events.UpdateEvent;
@ -41,8 +45,7 @@ public class App implements AppAccess {
private static SoundSystem soundSystem;
private EventBus eventBus;
private MainLoop mainLoop;
public ScreenRegistry screens;
private ScreenRegistry screens;
/**
@ -73,6 +76,8 @@ public class App implements AppAccess {
initialize();
Log.i("Starting main loop...");
// open first screen
mainLoop.start();
}
@ -84,7 +89,12 @@ public class App implements AppAccess {
*/
public static void onCrash(Throwable error)
{
Log.e("The game has crashed!", error);
if (Log.ready()) {
Log.e("The game has crashed!", error);
} else {
System.err.println("The game has crashed!");
error.printStackTrace();
}
if (inst != null) inst.shutdown();
}
@ -93,12 +103,12 @@ public class App implements AppAccess {
@Override
public void shutdown()
{
bus().send(new DestroyEvent());
Log.i("Shutting down subsystems...");
bus().send(new DestroyEvent());
bus().destroy();
Log.i("Shutting down...");
Log.i("Terminating...");
System.exit(0);
}
@ -142,6 +152,14 @@ public class App implements AppAccess {
soundSystem = new SoundSystem(this);
soundSystem.setMasterVolume(1);
/*
* Load resources
*/
Log.f1("Registering resources...");
bus().subscribe(new DeferredLoader(this));
Res.load(this);
/*
* Input
*/
@ -154,18 +172,14 @@ public class App implements AppAccess {
*/
Log.f2("Initializing screen registry...");
screens = new ScreenRegistry(this);
/*
* Load resources
*/
Log.f1("Registering resources...");
Res.load(this);
initScreens();
/*
* Prepare main loop
*/
Log.f1("Preparing main loop...");
ArrayList<Runnable> loopTasks = new ArrayList<Runnable>();
loopTasks.add(new Runnable() {
@Override
@ -179,24 +193,44 @@ public class App implements AppAccess {
}
private void initScreens()
{
Log.f3("Registering game screens...");
screens.add(new ScreenTestBouncy(this));
screens.add(new ScreenTestCat(this));
screens.showScreen("test.cat");
}
private void initChannels()
{
Log.f3("Registering channels...");
// framework events
bus().addChannel(DestroyEvent.class, Destroyable.class);
bus().addChannel(UpdateEvent.class, Updateable.class);
// input events
bus().addChannel(ScreenChangeEvent.class, ScreenChangeEvent.Listener.class);
bus().addChannel(KeyboardEvent.class, KeyboardEvent.Listener.class);
bus().addChannel(MouseMotionEvent.class, MouseMotionEvent.Listener.class);
bus().addChannel(MouseButtonEvent.class, MouseButtonEvent.Listener.class);
// control events
bus().addChannel(ScreenRequestEvent.class, ScreenRequestEvent.Listener.class);
bus().addChannel(ResourceLoadRequest.class, ResourceLoadRequest.Listener.class);
bus().addChannel(ActionRequest.class, ActionRequest.Listener.class);
bus().addChannel(MainLoopTaskRequest.class, MainLoopTaskRequest.Listener.class);
}
private void setupGlobalKeystrokes()
{
Log.f3("Setting up hot keys...");
// Go fullscreen
input().bindKeyStroke(new KeyStroke(Keyboard.KEY_F11), new Runnable() {
@Override
@ -206,6 +240,7 @@ public class App implements AppAccess {
}
});
// Take screenshot
input().bindKeyStroke(new KeyStroke(Keyboard.KEY_F2), new Runnable() {
@Override
@ -215,6 +250,7 @@ public class App implements AppAccess {
}
});
// Exit
input().bindKeyStroke(new KeyStroke(Keyboard.KEY_LCONTROL, Keyboard.KEY_Q), new Runnable() {
@Override

@ -1,9 +1,9 @@
package mightypork.rogue;
import mightypork.rogue.audio.SoundSystem;
import mightypork.rogue.input.InputSystem;
import mightypork.rogue.render.DisplaySystem;
import mightypork.rogue.sound.SoundSystem;
import mightypork.utils.control.bus.EventBus;

@ -1,9 +1,9 @@
package mightypork.rogue;
import mightypork.rogue.audio.SoundSystem;
import mightypork.rogue.input.InputSystem;
import mightypork.rogue.render.DisplaySystem;
import mightypork.rogue.sound.SoundSystem;
import mightypork.utils.control.bus.EventBus;

@ -8,15 +8,15 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import mightypork.rogue.bus.Subsystem;
import mightypork.rogue.bus.events.ActionRequest;
import mightypork.rogue.bus.events.RequestType;
import mightypork.rogue.bus.events.ScreenRequestEvent;
import mightypork.rogue.bus.events.ActionRequest.RequestType;
import mightypork.rogue.bus.events.MainLoopTaskRequest;
import mightypork.rogue.tasks.TaskTakeScreenshot;
import mightypork.rogue.util.Utils;
import mightypork.utils.control.bus.events.UpdateEvent;
import mightypork.utils.control.timing.TimerDelta;
public class MainLoop extends Subsystem implements ActionRequest.Listener {
public class MainLoop extends Subsystem implements ActionRequest.Listener, MainLoopTaskRequest.Listener {
private Queue<Runnable> taskQueue = new ConcurrentLinkedQueue<Runnable>();
private List<Runnable> regularTasks;
@ -35,8 +35,6 @@ public class MainLoop extends Subsystem implements ActionRequest.Listener {
public void start()
{
bus().queue(new ScreenRequestEvent("test.texture"));
timer = new TimerDelta();
while (running) {
@ -70,18 +68,19 @@ public class MainLoop extends Subsystem implements ActionRequest.Listener {
{
switch (request) {
case FULLSCREEN:
taskQueue.add(taskFullscreen);
queueTask(taskFullscreen);
break;
case SCREENSHOT:
taskQueue.add(taskScreenshot);
queueTask(taskScreenshot);
break;
case SHUTDOWN:
taskQueue.add(taskShutdown);
queueTask(taskShutdown);
}
}
/** Take a screenshot */
private final Runnable taskScreenshot = new Runnable() {
@Override
@ -92,6 +91,7 @@ public class MainLoop extends Subsystem implements ActionRequest.Listener {
}
};
/** Shutdown the application */
private final Runnable taskShutdown = new Runnable() {
@Override
@ -101,6 +101,7 @@ public class MainLoop extends Subsystem implements ActionRequest.Listener {
}
};
/** Toggle fullscreen */
private final Runnable taskFullscreen = new Runnable() {
@Override
@ -109,4 +110,11 @@ public class MainLoop extends Subsystem implements ActionRequest.Listener {
disp().switchFullscreen();
}
};
@Override
public void queueTask(Runnable request)
{
taskQueue.add(request);
}
}

@ -1,13 +1,11 @@
package mightypork.rogue;
import mightypork.rogue.audio.EffectPlayer;
import mightypork.rogue.audio.LoopPlayer;
import mightypork.rogue.audio.SoundBank;
import mightypork.rogue.gui.screens.screenBouncy.ScreenTestAnim;
import mightypork.rogue.gui.screens.screenTextures.ScreenTextureTest;
import mightypork.rogue.render.textures.TextureBank;
import mightypork.rogue.render.textures.TxQuad;
import mightypork.rogue.sound.SoundBank;
import mightypork.rogue.sound.players.EffectPlayer;
import mightypork.rogue.sound.players.LoopPlayer;
import mightypork.rogue.texture.TextureBank;
import mightypork.rogue.texture.TxQuad;
import org.newdawn.slick.opengl.Texture;
@ -27,26 +25,25 @@ public class Res {
textures = new TextureBank(app);
sounds = new SoundBank(app);
loadSounds(app);
loadTextures(app);
loadFonts(app);
loadScreens(app);
loadSounds();
loadTextures();
loadFonts();
}
private static void loadFonts(App app)
private static void loadFonts()
{
//
}
private static void loadTextures(App app)
private static void loadTextures()
{
textures.loadTexture("test.kitten", "/res/img/kitten.png");
}
private static void loadSounds(App app)
private static void loadSounds()
{
sounds.addEffect("gui.shutter", "/res/audio/shutter.ogg", 1, 1);
@ -54,13 +51,6 @@ public class Res {
}
private static void loadScreens(App app)
{
app.screens.add("test.anim", new ScreenTestAnim(app));
app.screens.add("test.texture", new ScreenTextureTest(app));
}
public static TxQuad getTxQuad(String key)
{
return textures.getTxQuad(key);

@ -25,7 +25,7 @@ public class ChildClient extends AppAdapter implements DelegatingClient, Togglea
super(app);
}
private Set<Object> clients = new LinkedHashSet<Object>();
private final Set<Object> clients = new LinkedHashSet<Object>();
private boolean listening = true;
private boolean delegating = true;

@ -2,16 +2,17 @@ package mightypork.rogue.bus.events;
import mightypork.utils.control.bus.Event;
import mightypork.utils.control.bus.SingularEvent;
/**
* Request for action that should be performed in the main thread.
* Request for a global sction to be done in the main loop.
*
* @author MightyPork
*/
public class ActionRequest implements Event<ActionRequest.Listener> {
public class ActionRequest implements Event<ActionRequest.Listener>, SingularEvent {
private RequestType type;
private final RequestType type;
public ActionRequest(RequestType request) {
@ -27,7 +28,16 @@ public class ActionRequest implements Event<ActionRequest.Listener> {
public interface Listener {
/**
* Perform the requested action
*
* @param request
*/
public void requestAction(RequestType request);
}
public static enum RequestType
{
FULLSCREEN, SCREENSHOT, SHUTDOWN;
}
}

@ -13,9 +13,9 @@ import org.lwjgl.input.Keyboard;
*/
public class KeyboardEvent implements Event<KeyboardEvent.Listener> {
private int key;
private boolean down;
private char c;
private final int key;
private final boolean down;
private final char c;
public KeyboardEvent(int key, char c, boolean down) {

@ -0,0 +1,38 @@
package mightypork.rogue.bus.events;
import mightypork.utils.control.bus.Event;
import mightypork.utils.control.bus.SingularEvent;
/**
* Request to execute given {@link Runnable} in main loop.
*
* @author MightyPork
*/
public class MainLoopTaskRequest implements Event<MainLoopTaskRequest.Listener>, SingularEvent {
private final Runnable task;
public MainLoopTaskRequest(Runnable task) {
this.task = task;
}
@Override
public void handleBy(Listener handler)
{
handler.queueTask(task);
}
public interface Listener {
/**
* Perform the requested action
*
* @param request
*/
public void queueTask(Runnable request);
}
}

@ -16,10 +16,10 @@ public class MouseButtonEvent implements Event<MouseButtonEvent.Listener> {
public static final int BUTTON_MIDDLE = 1;
public static final int BUTTON_RIGHT = 2;
private int button;
private int wheeld;
private Coord pos;
private boolean down;
private final int button;
private final int wheeld;
private final Coord pos;
private final boolean down;
/**

@ -7,8 +7,8 @@ import mightypork.utils.math.coord.Coord;
public class MouseMotionEvent implements Event<MouseMotionEvent.Listener> {
private Coord move;
private Coord pos;
private final Coord move;
private final Coord pos;
public MouseMotionEvent(Coord pos, Coord move) {

@ -1,7 +0,0 @@
package mightypork.rogue.bus.events;
public enum RequestType
{
FULLSCREEN, SCREENSHOT, SHUTDOWN;
}

@ -0,0 +1,39 @@
package mightypork.rogue.bus.events;
import mightypork.rogue.Deferred;
import mightypork.utils.control.bus.Event;
import mightypork.utils.control.bus.SingularEvent;
/**
* Request to schedule loading a deferred resource.
*
* @author MightyPork
*/
public class ResourceLoadRequest implements Event<ResourceLoadRequest.Listener>, SingularEvent {
private final Deferred resource;
public ResourceLoadRequest(Deferred resource) {
this.resource = resource;
}
@Override
public void handleBy(Listener handler)
{
handler.loadResource(resource);
}
public interface Listener {
/**
* Load a resource
*
* @param resource
*/
public void loadResource(Deferred resource);
}
}

@ -7,9 +7,9 @@ import mightypork.utils.math.coord.Coord;
public class ScreenChangeEvent implements Event<ScreenChangeEvent.Listener> {
private boolean fullscreen;
private Coord screenSize;
private boolean fsChanged;
private final boolean fullscreen;
private final Coord screenSize;
private final boolean fsChanged;
public ScreenChangeEvent(boolean fsChanged, boolean fullscreen, Coord size) {

@ -2,11 +2,12 @@ package mightypork.rogue.bus.events;
import mightypork.utils.control.bus.Event;
import mightypork.utils.control.bus.SingularEvent;
public class ScreenRequestEvent implements Event<ScreenRequestEvent.Listener> {
public class ScreenRequestEvent implements Event<ScreenRequestEvent.Listener>, SingularEvent {
private String scrName;
private final String scrName;
public ScreenRequestEvent(String screenKey) {

@ -1,15 +1,15 @@
package mightypork.rogue.gui.screens;
package mightypork.rogue.gui;
import java.util.Collection;
import java.util.LinkedList;
import mightypork.rogue.AppAccess;
import mightypork.utils.control.interf.Updateable;
public abstract class LayeredScreen extends Screen {
private final LinkedList<ScreenLayer> layers = new LinkedList<ScreenLayer>();
private final Collection<ScreenLayer> layers = new LinkedList<ScreenLayer>();
public LayeredScreen(AppAccess app) {
@ -17,18 +17,6 @@ public abstract class LayeredScreen extends Screen {
}
@Override
protected abstract void deinitScreen();
@Override
protected abstract void onScreenEnter();
@Override
protected abstract void onScreenLeave();
@Override
protected final void renderScreen()
{
@ -38,14 +26,6 @@ public abstract class LayeredScreen extends Screen {
}
/**
* Update screen. Layers should implement {@link Updateable} to receive
* updates directly from bus.
*/
@Override
protected abstract void updateScreen(double delta);
/**
* Add a layer to the screen.
*

@ -1,4 +1,4 @@
package mightypork.rogue.gui.screens;
package mightypork.rogue.gui;
import static org.lwjgl.opengl.GL11.*;
@ -10,20 +10,17 @@ import mightypork.rogue.input.KeyBindingPool;
import mightypork.rogue.input.KeyStroke;
import mightypork.rogue.render.Render;
import mightypork.utils.control.interf.Destroyable;
import mightypork.utils.control.interf.Updateable;
import mightypork.utils.math.constraints.ConstraintContext;
import mightypork.utils.math.coord.Coord;
import mightypork.utils.math.coord.Rect;
/**
* Screen class.<br>
* Screen animates 3D world, while contained panels render 2D overlays, process
* inputs and run the game logic.
* Screen class.
*
* @author MightyPork
*/
public abstract class Screen extends ChildClient implements Destroyable, Updateable, KeyBinder, ConstraintContext, ScreenChangeEvent.Listener {
public abstract class Screen extends ChildClient implements Destroyable, KeyBinder, ConstraintContext, ScreenChangeEvent.Listener {
private final KeyBindingPool keybindings = new KeyBindingPool();
@ -127,14 +124,6 @@ public abstract class Screen extends ChildClient implements Destroyable, Updatea
protected abstract void renderScreen();
/**
* Update animations and timing.<br>
*
* @param delta time elapsed
*/
protected abstract void updateScreen(double delta);
/**
* Render screen
*/
@ -173,16 +162,6 @@ public abstract class Screen extends ChildClient implements Destroyable, Updatea
}
/**
* Update and render the screen
*/
@Override
public final void update(double delta)
{
updateScreen(delta);
}
@Override
public final Rect getRect()
{
@ -241,4 +220,6 @@ public abstract class Screen extends ChildClient implements Destroyable, Updatea
glMatrixMode(GL_MODELVIEW);
}
public abstract String getId();
}

@ -1,9 +1,11 @@
package mightypork.rogue.gui.screens;
package mightypork.rogue.gui;
import mightypork.rogue.bus.ChildClient;
import mightypork.rogue.gui.constraints.Renderable;
import mightypork.utils.control.interf.Updateable;
import mightypork.rogue.input.KeyBinder;
import mightypork.rogue.input.KeyBindingPool;
import mightypork.rogue.input.KeyStroke;
import mightypork.utils.math.constraints.ConstraintContext;
import mightypork.utils.math.coord.Rect;
@ -13,24 +15,33 @@ import mightypork.utils.math.coord.Rect;
*
* @author MightyPork
*/
public abstract class ScreenLayer extends ChildClient implements Renderable, Updateable, ConstraintContext {
public abstract class ScreenLayer extends ChildClient implements Renderable, ConstraintContext, KeyBinder {
private Screen screen;
private final Screen screen;
private final KeyBindingPool keybindings = new KeyBindingPool();
public ScreenLayer(Screen screen) {
super(screen); // screen as AppAccess
this.screen = screen;
addChildClient(keybindings);
}
@Override
public abstract void render();
public final void bindKeyStroke(KeyStroke stroke, Runnable task)
{
keybindings.bindKeyStroke(stroke, task);
}
@Override
public abstract void update(double delta);
public final void unbindKeyStroke(KeyStroke stroke)
{
keybindings.unbindKeyStroke(stroke);
}
protected Screen screen()

@ -1,4 +1,4 @@
package mightypork.rogue.gui.screens;
package mightypork.rogue.gui;
import java.util.HashMap;
@ -6,11 +6,12 @@ import java.util.HashMap;
import mightypork.rogue.AppAccess;
import mightypork.rogue.bus.Subsystem;
import mightypork.rogue.bus.events.ScreenRequestEvent;
import mightypork.utils.logging.Log;
public class ScreenRegistry extends Subsystem implements ScreenRequestEvent.Listener {
private HashMap<String, Screen> screens = new HashMap<String, Screen>();
private final HashMap<String, Screen> screens = new HashMap<String, Screen>();
private Screen active = null;
@ -19,9 +20,9 @@ public class ScreenRegistry extends Subsystem implements ScreenRequestEvent.List
}
public void add(String key, Screen screen)
public void add(Screen screen)
{
screens.put(key, screen);
screens.put(screen.getId(), screen);
addChildClient(screen);
}
@ -29,6 +30,8 @@ public class ScreenRegistry extends Subsystem implements ScreenRequestEvent.List
@Override
public void showScreen(String key)
{
Log.f3("Request to show screen \"" + key + "\"");
Screen toshow = screens.get(key);
if (toshow == null) throw new RuntimeException("Screen " + key + " not defined.");

@ -0,0 +1,45 @@
package mightypork.rogue.gui.constraints;
import static mightypork.utils.math.constraints.ConstraintFactory.*;
import mightypork.rogue.AppAccess;
import mightypork.utils.math.constraints.ConstraintContext;
public class ColumnHolder extends ElementHolder {
private final int cols;
private int col = 0;
public ColumnHolder(AppAccess app, ConstraintContext context, int rows) {
super(app, context);
this.cols = rows;
}
public ColumnHolder(AppAccess app, int rows) {
super(app);
this.cols = rows;
}
/**
* Add a row to the holder.
*
* @param elem
*/
public void addRow(RenderableWithContext elem)
{
if (elem == null) return;
add(elem, c_column(null, cols, col++));
}
@Override
public void remove(RenderableWithContext elem)
{
throw new UnsupportedOperationException("Can't remove from ColumnHolder.");
}
}

@ -19,7 +19,7 @@ import mightypork.utils.math.coord.Rect;
*/
public class ElementHolder extends ChildClient implements ConstraintContext, RenderableWithContext {
private LinkedList<RenderableWithContext> elements = new LinkedList<RenderableWithContext>();
private final LinkedList<RenderableWithContext> elements = new LinkedList<RenderableWithContext>();
private ConstraintContext context;
@ -57,19 +57,18 @@ public class ElementHolder extends ChildClient implements ConstraintContext, Ren
}
/**
* Add element to the holder.
*
* @param elem
*/
public void add(RenderableWithContext elem)
{
if (elem == null) return;
elem.setContext(this);
elements.add(elem);
addChildClient(elem);
}
// /**
// * Add element to the holder.
// *
// * @param elem
// */
// public void add(RenderableWithContext elem)
// {
// if (elem == null) return;
// elem.setContext(this);
// elements.add(elem);
// addChildClient(elem);
// }
/**
* Add element to the holder.

@ -0,0 +1,45 @@
package mightypork.rogue.gui.constraints;
import static mightypork.utils.math.constraints.ConstraintFactory.*;
import mightypork.rogue.AppAccess;
import mightypork.utils.math.constraints.ConstraintContext;
public class RowHolder extends ElementHolder {
private final int rows;
private int row = 0;
public RowHolder(AppAccess app, ConstraintContext context, int rows) {
super(app, context);
this.rows = rows;
}
public RowHolder(AppAccess app, int rows) {
super(app);
this.rows = rows;
}
/**
* Add a row to the holder.
*
* @param elem
*/
public void addRow(RenderableWithContext elem)
{
if (elem == null) return;
add(elem, c_row(null, rows, row++));
}
@Override
public void remove(RenderableWithContext elem)
{
throw new UnsupportedOperationException("Can't remove from RowHolder.");
}
}

@ -1,70 +0,0 @@
package mightypork.rogue.gui.screens.screenBouncy;
import mightypork.rogue.AppAccess;
import mightypork.rogue.gui.screens.LayeredScreen;
import mightypork.rogue.input.KeyStroke;
import org.lwjgl.input.Keyboard;
public class ScreenTestAnim extends LayeredScreen {
private LayerBouncyBoxes layer;
public ScreenTestAnim(AppAccess app) {
super(app);
layer = new LayerBouncyBoxes(this);
addLayer(layer);
bindKeyStroke(new KeyStroke(Keyboard.KEY_RIGHT), new Runnable() {
@Override
public void run()
{
layer.goRight();
}
});
bindKeyStroke(new KeyStroke(Keyboard.KEY_LEFT), new Runnable() {
@Override
public void run()
{
layer.goLeft();
}
});
}
@Override
protected void deinitScreen()
{
// no impl
}
@Override
protected void onScreenEnter()
{
// no impl
}
@Override
protected void onScreenLeave()
{
// no impl
}
@Override
protected void updateScreen(double delta)
{
// no impl
}
}

@ -1,4 +1,4 @@
package mightypork.rogue.gui.screens.screenBouncy;
package mightypork.rogue.gui.screens.test_bouncyboxes;
import static mightypork.utils.math.constraints.ConstraintFactory.*;

@ -1,4 +1,4 @@
package mightypork.rogue.gui.screens.screenBouncy;
package mightypork.rogue.gui.screens.test_bouncyboxes;
import static mightypork.utils.math.constraints.ConstraintFactory.*;
@ -6,29 +6,29 @@ import static mightypork.utils.math.constraints.ConstraintFactory.*;
import java.util.ArrayList;
import java.util.List;
import mightypork.rogue.gui.constraints.ElementHolder;
import mightypork.rogue.gui.screens.Screen;
import mightypork.rogue.gui.screens.ScreenLayer;
import mightypork.rogue.gui.Screen;
import mightypork.rogue.gui.ScreenLayer;
import mightypork.rogue.gui.constraints.RowHolder;
import mightypork.utils.math.constraints.RectConstraint;
public class LayerBouncyBoxes extends ScreenLayer {
List<BouncyBox> boxes = new ArrayList<BouncyBox>();
private ElementHolder layout;
private RowHolder layout;
public LayerBouncyBoxes(Screen screen) {
super(screen);
// shrink screen rect by 8% on all sides
RectConstraint holder_rect = c_shrink(this, c_percent(c_height(this), c_n(8)));
layout = new ElementHolder(screen, holder_rect);
addChildClient(layout);
addChildClient(layout = new RowHolder(screen, holder_rect, 16));
for (int i = 0; i < 32; i++) {
for (int i = 0; i < 16; i++) {
BouncyBox bbr = new BouncyBox();
layout.add(bbr, c_row(null, 32, i));
layout.addRow(bbr);
boxes.add(bbr);
}
@ -42,13 +42,6 @@ public class LayerBouncyBoxes extends ScreenLayer {
}
@Override
public void update(double delta)
{
// no impl
}
public void goLeft()
{
for (BouncyBox bbr : boxes) {

@ -0,0 +1,80 @@
package mightypork.rogue.gui.screens.test_bouncyboxes;
import mightypork.rogue.AppAccess;
import mightypork.rogue.bus.events.ScreenRequestEvent;
import mightypork.rogue.gui.LayeredScreen;
import mightypork.rogue.input.KeyStroke;
import org.lwjgl.input.Keyboard;
public class ScreenTestBouncy extends LayeredScreen {
private LayerBouncyBoxes layer;
public ScreenTestBouncy(AppAccess app) {
super(app);
layer = new LayerBouncyBoxes(this);
addLayer(layer);
bindKeyStroke(new KeyStroke(true, Keyboard.KEY_RIGHT), new Runnable() {
@Override
public void run()
{
layer.goRight();
}
});
bindKeyStroke(new KeyStroke(true, Keyboard.KEY_LEFT), new Runnable() {
@Override
public void run()
{
layer.goLeft();
}
});
bindKeyStroke(new KeyStroke(Keyboard.KEY_C), new Runnable() {
@Override
public void run()
{
bus().queue(new ScreenRequestEvent("test.cat"));
}
});
}
@Override
protected void deinitScreen()
{
// no impl
}
@Override
protected void onScreenEnter()
{
// no impl
}
@Override
protected void onScreenLeave()
{
// no impl
}
@Override
public String getId()
{
return "test.bouncy";
}
}

@ -1,27 +1,27 @@
package mightypork.rogue.gui.screens.screenTextures;
package mightypork.rogue.gui.screens.test_cat_sound;
import static mightypork.utils.math.constraints.ConstraintFactory.*;
import java.util.Random;
import mightypork.rogue.AppAccess;
import mightypork.rogue.Res;
import mightypork.rogue.bus.events.ActionRequest;
import mightypork.rogue.bus.events.MouseButtonEvent;
import mightypork.rogue.bus.events.RequestType;
import mightypork.rogue.gui.screens.Screen;
import mightypork.rogue.gui.Screen;
import mightypork.rogue.gui.ScreenLayer;
import mightypork.rogue.input.KeyStroke;
import mightypork.rogue.render.Render;
import mightypork.utils.control.interf.Updateable;
import mightypork.utils.math.animation.AnimDouble;
import mightypork.utils.math.animation.Easing;
import mightypork.utils.math.constraints.RectConstraint;
import mightypork.utils.math.coord.Coord;
import org.lwjgl.input.Keyboard;
import org.newdawn.slick.opengl.Texture;
public class ScreenTextureTest extends Screen implements MouseButtonEvent.Listener {
public class LayerFlyingCat extends ScreenLayer implements Updateable, MouseButtonEvent.Listener {
private RectConstraint kittenbox;
@ -31,53 +31,28 @@ public class ScreenTextureTest extends Screen implements MouseButtonEvent.Listen
private Random rand = new Random();
private Texture cat_tx = Res.getTexture("test.kitten");
public ScreenTextureTest(AppAccess app) {
super(app);
public LayerFlyingCat(Screen screen) {
super(screen);
kittenbox = c_move(c_box_sized(this, c_n(s), c_n(s)), c_n(x), c_n(y));
bindKeyStroke(new KeyStroke(Keyboard.KEY_ESCAPE), new Runnable() {
bindKeyStroke(new KeyStroke(Keyboard.KEY_RETURN), new Runnable() {
@Override
public void run()
{
snd().fadeOutAllLoops();
bus().schedule(new ActionRequest(RequestType.SHUTDOWN), 3);
x.fadeTo(disp().getWidth() / 2 - s.getTo() / 2, 2);
y.fadeTo(disp().getHeight() / 2 - s.getTo() / 2, 2);
}
});
}
@Override
protected void deinitScreen()
{
}
@Override
protected void onScreenEnter()
{
System.out.println("YOLO");
Res.getLoop("test.wilderness").fadeIn();
}
@Override
protected void onScreenLeave()
{
}
@Override
protected void renderScreen()
{
Render.quadTextured(kittenbox.getRect(), Res.getTexture("test.kitten"));
}
@Override
protected void updateScreen(double delta)
public void update(double delta)
{
s.update(delta);
x.update(delta);
@ -101,4 +76,11 @@ public class ScreenTextureTest extends Screen implements MouseButtonEvent.Listen
y.fadeTo(pos.y - newSize / 2D, t);
}
@Override
public void render()
{
Render.quadTextured(kittenbox.getRect(), cat_tx);
}
}

@ -0,0 +1,73 @@
package mightypork.rogue.gui.screens.test_cat_sound;
import mightypork.rogue.AppAccess;
import mightypork.rogue.Res;
import mightypork.rogue.bus.events.ActionRequest;
import mightypork.rogue.bus.events.ActionRequest.RequestType;
import mightypork.rogue.bus.events.ScreenRequestEvent;
import mightypork.rogue.gui.LayeredScreen;
import mightypork.rogue.input.KeyStroke;
import org.lwjgl.input.Keyboard;
public class ScreenTestCat extends LayeredScreen {
LayerFlyingCat layer;
public ScreenTestCat(AppAccess app) {
super(app);
addLayer(layer = new LayerFlyingCat(this));
bindKeyStroke(new KeyStroke(Keyboard.KEY_ESCAPE), new Runnable() {
@Override
public void run()
{
snd().fadeOutAllLoops();
bus().schedule(new ActionRequest(RequestType.SHUTDOWN), 3);
}
});
bindKeyStroke(new KeyStroke(Keyboard.KEY_B), new Runnable() {
@Override
public void run()
{
bus().queue(new ScreenRequestEvent("test.bouncy"));
}
});
}
@Override
protected void deinitScreen()
{
}
@Override
protected void onScreenEnter()
{
snd().fadeOutAllLoops();
Res.getLoop("test.wilderness").fadeIn();
}
@Override
protected void onScreenLeave()
{
Res.getLoop("test.wilderness").fadeOut();
}
@Override
public String getId()
{
return "test.cat";
}
}

@ -4,10 +4,10 @@ package mightypork.rogue.input;
import mightypork.rogue.AppAccess;
import mightypork.rogue.bus.Subsystem;
import mightypork.rogue.bus.events.ActionRequest;
import mightypork.rogue.bus.events.ActionRequest.RequestType;
import mightypork.rogue.bus.events.KeyboardEvent;
import mightypork.rogue.bus.events.MouseButtonEvent;
import mightypork.rogue.bus.events.MouseMotionEvent;
import mightypork.rogue.bus.events.RequestType;
import mightypork.utils.control.interf.Updateable;
import mightypork.utils.math.coord.Coord;
@ -20,7 +20,7 @@ import org.lwjgl.opengl.Display;
public class InputSystem extends Subsystem implements Updateable, KeyBinder {
// listeners
private KeyBindingPool keybindings;
private final KeyBindingPool keybindings;
private boolean yAxisDown = true;
@ -127,6 +127,7 @@ public class InputSystem extends Subsystem implements Updateable, KeyBinder {
int key = Keyboard.getEventKey();
boolean down = Keyboard.getEventKeyState();
char c = Keyboard.getEventCharacter();
bus().queue(new KeyboardEvent(key, c, down));
}
@ -137,4 +138,16 @@ public class InputSystem extends Subsystem implements Updateable, KeyBinder {
c.setY_ip(disp().getSize().y - c.y);
}
}
/**
* Set whether Y axis should go top-down instead of LWJGL default bottom-up.<br>
* Default = true.
*
* @param yAxisDown
*/
public void setYDown(boolean yAxisDown)
{
this.yAxisDown = yAxisDown;
}
}

@ -6,7 +6,7 @@ import mightypork.rogue.bus.events.KeyboardEvent;
public class KeyBinding implements KeyboardEvent.Listener {
private KeyStroke keystroke;
private final KeyStroke keystroke;
private Runnable handler;
private boolean wasActive = false;

@ -16,7 +16,7 @@ import mightypork.utils.logging.Log;
*/
public class KeyBindingPool implements KeyBinder, KeyboardEvent.Listener {
private Set<KeyBinding> bindings = new HashSet<KeyBinding>();
private final Set<KeyBinding> bindings = new HashSet<KeyBinding>();
/**

@ -10,18 +10,18 @@ import org.lwjgl.input.Keyboard;
public class KeyStroke {
private Set<Integer> keys = new LinkedHashSet<Integer>();
private boolean down = true;
private final Set<Integer> keys = new LinkedHashSet<Integer>();
private final boolean fallingEdge;
/**
* KeyStroke
*
* @param down true for falling edge, up for rising edge
* @param fallingEdge true for falling edge, up for rising edge
* @param keys keys that must be pressed
*/
public KeyStroke(boolean down, int... keys) {
this.down = down;
public KeyStroke(boolean fallingEdge, int... keys) {
this.fallingEdge = fallingEdge;
for (int k : keys) {
this.keys.add(k);
}
@ -29,11 +29,12 @@ public class KeyStroke {
/**
* Falling edge keystroke
* Rising edge keystroke
*
* @param keys
*/
public KeyStroke(int... keys) {
fallingEdge = false;
for (int k : keys) {
this.keys.add(k);
}
@ -47,13 +48,7 @@ public class KeyStroke {
st &= Keyboard.isKeyDown(k);
}
return down ? st : !st;
}
public void setKeys(Set<Integer> keys)
{
this.keys = keys;
return fallingEdge ? st : !st;
}
@ -81,7 +76,7 @@ public class KeyStroke {
return false;
}
if (down != other.down) return false;
if (fallingEdge != other.fallingEdge) return false;
return true;
}
@ -99,7 +94,7 @@ public class KeyStroke {
s += Keyboard.getKeyName(i.next());
}
s += down ? ",DOWN" : "UP";
s += fallingEdge ? ",DOWN" : ",UP";
s += ")";

@ -140,7 +140,19 @@ public class DisplaySystem extends Subsystem implements ConstraintContext {
*/
public Coord getSize()
{
return new Coord(Display.getWidth(), Display.getHeight());
return new Coord(getWidth(), getHeight());
}
public int getWidth()
{
return Display.getWidth();
}
public int getHeight()
{
return Display.getHeight();
}

@ -5,7 +5,7 @@ import static org.lwjgl.opengl.GL11.*;
import java.io.IOException;
import mightypork.rogue.render.textures.TxQuad;
import mightypork.rogue.texture.TxQuad;
import mightypork.utils.files.FileUtils;
import mightypork.utils.logging.Log;
import mightypork.utils.math.color.RGB;
@ -110,14 +110,16 @@ public class Render {
* @param resourcePath
* @return the loaded texture
*/
public static Texture loadTexture(String resourcePath)
public synchronized static Texture loadTexture(String resourcePath)
{
if (!inited) {
inited = true;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
inited = true;
}
try {
@ -187,7 +189,7 @@ public class Render {
{
double left = quad.xMin();
double bottom = quad.yMin();
double right = quad.yMax();
double right = quad.xMax();
double top = quad.yMax();
// draw with color

@ -1,4 +1,4 @@
package mightypork.rogue.audio;
package mightypork.rogue.sound;
import mightypork.rogue.Deferred;
@ -90,14 +90,14 @@ public class DeferredAudio implements Destroyable, Deferred {
* @return resource is loaded
*/
@Override
public boolean isLoaded()
public synchronized boolean isLoaded()
{
return audio != null;
}
@Override
public void load()
public synchronized void load()
{
ensureLoaded();
}
@ -108,7 +108,7 @@ public class DeferredAudio implements Destroyable, Deferred {
*
* @return is loaded
*/
protected boolean ensureLoaded()
protected synchronized boolean ensureLoaded()
{
if (isLoaded()) return true; // already loaded
if (loadFailed || resourcePath == null) return false;
@ -295,4 +295,11 @@ public class DeferredAudio implements Destroyable, Deferred {
return true;
}
@Override
public String toString()
{
return "Audio(\"" + resourcePath + "\")";
}
}

@ -1,4 +1,4 @@
package mightypork.rogue.audio;
package mightypork.rogue.sound;
import mightypork.utils.math.Calc;
@ -12,7 +12,7 @@ import mightypork.utils.objects.Mutable;
*/
public class JointVolume extends Mutable<Double> {
private Mutable<Double>[] volumes;
private final Mutable<Double>[] volumes;
/**

@ -1,4 +1,4 @@
package mightypork.rogue.audio;
package mightypork.rogue.sound;
public class NullAudio extends DeferredAudio {

@ -1,4 +1,4 @@
package mightypork.rogue.audio;
package mightypork.rogue.sound;
import java.util.HashMap;
@ -6,6 +6,8 @@ import java.util.Map;
import mightypork.rogue.AppAccess;
import mightypork.rogue.AppAdapter;
import mightypork.rogue.sound.players.EffectPlayer;
import mightypork.rogue.sound.players.LoopPlayer;
import mightypork.utils.logging.Log;
@ -15,8 +17,8 @@ public class SoundBank extends AppAdapter {
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 Map<String, EffectPlayer> effects = new HashMap<String, EffectPlayer>();
private Map<String, LoopPlayer> loops = new HashMap<String, LoopPlayer>();
private final Map<String, EffectPlayer> effects = new HashMap<String, EffectPlayer>();
private final Map<String, LoopPlayer> loops = new HashMap<String, LoopPlayer>();
public SoundBank(AppAccess app) {

@ -1,4 +1,4 @@
package mightypork.rogue.audio;
package mightypork.rogue.sound;
import java.nio.FloatBuffer;
@ -7,6 +7,9 @@ import java.util.Set;
import mightypork.rogue.AppAccess;
import mightypork.rogue.bus.Subsystem;
import mightypork.rogue.bus.events.ResourceLoadRequest;
import mightypork.rogue.sound.players.EffectPlayer;
import mightypork.rogue.sound.players.LoopPlayer;
import mightypork.utils.control.interf.Updateable;
import mightypork.utils.math.Calc.Buffers;
import mightypork.utils.math.coord.Coord;
@ -69,12 +72,12 @@ public class SoundSystem extends Subsystem implements Updateable {
// -- instance --
public Mutable<Double> masterVolume = new Mutable<Double>(1D);
public Mutable<Double> effectsVolume = new JointVolume(masterVolume);
public Mutable<Double> loopsVolume = new JointVolume(masterVolume);
public final Mutable<Double> masterVolume = new Mutable<Double>(1D);
public final Mutable<Double> effectsVolume = new JointVolume(masterVolume);
public final Mutable<Double> loopsVolume = new JointVolume(masterVolume);
private Set<LoopPlayer> loopPlayers = new HashSet<LoopPlayer>();
private Set<DeferredAudio> resources = new HashSet<DeferredAudio>();
private final Set<LoopPlayer> loopPlayers = new HashSet<LoopPlayer>();
private final Set<DeferredAudio> resources = new HashSet<DeferredAudio>();
public SoundSystem(AppAccess app) {
@ -146,6 +149,8 @@ public class SoundSystem extends Subsystem implements Updateable {
private DeferredAudio getResource(String res)
{
DeferredAudio a = new DeferredAudio(res);
bus().queue(new ResourceLoadRequest(a));
if (resources.contains(a)) throw new IllegalArgumentException("Sound resource " + res + " is already registered.");
resources.add(a);
return a;

@ -1,22 +1,24 @@
package mightypork.rogue.audio;
package mightypork.rogue.sound.players;
import mightypork.rogue.sound.DeferredAudio;
import mightypork.utils.control.interf.Destroyable;
import mightypork.utils.objects.Mutable;
public abstract class BaseAudioPlayer {
public abstract class BaseAudioPlayer implements Destroyable {
/** the track */
private DeferredAudio audio;
private final DeferredAudio audio;
/** base gain for sfx */
private double baseGain = 1;
private final double baseGain;
/** base pitch for sfx */
private double basePitch = 1;
private final double basePitch;
/** dedicated volume control */
private Mutable<Double> gainMultiplier = null;
private final Mutable<Double> gainMultiplier;
public BaseAudioPlayer(DeferredAudio track, double baseGain, Mutable<Double> gainMultiplier) {
@ -36,10 +38,10 @@ public abstract class BaseAudioPlayer {
}
@Override
public void destroy()
{
audio.destroy();
audio = null;
}

@ -1,6 +1,7 @@
package mightypork.rogue.audio;
package mightypork.rogue.sound.players;
import mightypork.rogue.sound.DeferredAudio;
import mightypork.utils.math.coord.Coord;
import mightypork.utils.objects.Mutable;

@ -1,6 +1,7 @@
package mightypork.rogue.audio;
package mightypork.rogue.sound.players;
import mightypork.rogue.sound.DeferredAudio;
import mightypork.utils.control.interf.Updateable;
import mightypork.utils.control.timing.Pauseable;
import mightypork.utils.math.animation.AnimDouble;
@ -14,7 +15,7 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable
private int sourceID = -1;
/** animator for fade in and fade out */
private AnimDouble fadeAnim = new AnimDouble(0);
private final AnimDouble fadeAnim = new AnimDouble(0);
private double lastUpdateGain = 0;

@ -0,0 +1,102 @@
package mightypork.rogue.texture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import mightypork.rogue.AppAccess;
import mightypork.rogue.Deferred;
import mightypork.rogue.bus.events.MainLoopTaskRequest;
import mightypork.rogue.bus.events.ResourceLoadRequest;
import mightypork.utils.control.interf.Destroyable;
import mightypork.utils.logging.Log;
/**
* Asynchronous resource loading thread.
*
* @author MightyPork
*/
public class DeferredLoader extends Thread implements ResourceLoadRequest.Listener, Destroyable {
public static void launch(AppAccess app)
{
(new DeferredLoader(app)).start();
}
private ExecutorService exs = Executors.newCachedThreadPool();
private LinkedBlockingQueue<Deferred> toLoad = new LinkedBlockingQueue<Deferred>();
private boolean stopped;
private AppAccess app;
public DeferredLoader(AppAccess app) {
super("Deferred loader");
this.app = app;
}
@Override
public void loadResource(Deferred resource)
{
toLoad.add(resource);
}
@Override
public void run()
{
while (!stopped) {
try {
final Deferred def = toLoad.take();
if (def == null) continue;
if (!def.isLoaded()) {
// texture needs to be loaded in main thread, unfortunately.
// -> delegate to MainLoop
if (def instanceof DeferredTexture) {
app.bus().queue(new MainLoopTaskRequest(new Runnable() {
@Override
public void run()
{
Log.f3("<DEFERRED> Loading \"" + Log.str(def) + "\"");
def.load();
}
}));
continue;
}
Log.f3("<DEFERRED> Loading \"" + Log.str(def) + "\"");
exs.submit(new Runnable() {
@Override
public void run()
{
def.load();
}
});
}
} catch (InterruptedException ignored) {
//
}
}
}
@Override
public void destroy()
{
stopped = true;
exs.shutdownNow();
}
}

@ -1,4 +1,4 @@
package mightypork.rogue.render.textures;
package mightypork.rogue.texture;
import mightypork.rogue.Deferred;
@ -8,13 +8,13 @@ import mightypork.utils.math.coord.Rect;
import org.newdawn.slick.opengl.Texture;
public class MultiTexture implements Texture, Deferred {
public class DeferredTexture implements Texture, Deferred {
private Texture backingTexture;
private String resourcePath;
private final String resourcePath;
public MultiTexture(String resourcePath) {
public DeferredTexture(String resourcePath) {
this.resourcePath = resourcePath;
}
@ -26,7 +26,7 @@ public class MultiTexture implements Texture, Deferred {
@Override
public void load()
public synchronized void load()
{
if (!isLoaded()) {
backingTexture = Render.loadTexture(resourcePath);
@ -144,4 +144,11 @@ public class MultiTexture implements Texture, Deferred {
backingTexture.setTextureFilter(textureFilter);
}
@Override
public String toString()
{
return "Texture(\"" + resourcePath + "\")";
}
}

@ -1,10 +1,11 @@
package mightypork.rogue.render.textures;
package mightypork.rogue.texture;
import java.util.HashMap;
import mightypork.rogue.AppAccess;
import mightypork.rogue.AppAdapter;
import mightypork.rogue.bus.events.ResourceLoadRequest;
import mightypork.utils.math.coord.Rect;
import org.newdawn.slick.opengl.Texture;
@ -21,11 +22,11 @@ public class TextureBank extends AppAdapter {
super(app);
}
private HashMap<String, MultiTexture> textures = new HashMap<String, MultiTexture>();
private final HashMap<String, DeferredTexture> textures = new HashMap<String, DeferredTexture>();
private HashMap<String, TxQuad> quads = new HashMap<String, TxQuad>();
private final HashMap<String, TxQuad> quads = new HashMap<String, TxQuad>();
private MultiTexture lastTx;
private DeferredTexture lastTx;
/**
@ -36,7 +37,9 @@ public class TextureBank extends AppAdapter {
*/
public void loadTexture(String key, String resourcePath)
{
MultiTexture tx = new MultiTexture(resourcePath);
DeferredTexture tx = new DeferredTexture(resourcePath);
bus().queue(new ResourceLoadRequest(tx));
textures.put(key, tx);
lastTx = tx;
}
@ -51,7 +54,7 @@ public class TextureBank extends AppAdapter {
*/
public void makeQuad(String quadKey, String textureKey, Rect quad)
{
MultiTexture tx = textures.get(textureKey);
DeferredTexture tx = textures.get(textureKey);
if (tx == null) throw new RuntimeException("Texture with key " + textureKey + " not defined!");
TxQuad txquad = tx.getQuad(quad);
@ -68,7 +71,7 @@ public class TextureBank extends AppAdapter {
*/
public void makeQuad(String quadKey, Rect quad)
{
MultiTexture tx = lastTx;
DeferredTexture tx = lastTx;
if (tx == null) throw new RuntimeException("There's no texture loaded yet, can't define quads!");
TxQuad txquad = tx.getQuad(quad);

@ -1,4 +1,4 @@
package mightypork.rogue.render.textures;
package mightypork.rogue.texture;
import mightypork.utils.math.coord.Rect;
@ -14,9 +14,9 @@ import org.newdawn.slick.opengl.Texture;
public class TxQuad {
/** The texture */
public Texture tx;
public final Texture tx;
/** Coords in texture (0-1) */
public Rect uvs;
public final Rect uvs;
/**

@ -16,17 +16,30 @@ import mightypork.utils.logging.Log;
*/
final public class EventBus implements Destroyable {
/** Message channels */
private BufferedHashSet<EventChannel<?, ?>> channels = new BufferedHashSet<EventChannel<?, ?>>();
/** Registered clients */
private BufferedHashSet<Object> clients = new BufferedHashSet<Object>();
/** Messages queued for delivery */
private DelayQueue<DelayedMessage> sendQueue = new DelayQueue<DelayedMessage>();
private BusThread busThread;
/** Queue polling thread */
private QueuePollingThread busThread;
/** Log all */
private boolean logging = false;
/** Whether the bus was destroyed */
private boolean dead = false;
/**
* Make a new bus and start it's queue thread.
*/
public EventBus() {
busThread = new BusThread();
busThread = new QueuePollingThread();
busThread.start();
}
@ -153,12 +166,18 @@ final public class EventBus implements Destroyable {
if (logging) Log.f3("<bus> - [ Sending: " + Log.str(message) + " ]");
boolean sent = false;
boolean channelAccepted = false;
for (EventChannel<?, ?> b : channels) {
if (b.canBroadcast(message)) channelAccepted = true;
sent |= b.broadcast(message, clients);
}
if (!sent) Log.w("<bus> Not accepted by any channel: " + Log.str(message));
// more severe
if (!channelAccepted) Log.w("<bus> Not accepted by any channel: " + Log.str(message));
// less severe
if (logging && !sent) Log.w("<bus> Not delivered to any client: " + Log.str(message));
channels.setBuffering(false);
clients.setBuffering(false);
@ -248,16 +267,23 @@ final public class EventBus implements Destroyable {
}
private class BusThread extends Thread {
private class QueuePollingThread extends Thread {
public boolean stopped = false;
public boolean stopped;
public QueuePollingThread() {
super("Queue Polling Thread");
}
@Override
public void run()
{
DelayedMessage dm;
while (!stopped) {
DelayedMessage dm = null;
dm = null;
try {
dm = sendQueue.take();

@ -55,7 +55,7 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
*
* @param message a message to be sent
* @param clients collection of clients
* @return true if message was accepted by this channel
* @return true if message was sent
*/
public boolean broadcast(Event<?> message, Collection<Object> clients)
{
@ -63,9 +63,7 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
EVENT evt = messageClass.cast(message);
doBroadcast(evt, clients, new HashSet<Object>());
return true;
return doBroadcast(evt, clients, new HashSet<Object>());
}
@ -75,14 +73,20 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
* @param message sent message
* @param clients subscribing clients
* @param processed clients already processed
* @return success
*/
private void doBroadcast(final EVENT message, final Collection<Object> clients, final Collection<Object> processed)
private boolean doBroadcast(final EVENT message, final Collection<Object> clients, final Collection<Object> processed)
{
boolean sent = false;
for (Object client : clients) {
// exclude obvious non-clients
if (!isClientValid(client)) {
continue;
}
// avoid executing more times
if (processed.contains(client)) {
Log.w("<bus> Client already served: " + Log.str(client));
continue;
@ -97,17 +101,28 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
}
}
sendTo(client, message);
sent |= sendTo(client, message);
// singular event ain't no whore, handled once only.
if (sent && message instanceof SingularEvent) return true;
// pass on to delegated clients
if (client instanceof DelegatingClient) {
if (((DelegatingClient) client).doesDelegate()) {
Collection<Object> children = ((DelegatingClient) client).getChildClients();
if (children != null && children.size() > 0) doBroadcast(message, children, processed);
if (children != null && children.size() > 0) {
sent |= doBroadcast(message, children, processed);
}
} else {
if (logging) Log.f3("<bus> Client not delegating: " + Log.str(client));
}
}
}
return sent;
}
@ -116,14 +131,17 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
*
* @param client target client
* @param message message to send
* @return success
*/
@SuppressWarnings("unchecked")
private void sendTo(Object client, EVENT message)
private boolean sendTo(Object client, EVENT message)
{
if (isClientOfType(client)) {
if (logging) Log.f3("<bus> Delivered " + Log.str(message) + " to " + Log.str(client));
((Event<CLIENT>) message).handleBy((CLIENT) client);
return true;
}
return false;
}

@ -0,0 +1,11 @@
package mightypork.utils.control.bus;
/**
* Event handled by only single client.
*
* @author MightyPork
*/
public interface SingularEvent {
}

@ -5,6 +5,11 @@ import mightypork.utils.control.bus.Event;
import mightypork.utils.control.interf.Destroyable;
/**
* Invoke destroy() method of all subscribers. Used to deinit a system.
*
* @author MightyPork
*/
public class DestroyEvent implements Event<Destroyable> {
@Override

@ -95,7 +95,6 @@ public class TimerFps {
*/
public void startNewFrame()
{
// System.out.println("! start new frame !");
long time = getTime();
lastFrame = time;
nextFrame = time + FRAME;

@ -18,7 +18,7 @@ public class Log {
*/
public static void f1(String msg)
{
if (esl && main != null) main.f1(msg);
if (esl && ready()) main.f1(msg);
}
@ -29,7 +29,7 @@ public class Log {
*/
public static void f2(String msg)
{
if (esl && main != null) main.f2(msg);
if (esl && ready()) main.f2(msg);
}
@ -40,7 +40,7 @@ public class Log {
*/
public static void f3(String msg)
{
if (esl && main != null) main.f3(msg);
if (esl && ready()) main.f3(msg);
}
@ -51,7 +51,7 @@ public class Log {
*/
public static void i(String msg)
{
if (esl && main != null) main.i(msg);
if (esl && ready()) main.i(msg);
}
@ -62,7 +62,7 @@ public class Log {
*/
public static void w(String msg)
{
if (esl && main != null) main.w(msg);
if (esl && ready()) main.w(msg);
}
@ -73,7 +73,7 @@ public class Log {
*/
public static void e(String msg)
{
if (esl && main != null) main.e(msg);
if (esl && ready()) main.e(msg);
}
@ -85,7 +85,7 @@ public class Log {
*/
public static void e(String msg, Throwable thrown)
{
if (esl && main != null) main.e(msg, thrown);
if (esl && ready()) main.e(msg, thrown);
}
@ -96,13 +96,13 @@ public class Log {
*/
public static void e(Throwable thrown)
{
if (esl && main != null) main.e(thrown);
if (esl && ready()) main.e(thrown);
}
public static void enable(boolean flag)
{
if (esl && main != null) main.enable(flag);
if (esl && ready()) main.enable(flag);
}
@ -163,7 +163,7 @@ public class Log {
public int addMonitor(LogMonitor mon)
{
if (main == null) throw new IllegalStateException("Main logger not initialized.");
if (!ready()) throw new IllegalStateException("Main logger not initialized.");
return main.addMonitor(mon);
}
@ -171,7 +171,7 @@ public class Log {
public void removeMonitor(int id)
{
if (main == null) throw new IllegalStateException("Main logger not initialized.");
if (!ready()) throw new IllegalStateException("Main logger not initialized.");
main.removeMonitor(id);
}
@ -207,4 +207,10 @@ public class Log {
return (enclosing == null ? "" : enclosing.getSimpleName() + ".") + cls.getSimpleName();
}
public static boolean ready()
{
return main != null;
}
}

@ -245,7 +245,7 @@ public class ConstraintFactory {
double height = getContext().getRect().getSize().y;
double perRow = height / rows;
return Rect.fromSize(getOrigin().add(0, perRow * (rows - index - 1)), getSize().setY(perRow));
return Rect.fromSize(getOrigin().add(0, perRow * index), getSize().setY(perRow));
}
};
}

@ -239,7 +239,7 @@ public class Rect {
*/
public Coord getCenterBottom()
{
return new Coord((max.x + min.x) / 2, min.y);
return new Coord((max.x + min.x) / 2D, min.y);
}
@ -250,7 +250,7 @@ public class Rect {
*/
public Coord getCenterLeft()
{
return new Coord(min.x, (max.y + min.y) / 2);
return new Coord(min.x, (max.y + min.y) / 2D);
}
@ -261,7 +261,7 @@ public class Rect {
*/
public Coord getCenterRight()
{
return new Coord(max.x, (max.y + min.y) / 2);
return new Coord(max.x, (max.y + min.y) / 2D);
}
@ -272,7 +272,7 @@ public class Rect {
*/
public Coord getCenterTop()
{
return new Coord((max.x + min.x) / 2, max.y);
return new Coord((max.x + min.x) / 2D, max.y);
}

Loading…
Cancel
Save