views:

81

answers:

2

I wasn't sure what to call this. I'm building a tile based game where the user can click on a tile. it is a 2d c++ vector of tiles. right now I have an algorithm that positions them like this:

[][][][][][][][][][][]
[][][][][][][][][][][]
[][][][][][][][][][][]
[][][][][][][][][][][]
[][][][][][][][][][][]
[][][][][][][][][][][]

they are positioned based on their size and my tile class holds each of their x and y coordinates, and I have 2 variables for the height and width.

Basically I'd like to find an algorithm that can return the tile my mouse is on based on the mouse's position.

For example: if my mouse (relative to the game window)'s position is 37,0 and each of my tiles is 10 * 10 in size and they are each tilewidth apart then by having my mouse over 37,0 it should return (4,1) meaning the 4th element on the x and the first element on the y. I thought about doing bounding box checks against each rectangle but I think that will use up too much cpu if i check 60 times / second.

Thanks

+3  A: 

According to the comments, it's claimed Allegro doesn't have mouse events. Not true. See Mouse routines.

extern void (*mouse_callback)(int flags);

Called by the interrupt handler whenever the mouse moves or one of the buttons changes state. This function must be in locked memory, and must execute very quickly! It is passed the event flags that triggered the call, which is a bitmask containing any of the values MOUSE_FLAG_MOVE, MOUSE_FLAG_LEFT_DOWN, MOUSE_FLAG_LEFT_UP, MOUSE_FLAG_RIGHT_DOWN, MOUSE_FLAG_RIGHT_UP, MOUSE_FLAG_MIDDLE_DOWN, MOUSE_FLAG_MIDDLE_UP, and MOUSE_FLAG_MOVE_Z. Note that even if the mouse has more than three buttons, only the first three can be trapped using a callback.

Alternatively you can use get_mouse_mickeys() to speed up your checking.

void get_mouse_mickeys(int *mickeyx, int *mickeyy);

Measures how far the mouse has moved since the last call to this function. The values of mickeyx and mickeyy will become negative if the mouse is moved left or up, respectively. The mouse will continue to generate movement mickeys even when it reaches the edge of the screen, so this form of input can be useful for games that require an infinite range of mouse movement.

Note that the infinite movement may not work in windowed mode, since under some platforms the mouse would leave the window, and may not work at all if the hardware cursor is in use.

So if you check lots of times a second and this function returns 0 for each of X and Y there's no need to recheck what the mouse is pointing at because it hasn't moved.

That being said, use the mouse callback. It's the most efficient way.

As for how to handle what tile you're pointing out, I would handle it this way: at some point you're rendering the pixels. Either you're using a frame buffer or you should be able to create one. For each pixel, if you're rendering a tile, store a pointer to that tile in a pixel map. That means 4 bytes (assuming 32 bit pointers) per pixel but at, say, 1280x1024, you're using a little over one megabyte of RAM to store what tile is at each (x,y) coordinate and your lookups will be incredibly fast.

cletus
+1  A: 

If you're not using an event based environment, you do need to code your own object intersection, mouse detection, etc.

Here's the formula in pseudo code for what you want to get:

tile_width = 10;
tile_height = 10;

x_tile = Math.ceil(mousex/tile_width);
y_tile = Math.ceil(mousey/tile_height);
milesmeow