math problems

Started by
8 comments, last by Trienco 10 years ago

I am trying to implement accurate selection tool for my level editor that would be able to use both isometric tiles and isometric hexagons. with the same sprite dimensions. I am now focusing on getting regular isometric tile to work properly.

Below is the color coded isometric tile that i will be using (it will be transparent with only lines visible, this one is for explanation only). I want my program to register specific tile if the cursor is only in green area.

tile_spr.jpg

The sprite has dimensions of 192x96. How do I calculate if the mouse is only in green area? Since from what I find everything is based on rectangle logic, because I check X, and Y coordinates of the mouse.

From here I have something like

if(mouse.x > 0 && mouse.y < 48)

if(mouse.x < 96 && mouse.y < 48)

select tile

but these coordinates also catch stuff from red triangle area in top left.

Advertisement

Im not an expert on the subject, but i beleive what you want is a test to check if a point is inside a polygon. Here's some code that should work.

I'm curious, how are you storing the tile information in memory? Is this a 3D engine with the view set to this 2.5D viewing angle, or are you displaying everything in 2D? I only ask because while it would be easy to take the four corners of each tile and perform a point-in-polygon test, if the tiles are not drawn in pixel space, but a world space mapped to the screen space, the mouse coordinates will need to be converted, in which case probably a ray cast or a picking algorithm would be easier.

But again, this could go from really easy to really hard, depending on where the engine goes and how the level is stored for use in the game.

I think, therefore I am. I think? - "George Carlin"
My Website: Indie Game Programming

My Twitter: https://twitter.com/indieprogram

My Book: http://amzn.com/1305076532

Another common technique is to store a copy of that image above (simplified to save memory)

Then to test for a click on a tile you build a list of tiles it could be (usually only two) convert the coordinate into a relative one for the tile and pick from the stored image.

If the colour you pick up is green, you have the tile.

I think it would probably be easier to do a ray polygon check, but this is the way we used to do it when floating point was expensive.

have a look at http://content.gpwiki.org/OpenGL_Selection_Using_Unique_Color_IDs

This is all completely 2D stuff. What I did is, I created grid using one sprite and simply placing it on calculated X and Y coordinates to form a grid.

I am looking into point in polygon stuff, but I am not sure how to do this yet. This is what I am testing with


// triangle to test against
sf::ConvexShape hex;
hex.setPointCount(3);
hex.setPoint(0, sf::Vector2f(0, 0));
hex.setPoint(1, sf::Vector2f(96, 0));
hex.setPoint(2, sf::Vector2f(0, 48));


// check coordinates if inside the triangle
if(Mouse.x >= hex.getPoint(0).x && Mouse.y >= hex.getPoint(0).y)
  if(Mouse.x <= hex.getPoint(1).x && Mouse.y >= hex.getPoint(1).y)
    if(Mouse.x >= hex.getPoint(2).x && Mouse.y <= hex.getPoint(2).y)
    {
	diamond.setPosition(0, 0); // this is tile marker - it will highlight the tile mouse pointer hovers over
    }

Something is off since I am still in rectangle calculation and not triangle. Am I on the right track?

EDIT: I found this - http://www.geeksforgeeks.org/how-to-check-if-a-given-point-lies-inside-a-polygon/ - looks close to the first reply, and this does answer my question. Thanks for help everyone.

If your map is diamond shaped and all tiles are flat and regular, the easiest way is to just convert from world to tile coordinates without fancy look ups or unnecessarily generic point-in-geometry tests.

const int tile_x = x/192 + y/96;
const int tile_y = y/96 - x/192;
x and y are world coordinates in relation to the rectangle around your map (so mouse coordinates need to be adjusted for scrolling and zooming).
Or just base your math on the simple idea that your map is a rectangular grid rotated by 45° and 60°, transform your mouse coordinates accordingly and you should get the same result (essentially the above).
Getting a feeling for this mapping/transformation also helps if you want to combine 3D objects with a 2D iso map or visualize internal 3D info for debugging. For example, the internal data used in Jagged Alliance 2 for line of sight etc. (video)
f@dzhttp://festini.device-zero.de

const int tile_x = x/192 + y/96;
const int tile_y = y/96 - x/192;


Be careful with integer division. If x and y are integers, you may want to do the computations differently. For instance:
const int tile_x = round(x/192.0 + y/96.0);
const int tile_y = round(y/96.0 - x/192.0);

Be careful with integer division. If x and y are integers, you may want to do the computations differently. For instance:


const int tile_x = round(x/192.0 + y/96.0);
const int tile_y = round(y/96.0 - x/192.0);

Good point, I neglected to mention that x and y were meant to be float (in my code the zooming and scrolling was already applied).

I also should have pointed out that the result is the x and y index of the selected tile (not any kind of transformed coordinate within the iso map). So (0,0) would be the topmost tile, with x going right and down and y going left and down.

Generally the only time you want to treat the map as anything but a rectangular grid of squares is to draw the map and for picking (and technically you're transforming the mouse position to the simple non-iso grid). Things can get less neat if you decide that picking should handle irregular tiles or overlapping sprites.

f@dzhttp://festini.device-zero.de

Or just base your math on the simple idea that your map is a rectangular grid rotated by 45° and 60°, transform your mouse coordinates accordingly and you should get the same result

Wouldn't this actually be more complicated? I would need to create regular greed and rotate it 45 degrees, and than additionally transform mouse coordinates. Seems interesting but I am not quite sure how I would handle data in this case. Would I save out all data as if it was square greed and transform it on run-time?

Wouldn't this actually be more complicated? I would need to create regular greed and rotate it 45 degrees, and than additionally transform mouse coordinates. Seems interesting but I am not quite sure how I would handle data in this case. Would I save out all data as if it was square greed and transform it on run-time?

You need to separate the internal logic of your game and how you visualize it. When your characters move from tile to tile, you don't think "iso". When you determine line-of-sight, you don't think "iso". The iso perspective only exists on your screen and the only time you should give yourself an iso-head ache is for rendering and mouse input.

I'm not saying "draw a rectangular grid and transform it", I'm saying "think of the non-rotated top-down view as much as you can".

How are you storing your grid in memory?

f@dzhttp://festini.device-zero.de

This topic is closed to new replies.

Advertisement