v5stable
Ondřej Hruška 11 years ago
parent e14be3ec1b
commit 880bcfb553
  1. 4
      src/mightypork/rogue/App.java
  2. 21
      src/mightypork/rogue/world/ClientWorld.java
  3. 6
      src/mightypork/rogue/world/MapGenerator.java
  4. 16
      src/mightypork/rogue/world/MapObserver.java
  5. 49
      src/mightypork/rogue/world/PathStep.java
  6. 140
      src/mightypork/rogue/world/Player.java
  7. 83
      src/mightypork/rogue/world/PlayerEntity.java
  8. 33
      src/mightypork/rogue/world/ServerWorld.java
  9. 2
      src/mightypork/rogue/world/WorldAccess.java
  10. 139
      src/mightypork/rogue/world/WorldEntity.java
  11. 31
      src/mightypork/rogue/world/WorldPos.java
  12. 38
      src/mightypork/rogue/world/map/Level.java
  13. 13
      src/mightypork/rogue/world/map/MapObserver.java
  14. 10
      src/mightypork/rogue/world/tile/Tile.java
  15. 10
      src/mightypork/rogue/world/tile/TileModel.java

@ -22,7 +22,7 @@ import mightypork.rogue.screens.main_menu.ScreenMainMenu;
import mightypork.rogue.screens.test_bouncyboxes.ScreenTestBouncy;
import mightypork.rogue.screens.test_cat_sound.ScreenTestCat;
import mightypork.rogue.screens.test_render.ScreenTestRender;
import mightypork.rogue.world.Player;
import mightypork.rogue.world.PlayerEntity;
import mightypork.rogue.world.item.Item;
import mightypork.rogue.world.map.Level;
import mightypork.rogue.world.tile.Tile;
@ -110,7 +110,7 @@ public final class App extends BaseApp {
Ion.registerBinary(Tile.ION_MARK, Tile.class);
Ion.registerBinary(Item.ION_MARK, Item.class);
Ion.registerBinary(Level.ION_MARK, Level.class);
Ion.registerBinary(Level.ION_MARK, Player.class);
Ion.registerBinary(Level.ION_MARK, PlayerEntity.class);
}

@ -10,11 +10,11 @@ import mightypork.util.constraints.vect.VectConst;
import mightypork.util.control.timing.Updateable;
public class WorldClient implements Updateable {
public class ClientWorld implements Updateable, WorldAccess {
private Level level = null;
private final Player player = null;
private final PlayerEntity player = null;
@Override
@ -50,8 +50,8 @@ public class WorldClient implements Updateable {
final VectConst vpCenter = r.center().sub(tileSize * 0.5, tileSize).freeze(); // 0.5 to center, 1 to move up (down is teh navbar)
final double playerX = player.getPosition().getXVisual();
final double playerY = player.getPosition().getYVisual();
final double playerX = player.getPosition().getVisualX();
final double playerY = player.getPosition().getVisualY();
// total map area
//@formatter:off
@ -63,9 +63,6 @@ public class WorldClient implements Updateable {
).freeze();
//@formatter:on
System.out.println(playerX + "," + playerY + " : " + mapRect);
System.out.println(level.getWidth() + "," + level.getHeight());
// tiles to render
final int x1 = (int) Math.floor(playerX - (vpW / tileSize));
final int y1 = (int) Math.floor(playerY - (vpH / tileSize));
@ -81,9 +78,17 @@ public class WorldClient implements Updateable {
}
public Player getPlayer()
public PlayerEntity getPlayer()
{
return player;
}
@Override
public boolean isServer()
{
// TODO Auto-generated method stub
return false;
}
}

@ -13,19 +13,19 @@ public class MapGenerator {
public static final Random rand = new Random();
public static WorldServer createWorld(long seed)
public static ServerWorld createWorld(long seed)
{
synchronized (rand) {
rand.setSeed(seed);
final WorldServer w = new WorldServer();
final ServerWorld w = new ServerWorld();
w.setSeed(seed);
w.addLevel(createLevel(rand.nextLong(), Tiles.CRYSTAL_FLOOR, Tiles.CRYSTAL_WALL));
w.addLevel(createLevel(rand.nextLong(), Tiles.BRCOBBLE_FLOOR, Tiles.BRCOBBLE_WALL));
// TODO place on start position
w.addPlayer("local", new Player(10, 10, 0));
w.addPlayer("local", new PlayerEntity(10, 10, 0));
return w;
}
}

@ -1,16 +0,0 @@
package mightypork.rogue.world;
/**
* Player observing a map represented by an observer.
*
* @author MightyPork
*/
public interface MapObserver extends WorldEntity {
/**
* @return observed range (in tiles)
*/
public int getViewRange();
}

@ -0,0 +1,49 @@
package mightypork.rogue.world;
import java.io.IOException;
import mightypork.util.ion.IonBinary;
import mightypork.util.ion.IonInput;
import mightypork.util.ion.IonOutput;
public class PathStep implements IonBinary {
public static final int ION_MARK = 0;
public int x;
public int y;
public PathStep(int x, int y) {
this.x = x < 1 ? -1 : x > 0 ? 1 : 0;
this.y = y < 1 ? -1 : y > 0 ? 1 : 0;
y = (int) Math.signum(x);
}
@Override
public void load(IonInput in) throws IOException
{
x = in.readByte();
y = in.readByte();
}
@Override
public void save(IonOutput out) throws IOException
{
out.writeByte(x);
out.writeByte(y);
}
@Override
public short getIonMark()
{
return ION_MARK;
}
}

@ -1,140 +0,0 @@
package mightypork.rogue.world;
import java.io.IOException;
import mightypork.util.ion.IonBinary;
import mightypork.util.ion.IonBundle;
import mightypork.util.ion.IonInput;
import mightypork.util.ion.IonOutput;
/**
* Player info
*
* @author MightyPork
*/
public class Player implements IonBinary, MapObserver {
public static final short ION_MARK = 0;
private final double walktime = 0.3; // possibly make changeable for speed potion
private final WorldPos position = new WorldPos();
private final WorldPos target = new WorldPos();
private Runnable moveListenerCustom;
private Runnable moveListener = new Runnable() {
@Override
public void run()
{
if (moveListenerCustom != null) moveListenerCustom.run();
if (!target.equals(position)) {
int x = (target.x - position.x);
int y = (target.y - position.y);
if (Math.abs(x) >= Math.abs(y)) y = 0;
if (Math.abs(y) > Math.abs(x)) x = 0;
if (x > 0) x = 1;
if (x < 0) x = -1;
if (y > 0) y = 1;
if (y < 0) y = -1;
position.walk(x, y, walktime);
}
}
};
public Player()
{
position.setMoveListener(moveListener);
}
public Player(int x, int y, int floor)
{
position.setTo(x, y, floor);
target.setTo(position);
}
public Player(WorldPos pos)
{
this(pos.x, pos.y, pos.floor);
}
@Override
public void load(IonInput in) throws IOException
{
IonBundle ib = in.readBundle();
ib.loadBundled("pos", position);
}
@Override
public void save(IonOutput out) throws IOException
{
IonBundle ib = new IonBundle();
ib.putBundled("target", target);
out.writeBundle(ib);
}
@Override
public short getIonMark()
{
return ION_MARK;
}
@Override
public WorldPos getPosition()
{
return position;
}
@Override
public int getViewRange()
{
return 15;
}
public void teleport(WorldPos pos)
{
position.setTo(pos);
target.setTo(pos);
}
public void walk(int offsetX, int offsetY)
{
target.setTo(position.x + offsetX, position.y + offsetY, this.position.floor);
}
public void setMoveListener(Runnable r)
{
this.moveListenerCustom = r;
}
public void updateVisual(double delta)
{
position.update(delta);
}
public void updateLogic(double delta)
{
// server stuffs (sleep timer etc)
}
}

@ -0,0 +1,83 @@
package mightypork.rogue.world;
import java.io.IOException;
import mightypork.rogue.world.map.MapObserver;
import mightypork.util.ion.IonBundle;
/**
* Player info
*
* @author MightyPork
*/
public class PlayerEntity extends WorldEntity implements MapObserver {
public static final double PLAYER_STEP_TIME = 0.3;
public boolean connected = false;
public PlayerEntity() {
super();
}
public PlayerEntity(ServerWorld world, int x, int y, int floor) {
super(world, new WorldPos(x, y, floor));
}
@Override
public void load(IonBundle bundle) throws IOException
{
super.load(bundle);
}
@Override
public void save(IonBundle bundle) throws IOException
{
super.save(bundle);
}
@Override
public int getViewRange()
{
return 15;
}
@Override
protected double getStepTime()
{
return PLAYER_STEP_TIME;
}
public boolean isConnected()
{
return connected;
}
public void setConnected(boolean connected)
{
this.connected = connected;
}
@Override
public WorldPos getViewPosition()
{
return getPosition();
}
@Override
public boolean isPhysical()
{
return isConnected();
}
}

@ -12,24 +12,28 @@ import mightypork.util.ion.IonBundled;
/**
* World server. To a server, all players and levels are equal.
* World on a server. To a server, all players and levels are equal.
*
* @author MightyPork
*/
public class WorldServer implements IonBundled, Updateable {
public class ServerWorld implements IonBundled, Updateable, WorldAccess {
private final ArrayList<Level> levels = new ArrayList<>();
private final Map<String, Player> players = new HashMap<>();
private final Map<String, PlayerEntity> players = new HashMap<>();
/** This seed can be used to re-create identical world. */
private long seed;
/** Next spawned entity ID */
private long eid;
@Override
public void load(IonBundle in) throws IOException
{
seed = in.get("seed", 0L);
eid = in.get("eid", 0L);
in.loadSequence("levels", levels);
in.loadMap("players", players);
}
@ -39,6 +43,7 @@ public class WorldServer implements IonBundled, Updateable {
public void save(IonBundle out) throws IOException
{
out.put("seed", seed);
out.put("eid", eid);
out.putSequence("levels", levels);
out.putMap("players", players);
}
@ -49,7 +54,7 @@ public class WorldServer implements IonBundled, Updateable {
levels.add(level);
}
public void addPlayer(String name, Player player)
public void addPlayer(String name, PlayerEntity player)
{
players.put(name, player);
}
@ -63,16 +68,16 @@ public class WorldServer implements IonBundled, Updateable {
public void update(double delta)
{
// food meters and such
for (final Player pl : players.values()) {
pl.updateLogic(delta);
for (final PlayerEntity pl : players.values()) {
if(pl.isConnected()) pl.updateLogic(this, delta);
}
for (int level = 0; level < levels.size(); level++) {
// more than 1 player can be on floor, update for all of them
for (final Player pl : players.values()) {
for (final PlayerEntity pl : players.values()) {
if (pl.getPosition().floor == level) {
levels.get(level).updateLogic(pl, delta);
levels.get(level).updateLogic(this, pl, delta);
}
}
@ -90,4 +95,16 @@ public class WorldServer implements IonBundled, Updateable {
{
return seed;
}
public long genEid()
{
return eid++;
}
@Override
public boolean isServer()
{
return true;
}
}

@ -3,4 +3,6 @@ package mightypork.rogue.world;
public interface WorldAccess {
public boolean isServer();
}

@ -1,10 +1,143 @@
package mightypork.rogue.world;
import mightypork.util.constraints.vect.Vect;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;
import mightypork.util.ion.IonBundle;
import mightypork.util.ion.IonBundled;
public interface WorldEntity {
public abstract class WorldEntity implements IonBundled {
private final WorldPos position = new WorldPos();
private Runnable moveEndListener, pathEndListener;
private long serial_id = 0L;
private final Queue<PathStep> path = new LinkedList<>();
public WorldEntity(ServerWorld world, WorldPos pos) {
this.serial_id = world.genEid();
this.position.setTo(pos);
}
public WorldEntity() {
// for ion
}
@Override
public void save(IonBundle bundle) throws IOException
{
bundle.putBundled("pos", position);
bundle.putSequence("steps", path);
bundle.put("eid", serial_id);
}
@Override
public void load(IonBundle bundle) throws IOException
{
bundle.loadBundled("pos", position);
bundle.loadSequence("path", path);
serial_id = bundle.get("eid", 0L);
}
public void setMoveEndListener(Runnable moveEndListener)
{
this.moveEndListener = moveEndListener;
}
public void setPathEndListener(Runnable pathEndListener)
{
this.pathEndListener = pathEndListener;
}
public WorldPos getPosition()
{
return position;
}
public void setPosition(WorldPos pos)
{
position.setTo(pos);
}
public void setPosition(int x, int y, int floor)
{
position.setTo(x, y, floor);
cancelPath(); // discard remaining steps
}
/**
* @param world the world
* @param delta delta time
*/
public void updateLogic(WorldAccess world, double delta)
{
if(!isPhysical()) return;
if (!position.isFinished()) {
position.update(delta);
}
if (position.isFinished()) {
if (moveEndListener != null) moveEndListener.run();
if (!path.isEmpty()) {
// get next step to walk
PathStep step = path.poll();
position.walk(step.x, step.y, getStepTime());
} else {
// notify AI or whatever
if (pathEndListener != null) pathEndListener.run();
}
}
}
/**
* @param world the world
* @param delta delta time
*/
public void updateVisual(WorldAccess world, double delta)
{
}
public boolean isPathFinished()
{
return position.isFinished() && path.isEmpty();
}
public void addStep(PathStep step)
{
path.add(step);
}
public void cancelPath()
{
path.clear();
}
protected abstract double getStepTime();
public boolean isPhysical() {
return true;
}
WorldPos getPosition();
}

@ -20,11 +20,9 @@ public class WorldPos implements IonBundled, Updateable {
public int x, y, floor;
private final VectAnimated walkOffset = new VectAnimated(Vect.ZERO, Easing.LINEAR);
private Runnable moveListener;
public WorldPos(int x, int y, int floor)
{
public WorldPos(int x, int y, int floor) {
super();
this.x = x;
this.y = y;
@ -32,8 +30,13 @@ public class WorldPos implements IonBundled, Updateable {
}
public WorldPos()
public WorldPos() {
}
public double getProgress()
{
return walkOffset.getProgress();
}
@ -74,13 +77,13 @@ public class WorldPos implements IonBundled, Updateable {
}
public double getXVisual()
public double getVisualX()
{
return x + walkOffset.x();
}
public double getYVisual()
public double getVisualY()
{
return y + walkOffset.y();
}
@ -135,12 +138,6 @@ public class WorldPos implements IonBundled, Updateable {
}
public void add(int x, int y)
{
setTo(this.x + x, this.y + y);
}
public void walk(int x, int y, double secs)
{
setTo(this.x + x, this.y + y);
@ -152,17 +149,13 @@ public class WorldPos implements IonBundled, Updateable {
@Override
public void update(double delta)
{
if (!walkOffset.isFinished()) {
walkOffset.update(delta);
}
if (walkOffset.isFinished()) moveListener.run();
walkOffset.update(delta);
}
public void setMoveListener(Runnable listener)
public boolean isFinished()
{
this.moveListener = listener;
return walkOffset.isFinished();
}
}

@ -2,9 +2,12 @@ package mightypork.rogue.world.map;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import mightypork.rogue.world.MapObserver;
import mightypork.rogue.world.Player;
import mightypork.rogue.world.PlayerEntity;
import mightypork.rogue.world.WorldAccess;
import mightypork.rogue.world.WorldEntity;
import mightypork.rogue.world.WorldPos;
import mightypork.rogue.world.tile.Tile;
import mightypork.rogue.world.tile.TileModel;
@ -30,19 +33,19 @@ public class Level implements MapAccess, IonBinary {
/** Array of tiles [y][x] */
private Tile[][] tiles;
private final List<WorldEntity> entities = new ArrayList<>();
/** Level seed (used for generation and tile variation) */
public long seed;
private transient NoiseGen noiseGen;
public Level()
{
public Level() {
}
public Level(int width, int height)
{
public Level(int width, int height) {
this.width = width;
this.height = height;
buildArray();
@ -136,6 +139,8 @@ public class Level implements MapAccess, IonBinary {
width = ib.get("w", 0);
height = ib.get("h", 0);
ib.loadSequence("entities", entities);
// init array of size
buildArray();
@ -159,6 +164,7 @@ public class Level implements MapAccess, IonBinary {
ib.put("seed", seed);
ib.put("w", width);
ib.put("h", height);
ib.putSequence("entities", entities);
out.writeBundle(ib);
// tiles (writing this way to save space)
@ -178,25 +184,25 @@ public class Level implements MapAccess, IonBinary {
}
public void updateLogic(MapObserver observer, double delta)
public void updateLogic(WorldAccess world, MapObserver observer, double delta)
{
updateForObserver(observer, delta, true, false);
updateForObserver(world, observer, delta, true, false);
}
public void updateVisual(Player player, double delta)
public void updateVisual(WorldAccess world, PlayerEntity player, double delta)
{
updateForObserver(player, delta, false, true);
updateForObserver(world, player, delta, false, true);
}
private void updateForObserver(MapObserver observer, double delta, boolean logic, boolean visual)
private void updateForObserver(WorldAccess world, MapObserver observer, double delta, boolean logic, boolean visual)
{
final int viewRange = observer.getViewRange();
final WorldPos position = observer.getPosition();
final WorldPos eyepos = observer.getViewPosition();
int x1 = position.x - viewRange;
int y1 = position.y - viewRange;
int x1 = eyepos.x - viewRange;
int y1 = eyepos.y - viewRange;
int x2 = x1 + viewRange * 2;
int y2 = y1 + viewRange * 2;
@ -208,8 +214,8 @@ public class Level implements MapAccess, IonBinary {
for (int y = y1; y <= y2; y++) {
for (int x = x1; x <= x2; x++) {
if (logic) getTile(x, y).updateLogic(delta);
if (visual) getTile(x, y).updateVisual(delta);
if (logic) getTile(x, y).updateLogic(world, delta);
if (visual) getTile(x, y).updateVisual(world, delta);
}
}
}

@ -0,0 +1,13 @@
package mightypork.rogue.world.map;
import mightypork.rogue.world.WorldPos;
public interface MapObserver {
int getViewRange();
WorldPos getViewPosition();
}

@ -4,10 +4,10 @@ package mightypork.rogue.world.tile;
import java.io.IOException;
import java.util.Stack;
import mightypork.rogue.world.WorldAccess;
import mightypork.rogue.world.item.Item;
import mightypork.rogue.world.map.TileRenderContext;
import mightypork.util.control.timing.Animator;
import mightypork.util.control.timing.Updateable;
import mightypork.util.ion.IonBinary;
import mightypork.util.ion.IonBundle;
import mightypork.util.ion.IonInput;
@ -99,14 +99,14 @@ public final class Tile implements IonBinary {
}
public void updateLogic(double delta)
public void updateLogic(WorldAccess world, double delta)
{
model.updateLogic(this, delta);
model.updateLogic(this, world, delta);
}
public void updateVisual(double delta)
public void updateVisual(WorldAccess world, double delta)
{
model.updateVisual(this, delta);
model.updateVisual(this, world, delta);
if (hasItems()) {
getItemRenderer().updateVisual(delta);
}

@ -1,6 +1,7 @@
package mightypork.rogue.world.tile;
import mightypork.rogue.world.WorldAccess;
import mightypork.rogue.world.map.TileRenderContext;
import mightypork.util.annotations.DefaultImpl;
import mightypork.util.ion.IonBundle;
@ -17,8 +18,7 @@ public abstract class TileModel {
public final int id;
public TileModel(int id)
{
public TileModel(int id) {
Tiles.register(id, this);
this.id = id;
}
@ -73,18 +73,20 @@ public abstract class TileModel {
* Update tile state etc
*
* @param tile tile
* @param world
* @param delta delta time
*/
public abstract void updateLogic(Tile tile, double delta);
public abstract void updateLogic(Tile tile, WorldAccess world, double delta);
/**
* Update tile effects
*
* @param tile tile
* @param world
* @param delta delta time
*/
public abstract void updateVisual(Tile tile, double delta);
public abstract void updateVisual(Tile tile, WorldAccess world, double delta);
/**

Loading…
Cancel
Save