Isometric tile coordinates

Forums Programming cocos2d support (graphics engine) Isometric tile coordinates

This topic contains 11 replies, has 6 voices, and was last updated by  clayh 1 year, 11 months ago.

Viewing 12 posts - 1 through 12 (of 12 total)
Author Posts
Author Posts
January 30, 2011 at 8:58 pm #228009

gavinb
Participant
@gavinb

Hi all

I am having a play around will tile maps via Cocos2D (for mac) and have some basics working, Ie I can scroll the map around and select a tile within the map and get the relative coordinate in the grid.

The part thats baffling me at the moment is working out the correct screen coordinate of the centre of the tile. I am trying to place a sprite upon the tile when it is selected. I’ve tried doing:

x = map.position.x + (tilecoord.x * 64);
y = map.position.y + (tilecoord.y * 64)

but this is obviously completely wrong, I’ve played with other various reworkings of the above, but none do the trick,

Any ideas of a working formula would be much appreciated

thanks in advance

Gav

January 30, 2011 at 9:59 pm #312616

itlgames
Moderator
@itlgames

On isometric, your tile height should be half the tile width, so from memory, did you use:

x = map.position.x + (tilecoord.x * 64);
y = map.position.y + (tilecoord.y * 32);

Assuming 64 is your tile width.

Anyway a good reference tutorial, in Flash but should be easy to port, it helped me a lot when did my isometric engine, scroll down the page to find the iso section:

http://www.kirupa.com/developer/actionscript/

January 31, 2011 at 12:05 am #312617

Benihana
Participant
@benihana

Have you looked at (note that there are two pages):

http://www.raywenderlich.com/1163/how-to-make-a-tile-based-game-with-cocos2d

No reason to write code from scratch when you can borrow it from someone else. ;)

January 31, 2011 at 9:12 am #312618

itlgames
Moderator
@itlgames

I think his question is more about the isometric coordinates, so how to convert from isometric map coordinates to screen coordinates, on those Flash tutorials they explain how to convert from screen to map coordinates and vice-versa.

On isometric games we play with two sets of coordinates, one is the real screen position, and another is the position on our isometric map, so we need a way to convert those coordinates from one system to another. On my game I came up with my own solution, but there are different ways to do it really. This is one way:

http://www.kirupa.com/developer/actionscript/isometric_transforms.htm

EDIT: the formula I suggested on my previous post is wrong, was just an quick idea from memory.

January 31, 2011 at 9:21 am #312619

Benihana
Participant
@benihana

Aww shoot. I need to drink more coffee (or less?). I posted in another thread recently and didn’t realize he was having the problem only when he ran using the leaks instrument, even though that was in both the title and body of his post.

January 31, 2011 at 9:36 am #312620

itlgames
Moderator
@itlgames

Yeah, it’s also cos he only put “Isometric” on the title, not the body of the post, so I had to read it twice.

January 31, 2011 at 10:26 am #312621

gavinb
Participant
@gavinb

Many thanks guys for your help!

I have looked at the Ray Wenderlich tutorial but this only seems to cover off Orthogrpahic tiles, which doesnt translate to isometric tile maps.

@itlgames – thanks, will have a look at that flash tutorial to see if it helps. Big thanks to all :)

February 1, 2011 at 9:11 pm #312622

gavinb
Participant
@gavinb

Just incase it helps anyone else. I couldn’t find an answer so worked it out the old fashioned way (on paper) and came up with this function:

- (CGPoint)positionForTileCoord:(CGPoint)tileLocation : (CGPoint)offset :(CGSize)mapSize{

int x = (offset.x + (mapSize.width*64)) + ((tileLocation.x-tileLocation.y)*64);
int y = (offset.y + (mapSize.height*64) - 32) - ((tileLocation.y+tileLocation.x)*32);
return ccp(x,y);
}

It takes 3 parameters.

tileLocation – the position within your grid of the tile you want a coordinate for (i.e tile 3, 2)

offset – this for me, is the x, y position of the map I am using

mapsize – this is the amount of tiles in the map (width and height) I just pass the mapSize of the CCTMXTiledMap.

This may not be the most effecient way to do it, but it seems to work!!

http://www.youtube.com/watch?v=2FjxTymwHGQ

April 26, 2011 at 5:01 am #312623

phpbug
@phpbug

Hi Guys,

Hope is not too late to post here for asking questions. I’m following tutorial on this website

http://www.raywenderlich.com/1186/collisions-and-collectables-how-to-make-a-tile-based-game-with-cocos2d-part-2

Everything working fine except for the collisions, i’m using the map editor java version where enable me to view at the coordinate.

I’ve set several tile in meta layer where those area are not allow player to go there.

Example (8,9) is the tile that block user from entering but then i try it on the game by using a function to conver the coordinate in game to tile, it seems bit off. It turn out to be (10,9) where it block player from going.

This is the function that i borrow to convert x and y from map in iPhone to tile map

// Tilemap position must be subtracted, in case the tilemap position is not at 0,0 due to scrolling
CGPoint pos = ccpSub(location, tileYamatoMap.position);

float halfMapWidth = tileYamatoMap.mapSize.width * 0.5;
float mapHeight = tileYamatoMap.mapSize.height;

float tileWidth = (tileYamatoMap.tileSize.width);
float tileHeight = (tileYamatoMap.tileSize.height);

CGPoint tilePosDiv = CGPointMake(pos.x / tileWidth, pos.y / tileHeight);
float inverseTileY = mapHeight - tilePosDiv.y;

// Cast to int makes sure that result is in whole numbers, tile coordinates will be used as array indices
float posX = (int)(inverseTileY + tilePosDiv.x - halfMapWidth);
float posY = (int)(inverseTileY - tilePosDiv.x + halfMapWidth);

// make sure coordinates are within isomap bounds
posX = MAX(0, posX);
posX = MIN(tileYamatoMap.mapSize.width - 1, posX);
posY = MAX(0, posY);
posY = MIN(tileYamatoMap.mapSize.height - 1, posY);
pos = CGPointMake(posX, posY);

CCLOG(@"touch at (%.0f, %.0f) is at tileCoord (%i, %i)", location.x, location.y, (int)pos.x, (int)pos.y);
//CCLOG(@"tinverseY: %.2f -- tilePosDiv: (%.2f, %.2f) -- halfMapWidth: %.0fn", inverseTileY, tilePosDiv.x, tilePosDiv.y, halfMapWidth);
return pos;

My map size is 20×20 and my tile size is 32 x 16.

is it because of my tile size that is too large?, seems like i can’t get the right coordinate on tile

November 10, 2011 at 10:14 pm #312624

tutor
@tutor

Hi, everyone.

I have a question to member “gavinb”

I watched your youtube movie from previous post

you used the method :

- (CGPoint)positionForTileCoord:(CGPoint)tileLocation : (CGPoint)offset :(CGSize)mapSize{

int x = (offset.x + (mapSize.width*64)) + ((tileLocation.x-tileLocation.y)*64);

int y = (offset.y + (mapSize.height*64) – 32) – ((tileLocation.y+tileLocation.x)*32);

return ccp(x,y);

}

in method ccMouseUp and i saw that you called it something like that [self positionForTileCoord:newLocation :_tileMap.position :_tileMap.something<cant't see ))) >];

I am interested what values stored in newLocation and last parameter.

because i have similar problem and can’t find a solution, I am very grateful for the help

Thank you anyway, have a nice day to all

P.S. sorry for my English

I just learning it now )

May 2, 2012 at 3:53 am #312625

clayh
Participant
@clayh

This caused me some headache today. I have a scrollable isometric map and I wanted the user to be able to tap a building to select it. I have a SelectionController singleton that handles all ramifications of selecting an object in the game world. I detect touches in my MapLayer:

- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

{

if ([touches count] == 1) {

// Select the item underneath

CGPoint touchLocGL = [self locationFromTouch:[touches anyObject]];

//CCLOG(@"touchedPoint: %@", NSStringFromCGPoint(touchLocGL));

CGPoint coord = [self tileCoordFromLocation:touchLocGL tileMap:currentMap];

[[SelectionController sharedSelectionController] selectionAtCoord:coord];

}

}

-(CGPoint) locationFromTouch:(UITouch*)touch

{

CGPoint touchLocation = [touch locationInView: [touch view]];

return [[CCDirector sharedDirector] convertToGL:touchLocation];

}

The SelectionController checks out the coordinates and selects the appropriate building, updating a UI label and telling the MapLayer where to draw the selection circle:

- (void)selectionAtCoord:(CGPoint)coord

{

NSString *updatedLabel = @"";

NSMutableDictionary *buildings = [gameWorld buildings];

for (NSString *key in buildings) {

Building *b = [buildings objectForKey:key];

if (.x == coord.x && .y == coord.y) {

// found the building

updatedLabel = ;

[self setSelectedObject:b];

[self setHaveActiveSelection:YES];

break;

}

[self setHaveActiveSelection:NO];

}

// Update the label

[[[MainGameScene sharedLayer] uiLayer] updateSelectionLabel:updatedLabel];

// Draw the selection circle

if (haveActiveSelection) {

[self drawSelectionCircleAtCoord:coord];

} else {

[[[MainGameScene sharedLayer] mapLayer] setActiveSelectionExists:NO];

}

}

- (void)drawSelectionCircleAtCoord:(CGPoint)coord

{

// Get the layer with the map

MapLayer *mapLayer = [[MainGameScene sharedLayer] mapLayer];

// Get the position of the tile matching the incoming tile coordinates (4,12), for example

// The y value of coord is reduced by 1 to line things up appropriately

CGPoint tilePosition = [[[mapLayer currentMap] layerNamed:@"Ground"] positionAt:ccp(coord.x, coord.y - 1)];

// This uses the current map's position as an offset for the tile position, to match with screen coordinates

tilePosition = ccpAdd(tilePosition, [[mapLayer currentMap] position]);

// Fudge factor to make it appear more centered (for me, this is 1/2 of my tile height)

tilePosition.y += 13;

// This sets the approprate coordinate for the tile in my mapLayer

[mapLayer setActiveSelectionCoords:tilePosition];

// This switch tells the map layer to draw a circle at the tilePosition I just provided

[mapLayer setActiveSelectionExists:YES];

}

- (void)updateActiveSelectionLocation

{

if (haveActiveSelection) {

[self drawSelectionCircleAtCoord:selectedObject.coords];

}

}

The user might have an active selection when scrolling, so the final method above is called when the user scrolls the map — it simply updates the draw location for the selection circle.

The code probably is a bit clunky, but it works for me. Maybe it will help save somebody some headache here.

May 2, 2012 at 3:56 am #312626

clayh
Participant
@clayh

p.s. Which HTML tags do I use to make the code not look like crap? block quote? the code tags don’t seem to work properly.

Viewing 12 posts - 1 through 12 (of 12 total)

You must be logged in to reply to this topic.