Первый шаг, который я бы сделал, — создать объекты из чего угодно на уровне вашего домена:
public class Island {
private Point2D center = null;
private int radius = 0;
private List<Deposit> deposits = new ArrayList<Deposit>();
public Island(Point2D center, int radius) {
this.center = center;
this.radius = radius;
}
public void generateDeposits(int numDeposits) {
for (int i = 0; i < numDeposits; i++) {
// TODO: I leave it to you to find an x and y inside the island's
// boundary.
int x = getIntInsideCircle(center, radius);
int y = getIntInsideCircle(center, radius);
if (!depositInLocation(x, y)) {
deposits.add(new StoneDeposit(x, y));
} else {
i--; // TODO: This code could potentially go on forever,
// if we keep generating locations that have been used,
// but I'll leave this for you to handle.
}
}
}
}
public abstract class Deposit {
private Point2D location = null;
public Deposit(Point2D location) {
this.location = location;
}
}
public class StoneDeposit extends Deposit {
// TODO: You can fill this with StoneDeposit specifics.
}
Теперь у нас есть код, который будет генерировать остров со всеми его случайными отложениями. Осталось только разместить эти острова. Я собираюсь сделать это просто и добавить только один на карту, но я уверен, что вы можете понять, как добавить более одного (я оставлю несколько комментариев с моими идеями):
public class Map {
private final int WIDTH = 1000;
private final int HEIGHT = 1000;
private List<Island> islands = new ArrayList<Island>();
public void generate() {
// TODO: If you want to make more, make a for loop.
int radius = 100;
Island island = new Island(new Point2D(WIDTH / 2, HEIGHT / 2), radius);
// TODO: If you are going to add more, then you can't simply add them
// all willy-nilly. You are going to have to check if the islands collide
// and, if they do, find a way to handle that.
// You could let them collide and create a mountain range where they do, or,
// you could try to place the next island in a different position (similar
// to what we used above placing deposits, but both situations require
// code a bit better than what I've included).
islands.add(island);
}
}
Хорошо, теперь у нас есть все необходимые данные. Это подводит нас к финальной точке — рисованию на экране с помощью тайлов. Я не слишком разбираюсь в этом вопросе, так что это может быть неэффективно, но оно должно послужить отправной точкой.
Некоторые функции я обобщил (например, drawTile(int x, int y, тип TileType), потому что я не знаю, как вы рисуете плитки на экране).
// Generate our data.
Map map = new Map();
map.generate();
// Draw to the screen.
// 1. Fill the entire screen with water.
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
drawTile(x, y, Type.WATER);
}
}
// 2. Draw the islands.
// We're going to use this algorithm to draw the circle:
// http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
for (Island island : map.getIslands()) {
int f = 1 - island.getRadius();
int ddF_x = 1;
int ddF_y = -2 * island.getRadius();
int x = 0;
int y = 0;
Point2D center = island.getCenter();
int radius = island.getRadius();
drawTile(center.getX(), center.getY() + radius, TileType.LAND);
drawTile(center.getX(), center.getY() - radius, TileType.LAND);
drawTile(center.getX() + radius, center.getY(), TileType.LAND);
drawTile(center.getX() - radius, center.getY(), TileType.LAND);
while(x < y) {
if(f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
drawTile(center.getX() + x, center.getY() + y, TileType.LAND);
drawTile(center.getX() - x, center.getY() + y, TileType.LAND);
drawTile(center.getX() + x, center.getY() - y, TileType.LAND);
drawTile(center.getX() - x, center.getY() - y, TileType.LAND);
drawTile(center.getX() + y, center.getY() + x, TileType.LAND);
drawTile(center.getX() - y, center.getY() + x, TileType.LAND);
drawTile(center.getX() + y, center.getY() - x, TileType.LAND);
drawTile(center.getX() - y, center.getY() - x, TileType.LAND);
}
// TODO: Now you have to figure out how to fill in the guts of the island.
}
// 3. Draw the deposits.
// TODO: I'll leave this one for you.
Так что в принципе так - это не так уж и плохо.
Вы всегда можете пойти дальше и добавить плитки, которые в основном состоят из воды, но с береговой линией. Для этого вам нужно будет проверить, является ли плитка, которую вы рисуете, краем или углом:
+-+-+-+
|1|2|3|
+-+-+-+
+-+-+-+-+
|4|5|6|7|
+-+-+-+-+
+-+-+-+
|8|9|0|
+-+-+-+
Здесь вы можете видеть 2,9 и 4 — все плитки с краями. 1, 3, 8, 0 — все угловые плитки, а 5 — внутренняя плитка. Когда вы распознаете плитку как угол, вам нужно выбрать все прикрепленные плитки воды и нарисовать их как плитки «побережья»:
+-+-+
| |x|
+-+-+-+-+
|x|1|2|3|
+-+-+-+-+
+-+-+-+-+
|4|5|6|7|
+-+-+-+-+
+-+-+-+
|8|9|0|
+-+-+-+
Там все иксы будут прибрежными тайлами.
Надеюсь, это немного поможет.
person
sdasdadas
schedule
16.12.2012