about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorStarla Insigna <hatkirby@fourisland.com>2012-06-02 21:45:40 -0400
committerStarla Insigna <hatkirby@fourisland.com>2012-06-02 21:45:40 -0400
commitfa27ef18695e007deeaf8d2a372e85c13d54764a (patch)
tree7648b81a947ad04bf0a39ba24d2f635c573901f0
parentdf65f21501cf8e3de51d01fee4eab1d488bd568c (diff)
downloadfrigidearth-fa27ef18695e007deeaf8d2a372e85c13d54764a.tar.gz
frigidearth-fa27ef18695e007deeaf8d2a372e85c13d54764a.tar.bz2
frigidearth-fa27ef18695e007deeaf8d2a372e85c13d54764a.zip
Replaced basic dungeon generator with a much cooler one
Also added support for more than two types of tiles, which are represented by characters. Later I'll add the functionality for different coloring of characters, because the bright Xs are kind of annoying.
-rw-r--r--src/com/fourisland/frigidearth/Functions.java21
-rw-r--r--src/com/fourisland/frigidearth/MapViewGameState.java493
-rw-r--r--src/com/fourisland/frigidearth/Tile.java104
3 files changed, 537 insertions, 81 deletions
diff --git a/src/com/fourisland/frigidearth/Functions.java b/src/com/fourisland/frigidearth/Functions.java new file mode 100644 index 0000000..cb57086 --- /dev/null +++ b/src/com/fourisland/frigidearth/Functions.java
@@ -0,0 +1,21 @@
1/*
2 * To change this template, choose Tools | Templates
3 * and open the template in the editor.
4 */
5package com.fourisland.frigidearth;
6
7import java.util.Random;
8
9/**
10 *
11 * @author hatkirby
12 */
13public class Functions
14{
15 public static int random(int min, int max)
16 {
17 Random r = new Random();
18
19 return r.nextInt(max - min + 1) + min;
20 }
21}
diff --git a/src/com/fourisland/frigidearth/MapViewGameState.java b/src/com/fourisland/frigidearth/MapViewGameState.java index e8da885..f378d5a 100644 --- a/src/com/fourisland/frigidearth/MapViewGameState.java +++ b/src/com/fourisland/frigidearth/MapViewGameState.java
@@ -4,11 +4,8 @@
4 */ 4 */
5package com.fourisland.frigidearth; 5package com.fourisland.frigidearth;
6 6
7import java.awt.Color;
8import java.awt.Graphics2D; 7import java.awt.Graphics2D;
9import java.awt.Rectangle;
10import java.awt.event.KeyEvent; 8import java.awt.event.KeyEvent;
11import java.util.Random;
12 9
13/** 10/**
14 * 11 *
@@ -22,10 +19,13 @@ public class MapViewGameState implements GameState
22 private final int GAME_HEIGHT = 100; 19 private final int GAME_HEIGHT = 100;
23 private final int VIEWPORT_WIDTH = Main.GAME_WIDTH / TILE_WIDTH; 20 private final int VIEWPORT_WIDTH = Main.GAME_WIDTH / TILE_WIDTH;
24 private final int VIEWPORT_HEIGHT = Main.GAME_HEIGHT / TILE_HEIGHT; 21 private final int VIEWPORT_HEIGHT = Main.GAME_HEIGHT / TILE_HEIGHT;
25 private final int ROOM_MAX_SIZE = 10; 22 private final int MAX_ROOM_WIDTH = 13;
26 private final int ROOM_MIN_SIZE = 6; 23 private final int MIN_ROOM_WIDTH = 7;
27 private final int MAX_ROOMS = 30; 24 private final int MAX_ROOM_HEIGHT = 13;
28 private boolean[][] grid; 25 private final int MIN_ROOM_HEIGHT = 7;
26 private final int MAX_CORRIDOR_LENGTH = 6;
27 private final int MIN_CORRIDOR_LENGTH = 2;
28 private Tile[][] grid;
29 private int playerx = 4; 29 private int playerx = 4;
30 private int playery = 4; 30 private int playery = 4;
31 private int viewportx = 0; 31 private int viewportx = 0;
@@ -33,109 +33,447 @@ public class MapViewGameState implements GameState
33 33
34 public MapViewGameState() 34 public MapViewGameState()
35 { 35 {
36 grid = new boolean[GAME_WIDTH][GAME_HEIGHT]; 36 grid = new Tile[GAME_WIDTH][GAME_HEIGHT];
37 37
38 for (int x=0; x<GAME_WIDTH; x++) 38 for (int x=0; x<GAME_WIDTH; x++)
39 { 39 {
40 for (int y=0; y<GAME_HEIGHT; y++) 40 for (int y=0; y<GAME_HEIGHT; y++)
41 { 41 {
42 grid[x][y] = true; 42 if ((x == 0) || (x == GAME_WIDTH-1) || (y == 0) || (y == GAME_HEIGHT-1))
43 {
44 grid[x][y] = Tile.StoneWall;
45 } else {
46 grid[x][y] = Tile.Unused;
47 }
43 } 48 }
44 } 49 }
45 50
46 Rectangle[] rooms = new Rectangle[MAX_ROOMS]; 51 makeRoom(GAME_WIDTH/2, GAME_HEIGHT/2, Functions.random(0, 3));
47 int numRooms = 0; 52 playerx = GAME_WIDTH/2;
48 Random r = new Random(); 53 playery = GAME_HEIGHT/2;
49 54
50 for (int i=0; i<MAX_ROOMS; i++) 55 int currentFeatures = 1;
56 int objects = 300;
57
58 for (int countingTries = 0; countingTries < 1000; countingTries++)
51 { 59 {
52 int w = r.nextInt(ROOM_MAX_SIZE - ROOM_MIN_SIZE + 1) + ROOM_MIN_SIZE; 60 if (currentFeatures == objects)
53 int h = r.nextInt(ROOM_MAX_SIZE - ROOM_MIN_SIZE + 1) + ROOM_MIN_SIZE;
54 int x = r.nextInt(GAME_WIDTH - w - 1);
55 int y = r.nextInt(GAME_HEIGHT - h - 1);
56 Rectangle newRoom = new Rectangle(x, y, w, h);
57 boolean failed = false;
58
59 for (Rectangle room : rooms)
60 { 61 {
61 if ((room != null) && (newRoom.intersects(room))) 62 break;
62 {
63 failed = true;
64 break;
65 }
66 } 63 }
67 64
68 if (!failed) 65 int newx = 0;
66 int xmod = 0;
67 int newy = 0;
68 int ymod = 0;
69 int validTile = -1;
70 for (int testing = 0; testing < 1000; testing++)
69 { 71 {
70 createRoom(newRoom); 72 newx = Functions.random(1, GAME_WIDTH-1);
73 newy = Functions.random(1, GAME_HEIGHT-1);
74 validTile = -1;
71 75
72 int newX = (int) newRoom.getCenterX(); 76 if ((grid[newx][newy] == Tile.DirtWall) || (grid[newx][newy] == Tile.Corridor))
73 int newY = (int) newRoom.getCenterY();
74
75 if (numRooms == 0)
76 { 77 {
77 playerx = newX; 78 if ((grid[newx][newy+1] == Tile.DirtFloor) || (grid[newx][newy+1] == Tile.Corridor))
78 playery = newY; 79 {
80 validTile = 0;
81 xmod = 0;
82 ymod = -1;
83 } else if ((grid[newx-1][newy] == Tile.DirtFloor) || (grid[newx-1][newy] == Tile.Corridor))
84 {
85 validTile = 1;
86 xmod = 1;
87 ymod = 0;
88 } else if ((grid[newx][newy-1] == Tile.DirtFloor) || (grid[newx][newy-1] == Tile.Corridor))
89 {
90 validTile = 2;
91 xmod = 0;
92 ymod = 1;
93 } else if ((grid[newx+1][newy] == Tile.DirtFloor) || (grid[newx+1][newy] == Tile.Corridor))
94 {
95 validTile = 3;
96 xmod = -1;
97 ymod = 0;
98 }
79 99
80 adjustViewport(); 100 if (validTile > -1)
81 } else { 101 {
82 int prevX = (int) rooms[numRooms-1].getCenterX(); 102 if (grid[newx][newy+1] == Tile.Door)
83 int prevY = (int) rooms[numRooms-1].getCenterY(); 103 {
104 validTile = -1;
105 } else if (grid[newx-1][newy] == Tile.Door)
106 {
107 validTile = -1;
108 } else if (grid[newx][newy-1] == Tile.Door)
109 {
110 validTile = -1;
111 } else if (grid[newx+1][newy] == Tile.Door)
112 {
113 validTile = -1;
114 }
115 }
84 116
85 if (r.nextBoolean()) 117 if (validTile > -1)
86 { 118 {
87 createHTunnel(prevX, newX, prevY); 119 break;
88 createVTunnel(prevY, newY, newX);
89 } else {
90 createVTunnel(prevY, newY, prevX);
91 createHTunnel(prevX, newX, newY);
92 } 120 }
93 } 121 }
94
95 rooms[numRooms++] = newRoom;
96 } 122 }
97 } 123
98 } 124 if (validTile > -1)
99
100 private void createRoom(Rectangle room)
101 {
102 for (int x=room.x+1; x<room.x+room.width; x++)
103 {
104 for (int y=room.y+1; y<room.y+room.height; y++)
105 { 125 {
106 grid[x][y] = false; 126 if (Functions.random(0, 100) <= 75)
127 {
128 if (makeRoom(newx+xmod, newy+ymod, validTile))
129 {
130 currentFeatures++;
131 grid[newx][newy] = Tile.Door;
132 grid[newx+xmod][newy+ymod] = Tile.DirtFloor;
133 }
134 } else {
135 if (makeCorridor(newx+xmod, newy+ymod, validTile))
136 {
137 currentFeatures++;
138 grid[newx][newy] = Tile.Door;
139 }
140 }
107 } 141 }
108 } 142 }
109 } 143 }
110 144
111 private void createHTunnel(int x1, int x2, int y) 145 private boolean makeRoom(int x, int y, int direction)
112 { 146 {
113 if (x2 < x1) 147 int width = Functions.random(MIN_ROOM_WIDTH, MAX_ROOM_WIDTH);
148 int height = Functions.random(MIN_ROOM_HEIGHT, MAX_ROOM_HEIGHT);
149 Tile floor = Tile.DirtFloor;
150 Tile wall = Tile.DirtWall;
151 int dir = 0;
152
153 if ((direction > 0) && (direction < 4))
114 { 154 {
115 int temp = x1; 155 dir = direction;
116 x1 = x2;
117 x2 = temp;
118 } 156 }
119 157
120 for (int x=x1; x<x2+1; x++) 158 switch (dir)
121 { 159 {
122 grid[x][y] = false; 160 case 0: // North
161 for (int ytemp=y; ytemp > (y-height); ytemp--)
162 {
163 if ((ytemp < 0) || (ytemp > GAME_HEIGHT))
164 {
165 return false;
166 }
167
168 for (int xtemp=(x-width/2); xtemp < (x+(width+1)/2); xtemp++)
169 {
170 if ((xtemp < 0) || (xtemp > GAME_WIDTH))
171 {
172 return false;
173 }
174
175 if (grid[xtemp][ytemp] != Tile.Unused)
176 {
177 return false;
178 }
179 }
180 }
181
182 for (int ytemp = y; ytemp > (y-height); ytemp--)
183 {
184 for (int xtemp = (x-width/2); xtemp < (x+(width+1)/2); xtemp++)
185 {
186 if (xtemp == (x-width/2))
187 {
188 grid[xtemp][ytemp] = wall;
189 } else if (xtemp == (x+(width-1)/2))
190 {
191 grid[xtemp][ytemp] = wall;
192 } else if (ytemp == y)
193 {
194 grid[xtemp][ytemp] = wall;
195 } else if (ytemp == (y-height+1))
196 {
197 grid[xtemp][ytemp] = wall;
198 } else {
199 grid[xtemp][ytemp] = floor;
200 }
201 }
202 }
203
204 break;
205
206 case 1: // East
207 for (int ytemp=(y-height/2); ytemp < (y+(height+1)/2); ytemp++)
208 {
209 if ((ytemp < 0) || (ytemp > GAME_HEIGHT))
210 {
211 return false;
212 }
213
214 for (int xtemp=x; xtemp < (x+width); xtemp++)
215 {
216 if ((xtemp < 0) || (xtemp > GAME_WIDTH))
217 {
218 return false;
219 }
220
221 if (grid[xtemp][ytemp] != Tile.Unused)
222 {
223 return false;
224 }
225 }
226 }
227
228 for (int ytemp=(y-height/2); ytemp < (y+(height+1)/2); ytemp++)
229 {
230 for (int xtemp=x; xtemp < (x+width); xtemp++)
231 {
232 if (xtemp == x)
233 {
234 grid[xtemp][ytemp] = wall;
235 } else if (xtemp == (x+width-1))
236 {
237 grid[xtemp][ytemp] = wall;
238 } else if (ytemp == (y-height/2))
239 {
240 grid[xtemp][ytemp] = wall;
241 } else if (ytemp == (y+(height-1)/2))
242 {
243 grid[xtemp][ytemp] = wall;
244 } else {
245 grid[xtemp][ytemp] = floor;
246 }
247 }
248 }
249
250 break;
251
252 case 2: // South
253 for (int ytemp=y; ytemp < (y+height); ytemp++)
254 {
255 if ((ytemp < 0) || (ytemp > GAME_HEIGHT))
256 {
257 return false;
258 }
259
260 for (int xtemp=(x-width/2); xtemp < (x+(width+1)/2); xtemp++)
261 {
262 if ((xtemp < 0) || (xtemp > GAME_WIDTH))
263 {
264 return false;
265 }
266
267 if (grid[xtemp][ytemp] != Tile.Unused)
268 {
269 return false;
270 }
271 }
272 }
273
274 for (int ytemp=y; ytemp < (y+height); ytemp++)
275 {
276 for (int xtemp = (x-width/2); xtemp < (x+(width+1)/2); xtemp++)
277 {
278 if (xtemp == (x-width/2))
279 {
280 grid[xtemp][ytemp] = wall;
281 } else if (xtemp == (x+(width-1)/2))
282 {
283 grid[xtemp][ytemp] = wall;
284 } else if (ytemp == y)
285 {
286 grid[xtemp][ytemp] = wall;
287 } else if (ytemp == (y+height-1))
288 {
289 grid[xtemp][ytemp] = wall;
290 } else {
291 grid[xtemp][ytemp] = floor;
292 }
293 }
294 }
295
296 break;
297
298 case 3: // West
299 for (int ytemp=(y-height/2); ytemp < (y+(height+1)/2); ytemp++)
300 {
301 if ((ytemp < 0) || (ytemp > GAME_HEIGHT))
302 {
303 return false;
304 }
305
306 for (int xtemp=x; xtemp > (x-width); xtemp--)
307 {
308 if ((xtemp < 0) || (xtemp > GAME_WIDTH))
309 {
310 return false;
311 }
312
313 if (grid[xtemp][ytemp] != Tile.Unused)
314 {
315 return false;
316 }
317 }
318 }
319
320 for (int ytemp=(y-height/2); ytemp < (y+(height+1)/2); ytemp++)
321 {
322 for (int xtemp=x; xtemp > (x-width); xtemp--)
323 {
324 if (xtemp == x)
325 {
326 grid[xtemp][ytemp] = wall;
327 } else if (xtemp == (x-width+1))
328 {
329 grid[xtemp][ytemp] = wall;
330 } else if (ytemp == (y-height/2))
331 {
332 grid[xtemp][ytemp] = wall;
333 } else if (ytemp == (y+(height-1)/2))
334 {
335 grid[xtemp][ytemp] = wall;
336 } else {
337 grid[xtemp][ytemp] = floor;
338 }
339 }
340 }
341
342 break;
123 } 343 }
344
345 return true;
124 } 346 }
125 347
126 private void createVTunnel(int y1, int y2, int x) 348 private boolean makeCorridor(int x, int y, int direction)
127 { 349 {
128 if (y2 < y1) 350 int length = Functions.random(MIN_CORRIDOR_LENGTH, MAX_CORRIDOR_LENGTH);
351 Tile floor = Tile.Corridor;
352 int dir = 0;
353 if ((direction > 0) && (direction < 4))
129 { 354 {
130 int temp = y1; 355 dir = direction;
131 y1 = y2;
132 y2 = temp;
133 } 356 }
134 357
135 for (int y=y1; y<y2+1; y++) 358 int xtemp = 0;
359 int ytemp = 0;
360
361 switch (dir)
136 { 362 {
137 grid[x][y] = false; 363 case 0: // North
364 if ((x < 0) || (x > GAME_WIDTH))
365 {
366 return false;
367 } else {
368 xtemp = x;
369 }
370
371 for (ytemp = y; ytemp > (y-length); ytemp--)
372 {
373 if ((ytemp < 0) || (ytemp > GAME_HEIGHT))
374 {
375 return false;
376 }
377
378 if (grid[xtemp][ytemp] != Tile.Unused)
379 {
380 return false;
381 }
382 }
383
384 for (ytemp = y; ytemp > (y-length); ytemp--)
385 {
386 grid[xtemp][ytemp] = floor;
387 }
388
389 break;
390
391 case 1: // East
392 if ((y < 0) || (y > GAME_HEIGHT))
393 {
394 return false;
395 } else {
396 ytemp = y;
397 }
398
399 for (xtemp = x; xtemp < (x+length); xtemp++)
400 {
401 if ((xtemp < 0) || (xtemp > GAME_WIDTH))
402 {
403 return false;
404 }
405
406 if (grid[xtemp][ytemp] != Tile.Unused)
407 {
408 return false;
409 }
410 }
411
412 for (xtemp = x; xtemp < (x+length); xtemp++)
413 {
414 grid[xtemp][ytemp] = floor;
415 }
416
417 break;
418
419 case 2: // South
420 if ((x < 0) || (x > GAME_WIDTH))
421 {
422 return false;
423 } else {
424 xtemp = x;
425 }
426
427 for (ytemp = y; ytemp < (y+length); ytemp++)
428 {
429 if ((ytemp < 0) || (ytemp > GAME_HEIGHT))
430 {
431 return false;
432 }
433
434 if (grid[xtemp][ytemp] != Tile.Unused)
435 {
436 return false;
437 }
438 }
439
440 for (ytemp = y; ytemp < (y+length); ytemp++)
441 {
442 grid[xtemp][ytemp] = floor;
443 }
444
445 break;
446
447 case 3: // West
448 if ((y < 0) || (y > GAME_HEIGHT))
449 {
450 return false;
451 } else {
452 ytemp = y;
453 }
454
455 for (xtemp = x; xtemp > (x-length); xtemp--)
456 {
457 if ((xtemp < 0) || (xtemp > GAME_WIDTH))
458 {
459 return false;
460 }
461
462 if (grid[xtemp][ytemp] != Tile.Unused)
463 {
464 return false;
465 }
466 }
467
468 for (xtemp = x; xtemp > (x-length); xtemp--)
469 {
470 grid[xtemp][ytemp] = floor;
471 }
472
473 break;
138 } 474 }
475
476 return true;
139 } 477 }
140 478
141 public void render(Graphics2D g) 479 public void render(Graphics2D g)
@@ -145,14 +483,7 @@ public class MapViewGameState implements GameState
145 { 483 {
146 for (int y=viewporty; y<viewporty+VIEWPORT_HEIGHT; y++) 484 for (int y=viewporty; y<viewporty+VIEWPORT_HEIGHT; y++)
147 { 485 {
148 if (grid[x][y]) 486 g.drawImage(SystemFont.getCharacter(grid[x][y].getDisplayCharacter()), (x-viewportx)*TILE_WIDTH, (y-viewporty)*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT, null);
149 {
150 g.setColor(Color.GRAY);
151 } else {
152 g.setColor(Color.BLACK);
153 }
154
155 g.fillRect((x-viewportx)*TILE_WIDTH, (y-viewporty)*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
156 } 487 }
157 } 488 }
158 489
@@ -164,25 +495,25 @@ public class MapViewGameState implements GameState
164 { 495 {
165 if (e.getKeyCode() == KeyEvent.VK_LEFT) 496 if (e.getKeyCode() == KeyEvent.VK_LEFT)
166 { 497 {
167 if ((playerx > 0) && (!grid[playerx-1][playery])) 498 if ((playerx > 0) && (!grid[playerx-1][playery].isBlocked()))
168 { 499 {
169 playerx--; 500 playerx--;
170 } 501 }
171 } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) 502 } else if (e.getKeyCode() == KeyEvent.VK_RIGHT)
172 { 503 {
173 if ((playerx < GAME_WIDTH - 1) && (!grid[playerx+1][playery])) 504 if ((playerx < GAME_WIDTH - 1) && (!grid[playerx+1][playery].isBlocked()))
174 { 505 {
175 playerx++; 506 playerx++;
176 } 507 }
177 } else if (e.getKeyCode() == KeyEvent.VK_UP) 508 } else if (e.getKeyCode() == KeyEvent.VK_UP)
178 { 509 {
179 if ((playery > 0) && (!grid[playerx][playery-1])) 510 if ((playery > 0) && (!grid[playerx][playery-1].isBlocked()))
180 { 511 {
181 playery--; 512 playery--;
182 } 513 }
183 } else if (e.getKeyCode() == KeyEvent.VK_DOWN) 514 } else if (e.getKeyCode() == KeyEvent.VK_DOWN)
184 { 515 {
185 if ((playery < GAME_HEIGHT - 1) && (!grid[playerx][playery+1])) 516 if ((playery < GAME_HEIGHT - 1) && (!grid[playerx][playery+1].isBlocked()))
186 { 517 {
187 playery++; 518 playery++;
188 } 519 }
diff --git a/src/com/fourisland/frigidearth/Tile.java b/src/com/fourisland/frigidearth/Tile.java new file mode 100644 index 0000000..e25cedd --- /dev/null +++ b/src/com/fourisland/frigidearth/Tile.java
@@ -0,0 +1,104 @@
1/*
2 * To change this template, choose Tools | Templates
3 * and open the template in the editor.
4 */
5package com.fourisland.frigidearth;
6
7/**
8 *
9 * @author hatkirby
10 */
11public enum Tile
12{
13 Unused {
14 public boolean isBlocked()
15 {
16 return true;
17 }
18
19 public char getDisplayCharacter()
20 {
21 return 'X';
22 }
23 },
24 DirtWall {
25 public boolean isBlocked()
26 {
27 return true;
28 }
29
30 public char getDisplayCharacter()
31 {
32 return '#';
33 }
34 },
35 DirtFloor {
36 public boolean isBlocked()
37 {
38 return false;
39 }
40
41 public char getDisplayCharacter()
42 {
43 return ' ';
44 }
45 },
46 StoneWall {
47 public boolean isBlocked()
48 {
49 return true;
50 }
51
52 public char getDisplayCharacter()
53 {
54 return 'X';
55 }
56 },
57 Corridor {
58 public boolean isBlocked()
59 {
60 return false;
61 }
62
63 public char getDisplayCharacter()
64 {
65 return '.';
66 }
67 },
68 Door {
69 public boolean isBlocked()
70 {
71 return false;
72 }
73
74 public char getDisplayCharacter()
75 {
76 return 'D';
77 }
78 },
79 UpStairs {
80 public boolean isBlocked()
81 {
82 return false;
83 }
84
85 public char getDisplayCharacter()
86 {
87 return '>';
88 }
89 },
90 DownStairs {
91 public boolean isBlocked()
92 {
93 return false;
94 }
95
96 public char getDisplayCharacter()
97 {
98 return '<';
99 }
100 };
101
102 public abstract boolean isBlocked();
103 public abstract char getDisplayCharacter();
104}