Commit 97fc3b7e authored by Lucas Delcros's avatar Lucas Delcros

Ajout de RoomBuilder pour la gestion de salles speciales et pour le spawn

Deplacement de methodes vers Surface pour plus de coherence
parent 5e595711
......@@ -21,7 +21,7 @@ public final class MapBuilder implements Serializable{
*
*/
private static final long serialVersionUID = -3440045962055454975L;
private ArrayList<Surface> rooms;
private ArrayList<RoomBuilder> rooms;
private ArrayList<Surface> corridors;
private ArrayList<Surface> doors;
private ArrayList<Entity> entities;
......@@ -36,7 +36,7 @@ public final class MapBuilder implements Serializable{
entities = new ArrayList<Entity>();
}
public void addRoom(Surface room){
public void addRoom(RoomBuilder room){
rooms.add(room);
}
......@@ -67,89 +67,6 @@ public final class MapBuilder implements Serializable{
public void setWidth(int width) {
this.width = width;
}
/**
* Implements Bresenham's algorithm to make a line of walls beetween two nodes;
* @param tilebs
* @param xa
* @param ya
* @param xb
* @param yb
*/
private static void linkNodes(TileBuilder[][] tilebs, int xa, int ya, int xb, int yb){
int d = 0;
int dy = Math.abs(yb - ya), dx = Math.abs(xb - xa), dy2 = (dy << 1), dx2 = (dx << 1);
int ix = xa < xb ? 1 : -1, iy = ya < yb ? 1 : -1;
if (dy <= dx) {
for (;;) {
tilebs[xa][ya].setType(TileType.WALL);
if (xa == xb)
break;
xa += ix;
d += dy2;
if (d > dx) {
ya += iy;
d -= dx2;
}
}
} else {
for (;;) {
tilebs[xa][ya].setType(TileType.WALL);
if (ya == yb)
break;
ya += iy;
d += dx2;
if (d > dy) {
xa += ix;
d -= dy2;
}
}
}
}
/**
* Fills a surface
* @param map
* @param surface
*/
private static void fillSurfaceWith(TileBuilder[][] map, Surface surface, TileType tt){
for (int i = surface.j1; i <= surface.j2; i++) {
for (int j = surface.i1; j <= surface.i2; j++) {
map[i][j].setType(tt);
}
}
}
/**
* Surround a surface with walls
* @param map
* @param surface
*/
private static void surroundSurfaceWithWalls(TileBuilder[][] map, Surface surface){
final int x1 = surface.i1 - 1, x2 = surface.i2 +1;
final int y1 = surface.j1 - 1, y2 = surface.j2 +1;
linkNodes(map, y1, x1, y2, x1);
linkNodes(map, y2, x1, y2, x2);
linkNodes(map, y2, x2, y1, x2);
linkNodes(map, y1, x2, y1, x1);
}
private static void surroundSurfacesWithWalls(TileBuilder[][] map, List<Surface> surfaces){
for (Surface surface: surfaces) {
surroundSurfaceWithWalls(map, surface);
}
}
private void addWaterRandomly (TileBuilder[][] map, Surface room, double p){
Random r = new Random();
if (r.nextDouble() <= p){
int dw = r.nextInt((room.width-2)/2)+1, dh = r.nextInt((room.height-2)/2)+1;
Surface s = new Surface(room.i1+dh, room.j1+dw, room.i2-dh, room.j2-dw);
if(!s.isOnSurface(positionPlayerAtStart) && !s.isOnSurface(stairsPosition))fillSurfaceWith(map, s, TileType.WATER);
else System.out.println("EMP");
}
}
private void generateEntities(TileBuilder[][] tb) {
MapPatterns.read();
int nbRooms=rooms.size();
......@@ -160,8 +77,8 @@ public final class MapBuilder implements Serializable{
}
for(int i=0;i<nbEntities;i++) {
int room=r.nextInt(nbRooms);
int ii=rooms.get(room).i1+r.nextInt(rooms.get(room).height);
int jj=rooms.get(room).j1+r.nextInt(rooms.get(room).width);
int ii=rooms.get(room).getSurface().i1+r.nextInt(rooms.get(room).getSurface().height);
int jj=rooms.get(room).getSurface().j1+r.nextInt(rooms.get(room).getSurface().width);
int posY=ii*Point.TileScale;
int posX=jj*Point.TileScale;
//if(tb[jj][ii].getType() != TileType.WATER) entities.add(SpeciesArray.create(posX,posY,100,"Ronflex","Monster "+i));
......@@ -176,23 +93,28 @@ public final class MapBuilder implements Serializable{
public Map build(){
TileBuilder[][] map = SurfacesMapGeneration.emptyTiles(height, width);
surroundSurfacesWithWalls(map, rooms);
surroundSurfacesWithWalls(map, corridors);
for (Surface room : rooms) {
fillSurfaceWith(map, room, TileType.GROUND);
addWaterRandomly(map, room, 0.2);
for (RoomBuilder room : rooms) {
room.getSurface().surroundWithWalls(map);
}
for (Surface surface: corridors) {
surface.surroundWithWalls(map);
}
for (RoomBuilder room : rooms) {
room.build(map);
}
for (Surface corridor : corridors) {
fillSurfaceWith(map, corridor, TileType.GROUND);
corridor.fillSurfaceWith(map, TileType.GROUND);
}
generateEntities(map);
map[stairsPosition.getI()][stairsPosition.getJ()].setType(TileType.STAIRS);
//TODO uses doors
//Surface[] doors = this.doors.toArray(new Surface[this.doors.size()]);
Surface[] rooms = this.rooms.toArray(new Surface[this.rooms.size()]);
Surface[] rooms = new Surface[this.rooms.size()];
for (int i = 0; i < rooms.length; i++) {
rooms[i] = this.rooms.get(i).getSurface();
}
Surface[] corridors = this.corridors.toArray(new Surface[this.corridors.size()]);
Entity[] entities = this.entities.toArray(new Entity[this.entities.size()]);
return new Map(TileBuilder.buildTiles(map), rooms, corridors/*, doors*/, entities, positionPlayerAtStart, stairsPosition);
......
package map_generation.map;
import java.util.Random;
import map_generation.tiles.TileBuilder;
import map_generation.tiles.TileType;
public final class RoomBuilder {
public static enum RoomType{START, END, NORMAL, TORCHES, LAVA};
private Surface surface;
private RoomType type;
public RoomBuilder(Surface surface, RoomType type) {
this.surface = surface;
this.type = type;
}
public void setType(RoomType type){
this.type = type;
}
public Surface getSurface(){
return surface;
}
private void addLava(TileBuilder[][] map){
Random r = new Random();
int dw = r.nextInt((surface.width-2)/2)+1, dh = r.nextInt((surface.height-2)/2)+1;
Surface s = new Surface(surface.i1+dh, surface.j1+dw, surface.i2-dh, surface.j2-dw);
s.fillSurfaceWith(map, TileType.WATER);
}
public void setRandomlySpecial(double p){
Random r = new Random();
if(r.nextDouble() <= p){
if(r.nextDouble() <= 0.5) setType(RoomType.LAVA);
else setType(RoomType.TORCHES);
}
}
public void build(TileBuilder[][] map){
surface.fillSurfaceWith(map, TileType.GROUND);
switch (type){
case LAVA :
addLava(map);
break;
default :
}
}
}
......@@ -2,6 +2,9 @@ package map_generation.map;
import java.io.Serializable;
import map_generation.tiles.TileBuilder;
import map_generation.tiles.TileType;
public class Surface implements Serializable{
/**
*
......@@ -25,4 +28,71 @@ public class Surface implements Serializable{
public boolean isOnSurface(MapPoint mp){
return mp.getI() >= i1 && mp.getI() <= i2 && mp.getJ() >= j1 && mp.getJ() <= j2;
}
/**
* Implements Bresenham's algorithm to make a line of walls beetween two nodes;
* @param tilebs
* @param xa
* @param ya
* @param xb
* @param yb
*/
private static void linkNodes(TileBuilder[][] tilebs, int xa, int ya, int xb, int yb){
int d = 0;
int dy = Math.abs(yb - ya), dx = Math.abs(xb - xa), dy2 = (dy << 1), dx2 = (dx << 1);
int ix = xa < xb ? 1 : -1, iy = ya < yb ? 1 : -1;
if (dy <= dx) {
for (;;) {
tilebs[xa][ya].setType(TileType.WALL);
if (xa == xb)
break;
xa += ix;
d += dy2;
if (d > dx) {
ya += iy;
d -= dx2;
}
}
} else {
for (;;) {
tilebs[xa][ya].setType(TileType.WALL);
if (ya == yb)
break;
ya += iy;
d += dx2;
if (d > dy) {
xa += ix;
d -= dy2;
}
}
}
}
/**
* Surround a surface with walls
* @param map
* @param surface
*/
public void surroundWithWalls(TileBuilder[][] map){
final int x1 = i1 - 1, x2 = i2 +1;
final int y1 = j1 - 1, y2 = j2 +1;
linkNodes(map, y1, x1, y2, x1);
linkNodes(map, y2, x1, y2, x2);
linkNodes(map, y2, x2, y1, x2);
linkNodes(map, y1, x2, y1, x1);
}
/**
* Fills a surface
* @param map
* @param surface
*/
public void fillSurfaceWith(TileBuilder[][] map, TileType tt){
for (int i = j1; i <= j2; i++) {
for (int j = i1; j <= i2; j++) {
map[i][j].setType(tt);
}
}
}
}
......@@ -6,7 +6,9 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import map_generation.map.RoomBuilder.RoomType;
import map_generation.tiles.TileBuilder;
import map_generation.tiles.TileType;
/**
*
* This class contains methods that generates simple map to help for tests
......@@ -28,18 +30,19 @@ public class SurfacesMapGeneration implements Serializable{
return tilebs;
}
private static MapPoint defineStartPosition(Surface[] rooms) {
private static MapPoint defineStartPosition(RoomBuilder[] rooms) {
Random r = new Random();
int idRoom=r.nextInt(rooms.length);
//int posY=(rooms[idRoom].j1+rooms[idRoom].j2)/2;
//int posX=(rooms[idRoom].i1+rooms[idRoom].i2)/2;
int posX = rooms[idRoom].i1;
int posY = rooms[idRoom].j1;
int posX = rooms[idRoom].getSurface().i1;
int posY = rooms[idRoom].getSurface().j1;
rooms[idRoom].setType(RoomType.START);
MapPoint startPosition=new MapPoint(posY, posX);
return startPosition;
}
private static MapPoint defineStairsPosition(MapBuilder map,int height,int width,Surface[] rooms,MapPoint startPosition) {
private static MapPoint defineStairsPosition(MapBuilder map,int height,int width,RoomBuilder[] rooms,MapPoint startPosition) {
// This method chooses, once the structure of the map is done and the start position of the player is choosed, where the stairs should be
// First I do a BFS (Breadth First Search) starting at the start position of the player that I put in distanceToStart
......@@ -50,8 +53,8 @@ public class SurfacesMapGeneration implements Serializable{
}
}
for(int k=0;k<rooms.length;k++) {
for(int i=rooms[k].j1;i<=rooms[k].j2;i++) {
for(int j=rooms[k].i1;j<=rooms[k].i2;j++) {
for(int i=rooms[k].getSurface().j1;i<=rooms[k].getSurface().j2;i++) {
for(int j=rooms[k].getSurface().i1;j<=rooms[k].getSurface().i2;j++) {
distanceToStart[i][j]=-1;
}
}
......@@ -99,9 +102,12 @@ public class SurfacesMapGeneration implements Serializable{
idRoom=r.nextInt(rooms.length);
// posY=r.nextInt(rooms[idRoom].j2-rooms[idRoom].j1+1)+rooms[idRoom].j1;
// posX=r.nextInt(rooms[idRoom].i2-rooms[idRoom].i1+1)+rooms[idRoom].i1;
posX = rooms[idRoom].i1;
posY = rooms[idRoom].j1;
if (3*distanceToStart[posY][posX]>2*max_dist) bb=false; // If the distance from the start position to the stairs position is large enough I choose it (compared to the farest point the player can reach)
posX = rooms[idRoom].getSurface().i1;
posY = rooms[idRoom].getSurface().j1;
if (3*distanceToStart[posY][posX]>2*max_dist){
rooms[idRoom].setType(RoomType.END);
bb=false; // If the distance from the start position to the stairs position is large enough I choose it (compared to the farest point the player can reach)
}
}
MapPoint stairsPosition=new MapPoint(posY, posX);
return stairsPosition;
......@@ -174,18 +180,18 @@ public class SurfacesMapGeneration implements Serializable{
}
}
private static void addCorridorsByMST(Surface[] rooms, MapBuilder map) {
private static void addCorridorsByMST(RoomBuilder[] rooms, MapBuilder map) {
// Considering the graph made by the rooms with edges corresponding to the distance between any two of them
// I find the MST (Math.minimum SpamMath.ming Tree) of this graph in order to create a first set of corridors that connects all the rooms
int nbRooms=rooms.length;
int[][] distance=new int[nbRooms][nbRooms];
for (int i=0;i<nbRooms;i++) {
for (int j=i+1;j<nbRooms;j++) {
int d=distanceBetweenTwoSurface(rooms[i],rooms[j]);
int d=distanceBetweenTwoSurface(rooms[i].getSurface(),rooms[j].getSurface());
distance[i][j]=d;
distance[j][i]=d;
if(d<12) { // If we find two rooms with a small distance in between, we add a corridor anyway, independantly of the MST
LinkedList<Surface> corridorsToAdd=creationCorridor(rooms[i],rooms[j]);
LinkedList<Surface> corridorsToAdd=creationCorridor(rooms[i].getSurface(),rooms[j].getSurface());
for (int k=0;k<corridorsToAdd.size();k++) {
map.addCorridor(corridorsToAdd.get(k));
}
......@@ -213,7 +219,7 @@ public class SurfacesMapGeneration implements Serializable{
}
used[node2]=true;
nbConnected++;
LinkedList<Surface> corridorsToAdd=creationCorridor(rooms[node1],rooms[node2]);
LinkedList<Surface> corridorsToAdd=creationCorridor(rooms[node1].getSurface(),rooms[node2].getSurface());
for (int k=0;k<corridorsToAdd.size();k++) {
map.addCorridor(corridorsToAdd.get(k));
}
......@@ -227,7 +233,7 @@ public class SurfacesMapGeneration implements Serializable{
int widthMap=(meanRoomSize+6)*(int)Math.sqrt(numberOfRooms);
MapBuilder map = new MapBuilder();
Random r = new Random();
Surface[] rooms=new Surface[numberOfRooms];
RoomBuilder[] rooms = new RoomBuilder[numberOfRooms];
int numberOfRoomsCreated=0;
int nbIteration=0;
......@@ -249,11 +255,11 @@ public class SurfacesMapGeneration implements Serializable{
boolean bb=true;
for (int i=0;i<numberOfRoomsCreated;i++) { // Test of intersection with a room already created
// There's a Math.minimum distance between two rooms of 4 tiles
if(positionY<=rooms[i].j2+6 && positionY+height-1>=rooms[i].j1-6 && positionX<=rooms[i].i2+6 && positionX+width-1>=rooms[i].i1-6) bb=false;
if(positionY<=rooms[i].getSurface().j2+6 && positionY+height-1>=rooms[i].getSurface().j1-6 && positionX<=rooms[i].getSurface().i2+6 && positionX+width-1>=rooms[i].getSurface().i1-6) bb=false;
}
if (bb) { // If the current room fits with the others we had it
Surface room = new Surface(positionX, positionY, positionX+width-1, positionY+height-1);
rooms[numberOfRoomsCreated] = room;
rooms[numberOfRoomsCreated] = new RoomBuilder(room, RoomType.NORMAL);
numberOfRoomsCreated++;
}
}
......@@ -262,53 +268,6 @@ public class SurfacesMapGeneration implements Serializable{
map.addRoom(rooms[i]);
}
addCorridorsByMST(rooms, map); // Creation of the set of corridors
// Boolean[][] possibleDoor=new Boolean[heightMap][widthMap];
// for(int i=0;i<heightMap;i++) {
// for(int j=0;j<widthMap;j++) {
// possibleDoor[i][j]=false;
// }
// }
// int nbDoors=0;
// for(int k=0;k<numberOfRooms;k++) {
// int y1=rooms[k].x1;
// int x1=rooms[k].x1;
// int y2=rooms[k].y2;
// int x2=rooms[k].x2;
// if(y1>0) {
// for(int x=x1;x<=x2;x++) if(tilebs[y1-1][x].getType()==TileType.GROUND) {possibleDoor[y1-1][x]=true;nbDoors++;}
// }
// if(y2<heightMap-1) {
// for(int x=x1;x<=x2;x++) if(tilebs[y2+1][x].getType()==TileType.GROUND) {possibleDoor[y2+1][x]=true;nbDoors++;}
// }
// if(x1>0) {
// for(int y=y1;y<=y2;y++) if(tilebs[y][x1-1].getType()==TileType.GROUND) {possibleDoor[y][x1-1]=true;nbDoors++;}
// }
// if(x2<widthMap-1) {
// for(int y=y1;y<=y2;y++) if(tilebs[y][x2+1].getType()==TileType.GROUND) {possibleDoor[y][x2+1]=true;nbDoors++;}
// }
// }
// int[][] doors=new int[(int)(nbDoors/2)][4];
// int k=0;
// for(int i=0;i<heightMap;i++) {
// for(int j=0;j<widthMap;j++) {
// if(i<heightMap-1 && possibleDoor[i][j] && possibleDoor[i+1][j] && k<(int)(nbDoors/2)) {
// doors[k].x1=i;
// doors[k].x1=j;
// doors[k].y2=i+1;
// doors[k].x2=j;
// k++;
// }
// if(j<widthMap-1 && possibleDoor[i][j] && possibleDoor[i][j+1] && k<(int)(nbDoors/2)) {
// doors[k].x1=i;
// doors[k].x1=j;
// doors[k].y2=i;
// doors[k].x2=j+1;
// k++;
// }
// }
// }
//
MapPoint startPosition=defineStartPosition(rooms);
MapPoint stairsPosition=defineStairsPosition(map,heightMap,widthMap,rooms,startPosition);
......@@ -317,6 +276,10 @@ public class SurfacesMapGeneration implements Serializable{
map.setStairPosition(stairsPosition);
map.setPositionPlayerAtStart(startPosition);
for (RoomBuilder room : rooms) {
room.setRandomlySpecial(0.4);
}
return map.build();
}
......@@ -326,9 +289,9 @@ public class SurfacesMapGeneration implements Serializable{
map.setHeight(size);
map.setWidth(size);
Surface room=new Surface(2,2,size-3,size-3);
map.addRoom(room);
Surface[] rooms=new Surface[1];
rooms[0]=room;
map.addRoom(new RoomBuilder(room, RoomType.NORMAL));
RoomBuilder[] rooms=new RoomBuilder[1];
rooms[0]= new RoomBuilder(room, RoomType.NORMAL);
addCorridorsByMST(rooms, map);
MapPoint startPosition=defineStartPosition(rooms);
MapPoint stairsPosition=defineStairsPosition(map,size,size,rooms,startPosition);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment