parent
9e4a237192
commit
3e69505787
Before Width: | Height: | Size: 320 KiB After Width: | Height: | Size: 320 KiB |
@ -1,94 +0,0 @@ |
||||
package mightypork.rogue.world; |
||||
|
||||
|
||||
import mightypork.rogue.world.map.Level; |
||||
import mightypork.rogue.world.map.TileRenderContext; |
||||
import mightypork.util.constraints.rect.Rect; |
||||
import mightypork.util.constraints.rect.RectConst; |
||||
import mightypork.util.constraints.rect.proxy.RectBound; |
||||
import mightypork.util.constraints.vect.VectConst; |
||||
import mightypork.util.control.timing.Updateable; |
||||
|
||||
|
||||
public class ClientWorld implements Updateable, WorldAccess { |
||||
|
||||
private Level level = null; |
||||
|
||||
private final PlayerEntity player = null; |
||||
|
||||
|
||||
@Override |
||||
public void update(double delta) |
||||
{ |
||||
player.update(delta); |
||||
|
||||
level.updateVisual(player, delta); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Draw on screen |
||||
* |
||||
* @param viewport rendering area on screen |
||||
* @param xTiles Desired nr of tiles horizontally |
||||
* @param yTiles Desired nr of tiles vertically |
||||
* @param minSize minimum tile size |
||||
*/ |
||||
public void render(final RectBound viewport, final int yTiles, final int xTiles, final int minSize) |
||||
{ |
||||
final Rect r = viewport.getRect(); |
||||
final double vpH = r.height().value(); |
||||
final double vpW = r.width().value(); |
||||
|
||||
// adjust tile size to fit desired amount of tiles
|
||||
|
||||
final double allowedSizeW = vpW / xTiles; |
||||
final double allowedSizeH = vpH / yTiles; |
||||
int tileSize = (int) Math.round(Math.max(Math.min(allowedSizeH, allowedSizeW), minSize)); |
||||
|
||||
tileSize -= tileSize % 16; |
||||
|
||||
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().getVisualX(); |
||||
final double playerY = player.getPosition().getVisualY(); |
||||
|
||||
// total map area
|
||||
//@formatter:off
|
||||
final RectConst mapRect = vpCenter.startRect().grow( |
||||
playerX*tileSize, |
||||
(level.getWidth() - playerX) * tileSize, |
||||
playerY*tileSize, |
||||
(level.getHeight() - playerY) * tileSize |
||||
).freeze(); |
||||
//@formatter:on
|
||||
|
||||
// tiles to render
|
||||
final int x1 = (int) Math.floor(playerX - (vpW / tileSize)); |
||||
final int y1 = (int) Math.floor(playerY - (vpH / tileSize)); |
||||
final int x2 = (int) Math.ceil(playerX + (vpW / tileSize)); |
||||
final int y2 = (int) Math.ceil(playerY + (vpH / tileSize)); |
||||
|
||||
final TileRenderContext trc = new TileRenderContext(level, mapRect); //-tileSize*0.5
|
||||
for (trc.y = y1; trc.y <= y2; trc.y++) { |
||||
for (trc.x = x1; trc.x <= x2; trc.x++) { |
||||
trc.render(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
public PlayerEntity getPlayer() |
||||
{ |
||||
return player; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public boolean isServer() |
||||
{ |
||||
// TODO Auto-generated method stub
|
||||
return false; |
||||
} |
||||
|
||||
} |
@ -1,16 +0,0 @@ |
||||
package mightypork.rogue.world; |
||||
|
||||
import mightypork.rogue.world.map.Level; |
||||
import mightypork.util.control.timing.Updateable; |
||||
|
||||
|
||||
/** |
||||
* Abstraction of client-server connection from the client's view |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public abstract class ClientWorldAccess implements Updateable { |
||||
|
||||
public abstract Level getLevel(); |
||||
|
||||
} |
@ -1,64 +0,0 @@ |
||||
package mightypork.rogue.world; |
||||
|
||||
|
||||
import mightypork.rogue.world.map.Level; |
||||
import mightypork.rogue.world.map.TileRenderContext; |
||||
import mightypork.util.constraints.rect.Rect; |
||||
import mightypork.util.constraints.rect.RectConst; |
||||
import mightypork.util.constraints.rect.proxy.RectBound; |
||||
import mightypork.util.constraints.vect.VectConst; |
||||
|
||||
|
||||
public class LevelRenderer { |
||||
|
||||
/** |
||||
* Draw on screen |
||||
* |
||||
* @param viewport rendering area on screen |
||||
* @param xTiles Desired nr of tiles horizontally |
||||
* @param yTiles Desired nr of tiles vertically |
||||
* @param minSize minimum tile size |
||||
*/ |
||||
public static void render(Level level, PlayerEntity player, RectBound viewport, final int yTiles, final int xTiles, final int minSize) |
||||
{ |
||||
final Rect r = viewport.getRect(); |
||||
final double vpH = r.height().value(); |
||||
final double vpW = r.width().value(); |
||||
|
||||
// adjust tile size to fit desired amount of tiles
|
||||
|
||||
final double allowedSizeW = vpW / xTiles; |
||||
final double allowedSizeH = vpH / yTiles; |
||||
int tileSize = (int) Math.round(Math.max(Math.min(allowedSizeH, allowedSizeW), minSize)); |
||||
|
||||
tileSize -= tileSize % 16; |
||||
|
||||
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().getVisualX(); |
||||
final double playerY = player.getPosition().getVisualY(); |
||||
|
||||
// total map area
|
||||
//@formatter:off
|
||||
final RectConst mapRect = vpCenter.startRect().grow( |
||||
playerX*tileSize, |
||||
(level.getWidth() - playerX) * tileSize, |
||||
playerY*tileSize, |
||||
(level.getHeight() - playerY) * tileSize |
||||
).freeze(); |
||||
//@formatter:on
|
||||
|
||||
// tiles to render
|
||||
final int x1 = (int) Math.floor(playerX - (vpW / tileSize)); |
||||
final int y1 = (int) Math.floor(playerY - (vpH / tileSize)); |
||||
final int x2 = (int) Math.ceil(playerX + (vpW / tileSize)); |
||||
final int y2 = (int) Math.ceil(playerY + (vpH / tileSize)); |
||||
|
||||
final TileRenderContext trc = new TileRenderContext(level, mapRect); //-tileSize*0.5
|
||||
for (trc.y = y1; trc.y <= y2; trc.y++) { |
||||
for (trc.x = x1; trc.x <= x2; trc.x++) { |
||||
trc.render(); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,83 +0,0 @@ |
||||
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(); |
||||
} |
||||
} |
@ -0,0 +1,62 @@ |
||||
package mightypork.rogue.world; |
||||
|
||||
|
||||
import java.io.IOException; |
||||
|
||||
import mightypork.util.ion.IonBundle; |
||||
import mightypork.util.ion.IonBundled; |
||||
|
||||
|
||||
public class PlayerInfo implements IonBundled { |
||||
|
||||
private int eid = -1; // marks not initialized
|
||||
private int level; |
||||
|
||||
|
||||
@Override |
||||
public void load(IonBundle bundle) throws IOException |
||||
{ |
||||
eid = bundle.get("attached_eid", 0); |
||||
level = bundle.get("current_level", 0); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void save(IonBundle bundle) throws IOException |
||||
{ |
||||
bundle.put("attached_eid", eid); |
||||
bundle.put("current_level", level); |
||||
} |
||||
|
||||
|
||||
public void setEID(int eid) |
||||
{ |
||||
if (isInitialized()) throw new RuntimeException("Cannot change player EID."); |
||||
this.eid = eid; |
||||
} |
||||
|
||||
|
||||
public void setLevel(int level) |
||||
{ |
||||
this.level = level; |
||||
} |
||||
|
||||
|
||||
public int getEID() |
||||
{ |
||||
return eid; |
||||
} |
||||
|
||||
|
||||
public int getLevel() |
||||
{ |
||||
return level; |
||||
} |
||||
|
||||
|
||||
public boolean isInitialized() |
||||
{ |
||||
return eid != -1; |
||||
} |
||||
|
||||
} |
@ -1,107 +0,0 @@ |
||||
package mightypork.rogue.world; |
||||
|
||||
|
||||
import java.io.IOException; |
||||
import java.util.*; |
||||
|
||||
import mightypork.rogue.world.map.Level; |
||||
import mightypork.util.control.timing.Updateable; |
||||
import mightypork.util.ion.IonBundle; |
||||
import mightypork.util.ion.IonBundled; |
||||
|
||||
|
||||
/** |
||||
* World on a server. To a server, all players and levels are equal. |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public class ServerWorld implements IonBundled, Updateable, WorldAccess { |
||||
|
||||
private final ArrayList<Level> levels = new ArrayList<>(); |
||||
|
||||
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); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void save(IonBundle out) throws IOException |
||||
{ |
||||
out.put("seed", seed); |
||||
out.put("eid", eid); |
||||
out.putSequence("levels", levels); |
||||
out.putMap("players", players); |
||||
} |
||||
|
||||
|
||||
public void addLevel(Level level) |
||||
{ |
||||
levels.add(level); |
||||
} |
||||
|
||||
public void addPlayer(String name, PlayerEntity player) |
||||
{ |
||||
players.put(name, player); |
||||
} |
||||
|
||||
public void removePlayer(String name) |
||||
{ |
||||
players.remove(name); |
||||
} |
||||
|
||||
@Override |
||||
public void update(double delta) |
||||
{ |
||||
Set<Integer> occupiedLevels = new HashSet<>(); |
||||
|
||||
// food meters and such
|
||||
for (final PlayerEntity pl : players.values()) { |
||||
if(pl.isConnected()) { |
||||
pl.updateLogic(this, delta); |
||||
occupiedLevels.add(pl.getPosition().floor); |
||||
} |
||||
} |
||||
|
||||
for(int i : occupiedLevels) { |
||||
levels.get(i).updateLogic(this, delta); |
||||
} |
||||
} |
||||
|
||||
|
||||
public void setSeed(long seed) |
||||
{ |
||||
this.seed = seed; |
||||
} |
||||
|
||||
|
||||
public long getSeed() |
||||
{ |
||||
return seed; |
||||
} |
||||
|
||||
|
||||
public long generateEntityId() |
||||
{ |
||||
return eid++; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isServer() |
||||
{ |
||||
return true; |
||||
} |
||||
} |
@ -0,0 +1,121 @@ |
||||
package mightypork.rogue.world; |
||||
|
||||
|
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
|
||||
import mightypork.rogue.world.entity.Entities; |
||||
import mightypork.rogue.world.entity.Entity; |
||||
import mightypork.rogue.world.level.Level; |
||||
import mightypork.util.constraints.rect.proxy.RectBound; |
||||
import mightypork.util.control.timing.Updateable; |
||||
import mightypork.util.ion.IonBundle; |
||||
import mightypork.util.ion.IonBundled; |
||||
|
||||
|
||||
/** |
||||
* World on a server. To a server, all players and levels are equal. |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public class World implements IonBundled, Updateable { |
||||
|
||||
private final ArrayList<Level> levels = new ArrayList<>(); |
||||
|
||||
private final PlayerInfo player = new PlayerInfo(); |
||||
|
||||
private long seed; // world seed
|
||||
private int eid; // next entity ID
|
||||
|
||||
|
||||
@Override |
||||
public void load(IonBundle in) throws IOException |
||||
{ |
||||
seed = in.get("seed", 0L); |
||||
eid = in.get("next_eid", 0); |
||||
in.loadSequence("levels", levels); |
||||
in.loadBundled("player", player); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void save(IonBundle out) throws IOException |
||||
{ |
||||
out.put("seed", seed); |
||||
out.put("next_eid", eid); |
||||
out.putSequence("levels", levels); |
||||
out.putBundled("player", player); |
||||
} |
||||
|
||||
|
||||
public void addLevel(Level level) |
||||
{ |
||||
levels.add(level); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void update(double delta) |
||||
{ |
||||
getCurrentLevel().update(delta); |
||||
} |
||||
|
||||
|
||||
public void setSeed(long seed) |
||||
{ |
||||
this.seed = seed; |
||||
} |
||||
|
||||
|
||||
public long getSeed() |
||||
{ |
||||
return seed; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @return new entity ID |
||||
*/ |
||||
public int getNewEID() |
||||
{ |
||||
return eid++; |
||||
} |
||||
|
||||
|
||||
public void createPlayer(int x, int y, int level) |
||||
{ |
||||
if (player.isInitialized()) { |
||||
throw new RuntimeException("Player already created."); |
||||
} |
||||
|
||||
// make entity
|
||||
int playerEid = getNewEID(); |
||||
|
||||
final Entity entity = Entities.PLAYER.createEntity(playerEid, new WorldPos(x, y)); |
||||
|
||||
player.setLevel(level); |
||||
player.setEID(playerEid); |
||||
|
||||
levels.get(level).addEntity(entity); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Draw on screen |
||||
* |
||||
* @param viewport rendering area on screen |
||||
* @param xTiles Desired nr of tiles horizontally |
||||
* @param yTiles Desired nr of tiles vertically |
||||
* @param minSize minimum tile size |
||||
*/ |
||||
public void render(RectBound viewport, final int yTiles, final int xTiles, final int minSize) |
||||
{ |
||||
getCurrentLevel().render(player, viewport, yTiles, xTiles, minSize); |
||||
} |
||||
|
||||
|
||||
public Level getCurrentLevel() |
||||
{ |
||||
return levels.get(player.getLevel()); |
||||
} |
||||
} |
@ -1,8 +0,0 @@ |
||||
package mightypork.rogue.world; |
||||
|
||||
|
||||
public interface WorldAccess { |
||||
|
||||
public boolean isServer(); |
||||
|
||||
} |
@ -1,143 +0,0 @@ |
||||
package mightypork.rogue.world; |
||||
|
||||
|
||||
import java.io.IOException; |
||||
import java.util.LinkedList; |
||||
import java.util.Queue; |
||||
|
||||
import mightypork.util.ion.IonBundle; |
||||
import mightypork.util.ion.IonBundled; |
||||
|
||||
|
||||
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.generateEntityId(); |
||||
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; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,44 @@ |
||||
package mightypork.rogue.world.entity; |
||||
|
||||
|
||||
import mightypork.rogue.world.entity.models.EntityModel; |
||||
import mightypork.rogue.world.entity.models.PlayerModel; |
||||
|
||||
|
||||
/** |
||||
* Tile registry |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public final class Entities { |
||||
|
||||
private static final EntityModel[] entities = new EntityModel[256]; |
||||
|
||||
public static final EntityModel PLAYER = new PlayerModel(0); |
||||
|
||||
|
||||
public static void register(int id, EntityModel model) |
||||
{ |
||||
if (id < 0 || id >= entities.length) { |
||||
throw new IllegalArgumentException("Entity model ID " + id + " is out of range."); |
||||
} |
||||
|
||||
if (entities[id] != null) { |
||||
throw new IllegalArgumentException("Entity model ID " + id + " already in use."); |
||||
} |
||||
|
||||
entities[id] = model; |
||||
} |
||||
|
||||
|
||||
public static EntityModel get(int id) |
||||
{ |
||||
final EntityModel e = entities[id]; |
||||
|
||||
if (e == null) { |
||||
throw new IllegalArgumentException("No entity model with ID " + id + "."); |
||||
} |
||||
|
||||
return e; |
||||
} |
||||
} |
@ -0,0 +1,192 @@ |
||||
package mightypork.rogue.world.entity; |
||||
|
||||
|
||||
import java.io.IOException; |
||||
import java.util.LinkedList; |
||||
import java.util.Queue; |
||||
|
||||
import mightypork.rogue.world.PathStep; |
||||
import mightypork.rogue.world.World; |
||||
import mightypork.rogue.world.WorldPos; |
||||
import mightypork.rogue.world.entity.models.EntityModel; |
||||
import mightypork.rogue.world.level.Level; |
||||
import mightypork.util.ion.IonBinary; |
||||
import mightypork.util.ion.IonBundle; |
||||
import mightypork.util.ion.IonBundled; |
||||
import mightypork.util.ion.IonInput; |
||||
import mightypork.util.ion.IonOutput; |
||||
|
||||
|
||||
/** |
||||
* World entity (mob or player) |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public final class Entity implements IonBinary, IonBundled { |
||||
|
||||
// binary & bundled - binary stores via a bundle
|
||||
|
||||
public static final int ION_MARK = 52; |
||||
|
||||
private final WorldPos position = new WorldPos(); |
||||
|
||||
/** Entity ID */ |
||||
private int eid = 0; |
||||
|
||||
/** Model ID */ |
||||
private int id; |
||||
|
||||
private final Queue<PathStep> path = new LinkedList<>(); |
||||
private EntityModel model; |
||||
private final IonBundle metadata = new IonBundle(); |
||||
|
||||
|
||||
public Entity(int eid, WorldPos pos, EntityModel entityModel) |
||||
{ |
||||
this.eid = eid; |
||||
this.position.setTo(pos); |
||||
|
||||
setModel(entityModel); |
||||
} |
||||
|
||||
|
||||
private void setModel(EntityModel entityModel) |
||||
{ |
||||
this.id = entityModel.id; |
||||
this.model = entityModel; |
||||
} |
||||
|
||||
|
||||
public Entity() |
||||
{ |
||||
// for ion
|
||||
} |
||||
|
||||
|
||||
@Override |
||||
public short getIonMark() |
||||
{ |
||||
return ION_MARK; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void save(IonOutput out) throws IOException |
||||
{ |
||||
final IonBundle ib = new IonBundle(); |
||||
save(ib); |
||||
out.writeBundle(ib); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void load(IonInput in) throws IOException |
||||
{ |
||||
load(in.readBundle()); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void save(IonBundle bundle) throws IOException |
||||
{ |
||||
bundle.put("id", id); |
||||
bundle.putBundled("pos", position); |
||||
bundle.putSequence("steps", path); |
||||
bundle.put("eid", eid); |
||||
bundle.put("metadata", metadata); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void load(IonBundle bundle) throws IOException |
||||
{ |
||||
id = bundle.get("id", 0); |
||||
|
||||
if (model == null || id != model.id) { |
||||
setModel(Entities.get(id)); |
||||
} |
||||
|
||||
bundle.loadBundled("pos", position); |
||||
bundle.loadSequence("path", path); |
||||
eid = bundle.get("eid", eid); |
||||
|
||||
metadata.clear(); |
||||
bundle.loadBundle("metadata", metadata); |
||||
} |
||||
|
||||
|
||||
public int getEID() |
||||
{ |
||||
return eid; |
||||
} |
||||
|
||||
|
||||
public WorldPos getPosition() |
||||
{ |
||||
return position; |
||||
} |
||||
|
||||
|
||||
public void setPosition(WorldPos pos) |
||||
{ |
||||
position.setTo(pos); |
||||
} |
||||
|
||||
|
||||
public void setPosition(int x, int y) |
||||
{ |
||||
position.setTo(x, y); |
||||
cancelPath(); // discard remaining steps
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* @param world the world |
||||
* @param delta delta time |
||||
*/ |
||||
public void update(World world, Level level, double delta) |
||||
{ |
||||
if (!position.isFinished()) { |
||||
position.update(delta); |
||||
} |
||||
|
||||
if (position.isFinished()) { |
||||
|
||||
model.onStepFinished(this, world, level); |
||||
|
||||
if (!path.isEmpty()) { |
||||
// get next step to walk
|
||||
final PathStep step = path.poll(); |
||||
position.walk(step.x, step.y, getStepTime()); |
||||
} else { |
||||
// notify AI or whatever
|
||||
model.onPathFinished(this, world, level); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
public boolean isPathFinished() |
||||
{ |
||||
return position.isFinished() && path.isEmpty(); |
||||
} |
||||
|
||||
|
||||
public void addStep(PathStep step) |
||||
{ |
||||
path.add(step); |
||||
} |
||||
|
||||
|
||||
public void cancelPath() |
||||
{ |
||||
path.clear(); |
||||
} |
||||
|
||||
|
||||
protected double getStepTime() |
||||
{ |
||||
return model.getStepTime(this); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,71 @@ |
||||
package mightypork.rogue.world.entity.models; |
||||
|
||||
|
||||
import mightypork.rogue.world.World; |
||||
import mightypork.rogue.world.WorldPos; |
||||
import mightypork.rogue.world.entity.Entities; |
||||
import mightypork.rogue.world.entity.Entity; |
||||
import mightypork.rogue.world.entity.renderers.EntityRenderer; |
||||
import mightypork.rogue.world.level.Level; |
||||
|
||||
|
||||
/** |
||||
* Entity model |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public abstract class EntityModel { |
||||
|
||||
/** Model ID */ |
||||
public final int id; |
||||
public EntityRenderer renderer = EntityRenderer.NONE; |
||||
|
||||
|
||||
public EntityModel(int id) |
||||
{ |
||||
Entities.register(id, this); |
||||
this.id = id; |
||||
} |
||||
|
||||
|
||||
public EntityModel setRenderer(EntityRenderer renderer) |
||||
{ |
||||
this.renderer = renderer; |
||||
return this; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @return new tile of this type; if 100% invariant, can return cached one. |
||||
*/ |
||||
public Entity createEntity(int eid, WorldPos pos) |
||||
{ |
||||
return new Entity(eid, pos, this); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Update entity |
||||
*/ |
||||
public abstract void update(Entity entity, Level level, double delta); |
||||
|
||||
|
||||
/** |
||||
* @return true if this entity type has metadata worth saving |
||||
*/ |
||||
public abstract boolean hasMetadata(); |
||||
|
||||
|
||||
/** |
||||
* @param entity the value is valid for |
||||
* @return step time (seconds) |
||||
*/ |
||||
public abstract double getStepTime(Entity entity); |
||||
|
||||
|
||||
public abstract void onStepFinished(Entity entity, World world, Level level); |
||||
|
||||
|
||||
public abstract void onPathFinished(Entity entity, World world, Level level); |
||||
|
||||
} |
@ -0,0 +1,67 @@ |
||||
package mightypork.rogue.world.entity.models; |
||||
|
||||
|
||||
import mightypork.rogue.world.World; |
||||
import mightypork.rogue.world.WorldPos; |
||||
import mightypork.rogue.world.entity.Entity; |
||||
import mightypork.rogue.world.level.Level; |
||||
|
||||
|
||||
/** |
||||
* Player info |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public class PlayerModel extends EntityModel { |
||||
|
||||
private static final double STEP_TIME = 0.3; |
||||
|
||||
|
||||
public PlayerModel(int id) |
||||
{ |
||||
super(id); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public Entity createEntity(int eid, WorldPos pos) |
||||
{ |
||||
final Entity e = super.createEntity(eid, pos); |
||||
|
||||
// set metadata
|
||||
|
||||
return e; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void update(Entity entity, Level level, double delta) |
||||
{ |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public boolean hasMetadata() |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public double getStepTime(Entity entity) |
||||
{ |
||||
return STEP_TIME; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void onStepFinished(Entity entity, World world, Level level) |
||||
{ |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void onPathFinished(Entity entity, World world, Level level) |
||||
{ |
||||
} |
||||
} |
@ -0,0 +1,8 @@ |
||||
package mightypork.rogue.world.entity.renderers; |
||||
|
||||
|
||||
public class EntityRenderer { |
||||
|
||||
public static final EntityRenderer NONE = new NullEntityRenderer(); |
||||
|
||||
} |
@ -0,0 +1,6 @@ |
||||
package mightypork.rogue.world.entity.renderers; |
||||
|
||||
|
||||
public class NullEntityRenderer extends EntityRenderer { |
||||
|
||||
} |
@ -0,0 +1,330 @@ |
||||
package mightypork.rogue.world.level; |
||||
|
||||
|
||||
import java.io.IOException; |
||||
import java.util.HashMap; |
||||
import java.util.HashSet; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
import org.lwjgl.opengl.GL11; |
||||
|
||||
import mightypork.gamecore.render.Render; |
||||
import mightypork.rogue.Res; |
||||
import mightypork.rogue.world.PlayerInfo; |
||||
import mightypork.rogue.world.WorldPos; |
||||
import mightypork.rogue.world.entity.Entity; |
||||
import mightypork.rogue.world.level.render.TileRenderContext; |
||||
import mightypork.rogue.world.tile.Tile; |
||||
import mightypork.rogue.world.tile.Tiles; |
||||
import mightypork.rogue.world.tile.models.TileModel; |
||||
import mightypork.util.constraints.rect.Rect; |
||||
import mightypork.util.constraints.rect.RectConst; |
||||
import mightypork.util.constraints.rect.proxy.RectBound; |
||||
import mightypork.util.constraints.vect.VectConst; |
||||
import mightypork.util.ion.IonBinary; |
||||
import mightypork.util.ion.IonBundle; |
||||
import mightypork.util.ion.IonInput; |
||||
import mightypork.util.ion.IonOutput; |
||||
import mightypork.util.math.noise.NoiseGen; |
||||
|
||||
|
||||
/** |
||||
* One level of the dungeon |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public class Level implements MapAccess, IonBinary { |
||||
|
||||
public static final int ION_MARK = 53; |
||||
|
||||
private static final boolean USE_BATCH_RENDERING = true; |
||||
|
||||
private int width, height; |
||||
|
||||
/** Array of tiles [y][x] */ |
||||
private Tile[][] tiles; |
||||
|
||||
private final Map<Integer, Entity> entity_map = new HashMap<>(); |
||||
private final Set<Entity> entity_set = new HashSet<>(); |
||||
|
||||
/** Level seed (used for generation and tile variation) */ |
||||
public long seed; |
||||
|
||||
private transient NoiseGen noiseGen; |
||||
|
||||
|
||||
public Level() |
||||
{ |
||||
} |
||||
|
||||
|
||||
public Level(int width, int height) |
||||
{ |
||||
this.width = width; |
||||
this.height = height; |
||||
buildArray(); |
||||
} |
||||
|
||||
|
||||
private void buildArray() |
||||
{ |
||||
this.tiles = new Tile[height][width]; |
||||
} |
||||
|
||||
|
||||
public void fill(short id) |
||||
{ |
||||
fill(Tiles.get(id)); |
||||
} |
||||
|
||||
|
||||
public void fill(TileModel model) |
||||
{ |
||||
for (int y = 0; y < height; y++) { |
||||
for (int x = 0; x < width; x++) { |
||||
tiles[y][x] = model.createTile(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public final Tile getTile(int x, int y) |
||||
{ |
||||
if (x < 0 || x >= width || y < 0 || y >= height) return Tiles.NULL_SOLID.createTile(); // out of range
|
||||
|
||||
return tiles[y][x]; |
||||
} |
||||
|
||||
|
||||
public final void setTile(TileModel model, int x, int y) |
||||
{ |
||||
setTile(model.createTile(), x, y); |
||||
} |
||||
|
||||
|
||||
public final void setTile(int tileId, int x, int y) |
||||
{ |
||||
setTile(new Tile(tileId), x, y); |
||||
} |
||||
|
||||
|
||||
public final void setTile(Tile tile, int x, int y) |
||||
{ |
||||
if (x < 0 || x > width || y < 0 || y >= height) return; // out of range
|
||||
|
||||
tiles[y][x] = tile; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public final int getWidth() |
||||
{ |
||||
return width; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public final int getHeight() |
||||
{ |
||||
return height; |
||||
} |
||||
|
||||
|
||||
public void setSeed(long seed) |
||||
{ |
||||
this.seed = seed; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public long getSeed() |
||||
{ |
||||
return seed; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void load(IonInput in) throws IOException |
||||
{ |
||||
// metadata
|
||||
final IonBundle ib = in.readBundle(); |
||||
seed = ib.get("seed", 0L); |
||||
width = ib.get("w", 0); |
||||
height = ib.get("h", 0); |
||||
|
||||
ib.loadSequence("entities", entity_set); |
||||
for (final Entity ent : entity_set) { |
||||
entity_map.put(ent.getEID(), ent); |
||||
} |
||||
|
||||
// init array of size
|
||||
buildArray(); |
||||
|
||||
// load tiles
|
||||
for (int y = 0; y < height; y++) { |
||||
for (int x = 0; x < width; x++) { |
||||
// no mark
|
||||
tiles[y][x] = new Tile(); |
||||
tiles[y][x].load(in); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void save(IonOutput out) throws IOException |
||||
{ |
||||
// metadata
|
||||
final IonBundle ib = new IonBundle(); |
||||
ib.put("seed", seed); |
||||
ib.put("w", width); |
||||
ib.put("h", height); |
||||
ib.putSequence("entities", entity_set); |
||||
out.writeBundle(ib); |
||||
|
||||
// tiles (writing this way to save space)
|
||||
for (int y = 0; y < height; y++) { |
||||
for (int x = 0; x < width; x++) { |
||||
// no mark to save space
|
||||
tiles[y][x].save(out); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public short getIonMark() |
||||
{ |
||||
return ION_MARK; |
||||
} |
||||
|
||||
|
||||
public void update(double delta) |
||||
{ |
||||
// just update them all
|
||||
for (int y = 0; y < height; y++) { |
||||
for (int x = 0; x < width; x++) { |
||||
getTile(x, y).update(this, delta); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public NoiseGen getNoiseGen() |
||||
{ |
||||
if (noiseGen == null) { |
||||
noiseGen = new NoiseGen(0.2, 0, 0.5, 1, seed); |
||||
} |
||||
|
||||
return noiseGen; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Draw on screen |
||||
* |
||||
* @param playerInfo layer |
||||
* @param viewport rendering area on screen |
||||
* @param xTiles Desired nr of tiles horizontally |
||||
* @param yTiles Desired nr of tiles vertically |
||||
* @param minSize minimum tile size |
||||
*/ |
||||
public void render(PlayerInfo playerInfo, RectBound viewport, final int yTiles, final int xTiles, final int minSize) |
||||
{ |
||||
final WorldPos pos; |
||||
|
||||
try { |
||||
pos = getEntity(playerInfo.getEID()).getPosition(); |
||||
} catch (NullPointerException e) { |
||||
throw new RuntimeException("Player entity not found in level.", e); |
||||
} |
||||
|
||||
final Rect r = viewport.getRect(); |
||||
final double vpH = r.height().value(); |
||||
final double vpW = r.width().value(); |
||||
|
||||
// adjust tile size to fit desired amount of tiles
|
||||
|
||||
final double allowedSizeW = vpW / xTiles; |
||||
final double allowedSizeH = vpH / yTiles; |
||||
int tileSize = (int) Math.round(Math.max(Math.min(allowedSizeH, allowedSizeW), minSize)); |
||||
|
||||
tileSize -= tileSize % 16; |
||||
|
||||
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 = pos.getVisualX(); |
||||
final double playerY = pos.getVisualY(); |
||||
|
||||
// total map area
|
||||
//@formatter:off
|
||||
final RectConst mapRect = vpCenter.startRect().grow( |
||||
playerX*tileSize, |
||||
(getWidth() - playerX) * tileSize, |
||||
playerY*tileSize, |
||||
(getHeight() - playerY) * tileSize |
||||
).freeze(); |
||||
//@formatter:on
|
||||
|
||||
// tiles to render
|
||||
final int x1 = (int) Math.floor(playerX - (vpW / tileSize / 2)); |
||||
|
||||
final int y1 = (int) Math.floor(playerY - (vpH / tileSize / 2)); |
||||
final int x2 = (int) Math.ceil(playerX + (vpW / tileSize / 2)); |
||||
final int y2 = (int) Math.ceil(playerY + (vpH / tileSize / 2)); |
||||
|
||||
final TileRenderContext trc = new TileRenderContext(this, mapRect); //-tileSize*0.5
|
||||
|
||||
// batch rendering of the tiles
|
||||
if (USE_BATCH_RENDERING) { |
||||
Render.enterBatchTexturedQuadMode(Res.getTexture("tiles")); |
||||
} |
||||
|
||||
for (trc.y = y1; trc.y <= y2; trc.y++) { |
||||
for (trc.x = x1; trc.x <= x2; trc.x++) { |
||||
trc.renderTile(); |
||||
} |
||||
} |
||||
|
||||
if (USE_BATCH_RENDERING) { |
||||
Render.leaveBatchTexturedQuadMode(); |
||||
} |
||||
|
||||
// render extras
|
||||
for (trc.y = y1; trc.y <= y2; trc.y++) { |
||||
for (trc.x = x1; trc.x <= x2; trc.x++) { |
||||
trc.renderItems(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
public Entity getEntity(int eid) |
||||
{ |
||||
return entity_map.get(eid); |
||||
} |
||||
|
||||
|
||||
public void addEntity(Entity entity) |
||||
{ |
||||
entity_map.put(entity.getEID(), entity); |
||||
entity_set.add(entity); |
||||
} |
||||
|
||||
|
||||
public void removeEntity(Entity entity) |
||||
{ |
||||
entity_map.remove(entity.getEID()); |
||||
entity_set.remove(entity); |
||||
} |
||||
|
||||
|
||||
public void removeEntity(int eid) |
||||
{ |
||||
final Entity removed = entity_map.remove(eid); |
||||
entity_set.remove(removed); |
||||
} |
||||
} |
@ -1,4 +1,4 @@ |
||||
package mightypork.rogue.world.map; |
||||
package mightypork.rogue.world.level; |
||||
|
||||
|
||||
import mightypork.rogue.world.tile.Tile; |
@ -1,6 +1,7 @@ |
||||
package mightypork.rogue.world.map; |
||||
package mightypork.rogue.world.level.render; |
||||
|
||||
|
||||
import mightypork.rogue.world.level.MapAccess; |
||||
import mightypork.util.constraints.rect.Rect; |
||||
|
||||
|
@ -1,6 +1,7 @@ |
||||
package mightypork.rogue.world.map; |
||||
package mightypork.rogue.world.level.render; |
||||
|
||||
|
||||
import mightypork.rogue.world.level.MapAccess; |
||||
import mightypork.util.constraints.rect.Rect; |
||||
import mightypork.util.constraints.rect.builders.TiledRect; |
||||
|
@ -1,248 +0,0 @@ |
||||
package mightypork.rogue.world.map; |
||||
|
||||
|
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
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; |
||||
import mightypork.rogue.world.tile.Tiles; |
||||
import mightypork.util.ion.IonBinary; |
||||
import mightypork.util.ion.IonBundle; |
||||
import mightypork.util.ion.IonInput; |
||||
import mightypork.util.ion.IonOutput; |
||||
import mightypork.util.math.noise.NoiseGen; |
||||
|
||||
|
||||
/** |
||||
* One level of the dungeon |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public class Level implements MapAccess, IonBinary { |
||||
|
||||
public static final int ION_MARK = 53; |
||||
|
||||
private int width, height; |
||||
|
||||
/** 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(int width, int height) |
||||
{ |
||||
this.width = width; |
||||
this.height = height; |
||||
buildArray(); |
||||
} |
||||
|
||||
|
||||
private void buildArray() |
||||
{ |
||||
this.tiles = new Tile[height][width]; |
||||
} |
||||
|
||||
|
||||
public void fill(short id) |
||||
{ |
||||
fill(Tiles.get(id)); |
||||
} |
||||
|
||||
|
||||
public void fill(TileModel model) |
||||
{ |
||||
for (int y = 0; y < height; y++) { |
||||
for (int x = 0; x < width; x++) { |
||||
tiles[y][x] = model.createTile(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public final Tile getTile(int x, int y) |
||||
{ |
||||
if (x < 0 || x >= width || y < 0 || y >= height) return Tiles.NULL_SOLID.createTile(); // out of range
|
||||
|
||||
return tiles[y][x]; |
||||
} |
||||
|
||||
|
||||
public final void setTile(TileModel model, int x, int y) |
||||
{ |
||||
setTile(model.createTile(), x, y); |
||||
} |
||||
|
||||
|
||||
public final void setTile(int tileId, int x, int y) |
||||
{ |
||||
setTile(new Tile(tileId), x, y); |
||||
} |
||||
|
||||
|
||||
public final void setTile(Tile tile, int x, int y) |
||||
{ |
||||
if (x < 0 || x > width || y < 0 || y >= height) return; // out of range
|
||||
|
||||
tiles[y][x] = tile; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public final int getWidth() |
||||
{ |
||||
return width; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public final int getHeight() |
||||
{ |
||||
return height; |
||||
} |
||||
|
||||
|
||||
public void setSeed(long seed) |
||||
{ |
||||
this.seed = seed; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public long getSeed() |
||||
{ |
||||
return seed; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void load(IonInput in) throws IOException |
||||
{ |
||||
// metadata
|
||||
final IonBundle ib = in.readBundle(); |
||||
seed = ib.get("seed", 0L); |
||||
width = ib.get("w", 0); |
||||
height = ib.get("h", 0); |
||||
|
||||
ib.loadSequence("entities", entities); |
||||
|
||||
// init array of size
|
||||
buildArray(); |
||||
|
||||
// load tiles
|
||||
for (int y = 0; y < height; y++) { |
||||
for (int x = 0; x < width; x++) { |
||||
// no mark
|
||||
tiles[y][x] = new Tile(); |
||||
tiles[y][x].load(in); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void save(IonOutput out) throws IOException |
||||
{ |
||||
// metadata
|
||||
final IonBundle ib = new IonBundle(); |
||||
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)
|
||||
for (int y = 0; y < height; y++) { |
||||
for (int x = 0; x < width; x++) { |
||||
// no mark to save space
|
||||
tiles[y][x].save(out); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public short getIonMark() |
||||
{ |
||||
return ION_MARK; |
||||
} |
||||
|
||||
|
||||
public void updateLogic(WorldAccess world, double delta) |
||||
{ |
||||
if (!world.isServer()) { |
||||
throw new RuntimeException("Not allowed for client."); |
||||
} |
||||
|
||||
// just update them all
|
||||
for (int y = 0; y < height; y++) { |
||||
for (int x = 0; x < width; x++) { |
||||
getTile(x, y).updateLogic(world, this, delta); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Update visuals for player (particle effects etc) |
||||
* |
||||
* @param world |
||||
* @param player |
||||
* @param delta |
||||
*/ |
||||
public void updateVisual(WorldAccess world, PlayerEntity player, double delta) |
||||
{ |
||||
if (world.isServer()) { |
||||
throw new RuntimeException("Not allowed for server."); |
||||
} |
||||
|
||||
final int viewRange = player.getViewRange(); |
||||
final WorldPos eyepos = player.getViewPosition(); |
||||
|
||||
int x1 = eyepos.x - viewRange; |
||||
int y1 = eyepos.y - viewRange; |
||||
|
||||
int x2 = x1 + viewRange * 2; |
||||
int y2 = y1 + viewRange * 2; |
||||
|
||||
x1 = Math.min(Math.max(0, x1), width); |
||||
y1 = Math.min(Math.max(0, y1), height); |
||||
x2 = Math.min(x2, width); |
||||
y2 = Math.max(y2, height); |
||||
|
||||
for (int y = y1; y <= y2; y++) { |
||||
for (int x = x1; x <= x2; x++) { |
||||
getTile(x, y).updateVisual(world, this, delta); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public NoiseGen getNoiseGen() |
||||
{ |
||||
if (noiseGen == null) { |
||||
noiseGen = new NoiseGen(0.2, 0, 0.5, 1, seed); |
||||
} |
||||
|
||||
return noiseGen; |
||||
} |
||||
|
||||
} |
@ -1,13 +0,0 @@ |
||||
package mightypork.rogue.world.map; |
||||
|
||||
|
||||
import mightypork.rogue.world.WorldPos; |
||||
|
||||
|
||||
public interface MapObserver { |
||||
|
||||
int getViewRange(); |
||||
|
||||
|
||||
WorldPos getViewPosition(); |
||||
} |
@ -1,9 +1,9 @@ |
||||
package mightypork.rogue.world.tile; |
||||
package mightypork.rogue.world.tile.renderers; |
||||
|
||||
|
||||
import mightypork.rogue.world.item.Item; |
||||
import mightypork.rogue.world.map.TileRenderContext; |
||||
import mightypork.rogue.world.tile.renderers.NullTileRenderer; |
||||
import mightypork.rogue.world.level.render.TileRenderContext; |
||||
import mightypork.rogue.world.tile.DroppedItemRenderer; |
||||
|
||||
|
||||
/** |
Loading…
Reference in new issue