world eventization & pause evt

v5stable
Ondřej Hruška 11 years ago
parent 1121c31509
commit 66adc1ffa9
  1. BIN
      res/img/tiles16.png
  2. BIN
      res/img/tiles16.xcf
  3. 18
      src/mightypork/gamecore/eventbus/EventBus.java
  4. 16
      src/mightypork/rogue/screens/game/ScreenGame.java
  5. 4
      src/mightypork/rogue/screens/game/WorldLayer.java
  6. 26
      src/mightypork/rogue/world/PlayerControl.java
  7. 60
      src/mightypork/rogue/world/World.java
  8. 6
      src/mightypork/rogue/world/WorldCreator.java
  9. 2
      src/mightypork/rogue/world/entity/Entity.java
  10. 11
      src/mightypork/rogue/world/entity/entities/PlayerEntity.java
  11. 2
      src/mightypork/rogue/world/entity/modules/EntityModulePosition.java
  12. 28
      src/mightypork/rogue/world/events/PlayerStepEndEvent.java
  13. 10
      src/mightypork/rogue/world/events/PlayerStepEndListener.java
  14. 27
      src/mightypork/rogue/world/events/WorldPauseRequest.java
  15. 2
      src/mightypork/rogue/world/gen/LevelGenerator.java
  16. 59
      src/mightypork/rogue/world/gui/MapView.java
  17. 32
      src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java
  18. 62
      src/mightypork/rogue/world/gui/interaction/MIPMouse.java
  19. 21
      src/mightypork/rogue/world/gui/interaction/MapInteractionPlugin.java
  20. 35
      src/mightypork/rogue/world/level/Level.java
  21. 28
      src/mightypork/rogue/world/tile/Tile.java
  22. 2
      src/mightypork/rogue/world/tile/tiles/NullTile.java
  23. 4
      src/mightypork/rogue/world/tile/tiles/TileWithItems.java

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

@ -91,7 +91,11 @@ final public class EventBus implements Destroyable, BusAccess {
} }
if (evt != null) { if (evt != null) {
dispatch(evt.getEvent()); try {
dispatch(evt.getEvent());
} catch (final Throwable t) {
Log.w(logMark + "Error while dispatching event: " + t);
}
} }
} }
} }
@ -137,6 +141,8 @@ final public class EventBus implements Destroyable, BusAccess {
/** Messages queued for delivery */ /** Messages queued for delivery */
private final DelayQueue<DelayQueueEntry> sendQueue = new DelayQueue<>(); private final DelayQueue<DelayQueueEntry> sendQueue = new DelayQueue<>();
private volatile boolean sendingDirect = false;
/** /**
* Make a new bus and start it's queue thread. * Make a new bus and start it's queue thread.
@ -335,9 +341,19 @@ final public class EventBus implements Destroyable, BusAccess {
{ {
assertLive(); assertLive();
if (sendingDirect) {
Log.w("Cannot send a direct event in response to another.");
sendQueued(event);
return;
}
sendingDirect = true;
clients.setBuffering(true); clients.setBuffering(true);
doDispatch(clients, event); doDispatch(clients, event);
clients.setBuffering(false); clients.setBuffering(false);
sendingDirect = false;
} }

@ -8,6 +8,7 @@ import mightypork.gamecore.gui.screens.LayeredScreen;
import mightypork.gamecore.input.KeyStroke; import mightypork.gamecore.input.KeyStroke;
import mightypork.gamecore.input.Keys; import mightypork.gamecore.input.Keys;
import mightypork.rogue.world.WorldProvider; import mightypork.rogue.world.WorldProvider;
import mightypork.rogue.world.events.WorldPauseRequest;
public class ScreenGame extends LayeredScreen { public class ScreenGame extends LayeredScreen {
@ -23,7 +24,7 @@ public class ScreenGame extends LayeredScreen {
addLayer(new HudLayer(this)); addLayer(new HudLayer(this));
addLayer(new WorldLayer(this)); addLayer(new WorldLayer(this));
bindKey(new KeyStroke(Keys.N), new Runnable() { bindKey(new KeyStroke(Keys.L_CONTROL, Keys.N), new Runnable() {
@Override @Override
public void run() public void run()
@ -31,6 +32,19 @@ public class ScreenGame extends LayeredScreen {
WorldProvider.get().createWorld(rand.nextLong()); WorldProvider.get().createWorld(rand.nextLong());
} }
}); });
final Runnable pauseIt = new Runnable() {
@Override
public void run()
{
getEventBus().send(new WorldPauseRequest());
}
};
//pause key
bindKey(new KeyStroke(Keys.L_CONTROL, Keys.P), pauseIt);
bindKey(new KeyStroke(Keys.PAUSE), pauseIt);
} }

@ -23,8 +23,8 @@ public class WorldLayer extends ScreenLayer {
worldView = new MapView(); worldView = new MapView();
// map input plugins // map input plugins
worldView.addPlugin(new MIPKeyboard()); worldView.addPlugin(new MIPKeyboard(worldView));
worldView.addPlugin(new MIPMouse()); worldView.addPlugin(new MIPMouse(worldView));
// size of lower navbar // size of lower navbar
final Num lownav = root.width().min(root.height()).max(700).perc(7); final Num lownav = root.width().min(root.height()).max(700).perc(7);

@ -18,6 +18,11 @@ public abstract class PlayerControl {
private World lastWorld; private World lastWorld;
/**
* Implementing classes should return a world instance from this method.
*
* @return
*/
protected abstract World provideWorld(); protected abstract World provideWorld();
@ -25,12 +30,6 @@ public abstract class PlayerControl {
{ {
final World newWorld = provideWorld(); final World newWorld = provideWorld();
if (newWorld != lastWorld) {
for (final EntityMoveListener eml : playerMoveListeners) {
newWorld.getPlayerEntity().pos.addMoveListener(eml);
}
}
lastWorld = newWorld; lastWorld = newWorld;
return newWorld; return newWorld;
@ -77,15 +76,6 @@ public abstract class PlayerControl {
} }
public void addMoveListener(EntityMoveListener eml)
{
playerMoveListeners.add(eml);
if (getPlayerEntity() != null) {
getPlayerEntity().pos.addMoveListener(eml);
}
}
public LevelAccess getLevel() public LevelAccess getLevel()
{ {
return getWorld().getCurrentLevel(); return getWorld().getCurrentLevel();
@ -104,6 +94,12 @@ public abstract class PlayerControl {
} }
/**
* Click tile on player's side
*
* @param side
* @return
*/
public boolean clickTile(Step side) public boolean clickTile(Step side)
{ {
return clickTile(getCoord().add(side)); return clickTile(getCoord().add(side));

@ -3,12 +3,15 @@ package mightypork.rogue.world;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import mightypork.gamecore.eventbus.BusAccess; import mightypork.gamecore.eventbus.BusAccess;
import mightypork.gamecore.eventbus.EventBus; import mightypork.gamecore.eventbus.EventBus;
import mightypork.gamecore.eventbus.events.Updateable; import mightypork.gamecore.eventbus.clients.DelegatingClient;
import mightypork.gamecore.util.ion.IonBundle; import mightypork.gamecore.util.ion.IonBundle;
import mightypork.gamecore.util.ion.IonObjBundled; import mightypork.gamecore.util.ion.IonObjBundled;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.timing.Pauseable;
import mightypork.rogue.world.entity.Entities; import mightypork.rogue.world.entity.Entities;
import mightypork.rogue.world.entity.Entity; import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.level.Level; import mightypork.rogue.world.level.Level;
@ -20,7 +23,7 @@ import mightypork.rogue.world.level.LevelAccess;
* *
* @author MightyPork * @author MightyPork
*/ */
public class World implements BusAccess, IonObjBundled, Updateable { public class World implements DelegatingClient, BusAccess, IonObjBundled, Pauseable {
private final ArrayList<Level> levels = new ArrayList<>(); private final ArrayList<Level> levels = new ArrayList<>();
@ -35,6 +38,23 @@ public class World implements BusAccess, IonObjBundled, Updateable {
/** Next entity ID */ /** Next entity ID */
private int eid; private int eid;
private boolean paused;
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Collection getChildClients()
{
return levels;
}
@Override
public boolean doesDelegate()
{
return !paused;
}
@Override @Override
public void load(IonBundle in) throws IOException public void load(IonBundle in) throws IOException
@ -74,13 +94,6 @@ public class World implements BusAccess, IonObjBundled, Updateable {
} }
@Override
public void update(double delta)
{
getCurrentLevel().update(delta);
}
public void setSeed(long seed) public void setSeed(long seed)
{ {
this.seed = seed; this.seed = seed;
@ -117,8 +130,12 @@ public class World implements BusAccess, IonObjBundled, Updateable {
} }
playerEntity = Entities.PLAYER.createEntity(playerEid); playerEntity = Entities.PLAYER.createEntity(playerEid);
floor.addEntity(playerEntity, floor.getEnterPoint());
floor.explore(playerEntity.getCoord()); final Coord spawn = floor.getEnterPoint();
floor.forceFreeTile(spawn);
floor.addEntity(playerEntity, spawn);
floor.explore(spawn);
playerInfo.setLevel(level); playerInfo.setLevel(level);
playerInfo.setEID(playerEid); playerInfo.setEID(playerEid);
@ -155,4 +172,25 @@ public class World implements BusAccess, IonObjBundled, Updateable {
return bus.getEventBus(); return bus.getEventBus();
} }
@Override
public void pause()
{
paused = true;
}
@Override
public void resume()
{
paused = false;
}
@Override
public boolean isPaused()
{
return paused;
}
} }

@ -19,9 +19,9 @@ public class WorldCreator {
final World w = new World(); final World w = new World();
w.setSeed(seed); w.setSeed(seed);
for(int i=0; i<7; i++) { for (int i = 0; i < 7; i++) {
Level l = LevelGenerator.build(w, rand.nextLong(), i, LevelGenerator.DUNGEON_THEME); final Level l = LevelGenerator.build(w, rand.nextLong(), i, LevelGenerator.DUNGEON_THEME);
w.addLevel(l); w.addLevel(l);
} }

@ -23,7 +23,7 @@ import mightypork.rogue.world.level.render.MapRenderContext;
/** /**
* World entity (mob or player) * World entity (mob or player). Entities are attached to the event bus.
* *
* @author MightyPork * @author MightyPork
*/ */

@ -12,6 +12,7 @@ import mightypork.rogue.world.entity.modules.EntityMoveListener;
import mightypork.rogue.world.entity.render.EntityRenderer; import mightypork.rogue.world.entity.render.EntityRenderer;
import mightypork.rogue.world.entity.render.EntityRendererMobLR; import mightypork.rogue.world.entity.render.EntityRendererMobLR;
import mightypork.rogue.world.events.PlayerKilledEvent; import mightypork.rogue.world.events.PlayerKilledEvent;
import mightypork.rogue.world.events.PlayerStepEndEvent;
public class PlayerEntity extends Entity { public class PlayerEntity extends Entity {
@ -32,12 +33,14 @@ public class PlayerEntity extends Entity {
public void onStepFinished() public void onStepFinished()
{ {
entity.getLevel().explore(entity.pos.getCoord()); entity.getLevel().explore(entity.pos.getCoord());
fireEvt();
} }
@Override @Override
public void onPathFinished() public void onPathFinished()
{ {
fireEvt();
} }
@ -47,6 +50,12 @@ public class PlayerEntity extends Entity {
} }
private void fireEvt()
{
getWorld().getEventBus().send(new PlayerStepEndEvent(PlayerEntity.this));
}
@Override @Override
public boolean isModuleSaved() public boolean isModuleSaved()
{ {
@ -86,7 +95,7 @@ public class PlayerEntity extends Entity {
} }
return super.getCost(from, to); return super.getCost(from, to);
}; }
}; };
} }

@ -184,6 +184,8 @@ public class EntityModulePosition extends EntityModule {
/** /**
* Add a move listener. If already present, do nothing. * Add a move listener. If already present, do nothing.
*
* @param listener the listener
*/ */
public void addMoveListener(EntityMoveListener listener) public void addMoveListener(EntityMoveListener listener)
{ {

@ -0,0 +1,28 @@
package mightypork.rogue.world.events;
import mightypork.gamecore.eventbus.BusEvent;
import mightypork.gamecore.eventbus.event_flags.UnloggedEvent;
import mightypork.rogue.world.entity.entities.PlayerEntity;
@UnloggedEvent
public class PlayerStepEndEvent extends BusEvent<PlayerStepEndListener> {
private final PlayerEntity player;
public PlayerStepEndEvent(PlayerEntity player)
{
super();
this.player = player;
}
@Override
protected void handleBy(PlayerStepEndListener handler)
{
handler.onStepFinished(player);
}
}

@ -0,0 +1,10 @@
package mightypork.rogue.world.events;
import mightypork.rogue.world.entity.entities.PlayerEntity;
public interface PlayerStepEndListener {
void onStepFinished(PlayerEntity player);
}

@ -0,0 +1,27 @@
package mightypork.rogue.world.events;
import mightypork.gamecore.eventbus.BusEvent;
import mightypork.rogue.world.World;
/**
* Toggle world pause state
*
* @author MightyPork
*/
public class WorldPauseRequest extends BusEvent<World> {
@Override
protected void handleBy(World handler)
{
// toggle paused state
if (!handler.isPaused()) {
handler.pause();
} else {
handler.resume();
}
}
}

@ -23,7 +23,7 @@ public class LevelGenerator {
public static Level build(World world, long seed, int complexity, MapTheme theme) public static Level build(World world, long seed, int complexity, MapTheme theme)
{ {
Log.f3("Generating level of complexity: "+complexity); Log.f3("Generating level of complexity: " + complexity);
final Random rand = new Random(seed + 13); final Random rand = new Random(seed + 13);

@ -1,9 +1,11 @@
package mightypork.rogue.world.gui; package mightypork.rogue.world.gui;
import java.util.Collection;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
import mightypork.gamecore.eventbus.clients.DelegatingClient;
import mightypork.gamecore.eventbus.events.Updateable; import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.gui.components.InputComponent; import mightypork.gamecore.gui.components.InputComponent;
import mightypork.gamecore.input.Keys; import mightypork.gamecore.input.Keys;
@ -19,7 +21,6 @@ import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.world.PlayerControl; import mightypork.rogue.world.PlayerControl;
import mightypork.rogue.world.WorldProvider; import mightypork.rogue.world.WorldProvider;
import mightypork.rogue.world.WorldRenderer; import mightypork.rogue.world.WorldRenderer;
import mightypork.rogue.world.entity.modules.EntityMoveListener;
import mightypork.rogue.world.gui.interaction.MapInteractionPlugin; import mightypork.rogue.world.gui.interaction.MapInteractionPlugin;
@ -28,10 +29,10 @@ import mightypork.rogue.world.gui.interaction.MapInteractionPlugin;
* *
* @author MightyPork * @author MightyPork
*/ */
public class MapView extends InputComponent implements KeyListener, MouseButtonListener, EntityMoveListener, Updateable { public class MapView extends InputComponent implements DelegatingClient, KeyListener, MouseButtonListener, Updateable {
protected final WorldRenderer worldRenderer; protected final WorldRenderer worldRenderer;
private final PlayerControl pc; public final PlayerControl playerControl;
private final Set<MapInteractionPlugin> plugins = new LinkedHashSet<>(); private final Set<MapInteractionPlugin> plugins = new LinkedHashSet<>();
private final NumAnimated zoom = new NumAnimated(0, Easing.SINE_BOTH); private final NumAnimated zoom = new NumAnimated(0, Easing.SINE_BOTH);
@ -40,12 +41,26 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL
private final Num tileSize; private final Num tileSize;
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Collection getChildClients()
{
return plugins;
}
@Override
public boolean doesDelegate()
{
return true;
}
public MapView() public MapView()
{ {
this.tileSize = height().min(width()).div(10).max(32).mul(Num.make(1).sub(zoom.mul(0.5))); this.tileSize = height().min(width()).div(10).max(32).mul(Num.make(1).sub(zoom.mul(0.5)));
this.worldRenderer = new WorldRenderer(this, tileSize); this.worldRenderer = new WorldRenderer(this, tileSize);
pc = WorldProvider.get().getPlayerControl(); playerControl = WorldProvider.get().getPlayerControl();
pc.addMoveListener(this);
zoom.setDefaultDuration(0.5); zoom.setDefaultDuration(0.5);
} }
@ -70,40 +85,13 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL
} }
@Override
public void onStepFinished()
{
for (final MapInteractionPlugin p : plugins) {
if (p.onStepEnd(this, pc)) break;
}
}
@Override
public void onPathFinished()
{
for (final MapInteractionPlugin p : plugins) {
if (p.onStepEnd(this, pc)) break;
}
}
@Override
public void onPathInterrupted()
{
for (final MapInteractionPlugin p : plugins) {
if (p.onStepEnd(this, pc)) break;
}
}
@Override @Override
public void receive(MouseButtonEvent event) public void receive(MouseButtonEvent event)
{ {
if (!event.isOver(this)) return; if (!event.isOver(this)) return;
for (final MapInteractionPlugin p : plugins) { for (final MapInteractionPlugin p : plugins) {
if (p.onClick(this, pc, event.getPos(), event.getButton(), event.isDown())) { if (p.onClick(event.getPos(), event.getButton(), event.isDown())) {
event.consume(); event.consume();
break; break;
} }
@ -127,7 +115,7 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL
public void receive(KeyEvent event) public void receive(KeyEvent event)
{ {
for (final MapInteractionPlugin p : plugins) { for (final MapInteractionPlugin p : plugins) {
if (p.onKey(this, pc, event.getKey(), event.isDown())) break; if (p.onKey(event.getKey(), event.isDown())) break;
} }
if (event.getKey() == Keys.Z && event.isDown()) { if (event.getKey() == Keys.Z && event.isDown()) {
@ -158,9 +146,6 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL
@Override @Override
public void update(double delta) public void update(double delta)
{ {
for (final MapInteractionPlugin p : plugins) {
p.update(this, pc, delta);
}
zoom.update(delta); zoom.update(delta);
} }
} }

@ -6,38 +6,44 @@ import mightypork.gamecore.input.Keys;
import mightypork.gamecore.util.math.algo.Sides; import mightypork.gamecore.util.math.algo.Sides;
import mightypork.gamecore.util.math.algo.Step; import mightypork.gamecore.util.math.algo.Step;
import mightypork.gamecore.util.math.constraints.vect.Vect; import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.world.PlayerControl; import mightypork.rogue.world.entity.entities.PlayerEntity;
import mightypork.rogue.world.gui.MapView; import mightypork.rogue.world.gui.MapView;
public class MIPKeyboard implements MapInteractionPlugin { public class MIPKeyboard extends MapInteractionPlugin {
private static final int[] keys = { Keys.LEFT, Keys.RIGHT, Keys.UP, Keys.DOWN }; private static final int[] keys = { Keys.LEFT, Keys.RIGHT, Keys.UP, Keys.DOWN };
private static final Step[] sides = { Sides.W, Sides.E, Sides.N, Sides.S }; private static final Step[] sides = { Sides.W, Sides.E, Sides.N, Sides.S };
public MIPKeyboard(MapView mapView)
{
super(mapView);
}
@Override @Override
public boolean onStepEnd(MapView view, PlayerControl player) public void onStepFinished(PlayerEntity player)
{ {
return walkByKey(player); walkByKey();
} }
@Override @Override
public boolean onClick(MapView view, PlayerControl player, Vect mouse, int button, boolean down) public boolean onClick(Vect mouse, int button, boolean down)
{ {
return false; return false;
} }
@Override @Override
public boolean onKey(MapView view, PlayerControl player, int key, boolean down) public boolean onKey(int key, boolean down)
{ {
if (down) return false; // not interested if (down) return false; // not interested
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (key == keys[i]) { if (key == keys[i]) {
return player.clickTile(sides[i]); return mapView.playerControl.clickTile(sides[i]);
} }
} }
@ -45,16 +51,16 @@ public class MIPKeyboard implements MapInteractionPlugin {
} }
private boolean walkByKey(PlayerControl pc) private boolean walkByKey()
{ {
if (pc.getPlayerEntity().pos.isMoving()) return false; if (mapView.playerControl.getPlayerEntity().pos.isMoving()) return false;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (InputSystem.isKeyDown(keys[i])) { if (InputSystem.isKeyDown(keys[i])) {
final Step side = sides[i]; final Step side = sides[i];
if (pc.canGo(side)) { if (mapView.playerControl.canGo(side)) {
pc.go(side); mapView.playerControl.go(side);
return true; return true;
} else { } else {
return false; return false;
@ -66,8 +72,8 @@ public class MIPKeyboard implements MapInteractionPlugin {
@Override @Override
public void update(MapView mapView, PlayerControl pc, double delta) public void update(double delta)
{ {
walkByKey(pc); walkByKey();
} }
} }

@ -8,66 +8,72 @@ import mightypork.gamecore.util.math.Polar;
import mightypork.gamecore.util.math.algo.Coord; import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.algo.Sides; import mightypork.gamecore.util.math.algo.Sides;
import mightypork.gamecore.util.math.constraints.vect.Vect; import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.world.PlayerControl; import mightypork.rogue.world.entity.entities.PlayerEntity;
import mightypork.rogue.world.gui.MapView; import mightypork.rogue.world.gui.MapView;
import mightypork.rogue.world.tile.Tile; import mightypork.rogue.world.tile.Tile;
public class MIPMouse implements MapInteractionPlugin { public class MIPMouse extends MapInteractionPlugin {
private static final int BTN = 0; // left private static final int BTN = 0; // left
public MIPMouse(MapView mapView)
{
super(mapView);
}
@Override @Override
public void update(MapView view, PlayerControl pc, double delta) public void update(double delta)
{ {
if (!InputSystem.isKeyDown(Keys.L_SHIFT)) return; if (!InputSystem.isKeyDown(Keys.L_SHIFT)) return;
final Vect pos = InputSystem.getMousePos(); final Vect pos = InputSystem.getMousePos();
if (InputSystem.isMouseButtonDown(BTN)) { if (InputSystem.isMouseButtonDown(BTN)) {
if (mouseWalk(view, pc, pos)) return; if (mouseWalk(pos)) return;
if (troToNav(view, pc, pos)) return; if (troToNav(pos)) return;
} }
} }
@Override @Override
public boolean onClick(MapView view, PlayerControl pc, Vect mouse, int button, boolean down) public boolean onClick(Vect mouse, int button, boolean down)
{ {
if (button != BTN) return false; if (button != BTN) return false;
final Coord pos = view.toWorldPos(mouse); final Coord pos = mapView.toWorldPos(mouse);
final Tile t = pc.getLevel().getTile(pos); final Tile t = mapView.playerControl.getLevel().getTile(pos);
if (t.onClick()) return true; if (t.onClick()) return true;
if (!down && t.isWalkable()) { if (!down && t.isWalkable()) {
if (troToNav(view, pc, mouse)) return true; if (troToNav(mouse)) return true;
return mouseWalk(view, pc, mouse); return mouseWalk(mouse);
} }
return false; return false;
} }
private boolean troToNav(MapView view, PlayerControl pc, Vect mouse) private boolean troToNav(Vect mouse)
{ {
final Coord plpos = pc.getCoord(); final Coord plpos = mapView.playerControl.getCoord();
final Coord clicked = view.toWorldPos(mouse); final Coord clicked = mapView.toWorldPos(mouse);
if (clicked.equals(plpos)) return false; if (clicked.equals(plpos)) return false;
final Tile t = pc.getLevel().getTile(clicked); final Tile t = mapView.playerControl.getLevel().getTile(clicked);
if (!t.isWalkable() || !t.isExplored()) return false; if (!t.isWalkable() || !t.isExplored()) return false;
pc.navigateTo(clicked); mapView.playerControl.navigateTo(clicked);
return true; return true;
} }
private boolean mouseWalk(MapView view, PlayerControl pc, Vect pos) private boolean mouseWalk(Vect pos)
{ {
final Coord plpos = pc.getCoord(); final Coord plpos = mapView.playerControl.getCoord();
final Coord clicked = view.toWorldPos(pos); final Coord clicked = mapView.toWorldPos(pos);
if (clicked.equals(plpos)) return false; if (clicked.equals(plpos)) return false;
final Polar p = Polar.fromCoord(clicked.x - plpos.x, clicked.y - plpos.y); final Polar p = Polar.fromCoord(clicked.x - plpos.x, clicked.y - plpos.y);
@ -76,16 +82,16 @@ public class MIPMouse implements MapInteractionPlugin {
switch (dir) { switch (dir) {
case 0: case 0:
return pc.tryGo(Sides.E); return mapView.playerControl.tryGo(Sides.E);
case 1: case 1:
return pc.tryGo(Sides.S); return mapView.playerControl.tryGo(Sides.S);
case 2: case 2:
return pc.tryGo(Sides.W); return mapView.playerControl.tryGo(Sides.W);
case 3: case 3:
return pc.tryGo(Sides.N); return mapView.playerControl.tryGo(Sides.N);
} }
return false; return false;
@ -93,25 +99,23 @@ public class MIPMouse implements MapInteractionPlugin {
@Override @Override
public boolean onKey(MapView view, PlayerControl player, int key, boolean down) public boolean onKey(int key, boolean down)
{ {
return false; return false;
} }
@Override @Override
public boolean onStepEnd(MapView view, PlayerControl pc) public void onStepFinished(PlayerEntity player)
{ {
if (!InputSystem.isKeyDown(Keys.L_SHIFT)) return false; if (!InputSystem.isKeyDown(Keys.L_SHIFT)) return;
final Vect pos = InputSystem.getMousePos(); final Vect pos = InputSystem.getMousePos();
if (InputSystem.isMouseButtonDown(BTN)) { if (InputSystem.isMouseButtonDown(BTN)) {
if (mouseWalk(view, pc, pos)) return true; if (mouseWalk(pos)) return;
if (troToNav(view, pc, pos)) return true; if (troToNav(pos)) return;
} }
return false;
} }
} }

@ -1,22 +1,31 @@
package mightypork.rogue.world.gui.interaction; package mightypork.rogue.world.gui.interaction;
import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.util.math.constraints.vect.Vect; import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.world.PlayerControl; import mightypork.rogue.world.events.PlayerStepEndListener;
import mightypork.rogue.world.gui.MapView; import mightypork.rogue.world.gui.MapView;
public interface MapInteractionPlugin { public abstract class MapInteractionPlugin implements Updateable, PlayerStepEndListener {
boolean onStepEnd(MapView mapView, PlayerControl player); protected final MapView mapView;
boolean onClick(MapView mapView, PlayerControl player, Vect mouse, int button, boolean down); public MapInteractionPlugin(MapView mapView)
{
super();
this.mapView = mapView;
}
boolean onKey(MapView mapView, PlayerControl player, int key, boolean down); public abstract boolean onClick(Vect mouse, int button, boolean down);
void update(MapView mapView, PlayerControl pc, double delta); public abstract boolean onKey(int key, boolean down);
@Override
public abstract void update(double delta);
} }

@ -6,6 +6,8 @@ import java.util.*;
import mightypork.gamecore.eventbus.BusAccess; import mightypork.gamecore.eventbus.BusAccess;
import mightypork.gamecore.eventbus.EventBus; import mightypork.gamecore.eventbus.EventBus;
import mightypork.gamecore.eventbus.clients.DelegatingClient;
import mightypork.gamecore.eventbus.clients.ToggleableClient;
import mightypork.gamecore.logging.Log; import mightypork.gamecore.logging.Log;
import mightypork.gamecore.util.ion.IonBundle; import mightypork.gamecore.util.ion.IonBundle;
import mightypork.gamecore.util.ion.IonInput; import mightypork.gamecore.util.ion.IonInput;
@ -21,6 +23,7 @@ import mightypork.rogue.world.World;
import mightypork.rogue.world.entity.Entities; import mightypork.rogue.world.entity.Entities;
import mightypork.rogue.world.entity.Entity; import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.entity.EntityType; import mightypork.rogue.world.entity.EntityType;
import mightypork.rogue.world.entity.entities.PlayerEntity;
import mightypork.rogue.world.tile.Tile; import mightypork.rogue.world.tile.Tile;
import mightypork.rogue.world.tile.TileModel; import mightypork.rogue.world.tile.TileModel;
import mightypork.rogue.world.tile.Tiles; import mightypork.rogue.world.tile.Tiles;
@ -31,7 +34,7 @@ import mightypork.rogue.world.tile.Tiles;
* *
* @author MightyPork * @author MightyPork
*/ */
public class Level implements BusAccess, LevelAccess, IonObjBinary { public class Level implements BusAccess, DelegatingClient, ToggleableClient, LevelAccess, IonObjBinary {
public static final int ION_MARK = 53; public static final int ION_MARK = 53;
@ -46,6 +49,8 @@ public class Level implements BusAccess, LevelAccess, IonObjBinary {
private final Map<Integer, Entity> entityMap = new HashMap<>(); private final Map<Integer, Entity> entityMap = new HashMap<>();
private final Set<Entity> entitySet = new HashSet<>(); private final Set<Entity> entitySet = new HashSet<>();
private int playerCount = 0;
/** Level seed (used for generation and tile variation) */ /** Level seed (used for generation and tile variation) */
public long seed; public long seed;
@ -201,14 +206,13 @@ public class Level implements BusAccess, LevelAccess, IonObjBinary {
// just update them all // just update them all
for (final Coord c = Coord.zero(); c.x < size.x; c.x++) { for (final Coord c = Coord.zero(); c.x < size.x; c.x++) {
for (c.y = 0; c.y < size.y; c.y++) { for (c.y = 0; c.y < size.y; c.y++) {
getTile(c).update(delta); getTile(c).updateTile(delta);
} }
} }
final List<Entity> toRemove = new ArrayList<>(); final List<Entity> toRemove = new ArrayList<>();
for (final Entity e : entitySet) { for (final Entity e : entitySet) {
e.update(delta);
if (e.isDead() && e.canRemoveCorpse()) toRemove.add(e); if (e.isDead() && e.canRemoveCorpse()) toRemove.add(e);
} }
@ -249,6 +253,7 @@ public class Level implements BusAccess, LevelAccess, IonObjBinary {
entityMap.put(entity.getEntityId(), entity); entityMap.put(entity.getEntityId(), entity);
entitySet.add(entity); entitySet.add(entity);
if (entity instanceof PlayerEntity) playerCount++;
// join to level & world // join to level & world
entity.setLevel(this); entity.setLevel(this);
@ -271,6 +276,8 @@ public class Level implements BusAccess, LevelAccess, IonObjBinary {
public void removeEntity(int eid) public void removeEntity(int eid)
{ {
final Entity removed = entityMap.remove(eid); final Entity removed = entityMap.remove(eid);
if (removed == null) throw new NullPointerException("No such entity in level: " + eid);
if (removed instanceof PlayerEntity) playerCount--;
entitySet.remove(removed); entitySet.remove(removed);
freeTile(removed.getCoord()); freeTile(removed.getCoord());
} }
@ -462,4 +469,26 @@ public class Level implements BusAccess, LevelAccess, IonObjBinary {
{ {
return world.getEventBus(); return world.getEventBus();
} }
@Override
public boolean isListening()
{
return playerCount > 0;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Collection getChildClients()
{
return entitySet;
}
@Override
public boolean doesDelegate()
{
return isListening();
}
} }

@ -56,14 +56,7 @@ public abstract class Tile implements IonObjBlob {
{ {
if (!isExplored()) return; if (!isExplored()) return;
if (renderer == null) { initRenderer();
renderer = makeRenderer();
}
if (renderer == null) {
Log.w("No renderer for tile " + Log.str(this));
return;
}
renderer.renderTile(context); renderer.renderTile(context);
@ -73,6 +66,20 @@ public abstract class Tile implements IonObjBlob {
} }
private void initRenderer()
{
if (renderer == null) {
renderer = makeRenderer();
if (renderer == /*still*/null) {
Log.w("No renderer for tile " + Log.str(this));
renderer = TileRenderer.NONE;
return;
}
}
}
protected abstract TileRenderer makeRenderer(); protected abstract TileRenderer makeRenderer();
@ -151,9 +158,10 @@ public abstract class Tile implements IonObjBlob {
@DefaultImpl @DefaultImpl
public void update(double delta) public void updateTile(double delta)
{ {
makeRenderer().update(delta); initRenderer();
renderer.update(delta);
} }

@ -25,7 +25,7 @@ public class NullTile extends Tile {
@Override @Override
public void update(double delta) public void updateTile(double delta)
{ {
} }

@ -37,9 +37,9 @@ public abstract class TileWithItems extends Tile {
@Override @Override
public void update(double delta) public void updateTile(double delta)
{ {
super.update(delta); super.updateTile(delta);
itemRenderer.update(delta); itemRenderer.update(delta);
} }

Loading…
Cancel
Save