[Freeciv-Dev] (PR#9379) hex tilesets and rivers
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: |
undisclosed-recipients: ; |
Subject: |
[Freeciv-Dev] (PR#9379) hex tilesets and rivers |
From: |
"Jason Dorje Short" <jdorje@xxxxxxxxxxx> |
Date: |
Tue, 13 Jul 2004 20:12:47 -0700 |
Reply-to: |
rt@xxxxxxxxxxx |
<URL: http://rt.freeciv.org/Ticket/Display.html?id=9379 >
One of the biggest problems with playing in hex (with the hex-topology
patch and the isophex tileset) is that the rivers aren't drawn
correctly. Rivers connect along diagonal lines, but the tileset cannot
draw this.
This patch is a fix for that problem, and also a step toward a more
general design for doing "matching" sprites.
First of all it uses tileset directional lists (see PR#9338). A list of
valid directions and a list of cardinal directions is assembled,
although only the cardinal directions are used.
The cardinal direction lists is used for drawing river (spec_river)
graphics. The algorithm is pretty simple, surely less error-prone than
the one in place now. And it works for hex.
This is step toward a new design, so it deserves some scrutiny. However
I think this design is much better and should replace all users of
INDEX_CW/cw_str and INDEX_NSEW/nsew_str.
Also attached is a rivers.spec and rivers.png to be used with isophex.
Add this to the isophex tileset and the new algorithm will be used.
This is just something I scrapped together for testing. With hex there
are 2^6 = 64 needed river sprites, so there is some work to be done to
get good graphics. Of course each set of 4 of them can just be
duplicated to get the same bad behavior we have now.
jason
Index: client/tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.183
diff -u -r1.183 tilespec.c
--- client/tilespec.c 13 Jul 2004 18:16:53 -0000 1.183
+++ client/tilespec.c 14 Jul 2004 02:48:15 -0000
@@ -88,6 +88,9 @@
#define NUM_CORNER_DIRS 4
#define TILES_PER_CORNER 4
+static int num_valid_tileset_dirs, num_cardinal_tileset_dirs;
+static enum direction8 valid_tileset_dirs[8], cardinal_tileset_dirs[8];
+
static struct {
enum match_style match_style;
int count;
@@ -197,6 +200,64 @@
bool required, const char *what,
const char *name);
+/**************************************************************************
+ Return the tileset name of the direction. This is similar to
+ dir_get_name but you shouldn't change this or all tilesets will break.
+**************************************************************************/
+static const char *dir_get_tileset_name(enum direction8 dir)
+{
+ switch (dir) {
+ case DIR8_NORTH:
+ return "n";
+ case DIR8_NORTHEAST:
+ return "ne";
+ case DIR8_EAST:
+ return "e";
+ case DIR8_SOUTHEAST:
+ return "se";
+ case DIR8_SOUTH:
+ return "s";
+ case DIR8_SOUTHWEST:
+ return "sw";
+ case DIR8_WEST:
+ return "w";
+ case DIR8_NORTHWEST:
+ return "nw";
+ }
+ assert(0);
+ return "";
+}
+
+/****************************************************************************
+ Return TRUE iff the dir is valid in this tileset.
+****************************************************************************/
+static bool is_valid_tileset_dir(enum direction8 dir)
+{
+ if (hex_width > 0) {
+ return dir != DIR8_NORTHEAST && dir != DIR8_SOUTHWEST;
+ } else if (hex_height > 0) {
+ return dir != DIR8_NORTHWEST && dir != DIR8_SOUTHEAST;
+ } else {
+ return TRUE;
+ }
+}
+
+/****************************************************************************
+ Return TRUE iff the dir is cardinal in this tileset.
+
+ "Cardinal", in this sense, means that a tile will share a border with
+ another tile in the direction rather than sharing just a single vertex.
+****************************************************************************/
+static bool is_cardinal_tileset_dir(enum direction8 dir)
+{
+ if (hex_width > 0 || hex_height > 0) {
+ return is_valid_tileset_dir(dir);
+ } else {
+ return (dir == DIR8_NORTH || dir == DIR8_EAST
+ || dir == DIR8_SOUTH || dir == DIR8_WEST);
+ }
+}
+
/**********************************************************************
Returns a static list of tilesets available on the system by
searching all data directories for files matching TILESPEC_SUFFIX.
@@ -687,6 +748,7 @@
char **spec_filenames, **terrains;
char *file_capstr;
bool duplicates_ok, is_hex;
+ enum direction8 dir;
fname = tilespec_fullname(tileset_name);
freelog(LOG_VERBOSE, "tilespec file is %s", fname);
@@ -738,6 +800,24 @@
return tilespec_read_toplevel(NULL);
}
+ /* Create arrays of valid and cardinal tileset dirs. These depend
+ * entirely on the tileset, not the topology. They are also in clockwise
+ * rotational ordering. */
+ num_valid_tileset_dirs = num_cardinal_tileset_dirs = 0;
+ dir = DIR8_NORTH;
+ do {
+ if (is_valid_tileset_dir(dir)) {
+ valid_tileset_dirs[num_valid_tileset_dirs] = dir;
+ num_valid_tileset_dirs++;
+ }
+ if (is_cardinal_tileset_dir(dir)) {
+ cardinal_tileset_dirs[num_cardinal_tileset_dirs] = dir;
+ num_cardinal_tileset_dirs++;
+ }
+
+ dir = dir_cw(dir);
+ } while (dir != DIR8_NORTH);
+
NORMAL_TILE_WIDTH = secfile_lookup_int(file, "tilespec.normal_tile_width");
NORMAL_TILE_HEIGHT = secfile_lookup_int(file, "tilespec.normal_tile_height");
if (is_isometric) {
@@ -1006,6 +1086,27 @@
}
/****************************************************************************
+ Return a directional string for the cardinal directions. Normally the
+ binary value 1000 will be converted into "n1e0s0w0". This is in a
+ clockwise ordering.
+****************************************************************************/
+static const char *cardinal_str(int idx)
+{
+ static char c[64];
+ int i;
+
+ c[0] = '\0';
+ for (i = 0; i < num_cardinal_tileset_dirs; i++) {
+ int value = (idx >> i) & 1;
+
+ snprintf(c + strlen(c), sizeof(c) - strlen(c), "%s%d",
+ dir_get_tileset_name(cardinal_tileset_dirs[i]), value);
+ }
+
+ return c;
+}
+
+/****************************************************************************
Do the same thing as nsew_str, except including all the cardinal and
diagonal directions.
The returned string is a pointer to static memory.
@@ -1314,8 +1415,8 @@
SET_SPRITE(tx.airbase, "tx.airbase");
SET_SPRITE(tx.fog, "tx.fog");
- for(i=0; i<NUM_DIRECTION_NSEW; i++) {
- my_snprintf(buffer, sizeof(buffer), "tx.s_river_%s", nsew_str(i));
+ for (i = 0; i < NUM_DIRECTION_CARDINAL; i++) {
+ my_snprintf(buffer, sizeof(buffer), "tx.s_river_%s", cardinal_str(i));
SET_SPRITE(tx.spec_river[i], buffer);
}
@@ -2543,19 +2644,18 @@
pcity);
if (draw_terrain && contains_special(tspecial, S_RIVER)) {
+ int i;
+
/* Draw rivers on top of irrigation. */
- tileno = INDEX_NSEW((contains_special(tspecial_near[DIR8_NORTH],
- S_RIVER)
- || is_ocean(ttype_near[DIR8_NORTH])),
- (contains_special(tspecial_near[DIR8_SOUTH],
- S_RIVER)
- || is_ocean(ttype_near[DIR8_SOUTH])),
- (contains_special(tspecial_near[DIR8_EAST],
- S_RIVER)
- || is_ocean(ttype_near[DIR8_EAST])),
- (contains_special(tspecial_near[DIR8_WEST],
- S_RIVER)
- || is_ocean(ttype_near[DIR8_WEST])));
+ tileno = 0;
+ for (i = 0; i < num_cardinal_tileset_dirs; i++) {
+ enum direction8 dir = cardinal_tileset_dirs[i];
+
+ if (contains_special(tspecial_near[dir], S_RIVER)
+ || is_ocean(ttype_near[dir])) {
+ tileno |= 1 << i;
+ }
+ }
ADD_SPRITE_SIMPLE(sprites.tx.spec_river[tileno]);
}
Index: client/tilespec.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.h,v
retrieving revision 1.75
diff -u -r1.75 tilespec.h
--- client/tilespec.h 10 Jul 2004 18:48:17 -0000 1.75
+++ client/tilespec.h 14 Jul 2004 02:48:16 -0000
@@ -81,8 +81,8 @@
/* This the way directional indices are now encoded: */
-
#define NUM_DIRECTION_NSEW 16
+#define NUM_DIRECTION_CARDINAL 64
#define NUM_DIRECTION_CW 256
#define BIT_NORTH (0x01)
@@ -269,7 +269,7 @@
*airbase,
*fallout,
*fog,
- *spec_river[NUM_DIRECTION_NSEW],
+ *spec_river[NUM_DIRECTION_CARDINAL],
*darkness[NUM_DIRECTION_NSEW], /* first unused */
*river_outlet[4], /* indexed by enum direction4 */
/* for non-isometric */
Index: data/isotrident/terrain2.spec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/isotrident/terrain2.spec,v
retrieving revision 1.4
diff -u -r1.4 terrain2.spec
--- data/isotrident/terrain2.spec 4 May 2004 18:22:02 -0000 1.4
+++ data/isotrident/terrain2.spec 14 Jul 2004 02:48:17 -0000
@@ -25,22 +25,22 @@
; Rivers (as special type), and whether north, south, east, west
; also has river or is ocean:
- 2, 0, "tx.s_river_n0s0e0w0"
- 2, 1, "tx.s_river_n1s0e0w0"
- 2, 2, "tx.s_river_n0s0e1w0"
- 2, 3, "tx.s_river_n1s0e1w0"
- 2, 4, "tx.s_river_n0s1e0w0"
- 2, 5, "tx.s_river_n1s1e0w0"
- 2, 6, "tx.s_river_n0s1e1w0"
- 2, 7, "tx.s_river_n1s1e1w0"
- 3, 0, "tx.s_river_n0s0e0w1"
- 3, 1, "tx.s_river_n1s0e0w1"
- 3, 2, "tx.s_river_n0s0e1w1"
- 3, 3, "tx.s_river_n1s0e1w1"
- 3, 4, "tx.s_river_n0s1e0w1"
- 3, 5, "tx.s_river_n1s1e0w1"
- 3, 6, "tx.s_river_n0s1e1w1"
- 3, 7, "tx.s_river_n1s1e1w1"
+ 2, 0, "tx.s_river_n0e0s0w0"
+ 2, 1, "tx.s_river_n1e0s0w0"
+ 2, 2, "tx.s_river_n0e1s0w0"
+ 2, 3, "tx.s_river_n1e1s0w0"
+ 2, 4, "tx.s_river_n0e0s1w0"
+ 2, 5, "tx.s_river_n1e0s1w0"
+ 2, 6, "tx.s_river_n0e1s1w0"
+ 2, 7, "tx.s_river_n1e1s1w0"
+ 3, 0, "tx.s_river_n0e0s0w1"
+ 3, 1, "tx.s_river_n1e0s0w1"
+ 3, 2, "tx.s_river_n0e1s0w1"
+ 3, 3, "tx.s_river_n1e1s0w1"
+ 3, 4, "tx.s_river_n0e0s1w1"
+ 3, 5, "tx.s_river_n1e0s1w1"
+ 3, 6, "tx.s_river_n0e1s1w1"
+ 3, 7, "tx.s_river_n1e1s1w1"
; Rivers as overlay
Index: data/trident/tiles.spec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/trident/tiles.spec,v
retrieving revision 1.17
diff -u -r1.17 tiles.spec
--- data/trident/tiles.spec 29 Jun 2004 05:39:52 -0000 1.17
+++ data/trident/tiles.spec 14 Jul 2004 02:48:17 -0000
@@ -205,22 +205,22 @@
; Rivers (as special type), and whether north, south, east, west
; also has river or is ocean:
- 18, 0, "tx.s_river_n0s0e0w0"
- 18, 1, "tx.s_river_n1s0e0w0"
- 18, 2, "tx.s_river_n0s0e1w0"
- 18, 3, "tx.s_river_n1s0e1w0"
- 18, 4, "tx.s_river_n0s1e0w0"
- 18, 5, "tx.s_river_n1s1e0w0"
- 18, 6, "tx.s_river_n0s1e1w0"
- 18, 7, "tx.s_river_n1s1e1w0"
- 18, 8, "tx.s_river_n0s0e0w1"
- 18, 9, "tx.s_river_n1s0e0w1"
- 18, 10, "tx.s_river_n0s0e1w1"
- 18, 11, "tx.s_river_n1s0e1w1"
- 18, 12, "tx.s_river_n0s1e0w1"
- 18, 13, "tx.s_river_n1s1e0w1"
- 18, 14, "tx.s_river_n0s1e1w1"
- 18, 15, "tx.s_river_n1s1e1w1"
+ 18, 0, "tx.s_river_n0e0s0w0"
+ 18, 1, "tx.s_river_n1e0s0w0"
+ 18, 2, "tx.s_river_n0e1s0w0"
+ 18, 3, "tx.s_river_n1e1s0w0"
+ 18, 4, "tx.s_river_n0e0s1w0"
+ 18, 5, "tx.s_river_n1e0s1w0"
+ 18, 6, "tx.s_river_n0e1s1w0"
+ 18, 7, "tx.s_river_n1e1s1w0"
+ 18, 8, "tx.s_river_n0e0s0w1"
+ 18, 9, "tx.s_river_n1e0s0w1"
+ 18, 10, "tx.s_river_n0e1s0w1"
+ 18, 11, "tx.s_river_n1e1s0w1"
+ 18, 12, "tx.s_river_n0e0s1w1"
+ 18, 13, "tx.s_river_n1e0s1w1"
+ 18, 14, "tx.s_river_n0e1s1w1"
+ 18, 15, "tx.s_river_n1e1s1w1"
; Ocean, and whether terrain to north, south, east, west
; is more ocean (else shoreline)
[spec]
; Format and options of this spec file:
options = "+spec2"
[info]
artists = "
Tim F. Smith <yoohootim@xxxxxxxxxxx>
Daniel Speyer <dspeyer@xxxxxxxxxxxx> (mix)
Frederic Rodrigo <f.rodrigo@xxxxxxxxxxxxx> (mix)
Andreas Røsdal <andrearo@xxxxxxxxxxx> (hex mode)
Jason Short <jdorje@xxxxxxxxxxxx> (hex mixing)
"
[file]
gfx = "isophex/rivers"
[grid_main]
x_top_left = 1
y_top_left = 1
dx = 64
dy = 32
is_pixel_border = 1
tiles = { "row", "column","tag"
; Rivers (as special type), and whether north, south, east, west
; also has river or is ocean:
2, 0, "tx.s_river_n0e0se0s0w0nw0"
2, 1, "tx.s_river_n1e0se0s0w0nw0"
2, 2, "tx.s_river_n0e1se0s0w0nw0"
2, 3, "tx.s_river_n1e1se0s0w0nw0"
2, 4, "tx.s_river_n0e0se0s1w0nw0"
2, 5, "tx.s_river_n1e0se0s1w0nw0"
2, 6, "tx.s_river_n0e1se0s1w0nw0"
2, 7, "tx.s_river_n1e1se0s1w0nw0"
3, 0, "tx.s_river_n0e0se0s0w1nw0"
3, 1, "tx.s_river_n1e0se0s0w1nw0"
3, 2, "tx.s_river_n0e1se0s0w1nw0"
3, 3, "tx.s_river_n1e1se0s0w1nw0"
3, 4, "tx.s_river_n0e0se0s1w1nw0"
3, 5, "tx.s_river_n1e0se0s1w1nw0"
3, 6, "tx.s_river_n0e1se0s1w1nw0"
3, 7, "tx.s_river_n1e1se0s1w1nw0"
4, 0, "tx.s_river_n0e0se1s0w0nw0"
4, 1, "tx.s_river_n1e0se1s0w0nw0"
4, 2, "tx.s_river_n0e1se1s0w0nw0"
4, 3, "tx.s_river_n1e1se1s0w0nw0"
4, 4, "tx.s_river_n0e0se1s1w0nw0"
4, 5, "tx.s_river_n1e0se1s1w0nw0"
4, 6, "tx.s_river_n0e1se1s1w0nw0"
4, 7, "tx.s_river_n1e1se1s1w0nw0"
5, 0, "tx.s_river_n0e0se1s0w1nw0"
5, 1, "tx.s_river_n1e0se1s0w1nw0"
5, 2, "tx.s_river_n0e1se1s0w1nw0"
5, 3, "tx.s_river_n1e1se1s0w1nw0"
5, 4, "tx.s_river_n0e0se1s1w1nw0"
5, 5, "tx.s_river_n1e0se1s1w1nw0"
5, 6, "tx.s_river_n0e1se1s1w1nw0"
5, 7, "tx.s_river_n1e1se1s1w1nw0"
6, 0, "tx.s_river_n0e0se0s0w0nw1"
6, 1, "tx.s_river_n1e0se0s0w0nw1"
6, 2, "tx.s_river_n0e1se0s0w0nw1"
6, 3, "tx.s_river_n1e1se0s0w0nw1"
6, 4, "tx.s_river_n0e0se0s1w0nw1"
6, 5, "tx.s_river_n1e0se0s1w0nw1"
6, 6, "tx.s_river_n0e1se0s1w0nw1"
6, 7, "tx.s_river_n1e1se0s1w0nw1"
7, 0, "tx.s_river_n0e0se0s0w1nw1"
7, 1, "tx.s_river_n1e0se0s0w1nw1"
7, 2, "tx.s_river_n0e1se0s0w1nw1"
7, 3, "tx.s_river_n1e1se0s0w1nw1"
7, 4, "tx.s_river_n0e0se0s1w1nw1"
7, 5, "tx.s_river_n1e0se0s1w1nw1"
7, 6, "tx.s_river_n0e1se0s1w1nw1"
7, 7, "tx.s_river_n1e1se0s1w1nw1"
8, 0, "tx.s_river_n0e0se1s0w0nw1"
8, 1, "tx.s_river_n1e0se1s0w0nw1"
8, 2, "tx.s_river_n0e1se1s0w0nw1"
8, 3, "tx.s_river_n1e1se1s0w0nw1"
8, 4, "tx.s_river_n0e0se1s1w0nw1"
8, 5, "tx.s_river_n1e0se1s1w0nw1"
8, 6, "tx.s_river_n0e1se1s1w0nw1"
8, 7, "tx.s_river_n1e1se1s1w0nw1"
9, 0, "tx.s_river_n0e0se1s0w1nw1"
9, 1, "tx.s_river_n1e0se1s0w1nw1"
9, 2, "tx.s_river_n0e1se1s0w1nw1"
9, 3, "tx.s_river_n1e1se1s0w1nw1"
9, 4, "tx.s_river_n0e0se1s1w1nw1"
9, 5, "tx.s_river_n1e0se1s1w1nw1"
9, 6, "tx.s_river_n0e1se1s1w1nw1"
9, 7, "tx.s_river_n1e1se1s1w1nw1"
}
- [Freeciv-Dev] (PR#9379) hex tilesets and rivers,
Jason Dorje Short <=
|
|