[Freeciv-Dev] (PR#12356) correct gui_to_map_pos for hex tiles
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=12356 >
This patch makes gui_to_map_pos work properly for hex tiles.
Previously for hex tiles the function just used the isometric fallback.
This means mouse clicks and other actions don't follow the true
boundaries of the tile but behave as if the view were rectangular
isometric. This patch fixes it by completely re-implementing
gui_to_map_pos, in a completely different way, for hex tiles (this is
loosely based on the algorithm Wesnoth uses - see
pixel_position_to_hex() in display.cpp - although freeciv is quite
different internally so the code itself doesn't look at all the same).
This is a bugfix so should probably go to both branches.
Anyone interested in linear algebra should take a look at this and see
if you can understand it, or what/where documentation should be added (a
picture would help but I've given up on ascii art).
To prove that it works, see
http://freeciv.org/~jdorje/masks-hw.png
http://freeciv.org/~jdorje/masks-hh.png
-jason
? mask-128x64.png
? mask-12x6.png
? mask-16x8.png
? mask-192x96.png
? mask-24x12.png
? mask-256x128.png
? mask-2x1.png
? mask-32x16.png
? mask-48x24.png
? mask-4x2.png
? mask-64x32.png
? mask-8x4.png
? mask-96x48.png
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.195
diff -u -r1.195 mapview_common.c
--- client/mapview_common.c 24 Feb 2005 01:56:40 -0000 1.195
+++ client/mapview_common.c 25 Feb 2005 23:02:39 -0000
@@ -224,8 +224,45 @@
static void gui_to_map_pos(int *map_x, int *map_y, int gui_x, int gui_y)
{
const int W = NORMAL_TILE_WIDTH, H = NORMAL_TILE_HEIGHT;
+ const int HH = hex_height, HW = hex_width;
- if (is_isometric) {
+ if (HH > 0 || HW > 0) {
+ /* To handle hexagonal cases we have to revert to a less elegant method
+ * of calculation. */
+ int x, y, dx, dy;
+ int xmult, ymult, xmod = 0, ymod = 0;
+
+ assert(is_isometric);
+
+ x = DIVIDE(gui_x, W);
+ y = DIVIDE(gui_y, H);
+ dx = gui_x - x * W;
+ dy = gui_y - y * H;
+ assert(dx >= 0 && dx < W);
+ assert(dy >= 0 && dy < H);
+
+ /* Now fold so we consider only one-quarter tile. */
+ xmult = (dx >= W / 2) ? -1 : 1;
+ ymult = (dy >= H / 2) ? -1 : 1;
+ dx = (dx >= W / 2) ? (W - dx) : dx;
+ dy = (dy >= H / 2) ? (H - dy) : dy;
+
+ if (HW > 0) {
+ if ((dx - HW / 2) * (H / 2) - (H / 2 - dy) * (W / 2 - HW) < 0) {
+ xmod = -1;
+ ymod = -1;
+ }
+ } else {
+ assert(HH > 0);
+ if ((dy - HH / 2) * (W / 2) - (W / 2 - dx) * (H / 2 - HH) < 0) {
+ xmod = -1;
+ ymod = -1;
+ }
+ }
+
+ *map_x = (x + y) + (xmod * xmult + ymod * ymult) / 2;
+ *map_y = (y - x) + (ymod * ymult - xmod * xmult) / 2;
+ } else if (is_isometric) {
/* The basic operation here is a simple pi/4 rotation; however, we
* have to first scale because the tiles have different width and
* height. Mathematically, this looks like
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Freeciv-Dev] (PR#12356) correct gui_to_map_pos for hex tiles,
Jason Short <=
|
|