Start of world generator
This commit is contained in:
@@ -31,7 +31,7 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL
|
||||
public MapView(World world)
|
||||
{
|
||||
this.world = world;
|
||||
this.worldRenderer = new WorldRenderer(world, this, 8, 6, 72);
|
||||
this.worldRenderer = new WorldRenderer(world, this, 8, 8, 64);
|
||||
pc = world.getPlayerControl();
|
||||
pc.addMoveListener(this);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package mightypork.rogue.world;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import mightypork.rogue.world.gen.LevelGenerator;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.rogue.world.tile.Tiles;
|
||||
import mightypork.rogue.world.tile.models.TileModel;
|
||||
@@ -21,33 +22,15 @@ public class MapGenerator {
|
||||
final World w = new World();
|
||||
w.setSeed(seed);
|
||||
|
||||
w.addLevel(createLevel(rand.nextLong(), Tiles.FLOOR_DARK, Tiles.WALL_BRICK));
|
||||
//w.addLevel(createLevel(rand.nextLong(), Tiles.BRCOBBLE_FLOOR, Tiles.BRCOBBLE_WALL));
|
||||
Level l;
|
||||
|
||||
// first level
|
||||
l = LevelGenerator.build(rand.nextLong(), LevelGenerator.DUNGEON_THEME);
|
||||
w.addLevel(l);
|
||||
w.createPlayer(l.getEnterPoint(), 0);
|
||||
|
||||
// TODO place on start position
|
||||
w.createPlayer(10, 10, 0);
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Level createLevel(long seed, TileModel floor, TileModel wall)
|
||||
{
|
||||
// TODO
|
||||
|
||||
final Level lm = new Level(20, 20);
|
||||
lm.setSeed(seed);
|
||||
|
||||
lm.fill(floor);
|
||||
|
||||
final Random rand = new Random();
|
||||
rand.setSeed(seed);
|
||||
|
||||
for (int i = 0; i < 150; i++) {
|
||||
lm.setTile(wall, rand.nextInt(20), rand.nextInt(20));
|
||||
}
|
||||
|
||||
return lm;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -86,6 +86,11 @@ public class World implements IonBundled, Updateable {
|
||||
}
|
||||
|
||||
|
||||
public void createPlayer(WorldPos pos, int level)
|
||||
{
|
||||
createPlayer(pos.x, pos.y, level);
|
||||
}
|
||||
|
||||
public void createPlayer(int x, int y, int level)
|
||||
{
|
||||
if (playerInfo.isInitialized()) {
|
||||
@@ -120,4 +125,5 @@ public class World implements IonBundled, Updateable {
|
||||
{
|
||||
return playerEntity;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -107,6 +107,11 @@ public class WorldPos implements IonBundled, Updateable {
|
||||
setTo(other.x, other.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "WorldPos("+x+","+y+")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package mightypork.rogue.world.gen;
|
||||
|
||||
|
||||
import mightypork.util.annotations.FactoryMethod;
|
||||
|
||||
|
||||
// coord
|
||||
public class Coord {
|
||||
|
||||
public int x;
|
||||
public int y;
|
||||
|
||||
|
||||
@FactoryMethod
|
||||
public static Coord make(int x, int y)
|
||||
{
|
||||
return new Coord(x, y);
|
||||
}
|
||||
|
||||
@FactoryMethod
|
||||
public static Coord make(Coord other)
|
||||
{
|
||||
return new Coord(other);
|
||||
}
|
||||
|
||||
public Coord(int x, int y)
|
||||
{
|
||||
super();
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
|
||||
public Coord(Coord other)
|
||||
{
|
||||
this.x = other.x;
|
||||
this.y = other.y;
|
||||
}
|
||||
|
||||
|
||||
public Coord add(int addX, int addY)
|
||||
{
|
||||
return new Coord(x + addX, y + addY);
|
||||
}
|
||||
|
||||
|
||||
public Coord copy()
|
||||
{
|
||||
return make(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Coord("+x+","+y+")";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package mightypork.rogue.world.gen;
|
||||
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.gen.rooms.IntersectionRoom;
|
||||
import mightypork.rogue.world.gen.rooms.SquareRoom;
|
||||
import mightypork.rogue.world.gen.themes.ThemeDungeon;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.rogue.world.tile.Tiles;
|
||||
import mightypork.util.logging.Log;
|
||||
|
||||
|
||||
public class LevelGenerator {
|
||||
|
||||
public static final Theme DUNGEON_THEME = new ThemeDungeon();
|
||||
|
||||
public static final RoomBuilder ROOM_SQUARE = new SquareRoom();
|
||||
public static final RoomBuilder ROOM_INTERSECTION = new IntersectionRoom();
|
||||
|
||||
|
||||
public static Level build(long seed, Theme theme)
|
||||
{
|
||||
Random rand = new Random(seed + 47);
|
||||
|
||||
final int max_size = 500;
|
||||
|
||||
ScratchMap map = new ScratchMap(max_size, theme, rand);
|
||||
|
||||
// start
|
||||
map.addRoom(ROOM_SQUARE);
|
||||
|
||||
for (int i = 0; i < 5+rand.nextInt(4); i++) {
|
||||
map.addRoom(ROOM_SQUARE);
|
||||
for(int j=0;j<4;j++) map.addRoom(ROOM_INTERSECTION);
|
||||
}
|
||||
|
||||
|
||||
Coord size = map.getNeededSize();
|
||||
Level lvl = new Level(size.x, size.y);
|
||||
|
||||
map.writeToLevel(lvl);
|
||||
|
||||
return lvl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package mightypork.rogue.world.gen;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
|
||||
// room builder interface
|
||||
public interface RoomBuilder {
|
||||
|
||||
RoomDesc buildToFit(ScratchMap map, Theme theme, Random rand, Coord center);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package mightypork.rogue.world.gen;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
// room info
|
||||
public class RoomDesc {
|
||||
|
||||
final List<Coord> doors = new ArrayList<>();
|
||||
final Coord min;
|
||||
final Coord max;
|
||||
|
||||
|
||||
public RoomDesc(Coord min, Coord max, List<Coord> doors)
|
||||
{
|
||||
super();
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
|
||||
this.doors.addAll(doors);
|
||||
}
|
||||
|
||||
|
||||
public boolean intersectsWith(Coord amin, Coord amax)
|
||||
{
|
||||
int tw = max.x - min.x;
|
||||
int th = max.y - min.y;
|
||||
int rw = amax.x - amin.x;
|
||||
int rh = amax.y - amin.y;
|
||||
|
||||
if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int tx = min.x;
|
||||
final int ty = min.y;
|
||||
final int rx = amin.x;
|
||||
final int ry = amin.y;
|
||||
|
||||
rw += rx;
|
||||
rh += ry;
|
||||
tw += tx;
|
||||
th += ty;
|
||||
|
||||
return ((rw <= rx || rw >= tx) && (rh <= ry || rh >= ty) && (tw <= tx || tw >= rx) && (th <= ty || th >= ry));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Room [" + min.x + "," + min.y + " .. " + max.x + "," + max.y + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
package mightypork.rogue.world.gen;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.rogue.world.tile.Tiles;
|
||||
import mightypork.rogue.world.tile.models.TileModel;
|
||||
|
||||
|
||||
public class ScratchMap {
|
||||
|
||||
private Tile[][] map;
|
||||
private int width;
|
||||
private int height;
|
||||
|
||||
private List<RoomDesc> rooms = new ArrayList<>();
|
||||
|
||||
Coord genMin;
|
||||
Coord genMax;
|
||||
private Theme theme;
|
||||
private Random rand;
|
||||
private Coord enterPoint;
|
||||
|
||||
|
||||
public ScratchMap(int max_size, Theme theme, Random rand)
|
||||
{
|
||||
map = new Tile[max_size][max_size];
|
||||
|
||||
genMin = Coord.make(max_size / 2, max_size / 2);
|
||||
genMax = genMin.add(1, 1);
|
||||
|
||||
width = max_size;
|
||||
height = max_size;
|
||||
this.rand = rand;
|
||||
this.theme = theme;
|
||||
|
||||
fill(Coord.make(0, 0), Coord.make(width - 1, height - 1), Tiles.NULL_EMPTY);
|
||||
}
|
||||
|
||||
|
||||
public void addRoom(RoomBuilder rb)
|
||||
{
|
||||
Coord center = Coord.make(0, 0);
|
||||
|
||||
int failed = 0;
|
||||
|
||||
while (true) {
|
||||
center.x = genMin.x + rand.nextInt(genMax.x - genMin.x);
|
||||
center.y = genMin.y + rand.nextInt(genMax.y - genMin.y);
|
||||
|
||||
RoomDesc rd = rb.buildToFit(this, theme, rand, center);
|
||||
if (rd != null) {
|
||||
if (rooms.isEmpty()) {
|
||||
enterPoint = center.copy();
|
||||
}
|
||||
|
||||
rooms.add(rd);
|
||||
|
||||
genMin.x = Math.min(genMin.x, rd.min.x);
|
||||
genMin.y = Math.min(genMin.y, rd.min.y);
|
||||
|
||||
genMax.x = Math.max(genMax.x, rd.max.x);
|
||||
genMax.y = Math.max(genMax.y, rd.max.y);
|
||||
|
||||
return;
|
||||
} else {
|
||||
failed++;
|
||||
if (failed % 5 == 0) {
|
||||
switch(rand.nextInt(4)) {
|
||||
case 0: genMin.x--; break;
|
||||
case 1: genMin.y--; break;
|
||||
case 2: genMax.x++; break;
|
||||
case 3: genMax.y++; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (failed > 200) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public boolean isIn(Coord pos)
|
||||
{
|
||||
return pos.x >= 0 && pos.x < width && pos.y >= 0 && pos.y < height;
|
||||
}
|
||||
|
||||
|
||||
public Tile get(Coord pos)
|
||||
{
|
||||
if (!isIn(pos)) {
|
||||
return Tiles.NULL_SOLID.createTile();
|
||||
}
|
||||
|
||||
return map[pos.y][pos.x];
|
||||
}
|
||||
|
||||
|
||||
public boolean set(Coord pos, TileModel tm)
|
||||
{
|
||||
return set(pos, tm.createTile());
|
||||
}
|
||||
|
||||
|
||||
public boolean set(Coord pos, Tile tile)
|
||||
{
|
||||
if (!isIn(pos)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
map[pos.y][pos.x] = tile;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public boolean canBuild(Coord pos)
|
||||
{
|
||||
if (!isIn(pos)) return false;
|
||||
TileModel tm = get(pos).getModel();
|
||||
return tm.isNullTile() && tm.isWalkable();
|
||||
}
|
||||
|
||||
|
||||
public boolean isClear(Coord min, Coord max)
|
||||
{
|
||||
if (!isIn(min)) return false;
|
||||
if (!isIn(max)) return false;
|
||||
|
||||
for (RoomDesc r : rooms) {
|
||||
if (r.intersectsWith(min, max)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void fill(Coord min, Coord max, TileModel tm)
|
||||
{
|
||||
Coord c = Coord.make(0, 0);
|
||||
for (c.y = min.y; c.y <= max.y; c.y++)
|
||||
for (c.x = min.x; c.x <= max.x; c.x++)
|
||||
set(c, tm.createTile());
|
||||
}
|
||||
|
||||
|
||||
public void border(Coord min, Coord max, TileModel tm)
|
||||
{
|
||||
Coord c = Coord.make(0, 0);
|
||||
for (c.y = min.y; c.y <= max.y; c.y++) {
|
||||
for (c.x = min.x; c.x <= max.x; c.x++) {
|
||||
|
||||
if (c.y > min.y && c.y < max.y && c.x > min.x && c.x < max.x) continue;
|
||||
|
||||
set(c, tm.createTile());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Coord getNeededSize()
|
||||
{
|
||||
return Coord.make(genMax.x - genMin.x + 1, genMax.y - genMin.y + 1);
|
||||
}
|
||||
|
||||
|
||||
public void writeToLevel(Level level)
|
||||
{
|
||||
|
||||
Coord c1 = Coord.make(0, 0);
|
||||
Coord c = Coord.make(0, 0);
|
||||
for (c.x = genMin.x, c1.x = 0; c.x <= genMax.x; c.x++, c1.x++) {
|
||||
for (c.y = genMin.y, c1.y = 0; c.y <= genMax.y; c.y++, c1.y++) {
|
||||
level.setTile(get(c), c1.x, c1.y);
|
||||
}
|
||||
}
|
||||
|
||||
WorldPos p = new WorldPos(enterPoint.x - genMin.x, enterPoint.y - genMin.y);
|
||||
level.setEnterPoint(p);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package mightypork.rogue.world.gen;
|
||||
|
||||
import mightypork.rogue.world.tile.models.TileModel;
|
||||
|
||||
// map theme
|
||||
public interface Theme {
|
||||
|
||||
TileModel wall();
|
||||
|
||||
|
||||
TileModel floor();
|
||||
|
||||
|
||||
TileModel door();
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package mightypork.rogue.world.gen.rooms;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import mightypork.rogue.world.gen.Coord;
|
||||
import mightypork.rogue.world.gen.RoomBuilder;
|
||||
import mightypork.rogue.world.gen.RoomDesc;
|
||||
import mightypork.rogue.world.gen.Theme;
|
||||
import mightypork.rogue.world.gen.ScratchMap;
|
||||
|
||||
|
||||
public class IntersectionRoom extends SquareRoom {
|
||||
|
||||
@Override
|
||||
protected int getMinHalfSide()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected int getMaxHalfSide()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
protected int[] getDoorTypes()
|
||||
{
|
||||
//@formatter:off
|
||||
return new int[] {
|
||||
// dead ends
|
||||
0b1000,0b0100,0b0010,0b0001,
|
||||
|
||||
// corridor pieces
|
||||
0b0011, 0b0101, 0b0110, 0b1010, 0b1100, 0b1001,
|
||||
|
||||
// crossings
|
||||
0b0111, 0b1101, 0b1011, 0b1110, 0b1111,
|
||||
|
||||
// repeat to get more
|
||||
0b0111, 0b1101, 0b1011, 0b1110, 0b1111,
|
||||
};
|
||||
//@formatter:on
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package mightypork.rogue.world.gen.rooms;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import mightypork.rogue.world.gen.Coord;
|
||||
import mightypork.rogue.world.gen.RoomBuilder;
|
||||
import mightypork.rogue.world.gen.RoomDesc;
|
||||
import mightypork.rogue.world.gen.Theme;
|
||||
import mightypork.rogue.world.gen.ScratchMap;
|
||||
|
||||
|
||||
public class SquareRoom implements RoomBuilder {
|
||||
|
||||
@Override
|
||||
public RoomDesc buildToFit(ScratchMap map, Theme theme, Random rand, Coord center)
|
||||
{
|
||||
int hside = getMinHalfSide();
|
||||
if (getMaxHalfSide() > getMinHalfSide()) hside += rand.nextInt(getMaxHalfSide() - getMinHalfSide());
|
||||
|
||||
Coord min = new Coord(center.x - hside, center.y - hside);
|
||||
Coord max = new Coord(center.x + hside, center.y + hside);
|
||||
|
||||
for (;; hside--) {
|
||||
if (hside < getMinHalfSide()) return null;
|
||||
if (map.isClear(min, max)) break;
|
||||
}
|
||||
|
||||
map.fill(min, max, theme.floor());
|
||||
map.border(min, max, theme.wall());
|
||||
|
||||
List<Coord> doors = new ArrayList<>();
|
||||
|
||||
int door_types[] = getDoorTypes();
|
||||
|
||||
int drs = door_types[rand.nextInt(door_types.length)];
|
||||
|
||||
Coord door;
|
||||
|
||||
if ((drs & 1) != 0) {
|
||||
door = min.add(hside, 0);
|
||||
map.set(door, theme.door());
|
||||
doors.add(door);
|
||||
}
|
||||
|
||||
if ((drs & 2) != 0) {
|
||||
door = max.add(-hside, 0);
|
||||
map.set(door, theme.door());
|
||||
}
|
||||
|
||||
if ((drs & 4) != 0) {
|
||||
door = min.add(0, hside);
|
||||
map.set(door, theme.door());
|
||||
}
|
||||
|
||||
if ((drs & 8) != 0) {
|
||||
door = max.add(0, -hside);
|
||||
map.set(door, theme.door());
|
||||
}
|
||||
|
||||
return new RoomDesc(min.add(-1, -1), max.add(1, 1), doors);
|
||||
}
|
||||
|
||||
|
||||
protected int[] getDoorTypes()
|
||||
{
|
||||
//@formatter:off
|
||||
return new int[] {
|
||||
// one
|
||||
0b0001, 0b0010, 0b0100, 0b1000,
|
||||
|
||||
// two
|
||||
0b0011, 0b0101, 0b0110, 0b1010, 0b1100, 0b1001,
|
||||
0b0011, 0b0101, 0b0110, 0b1010, 0b1100, 0b1001,
|
||||
|
||||
//three+four
|
||||
0b0111, 0b1101, 0b1011, 0b1110, 0b1111,
|
||||
0b0111, 0b1101, 0b1011, 0b1110, 0b1111,
|
||||
0b0111, 0b1101, 0b1011, 0b1110, 0b1111
|
||||
};
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
|
||||
protected int getMinHalfSide()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
protected int getMaxHalfSide()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package mightypork.rogue.world.gen.themes;
|
||||
|
||||
import mightypork.rogue.world.gen.Theme;
|
||||
import mightypork.rogue.world.tile.Tiles;
|
||||
import mightypork.rogue.world.tile.models.TileModel;
|
||||
|
||||
// basic dungeon theme
|
||||
public class ThemeDungeon implements Theme {
|
||||
|
||||
@Override
|
||||
public TileModel wall()
|
||||
{
|
||||
return Tiles.WALL_BRICK;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TileModel floor()
|
||||
{
|
||||
return Tiles.FLOOR_DARK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileModel door()
|
||||
{
|
||||
return floor(); // TODO
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.rogue.world.tile.Tiles;
|
||||
@@ -31,6 +32,8 @@ public class Level implements MapAccess, IonBinary {
|
||||
|
||||
private int width, height;
|
||||
|
||||
private WorldPos enterPoint;
|
||||
|
||||
/** Array of tiles [y][x] */
|
||||
private Tile[][] tiles;
|
||||
|
||||
@@ -278,4 +281,16 @@ public class Level implements MapAccess, IonBinary {
|
||||
{
|
||||
return entity_set;
|
||||
}
|
||||
|
||||
|
||||
public void setEnterPoint(WorldPos enterPoint)
|
||||
{
|
||||
this.enterPoint = enterPoint;
|
||||
}
|
||||
|
||||
|
||||
public WorldPos getEnterPoint()
|
||||
{
|
||||
return enterPoint;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,10 @@ public final class Tiles {
|
||||
|
||||
public static final TileModel NULL_SOLID = new NullWall(0);
|
||||
public static final TileModel NULL_EMPTY = new NullFloor(1);
|
||||
public static final TileModel NULL_EMPTY_RESERVED = new NullFloor(2);
|
||||
|
||||
public static final TileModel FLOOR_DARK = new Floor(2).setTexture("tile16.floor.dark");
|
||||
public static final TileModel WALL_BRICK = new Wall(3).setTexture("tile16.wall.brick");
|
||||
public static final TileModel FLOOR_DARK = new Floor(10).setTexture("tile16.floor.dark");
|
||||
public static final TileModel WALL_BRICK = new Wall(11).setTexture("tile16.wall.brick");
|
||||
|
||||
|
||||
// public static final TileModel BRICK_FLOOR_VINES = new Floor(2).setTexture("tile.floor.mossy_bricks");
|
||||
|
||||
@@ -59,11 +59,11 @@ public class TiledRect extends RectProxy {
|
||||
public Rect tile(int x, int y)
|
||||
{
|
||||
if (x >= tilesX || x < 0) {
|
||||
throw new IndexOutOfBoundsException("X coordinate out fo range.");
|
||||
throw new IndexOutOfBoundsException("X coordinate out fo range: "+x);
|
||||
}
|
||||
|
||||
if (y >= tilesY || y < 0) {
|
||||
throw new IndexOutOfBoundsException("Y coordinate out of range.");
|
||||
throw new IndexOutOfBoundsException("Y coordinate out of range: "+y);
|
||||
}
|
||||
|
||||
return aTile.move(perCol.mul(x), perRow.mul(y));
|
||||
|
||||
Reference in New Issue
Block a user