Complete.Org: Mailing Lists: Archives: freeciv-dev: February 2005:
[Freeciv-Dev] (PR#12356) correct gui_to_map_pos for hex tiles
Home

[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]
Subject: [Freeciv-Dev] (PR#12356) correct gui_to_map_pos for hex tiles
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 25 Feb 2005 15:16:43 -0800
Reply-to: bugs@xxxxxxxxxxx

<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 <=