Let’s try that again…
2009/7/23 Ken Rogoway
If your game is using 2d art (vs. 3d models) then you can also use a mask
for each map tile and just test against the mask. ?This can be much simpler
to do; at least for 2d tile based games.
Like this:
bool pointontile(SDL_Surface* surface, int x, int y) {
Uint8* ptr = (Uint8*) surface->pixels + y * surface->pitch + x *
surface->format->BytesPerPixel;
return (((Uint32) ptr) & surface->format->Amask) != 0;
}
…
/* figure out what tile you’re over… /
/ for tiles in this order: below and right, below, below and left,
right, and at position… / {
if (pointontile(tile.image, mousex-tile.x, mousey-tile.y)) {
/ do stuff… */
break;
}
}
If all your tiles are the same size and don’t overlap though, then
this would be pretty wasteful.
Either way, you need to figure out what tile you’re over.
Let’s say you have a 32x32 square tile. Square tiles are pretty easy…
#define TILEWIDTH 32
#define TILEHEIGHT 32
void gettilepos(int pixelx, int pixely, int& tilex, int& tiley) {
tilex = pixelx / TILEWIDTH;
tiley = pixely / TILEHEIGHT;
}
Let’s say you have a 64x32 diamond shaped tile. Tiles in a row are
spaced 64 pixels apart. The second row is offset by 32x16 from the
first. The third row is offset by -32x16 from the second and 0x64
from the first. If this seems familiar, you’ve probably been playing
Furcadia.
#define TILEWIDTH 64
#define TILEHEIGHT 32
void gettilepos(int pixelx, int pixely, int& tilex, int& tiley) {
int divx = pixelx / TILEWIDTH, modx = (pixelx % TILEWIDTH);
int divy = pixely / TILEHEIGHT, mody = (pixely % TILEHEIGHT);
tilex = divx;
tiley = divy*2;
if (mody * 2 < TILEHEIGHT) {
if ((modx+1) * 2 * TILEHEIGHT < (TILEHEIGHT - mody*2) * TILEWIDTH) {
--tilex;
--tiley;
}
if (((modx-1) * 2 - TILEWIDTH) * TILEHEIGHT >= mody*2 * TILEWIDTH) {
--tiley;
}
} else {
if ((modx+1) * 2 * TILEHEIGHT < ((mody+1) * 2 - TILEHEIGHT) * TILEWIDTH) {
--tilex;
++tiley;
}
if (((modx-1) * 2 - TILEWIDTH) * TILEHEIGHT >= (TILEHEIGHT -
(mody+1))*TILEWIDTH * 2) {
++tiley;
}
}
}
Now let’s say you have a Wesnoth style hex tile. The top and bottom
of the hexagon are both 36 pixels. The sides are at a 1:2 angle and
are 18x36 pixels. The bounding box for each tile is 72x72 pixels.
Tiles in a row are spaced 108 pixels apart. The second row is offset
by 54x36 pixels from the first row. The third row is offset by -54x36
pixels from the second and 0x72 pixels from the first.
#define FLATSWIDTH 36
#define SIDEWIDTH 18
#define SIDEHEIGHT 36
#define TILEWIDTH (FLATSWIDTH+2SIDEWIDTH)
#define TILEHEIGHT (2SIDEHEIGHT)
#define ROWSPACING (2*(FLATSWIDTH+SIDEWIDTH))
void gettilepos(int pixelx, int pixely, int& tilex, int& tiley) {
int divx = pixelx / ROWSPACING, modx = pixelx % ROWSPACING;
int divy = pixely / TILEHEIGHT, mody = pixely % TILEHEIGHT;
tilex = divx;
tiley = divy * 2;
if (mody < SIDEHEIGHT) {
if (modx < SIDEWIDTH) {
if (modx * SIDEHEIGHT < (SIDEHEIGHT - mody) * SIDEWIDTH) {
--tilex;
--tiley;
}
} else {
modx -= SIDEWIDTH + FLATSWIDTH;
if (modx >= 0 && (modx >= SIDEWIDTH || modx * SIDEHEIGHT >= mody *
SIDEWIDTH))
–tiley;
}
} else {
mody -= SIDEHEIGHT;
if (modx < SIDEWIDTH) {
if (modx * SIDEHEIGHT < mody * SIDEWIDTH) {
–tilex;
++tiley;
}
} else {
modx -= SIDEWIDTH + FLATSWIDTH;
if (modx >= 0 && (modx >= SIDEWIDTH || modx * SIDEHEIGHT >=
(SIDEHEIGHT - mody) * SIDEWIDTH))
++tiley;
}
}
}
(this one acts funny when passed negative values, so don’t do that)
There’s a test program for these functions attached.
-------------- next part --------------
A non-text attachment was scrubbed…
Name: test.cpp
Type: text/x-c++src
Size: 4223 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20090724/5507bd8b/attachment.cpp