iPhone Game Programming – Tutorial 6 – Tiled Map Class
The next installment of the 71Squared iPhone Programming tutorials is now available. This tutorial covers a tile map class which can consume configuration files created using the Tiled map editor.
The Tiled editor can be found here.
Tile maps allow you to create large images or playing areas within your game using smaller tile images. Rather than have a large single background image, you create your background by using smaller tile images placed together.
There is no reason why this could not be as simple as an array which holds the x and y location within a tile map and for each given location an id is stored which identifies the tile to be rendered for that tile in the map. This is basically how the Tiled class works. The only difference is that the Tiled editor allows you to have multiple layers and tilesets in a single map along with user defined properties.
Once you have created your map using the Tiled tool it saves the map as an XML file. This XML file along with the spritesheets that was selected for your tilesets can then be copied into your iPhone project and referenced using the TiledMap class.
Tile maps are useful in a number of areas. Not only can they let you create very large playing area within your game from a number of small images, but it can be used within collision detection. You can easily work out which tile the player is within on the tile map and also for all the baddies. You can then only check for a collision between the player and baddies who are in the adjacent tiles reducing the number of collisions checks which need to be done.
As usual the Tutorial 6 project has been posted below as well.
I hope you enjoy this tutorial. As always feedback and comments are welcome and I hope to have the next tutorial on the Particle System up as soon as possible.
Mike
123 Comments
iamflimflam1 on May 8th, 2009
Thanks for fantastic tutorial.
I’ve been wanting to try my hand at writing a game for ages but found the whole openGL stuff completely opaque. There’s nothing like some example code to finally give you that “aha!” moment of understanding.
rilu on May 8th, 2009
Thanks for all the great tutorials, they seemed to be the only ones i could find that were well done and simple to understand.
I have one question. When i launch the glView from a different view (other than app delegate at start of app), everything works fine except for animations,font, and tile map – are opengl apps only suppose to work when launched from app delegate?
Anonymous on May 8th, 2009
Very good tutorials! Some few things are missing
though such:
- How to make the game full screen and get rid
of the status bar on the top of the screen.
- How to play music & sound effects.
- How to get use of the accelerometer & touch
screen to get player controls.
Any chance you’ll be able to supply a tutorial
on these small topics?
Thank you very much.
Tom on May 9th, 2009
You can remove the status bar in your application by editing the info.plist file in the resources folder within your project. You need to do the following.
- Right click on the property table and select “Add Row”
- Enter “UIStatusBarHidden” as the key and press enter
- Right click the new row and select “Value Type->Boolean”
- Tick the checkbox, compile and run
game time Blog » Blog Archive » Technical Lead -Video Game Content Creation/Scripter-Lua/C++ on May 9th, 2009
[...] 71² » iPhone Game Programming – Tutorial 6 – Tiled Map Class [...]
mike on May 9th, 2009
You can also remove the status bar by placing the following line in your applicationDidFinsihLoading method in the app delegate.
// Hide the status bar at the top of the screen [[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];
I will be covering music, sound effects and accelerometer in the coming tutorials :o)
Mike
mike on May 9th, 2009
@rilu, I’m not sure what the problem could be. There should be no problems with having an OpenGL view created by other classes etc. It seems odd all is ok apart from Animation.
If you have a project you can send to me that shows the problem I’ll take a look.
Mike
Praveen on May 10th, 2009
Hi Mike,
I am new to iPhone. I started iPhone programming a few days ago.
Ur tutorials are so far the best that I have come across.
I am planning to use some of your code in developing the applications.
I started to use iphone SDK 3.0
The main game loop doesnt seem to run with the CFRunLoopRunInMode. I havnt found a better solution yet.
The original version of startAnimation is working.
Thanks again for the awesome tutorials.
mike on May 10th, 2009
Hi Praveen, I’m really pleased your finding the tutorials useful and good luck with your project. If you get stuck at all don’t hesitate to comment on the blog as I’m happy to help out as are others who also comment on the blog as well.
There appear to be changes in the 3.0 SDK which are causing the code in the tutorials to not work correctly. I’m upgrading to 3.0 today in fact so I I’m going to test all my code on it and make the necessary changes.
For the mainGameLoop I’m currently using an NSTimer to call the method every 60 seconds but I still have the CFRunLoopRunInMode within that method as this processes any events on the OS queue such as touches etc.
Once I’ve had a look at my code running in 3.0, I’ll post any changes which need to be made.
Mike
mike on May 10th, 2009
@Praveen, I’ve just upgraded to SDK 3.0 Beta 5 on my iPod and tried my Tutorial 6 code. I got the same as you, a blank screen. I’m not sure what the problem is with having the gameLoop just running as a closed while loop, but there is a change you can make so that it works on 3.0.
Rather than having the mainGameLoop a closed while loop, if you move to using an NSTimer then it works fine. I’ve made that change to the Tutorial 6 project code, so if you download it now you should find that it works ok on SDK 3.0 Beta 5.
I’ll look into why it was not working but at the moment I’m not sure. I’ve been playing with moving back to an NSTimer anyway :) so this is not such a bad thing.
Let me know how you get on.
Mike
Greg on May 10th, 2009
I’ve noticed a few times that you’ve done something like this:
mapPoint.x -= 0.1 * delta; if(mapPoint.x j) x = 0; } while (1)
As you can see, you’d have gone from 8, back to 0, a jump of 2 instead of the expected 4.
But if instead you use:
if (x > j) x -= j;
Then x would progress: 0, 4, 8, 2, 6, 10, 0, 4… which smoothly jumps 4 per iteration.
I’m not sure if the scale of “anomaly” has much effect in your implementation, but it’s just something I noticed.
Greg
Greg on May 10th, 2009
Oooops, using less than and greater than signs messed up my last comment. I’ll try again using text.
I’ve noticed a few times that you’ve done something like this:
mapPoint.x -= 0.1 * delta;
if(mapPoint.x < (int)-[tileMap tileWidth]) {
mapPoint.x = 0;
tileMapX += 1;
}
The 3rd line "should" be:
mapPoint.x += -[tileMap tileWidth]
Because setting it to ’0′ *might* produce a jerkiness depending on *how much less* mapPoint.x is.
It’s easier to see with whole numbers:
int x = 0;
int j = 10;
do{
x += 4;
if (x > j) x = 0;
} while (1)
As you can see, you’d have gone from 8, back to 0, a jump of 2 instead of the expected 4.
But if instead you use:
if (x > j) x -= j;
Then x would progress: 0, 4, 8, 2, 6, 10, 0, 4… which smoothly jumps 4 per iteration.
I’m not sure if the scale of “anomaly” has much effect in your implementation, but it’s just something I noticed.
Greg
mike on May 10th, 2009
Hi Greg and thanks for the feedback. I had never even considered the anomaly that could be caused by doing what I was doing. I have been seeing a very small amount of jerkiness when moving the tilemap and making the change you have suggested seems to have removed it, so a top tip and much appreciated.
Mike
abbasi on May 12th, 2009
hi i found your tutorial very useful thanks for posting it. Justed wanted to ask a quick question. When i create a map using tiled 0.7.2 the tmx file generated is not in the same format as yours and the tiles are not shown on the iphone screen. so just wanted to know how to create a map in the format which you have created. wanted to know the tool and the version.Waiting for a prompt response….
mike on May 12th, 2009
Hi abbasi
I am also using version 0.7.2. There are some configuration changes which you need to make to get the output matching that which is produced in the tutorial.
When in Tiled select Edit > Preferences and then the Saving tab. Within this tab all options should NOT be ticked. This will then cause tiled to output raw XML which can then be read by the Tiled class.
I’m working on being able to use the base64 encoded gzip output which is created by default, but this is down the list at the moment.
Hope that helps.
Mike
abbasi on May 12th, 2009
yea i guessed it right options on this screen were not right anywayz dont u think its hectic parsing the xml file and loading the tiles one by one for the base64 case the map can be saved as tmx and tga file and used in the app without parsing This guy gas done it but i am having a hard with that as well if u can come up with some kind of solution like it this it would be really helpful http://kwigbo.com/wp/2009/03/2...../#comments
anywayz thankx for the prompt reply.
Tenchy on May 12th, 2009
Hi Mike,
First of all let me tell you that your tutorials are simple incredible and the are really helpful. I have followed them all, and i’m willing for more.
I’m writing a little game and using your tutorials but i have a big problem i really don’t know how to solve. I need to draw in screen the same mobe many times so for improving memori usage i have created a NSMutableArray to store all the images i will use in my game and every time i need a new enemy i simpli generate a new image from one of the ones in that array, but the proble comes when i draw them in the screen becouse the currentTexture variable is not updating properly and it uses the font texture to draw the enemys.
Sorry if i haven’t explained well.
Thx in advance
mike on May 12th, 2009
Hi Tenchy, I’m pleased you are finding the tutorials useful and I appreciate your kind words.
I think I understand your comment, but have you got any code you can share with me. There are so many ways of putting this stuff together its easier to see the code on these things to work out what is happening :o)
If you can email to me any code you can share I’d be happy to have a look for you.
Also, are you using the Image class to perform all the drawing? It sounds like text is being rendered to the screen and the new texture for the mobe is not being bound before it is being rendered.
The email address is mike@blog_domain.co.uk
Mike
raja on May 13th, 2009
Hi mike,
This is raja,First of all thank for u doing such a great job.I am new to iPhone. I started iPhone programming a few days ago.
Ur tutorials are so far the best that I have come across.
I am planning to use some of your code in developing the applications.
raja on May 13th, 2009
I am also following ur tutorial from few days.Is there any doubt, plz help me,because i am new to this iphone
Thanking u,
Raja.
Tenchy on May 13th, 2009
I’ll email you some code later, becouse this is driving me crazy, but while trying to sort out my problem i thing i came a cross whit a little bug in the AngelCodeFont class that may couse problems in the future.
In the drawStringAt when you bind the texture, to later on draw the full string in the screen, ther should be an update of the currenTexture becouse if this is not done and later you plan to draw an image on screen the texture won’t be binded becouse it did that in the las iteration so he thinks that the texture is already binded.
About my problem i found that for a reason i still don’t understend the [appDelegate setCurrentTexture:(int)] is not always executing abd for that reason the currentTexture is not update.
Tenchy on May 13th, 2009
I have solved the problem, and in the way found a bug in the AngelCodeFont class. How can if i can find the way to make thous code squares (the bloue ones in the coments) apear i’ll explain what i found to be wrong.
mike on May 13th, 2009
Hi Tenchy
There is a blog post on how to insert code into the comments. Basically you need to place < pre > a d around your code.
Looking forward to see your comments on the problems you’ve found.
Mike
mike on May 13th, 2009
Hmm, last post did not come out well, it should have been
< pre >
< /pre >
Mike
Tenchy on May 13th, 2009
Ok lets start then.
In the AngelCodeFont.m file in the renderAtPoint method we can find this line:
glBindTexture(GL_TEXTURE_2D, [[image texture] name])
The problem is that in this method we always bind the texture without udating the currentTexture variable and without cheking if the same texture is already binded. This could cause our images to not bind their texture becouse the last time we draw it in screen we updated the currenTexture but we didn’t do this in the AngelCodeFont method so these could cause what was happening to me. To solve this we have to do this:
Change this code:
glBindTexture(GL_TEXTURE_2D, [[image texture] name])
with this one:
Virus_WarsAppDelegate *del = [[UIApplication sharedApplication] delegate];
if([[image texture] name] != [del getCurrentTexture]) {
int a = [[image texture] name];
[del setCurrentTexture:a];
glBindTexture(GL_TEXTURE_2D, [[image texture] name]);
}
You can apreciate that i changed the appDelegat variable whit the del variable that gets the pointer every time. I did this becouse for a reason i don’t uderstand the currenTexture didn’t update if we only get the pointer in the init method.
This change sholud be done in the renderAtPoint method in the Image.m file.
Hope it helps
mike on May 13th, 2009
Thanks Tenchy and good catch :o)
Following on from another comment on the blog, I’ve actually moved away from using the appDelegate to store this info. I’ve now moved to having a singleton class which hold this state info to be used within the game. I talk about this a little in the recent Managing State post.
I’m going to cover my change in a future tutorial, but your code will certainly fix the current problem before I make my changed public.
Thanks again for your feedback, its much appreciated.
Mike
lorenb on May 13th, 2009
I discovered your site/tutorials recently and I’ve learned a lot from them. They are very good. Thanks for sharing the information.
I was looking at the TipedMap class and I think you have a memory leak in parseMapFile. When you are processing the layerProperties, you alloc/init an NSMutableDictionary called layerProps (line 185). After you assign it to the currentLayer I think you need to release it. If not, I believe you have an extra retain count.
That might also be happening in tileProperties (line 144). It might need to be released after it’s set in tileSetProperies (line 152).
I’m still new to Obj-C so I might be wrong but let me know your thoughts.
Martijn on May 13th, 2009
Hey Mike,
Thanks for taking the time to share all this information with us. The tutorials are great and very easy to follow. I will try to apply everything I learned to my own game.
I am quite new to programming in objective-C and these tutorials are also a great way to get some good insights in the objective C way of programming!
Thanks again! and I am looking forward to the next one!
-Martijn
mike on May 13th, 2009
Hi lorenb, I’m glad the tutorials are useful :o)
I’ve checked the code and you are spot on. Both of those dictionaries would be leaked. I rushed the properties implementation and that is what happens :o)
I’ve fixed the code in the Tutorial 6 project.
Thanks for spotting the leaks and keep the comments coming :o)
Mike
raja on May 14th, 2009
HI Mike,
First of all, I’d like to say a massive thanks for your game programming articles, they have been a really big help!!
Tutorial: mapy w grach | appledev.pl on May 18th, 2009
[...] Na stronie 712 pojawiła się szósta część tutoriala z programowania gier dla iPhone. Zachęcam do zapoznania się z postem. [...]
Peter on May 20th, 2009
Hi Mike,
I have been playing with the map editor and have created my own map which I am now trying to load into my game.
The problem is all the tiles are being displayed as flat grey as if the map was blank or empty. I have confirmed all checkboxes were OFF in preferences but can’t seem to figure out what is causing this.
I was hoping you might have some suggestions.
Thanks!
mike on May 20th, 2009
Hi Peter
I actually found a small bug within the tilemap class. It was only showing up if there was more than one tileset being used. The small piece of code below shows the addition of the missing line.
// Get ready to loop through any other tilesets we have on this layer x = point.x; y = point.y; currentQuad = 0;
The currentQuad = 0 is the line which needs to be added.
If that is not the problem then I’m not sure what it may be. If your happy sending me the tilemap file and spritesheets I will take a look and see what the problem is. The email address is mike@blog_domain_name.co.uk
Mike
Peter on May 20th, 2009
Thanks Mike!
It actually appears that it is the oppostie problem for me. It is only showing up if there is ONE tileset being used.
When I use multiple tile sets the actual tiles don’t appear. Although after a little experimenting it seems that they 2nd tile set is displayed when the first one isn’t or some strangeness anyways.
I will send you my tilemap and ss happily as well poke around a little myself.
Thanks so much!!
Peter on May 20th, 2009
Adding your fix posted above solved the problem!
Thanks again Mike and can’t wait to see what your particle system is like!!
I’m officially addicted to your tutorials now :)
Peter on May 21st, 2009
One last question for the map stuff :)
I have my map working wonderfully now and it is scrolling up the y axis however it is moving at warp speed and I can’t seem to slow it down?
When your map scrolls along the x axis it is a great pace but I can’t seem to get that same pace. Here is whats in my updateScene mapPoint.y += 0.1 * delta;
if(mapPoint.y > (int)[tileMap tileHeight])
{
mapPoint.y = 480;
tileMapY += 1;
}
if(tileMapY > (int)[tileMap mapHeight]) {
tileMapY = -1;
}
If you have any insight it would be much appreciated!
RoberRM on May 25th, 2009
Hello Mike!
I’m now watching this tutorial, and I just wondered if there is any reason why sometimes you use @theError to store the error you might get and other times you use nil. I know nil is used to just ignore the error you might get, what I don’t know is why you sometimes don’t ignore it and sometimes you do.
Everything else did make sense.
Well, I had to think a lot on why you used this code:
if(mapPoint.x < (int)-[tileMap tileWidth]) {
mapPoint.x = 0;
tileMapX += 1;
}
But I figured it out (took me five minutes). :D
Once again, thank you very much for such nice tutorials. You are a great teacher! ;)
mike on May 25th, 2009
Hi RoberRM, I’m glad you liked the tutorial. Sometimes code can be a little tough to understand, especially when its something I’ve not described much. If you do have any questions just post them.
As for the error checking, well, there is no reason to be honest. Sometime I’m feeling like I should check for errors and other times I just skip it. I really really should be more consistent with the error checking in the code, but its something I plan to go over once I’ve got the basics all up and running.
Thanks for the positive feedback as well, its much appreciated.
Mike
RoberRM on May 25th, 2009
Hello again, Mike!
I’ve just finished the tutorial. I just wanted to point out two things:
1.- Wow! The simulator does slow down noticeably when you ask OpenGL to render the tile map! I do not have an iPod to test the final product yet, but is it also noticeable in the iPod?
2.- In this tutorial we’ve removed the need to use the delegate to know which is the current texture. But you have forgotten to clean up the delegate as well! You’ll have to remove the
int currentTexture;
in the .h file and its corresponding @synthesize in the .m file. ;)
As for the positive feedback: you really deserve it! :D You are helping me to create the game of my dreams a lot, so all the praise i might give you will always come short. :D So, thank YOU. :)
Mark M on June 2nd, 2009
Hi Mike! Awesome tutorials! Its been a great start for me. I’ve added accelerometer controls to scroll around a tiledmap, and I’ve added a GUI class to print button, the framerate and other debug info I print to the screen using the bitmap fonts.
I wanted to provide feedback since you’ve been such a help. I noticed a bug in the rendering of the tiled map as I was adding boundary checks to my own app. Watching the tutorial in the simulator, the last two columns and bottom two rows of the map show stone tiles, but the map actually only ends with one column and has only one bottom row of all stone tiles.
I think the one off error is in the renderAtPoint method of tiledmap class. It assumes that a [mapWidth][mapHeight] tile exists, but the maps only go from [0][0] to [mapWidth-1][mapHeight-1]. I modified the lines…
// If outside the map boundary do nothing, otherwise render the tile
if(mapTileX < 0 || mapTileY mapWidth || mapTileY > mapHeight) {
// Do nothing
to…
// If outside the map boundary do nothing, otherwise render the tile
if(mapTileX < 0 || mapTileY mapWidth-1 || mapTileY > mapHeight-1) {
// Do nothing
… and it fixed it in my app.
Thanks again for all the great tutorials! I’m look forward to watching some more, they’ve let me hit the ground running.
Mark M on June 2nd, 2009
Ugg, I guess I didn’t get the code tags right.. It ate the logic.. :)
Basicly when looking to see if your outside the boundary you need to check against mapWidth-1 and mapHeight-1
mike on June 2nd, 2009
@Mark M, great feedback and you are of course completely right. I had noticed the same behavior and it was something I was going to check out but you got there first which is great. It saves me some time checking the code :o)
I edited your post to pop the tags in. They can be a pain at times.
Thanks again for the great feedback and I’m glad your finding the tutorials useful.
Mike
mike on June 2nd, 2009
@RoberRM, I do my device testing on an iPod Touch and I’ve not noticed any problems using the tilemap. It moves around find and does not slow things down that I’ve seen yet :o)
Mike
Nikita on June 5th, 2009
Hello Mike! Thanks for all tutorials. We have made isometric tileset. But when width>19 or height>19 => CRASH!
MapSize 70×70
TileSize 32×32
Why?
Nikita on June 5th, 2009
Sorry, width>19 and heigth>19
mike on June 5th, 2009
Hi Nikita, are you able to email me the map which is crashing. I would need the TMX file and the tile images files. I can then check it out and find out what is happening.
The email address is mike@71squared.co.uk
Thanks
Mike
mike on June 5th, 2009
Hi Nikita, I wanted to post the answer to this on the blog as well so others can understand the problem.
Unfortunately at the moment the Tiled class does not support isometric maps, it only supports orthogonal maps. This is something I may add later but I don’t have any timeframes on it at the moment.
Mike
Nikita on June 5th, 2009
Problem not in it.
Our isometric – is:
int isuda;
isuda++;
for(int mapTileY=mapY; mapTileY 20 heigth>20 = glitch and 40 40 crash :(
Will help?
Nikita on June 5th, 2009
Problem not in it.
Our isometric – is:
[code]int isuda;
isuda++;
for(int mapTileY=mapY; mapTileY 20 heigth>20 = glitch and 40 40 crash :(
Will help?
Nikita on June 5th, 2009
Problem not in it.
Our isometric – is:
int isuda;
isuda++;
for(int mapTileY=mapY; mapTileY < (mapY + height); mapTileY++) {
isuda++;
// Increment the x location for the next tile to be rendered
x += tileWidth-16;
y-=tileHeight-16;
}
// Now we have finished a move to the next row of tiles and reset x
y = point.y-(tileHeight/2)*isuda;
x = point.x-(tileWidth/2)*isuda;
in TiledMap.m
Instead of yours orthogonal maps:
x += tileWidth; } // Now we have finished a move to the next row of tiles and reset x y -= tileHeight; x = point.x;
In your tutorial/project if to make width>20 heigth>20 = glitch and 40 40 crash :(
Will help?
Nikita on June 5th, 2009
Hahaha, all so is simple:
When I made height*width > 13*13 т.е h=13, w=13
There were glitches.
13*13=169
((320/tileWidth)+1)*((480/tileHeight)+1)=176
If h or w > 13, for example 14. 13*14=182
182>176 => Glitch :)))))
Change to:
And everything is all right :)
mike on June 5th, 2009
Hi Nikita, I’m glad its all working now. The calculation above was supposed to be calculating how many tiles need to be visible to fill the iPhone screen. As you are not going to be rendering anything which is off the screen for the tile map, that is all the quads you need. In the actual code which renders the tilemap to the screen I have been limiting the area of the map which is rendered to just fill the screen. If you just draw the entire tilemap including tiles which are off the screen then you would see the glitch you have seen :o)
The code I have been using to render the map to the screen is
[tiled_ renderAtPoint:CGPointMake(0, tileMapPositionY_)
mapX:0
mapY:tileY_
width:screenTilesWide_
height:screenTilesHeight_ + 1
layer:0];
You can see when I am saying the the width and height of the tiles to render should only be as wide and as high as is needed to fill the screen with tiles.
I’m glad you got it working and I hope the info above is useful.
Have you actually got the code rendering an isometric tilemap? I’ve not tried it with my code.
Mike
Nikita on June 5th, 2009
>>I’m glad you got it working and I hope the info >>above is useful.
You have rescued us. :))))
>>Have you actually got the code rendering an >>isometric tilemap? I’ve not tried it with my >>code.
Above I already wrote.
int i;
for(int mapTileY=mapY;
mapTileY < (mapY + height);
mapTileY++) {
i++;
// Increment the x location for the next tile to be rendered
x += tileWidth-16;
y-=tileHeight-16;
}
// Now we have finished a move to the next row of tiles and reset x
y = point.y-(tileHeight/2)*i;
x = point.x-(tileWidth/2)*i;
i – buffer :), counts up rows.
And, certainly, ready isometric tiles.
Thanks for the help, Mike. :)
Austin on June 6th, 2009
Mike
I just finished watching your update video and now I’m wondering what code did you use to get your tilemap to scroll down along the y axis? Also how did you get the tilemap to start at the bottom of the screen instead of the top?
P.S. Thanks a lot for these tutorials!
mike on June 6th, 2009
Hi Austin, I’m glad you are enjoying the tutorials. I have been scrolling the tilemap using the following code.
The following code is in the init routine of the game
// Init the tilemap _tiled = [[TiledMap alloc] initWithTiledFile:@"techmap" fileExtension:@"tmx"]; _tileWidth = [_tiled tileWidth]; _tileHeight = [_tiled tileHeight]; _screenTilesWide = _screenBounds.size.width / _tileWidth; _screenTilesHeight = _screenBounds.size.height / _tileHeight; _tileMapScrollSpeed = 0.5; _tileMapPositionY = 480; _tileY = 99-_screenTilesHeight;
Then in the update method I use:
_tileMapPositionY -= _tileMapScrollSpeed * theDelta;
if(_tileMapPositionY < 460) {
_tileMapPositionY += _tileHeight;
_tileY -= 1;
if(_tileY < -24)
_tileY = 99;
}
And finally in the render method I use
// Render the tilemap
[_tiled renderAtPoint:CGPointMake(0, _tileMapPositionY)
mapX:0
mapY:_tileY
width:_screenTilesWide
height:_screenTilesHeight + 1
layer:0];
You should be able to see that I basically move the location the map is rendered down the screen each game loop. Once the map has moved an entire tile down the screen, I move the map coordinates so that I am now rendering from one tile further up the map from the button. I then start rendering the tilemap from 480 on the Y again.
I hope that makes sense and let me know if you have any questions :o)
Mike
Austin on June 6th, 2009
Thanks for the help but this still isn’t working for me. Currently nothing is being displayed on the screen. Here is the code I’m using…
In the .h file
TiledMap *tileMap;
CGPoint mapPoint;
int tileMapY;
int tileWidth;
int tileHeight;
int screenTilesWide;
int screenTilesHeight;
int speed;
In the init game
tileMap = [[TiledMap alloc] initWithTiledFile:@”testmap” fileExtension:@”tmx”];
tileWidth = 50;
tileHeight = 50;
screenTilesWide = screenBounds.size.width / tileWidth;
screenTilesHeight = screenBounds.size.height / tileHeight;
speed = 0.5;
mapPoint.y = 480;
tileMapY = 99 – screenTilesHeight;
In the update method
mapPoint.y -= speed * delta;
if(mapPoint.y < 460) {
mapPoint.y += tileHeight;
tileMapY -= 1;
}
if(tileMapY < -24) {
tileMapY = 99;
}
And in the render method
[tileMap renderAtPoint:CGPointMake(0, mapPoint.y) mapX:0 mapY:tileMapY width:8 height:10 layer:0];
When I use this code nothing shows up on the screen but, when I try the code below (in the update method) I see the tilemap scrolling at very fast speed. Any ideas?
mapPoint.y += 0.1 * delta;
if(mapPoint.y > (int)[tileMap tileHeight])
{
mapPoint.y = 480;
tileMapY += 1;
}
if(tileMapY > (int)[tileMap mapHeight]) {
tileMapY = -1;
}
mike on June 6th, 2009
Hmmm, not sure why the first set of code is not working. There was a problem with the code which ment that the lastTime variable in EAGLView was not being initialized which cause funny things to happen. Add the following line to the initWithCoder method in EAGLView if it is not already there.
lastTime = CFAbsoluteTimeGetCurrent();
That should stop the tilemap moving so fast. The problem is that without it being initialized, the delta which is generated in the game loop is a huge number which causes problems.
Let me know if this works or not. If not I can take a look at your project if you send it to mike@71squared.co.uk
Mike
Austin on June 7th, 2009
I still cannot get this to work and I want to move on to tutorial 7 so I will spend time on this later. Thanks for the help though!
I have another quick question for you, how would you invalidate the timer keeping track of an objects position? For example I have a message (scrolling down) that I want to disappear when it goes off the screen. Currently the message will go down and disappear off the screen but the message is still being tracked by delta. Any ideas?
Here is my code…
messageY -= 0.1 * delta;
if(messageY < -messageHeight)
{
[Some how disable delta]
}
mike on June 7th, 2009
Hi Austin. If I get some time I’ll put together a sample project to vertically scroll the tilemap.
As for stopping objects being tracked etc when they are off the screen, this is a subject I’m going to be covering in a tutorial. Basically it comes down to state management. Each action going on in your game could have a state which describes what it is currently doing. For a message this could be Scrolling or Stopped.
Using your code above it could look like this
enum {
kMessageScrolling,
kMessageStopped
}
uint _messageState = kMessageScrolling;
if(_messageState == kMessageScrolling) {
_messageY -= 0.1 * detla;
if(_messageY < -messageHeight)
_messageState = kMessageStopped
}
This will stop the messageY value from being changed unless the _messageState goes back to kMessageScrolling. This means you could set the location of the message back to the top and when you want it to scroll again you just set the _messageState to scrolling and it will start to scroll.
You will find that a large part of programming a game is around state management and understanding what state different objects are at when making decisions.
I hope that makes sense and I'll be covering this more in a future tutorial.
Mike
Austin on June 7th, 2009
Thank you so much for the help! By the way after some trial and error I got my vertical scrolling map working. Setting the lasttime to CFAbsoluteTimeCurrent did the trick. Thanks one more time for these tutorials!
mrspeaker on June 10th, 2009
Thanks for these tutorials – they are bloody awesome!
Just a question – I notice that if I set the colour filter on the player ship and render the ship before the tile map, then the filter gets applied to the entire tile map as well. Is this a “known issue”? Thanks!
mike on June 10th, 2009
Hi mrspeaker, thanks for the feedback :o)
I’ve had a look through my code and I have made some changes locally which stop this problem from occurring. I’ve not managed to cover these updates yet, but the easiest fix is to add the following line to the Image class
glColor4f(1.0f,1.0f,1.0f,1.0f);
This should be placed after the glDrawArrays command in the RenderAt: method in the Image class. That will reset the colour which is going to be used by the next OpenGL render.
I have actually added a colour property to the tiledmap class now which means you can set its own colour filter. I’m going to be covering these changes in video ASAP.
Hope that helps.
Mike
Jetwilson on July 10th, 2009
Hi
thanks for a brilliant tutorial!
I’ve been following though them in order which has really help me get off the ground with OpenGL
I have had one problem though and I have no idea why it happens.
When OpenGl tries to render the tiles it tries to fit them into a triangle so I end up with a moving, distorted map made of inaccurate triangles.
Do you have any idea why this would be happening?
thanks!
Incredible iPhone Game Programming Tutorials With Video | iPhone Development Tutorials and Tips on July 31st, 2009
[...] 4 – Bitmap Font Class iPhone Game Programming – Tutorial 5 – Animation Class iPhone Game Programming – Tutorial 6 – Tiled Map Class iPhone Game Programming – Tutorial 7 – Singleton Class iPhone Game Programming – [...]
Priyank on August 3rd, 2009
Hi
thanks for a brilliant tutorial!
I got my map working perfectly fine in portrait mode. But I want to render the map in the landscape mode as I have the game in landscape mode. It will be great of you, to help me out on this so that I can progress with my game with your brilliant tutorial and suggestions on how to render the map in landscape mode.
Many thanks for wonderful tutorials.
PaulC on August 30th, 2009
Hi Mike,
Firstly I want to say thankyou for the enormous help your tutorials have been. I’ve been getting back into programming as a career change after not having done any programming for 3 years, so it’s been quite a struggle but it’s been much easier because of your help. Thankyou very much.
Now, I’m having a bit of trouble with my project after this tutorial. It’s crashing in the parsemMapFile method, on the following line
DDXMLDocument *theXMLDocument = [[DDXMLDocument alloc] initWithXMLString:tiledXML error:&theError];
The debugger says something like
-[NSObject doesNotRecognizeSelector:]
I’ve looked online and most people who have this crash problem are those using interface builder and haven’t connected their view controllers properly. Since I’m not using interface builder, I can’t see that being the case.
I’ve tried it with the tilemap in your samplecode, so I don’t think the problem is with the file it’s reading.
Do you know what might be wrong? I could send you my sample code if you think it will help.
Also, I had a couple of other questions about the code:
Since the dictionary for the tileset properties stored in the TiledMap class contain the properties for every tile in the map, organised by globalID, what is the other tileSetProperties dictionary in the TileSet class used for? As far as I can see, it doesn’t get used. Does it get used in a later tutorial?
Also, in the getVerticesForSpriteAtX:Y:point:center: method in the SpriteSheet Class, The X and Y arguments don’t appear to be used. I only noticed this when I saw it being called in the renderAtPoint method in the TiledMap class, and wondered why mapTileX and mapTileY were being sent. Once again, is this for something later down the line?
Once again, thanks very much for these tutorials, and I wish you all the best with your presentation on wednesday.
mike on August 30th, 2009
Hi PaulC and thanks for your comments. I’m not sure from what you have said what the problem could be, but if you can send me your sample code I’d be happy to have a look. My email address is mike@71squared.co.uk.
As for the dictionary and the X and Y you are right, they are not used. As I’ve gone through the tutorials there is code which I used whilst developing and learning and then did not need. Sometimes this has been left lying around :o)
Thanks for the best wishes for Wednesday. I really need to get some slides done so I think tomorrow will be a book and keynote day :o)
Mike
PaulC on August 31st, 2009
Hi Mike. I’ve actually sorted the problem. If you notice in my previous message, I was allocating memory for a DDXMLDocument, wheras in the tutorial, memory was allocated for a DDXMLElement. I changed this and it sorted it. Not completely sure why but I’m glad it’s fixed.
Well, it’s not fixed, there’s an error with it displaying the tilemap, warping some of the quads across the screen. But I haven’t tried everything yet so I’ll wait until I get stuck before running back for help.
Thanks for getting back to me quickly.
mike on August 31st, 2009
Excellent, nice find. I’ve actually made major changes to the tilemap class for the book. I was finding that even using kissXML was slow. To sort the problem out Tom Bradley a regular reader of the blog and friend created a highly tuned XML parser. It doesn’t contain anything like the functions in kissXML but can parse a tiled map file really quickly.
I am using a map that is 200×200 and has three layers. To load and parse this map was taking, on the iPhone 3G, over 15 seconds. With the new parser its now taking 600ms. There are some other enhancements as well to help with the speed and size of the tile file. The parser is able to handle map files that contain tile info packed into base64 and gzipped, plus the actual tmx file is gzipped as well.
For my map its taken the size from a few MB to 4kb, another huge advantage when working on a small device.
I will be releasing some of this code on the blog ASAP, but given the changes I just want to make sure its stable.
Mike
PaulC on August 31st, 2009
I found the solution to the other problem I was having.
The problem:
First, as it scrolled by, some tiles would warp across the screen, as though one of their vertices had been reset to (0,0), while other tiles just wouldn’t render at all.
After removing the animation, it would simply crash.
solution:
In the tilemap renderAtPoint call, I still had the width and height parameters set for my own tileset, which I forgot to change when I tried to render the sample code’s tilemap.
I’m going to work out a way to calculate these values or at least output an error message in future so it doesn’t crash if I accidentally guess the wrong width & height parameters again.
PaulC on August 31st, 2009
The new XML stuff sounds excellent. Can’t wait to have a look at it.
Simon on September 8th, 2009
When I test my app I only have the option to run it on 3.0. Yet when I run the code downloaded from your website I can run it on 2.2, 2.2.1 and 3.0.
Do you know why this is?
Also I’ve being working on this tutorial, and for some reason in my app the tilemap isn’t displayed, the animation is frozen and the text doesn’t scroll. I don’t suppose you can hazard a guess why this has happened as I can’t see a reason for it.
THanks
Simon
PS I really appreciate the tutorials, their the best on the net
Simon on September 10th, 2009
Regarding my app being frozen, was a simple typo in the renderparticles method.
If you do know how I can resolve the other issue do let me know thanks
mike on September 10th, 2009
Hi Simon, glad you sorted out one of your problems :o)
I take it your tilemap is still not displaying and text is not scrolling?
Have you got any code you can share as it could be any number of issues. I’d be happy to have a look if you email your code to mike@71squared.com
Mike
Simon on September 10th, 2009
Hi Mike,
Sorry should have come back to this. It was once again a typo… to many late nights :O)
Simon on September 10th, 2009
Do you have any tips, for debugging (or simple how to guide for SKD) as little bugs take me hours to find looking through the code trying to spot the mistake (which isn’t always obvious). Is there a better way?
PaulC on September 12th, 2009
The thing that works for me is to fill the code with NSLogs, then see which line the code gets to before the bug occurs, then check the spelling/syntax of the line, aswell as any methods, arguments, variables that have been used.
Usually by that point I know what’s wrong. After which, it’s pretty much different every time.
Simon on September 12th, 2009
Paul,
Thanks for the tip NSLogs are not something I’ve used before. I think a bit more research is needed. I’ve seen them used by Mike and others. I’m only now starting to produce something complicated enough to need them I think.
If you’ve got anytips or know of any tutorials let me know simon.hurst@gmx.com
Thanks
mike on September 12th, 2009
Hi Simon
Using NSLog is certainly a great way to see what is happening in your code. Most programmers have their own workflow for chasing bugs, but logging and also using breakpoints in your code so you can then step through and check the values of variables are the most common tools used to track bugs down.
I’m not sure of any good debugging tutorials for Xcode, but I’m sure google has some somewhere.
Mike
Simon on September 12th, 2009
Thanks Mike,
I’ve found a few sources of inspiration. Kind of kicking myself now, for not looking up these sorts of things sooner. It’s making my life a whole lot easier and doesn’t add much in the way of development time to incorporate them.
Simon on September 12th, 2009
Too true, but harder still when you don’t know the question to ask ;)
youke on September 17th, 2009
这是我看了这么多教程最好的一个了
this is the best tutorial
I have watched many tutorial
I can say ,this is the best
Anonymous on October 7th, 2009
CFRunLoopRunInMode breakage on sdk 3.0 is destroying my world.
Chad Fuller on November 21st, 2009
When I moved this code in the SpriteSheet class:
horizontal = (([image imageWidth] – spriteWidth) / (spriteWidth * spacing)) + 1;
I get an EXC_ARITHMETIC error. Basically the app starts and crashes. When I run in breakpoints on it stops on this line of code and when I comment it out, the app runs normally. Got any ideas?
Thanks.
ChrisMan on January 7th, 2010
Hi Mike,
Love your tutorials they have REALLY helped me understand opeGL
The tiled mapeditor is giving a problem because im using 3.0 or something like that (its the new one) and i cant figure out how to save raw xml files from it
if you know of some way then thanks, but if not i will just use 0.7.2
ChrisMan
mike on January 7th, 2010
Hi ChrisMan
I’m glad the tutorials are helping. There is currently no option I’m aware of in the QT version of Tiled to save a map file as anything other than an XML file with gzipped layer info. To get that you will need to use the 0.7.2 Java version.
The code for Sir Lamorak’s Quest that is in the book has a tiled class that handles the gzipped layer info and that GREATLY increases the speed of parsing a tile map. I’m using TBXML to both process the XML and also unzip the data. TBML can be found at http://www.tbxml.co.uk
Mike
ChrisMan on January 7th, 2010
Hi mike thanks for the quick response
I will look over the website later it looks very interesting
Keep up the great tutorials!
ChrisMan
Melon on January 12th, 2010
Hey mike, great tutorials they help alot.
I was wondering i how would i go about adding gravity with the tile map system for a side scrolling platform game i am starting.
stevemaddox on January 16th, 2010
I made a simple map with tiled and then added it to your tutorial 6 and changed the file name in the program but it doesn’t work. I unchecked the preference options under saving and don’t know how to make it work. I was just wanting to test a simple map I made. Are there other things I should change besides the filename? Thanks.
stevemaddox on January 16th, 2010
code from NSLog
2010-01-16 15:47:36.689 OGLGame[12746:207] AngelCodeFont: Initializing vertex arrays for font ‘kerning’ with capacity of ’95′
2010-01-16 15:47:36.692 OGLGame[12746:207] Tiled: Tilemap map dimensions are 30×30
2010-01-16 15:47:36.692 OGLGame[12746:207] Tiled: Tilemap tile dimensions are 50×50
2010-01-16 15:47:36.693 OGLGame[12746:207] –> TILESET found named: wallfloortiles2, width=50, height=50, firstgid=1, spacing=0, id=0
2010-01-16 15:47:36.693 OGLGame[12746:207] —-> Found source for tileset called ‘wallfloor5050tiles3.png’.
2010-01-16 15:47:36.694 OGLGame[12746:207] –> LAYER found called: Layer 0, width=30, height=30
2010-01-16 15:47:36.696 OGLGame[12746:207] —-> Found ’900′ tile elements
2010-01-16 15:47:36.702 OGLGame[12746:207] –> Initializing vertex arrays for ’70′ quads.
2010-01-16 15:47:36.704 OGLGame[12746:207] Map Property value = ‘default’
2010-01-16 15:47:36.711 OGLGame[12746:207] *** Terminating app due to uncaught exception ‘NSRangeException’, reason: ‘*** -[NSCFArray objectAtIndex:]: index (1) beyond bounds (1)’
2010-01-16 15:47:36.712 OGLGame[12746:207] Stack: (
807902715,
2440533257,
807986683,
807986522,
810976489,
810572359,
71784,
14314,
14952,
2145684,
2145109,
2143150,
2142242,
2175712,
807689266,
807684014,
807683624,
814715661,
814752238,
11000,
10854
)
mike on January 17th, 2010
Hi Steve
What you have done is fine, although it seems like an array is not getting set up correctly somewhere. If you run the app with breakpoints on, where abouts does the app crash. This should help us work out which array you are trying to access beyond its bounds.
If you want to send me you tilemap xml file and tile image I can check that as well to make sure it looks ok mike@71squared.com
Mike
Dave on January 22nd, 2010
Hi all,
I’ve got this error message coming up when I try to compile my project :
Undefined symbols:
“.objc_class_name_TileSet”, referenced from:
literal-pointer@__OBJC@__cls_refs@TileSet in TiledMap.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
Does anyone know what might be the cause of this?
Dave :)
Dave on January 22nd, 2010
I fixed it, for some reason the compiler wasn’t picking up the file. Not sure why. To Fix I removed the file and added back in and everything seems to be back to normal : )
mike on January 22nd, 2010
You beat me to it. I was just typing a comment to get you to try that. Its happened to be loads of times before.
Glad you got it sorted out :o)
Mike
Dave on January 22nd, 2010
It’s not the first time I’d had that problem either – it is however the first time that I’d found out what it meant.
As previously I was reverting back to an older versions of the project and repeating the work (which fixed the problem), not the the most efficient way to work. Oh well at least I know what the problem is for the future.
Simon on January 26th, 2010
Hi Mike,
I’ve included the tiledmap in my project, however, I’m having a few issues.
Could you advise what are the restriction in relation to the tilemap. As i have a tile map
−
−
When this gets rendered to the screen the ordering of the tiles is shot to hell :(. However if I adjust the layer details like so
The tiles are rendered as expected. Am i missing something i.e. exceeding some sort of natural limit or should the tile map have an equal width and height?
If you or anyone else could shed some light on this that would be great.
Simon
Simon on January 26th, 2010
Whoops the first part of my query:
map version=”1.0″ orientation=”orthogonal” width=”40″ height=”23″ tilewidth=”50″ tileheight=”50″
tileset name=”Untitled” firstgid=”1″ tilewidth=”50″ tileheight=”50″
image source=”tilemp.png”/
tileset
and what i changed to make it work:
“layer name=”Layer 0″ width=”20″ height=”20″”
this is the XML page minus the”"
Simon on January 26th, 2010
Soryy for so many posts but the original layer data didn’t come out; it was
layer name=”Layer 0″ width=”40″ height=”23″
when the tiles didn’t render properly.
Christophe on February 7th, 2010
Hi Mike,
I have a question about the scrolling of the tilemap. I may be wrong about this, as I have not done much research on it, but it seems to me that it would make a lot of sense that the tilemap should remain fixed in location. All the other elements would move on top of it (sprites eg), as well as the viewport.
So you would have a static tilemap and move your viewport over it.
Did I miss the point? Or is what I’m suggesting not technically possible/performant?
Christophe
mike on February 7th, 2010
Hi Christophe
What you are saying is spot on. By having the map static and simply moving the viewport over the top along with entities is a clean way of using a tilemap. The implementation of the tilemap class has moved on a lot since I put this simple tutorial together.
I actually now load each layer into its own Vertex Buffer Object (VBO) marked as static i.e. the data in these buffers is not going to change. In each buffer are the vertices and texture coordinates that make up each layer of the tile map. A VBO holds data as close to the GPU as possible to reduce the bandwidth needed each frame moving geometry data around etc. At the moment, unless you are using an iPhone 3Gs, latest gen iPod or the soon to be released iPad, VBOs don’t really buy you any performance gain. I’ve implemented them anyway as when the game is run on a 3Gs, the GPU/Driver does make better use of VBOs and you get an performance boost.
My first trial was to render the entire map each frame and just let OpenGL ES work out what was not visible and drop it early in the rendering pipeline and just move the viewport. This turned out to not work well and performance was really poor. After a number of tests I settled on a mix of the two. I have the static layer info held in a VBO and move the viewport, but when I render the tilemap, I only use the entries in the VBO for tiles that are visible on the screen i.e. I use glDrawElements passing in the indices to the tiles I want rendered.
This has turned out really well and gives me all the performance I need to have it running nicely on the iPhone 3G and original :o)
So you didn’t miss the point and I would say your ready to move beyond this tutorial and start implementing your ideas :o)
Mike
Christophe on February 7th, 2010
Hi Mike,
Thank you for your reply. It’s nice to know I’m not missing the point :)
I was wondering though if you have these changes implemented in one of your currently available tutorial projects, or if you have a repository somewhere I can grab hold of that holds these changes.
I’m very eager to check them out.
Christophe
mike on February 7th, 2010
Hi Christophe
Unfortunately the new code is not available on the blog or to download. This is the all new code that is going into the book so it won’t be available until the book is done and published. I need to keep some surprises for the book ;o)
Mike
Creating Isometric Tile Map Games For the iPhone | iPhone Development Tutorials and Programming Tips on February 19th, 2010
[...] guys at 71 Squared have also created a tutorial on creating a Tiled Map Class as one of their excellent iPhone game programming [...]
Peter on April 13th, 2010
Hey Mike
Just wondering if you or any other readers have attempted to use transparencies in there tileset images?
I have a tileset that has some transparent areas that I was hoping could be used to display the map layer underneath but instead all that is displayed is flat black where the transparent sections are.
Any help on this would be super appreciated!
Thanks.
stevemaddox on April 13th, 2010
I use the free software GIMP and you have to tell it you want to start with a transparent background when you first draw. Then save under .png with that.
Peter on April 13th, 2010
@stevemaddox thanks for the post. I use Photoshop to do all my image manipulation and have a .png that has transparent areas.
The problem is getting openGL to render those transparent areas as transparent which it doesn’t do. At first it seemed straight forward enough but it looks like the problem lies within openGL itself as it doesn’t support rendering transparencies within images in the sense that I was hoping. If anyone has been able to do this I’d love to know how. In the meantime here’s a link I found.
Peter on April 14th, 2010
OMG I win the huge idiot award. I had the useBlending parameter set to the wrong value on the renderLayer call.
Talk about getting crazy :P
mike on April 14th, 2010
Lol, you answered your question before I had a chance to respond. Glad you got it sorted.
Mike
TheBiter on May 4th, 2010
Hey all,
I’ve been trying to convert this part of the tutorial series to sdk 3.1.3 but I’ve ran into some problems with the program crashing shortly after running it.
The problem only happens when I tell it to render the tile map with [tileMap renderAtPoint:mapPoint mapX:tileMapX mapY:0 width:8 height:10 layer:0]; otherwise there is no problem.
The NSLog also reports the quad number differently from the video. I’ve checked and compared all my files with the downloadable project and haven’t found anything wrong. I’ve checked for 2 days so far, please help.
Here’s the NSLog report from the debugger console
2010-05-04 16:43:16.324 OGLGame Tutorial[10392:207] AngelCodeFont: Initializing vertex arrays for font ‘test1′ with capacity of ’96′
2010-05-04 16:43:16.329 OGLGame Tutorial[10392:207] Tiled: Tilemap map dimensions are 100×6
2010-05-04 16:43:16.329 OGLGame Tutorial[10392:207] Tiled: Tilemap tile dimensions are 50×50
2010-05-04 16:43:16.330 OGLGame Tutorial[10392:207] Tiled: Tilemap property ‘My Value’ found with value ‘MyMapProp’
2010-05-04 16:43:16.331 OGLGame Tutorial[10392:207] –> TILESET found named: Untitled, width=50, height=50, firstgid=1, id=0
2010-05-04 16:43:16.332 OGLGame Tutorial[10392:207] —-> Found source for tileset called ’tiles.png’.
2010-05-04 16:43:16.337 OGLGame Tutorial[10392:207] –> LAYER found called: Layer 0, width=100, height=6
2010-05-04 16:43:16.338 OGLGame Tutorial[10392:207] —-> Found ’600′ tile elements
2010-05-04 16:43:16.340 OGLGame Tutorial[10392:207] –> LAYER found called: Layer 1, width=100, height=6
2010-05-04 16:43:16.342 OGLGame Tutorial[10392:207] —-> Found ’600′ tile elements
2010-05-04 16:43:16.344 OGLGame Tutorial[10392:207] –> Initializing vertex arrays for ’1′ quads
2010-05-04 16:43:16.345 OGLGame Tutorial[10392:207] Map Property value = ‘My Value’
Program received signal: “EXC_BAD_ACCESS”.
[Switching to process 10392]
TheBiter on May 6th, 2010
Ah I found the problem after reading through the entirety of the posted comments.
in the segment of code that says
int totalQuads = ((320 / tileWidth) + 1) * ((480 / tileHeight) + 1)
i had it as
int totalQuads = ((320 / tileWidth) + 1) / ((480 / tileHeight) + 1)
what a simple mistake… it took me many times looking at two lines before i noticed a difference. I guess this is what happens when you stare at long long segments of code for too long…
Peter on May 11th, 2010
Hey Mike,
I’ve been messing with your code on the iPad and found that I cannot load TileSets with a texture that is larger than 1024×1024 which is common for the iphone however the apple docs say that iPad supports 2048×2048 texture sizes? Is this a limitation of the TileMap class or is there something else I am missing?
Thanks!
Peter on May 12th, 2010
So I sort of figured out my problem. Line 219 of TileMap.m (new book code)
TileSet *tileSet = [tileSets objectAtIndex:0];
You’re only allowed 1 tileSet for the layer. I wonder if there is a specific reason for this limitation? It seems like a rather large one.
@Mike can you shed any light on this?
Thanks!!
mike on May 12th, 2010
Hi Peter
The 1024×1024 is not a limitation of the tilemap class. If you are running the code on an iPad or even iPhone 3GS then the Texture2D class needs to be changed. Inside this class the size of the image being turned into an OpenGL ES texture is checked. If it is larger than 1024 then it is scaled down. All you need to do is change that to 2048×2048 and those images will be handled.
As for the tilesets, almost everything you need to process multiple tilesets is in place. The parser identifies multiple tilesets in the tmx file and creates tileset instances for each of them. The code for the tile map tutorial should actually handle multiple tilesets and render them correctly.
The code in the book is different. I wanted to reduce the number of OpenGL ES state changes being performed to keep up performance. Binding to a new texture is a state change and each time a new tileset is rendered it requires the new tilesets texture to be bound.
This is the only reason the code for SLQ in the book does not render multiple tilesets. It should not be that hard though to look at the code in the tutorial project and see what needs to be done to the SLQ code.
I hope that helps.
Mike
Peter on May 12th, 2010
Thank’s so much Mike!! Super huge help and makes perfect sense.
Now I can’t wait to get home and get everything rendering on the iPad!
Thanks again,
Peter
blakeman13 on May 29th, 2010
i have a problem using the code from slq it wont let me use a tilemap bigger than 200X200 anything bigger does not work or gets stuck at the loading screen. I have changed the max tile width and hight in the global.h, the layer.h and yet it still wont work.
any ideas.
thanks,
Blake
Peter on June 9th, 2010
Hi Mike,
I think I found a little bug in the Layer class :)
In Layer.m in the InitWithWithName method you are callocing the tileImages array with (layerHeight * layerWidth) you will find that if you move the player close to the edges of your map that the renderLayer call will go off the bounds of this allocation.
I believe it should be ((layerHeight * layerWidth) + layerWidth). I fought with this one for a few hours the other night and thought others might appreciate the heads up.
Thanks again for all the awesome work and I’m looking forward to getting my printed copy of the book!
Peter
jimmyang on July 8th, 2010
Hi Mike,
I refer to your post on vertical scrolling dated June 6th, 2009, I have tried it out but am not able to get it work.
Need your help. Thank you.
Iain on August 9th, 2010
Hey,
The tutorial looks great but im afraid I cant run the source code.
“error: There is no SDK with the name or path ‘iphoneos2.2′
for some reason I cant change the simulator.
sorry Im abit new to this whole thing but have you got any idea about whats going?
mike on August 9th, 2010
Hi Iain
If you check the build settings for both the project and target and make sure the base SDK is set to a version of SDK you have, everything should work fine.
Let me know how you get on.
Mike
Iain on August 10th, 2010
Hi Mike
Thanks for the quick reply and I have now got it working.
Thanks a lot :)
Iain
the start of a new journey on August 14th, 2010
[...] Block from the Game Engine. I managed to integrated the Joypad Control and hopefully to complete theTile-Map class [...]





sebasong on May 7th, 2009
great stuff thx.