This will be a 3 part post demonstrating how to make a simple side scrolling game using libgdx (official project blog), a cross-platform library that allows you to simultaneously build for the desktop and for Android devices.
Updated 2011-09-19: Updated to use libgdx 0.9.2. No code changes required.
Updated 2011-09-18: Updated to use libgdx 0.9.1 (for real this time…) which meant renaming the pack file, TiledMapRenderer to TileMapRenderer, moving and renaming the tiles and pack file (and reindexing) due to new requirements from libgdx.
Updated 2011-06-12: Fixed some graphical glitches reported by Ed (in part 2′s comments). Thanks for all of your help Ed! Additionally, the tutorial is now based on libgdx 0.9.1 (it might have been libgdx 0.9.0 at the time, sorry folks) instead of an arbitrary nightly build, and it uses a modified TexturePacker in place of “manual” pack file generation.
This example is for anyone interested in making Android games, but is unsure where to start. By the end of part 3 you will have a basic Mario-like side-scrolling game with realistic physics, and (hopefully) you will be able to take this example and build something fun.
I’ve learned a few things since writing my previous post on using Tiled Map Editor with libgdx that I’ll apply in this series, things that make building a simple tiled-map game a lot easier. All code found here is released under the Apache 2.0 license, meaning, basically, you can use it for whatever you want. (IANAL, read the license for details.)
This is a much more involved tutorial than you have seen before on this site. There are a lot of different components used here and I tried to avoid cutting corners during explanations.
Post index
- Creating map tiles and the game map
- Integrating box2d
- Final touches: Scoring, lives, game over [coming soon]
- Add breaking blocks
- Add score and score display
- Add player death and a game over screen
- Hey, you’ve got a game
- Summary
Where to begin
This series was written with the assumption that you have read through all of the beginner libgdx tutorials, up through Projection Viewport Camera. libgdx has a tutorial on working with tiled maps, however that tutorial does things a little differently than what you’ll find in this series.
The box2d library includes a JNI wrapper for box2d, a “rigid body simulation library”, more commonly known as a physics library. It is pretty easy to use, although there are some box2d idiosyncrasies that you need to be aware of, and I will point those out in part 2. The box2d manual is worth reading, although its examples are all written for C++.
Your first steps are to create your libgdx project pair, named “JumperTutorial” and “JumperTutorialAndroid”. You can name them whatever you want, of course, but this series will use these names.
Next, download and install Tiled Map Editor and a graphics program before you begin. I can easily recommend using either Pixen on Mac OS X or GIMP on Windows (GIMP’s interface has come a long ways in recent years, I really like it).
Download the JumperTutorialProjects.zip projects used in part 1 and follow along as its components are explained. (14.4MB)
Creating map tiles
Your map will be made up of small, identically sized tiles, all eventually stored in a single image file, which I’ll refer to as “the tile image”. You can create this image file in any program (including MS Paint or similar), but some programs have features that make drawing easier.
Before you begin creating your graphics, take a moment to draw out a diagram of the sort of level you want to create. This will help you figure out how many different tiles you’re going to need to construct a whole map, and that will help you determine the size of your tile image.
Rough sketch of what a game map might look like
Based on my sketched map I’ll need tiles for the open air, a regular ol’ ground tile with a floor on top, a ground tile with no floor (that will go under the floor tile), a set of three tiles for the stairs (left-to-right and right-to-left stairs and a tile to sit between), two more ground tiles with left and right facing cliffs (and two more tiles to continue those cliffs downward), and six tiles for mountains in the background (left-to-right ramp and right-to-left ramps, a solid mountain block, and three for the mountain top). I’m skipping the clouds and exclamation-point blocks for now, as they will be handled separately as sprites (in part 3). I’m also skipping the pipes (part 4? if there is interest). That makes 16 tiles in total.
It’s important to decide early on what size you want each of your tiles to be. Consider the size of your target platform’s screen and how much detail you want to work in to each tile. For this example, I have chosen to make the tiles 32×32 pixels. On a ~400×900 pixel screen, the game will show around 12×28 tiles on screen at a time, which will work quite well for a Mario-clone.
The 16 different tiles will be saved to separate files, and then will be combined in to one large tile image file using a customized version of libgdx’s TexturePacker. TexturePacker combines the images together and creates a separate “pack” file that specifies where each tile is located within the tile image. TexturePacker also adds a buffer around the edge of each tile. This buffer seems to come in handy when the map display is automatically resized just a tiny bit. (I have not personally verified this.)
Some tiles next to part of the packed tile set
In the JumperTutoralProjects.zip file you’ll find the modified TexturePacker source and project. You can use Eclipse to export it as a runnable jar (File menu -> Export -> Runnable Jar). The modifications include support for numbering the tiles by their position within the tile image, rather than based on the tile filename, and support for including the level name inside the resulting pack file. These modifications together make the pack file work unmodified in the example code. Additionally, the TexturePacker code has been configured to add a 2 pixel buffer around images.
Important note: The resulting image and its pack file need to be named or renamed to “level.png” and “level packfile” (with a space) once you are done and before you create a map in Tiled Map Editor.
Steps for using the modified TexturePacker for this project:
- Create an input directory to hold your individual and an output directory to hold the tool’s output
- Create all of your individual tile images and save them to the input directory
- Open a command prompt and run
java -jar TexturePacker.java inputdirectory outputdirectory levelwhere “level” is the name of the level file you’ll create later on, without its extension. - Done. Inside the output directory you’ll see a single, larger png file and the “pack” file.
If you’re curious, go ahead and open the pack file in any standard editor. You shouldn’t need to make any changes in the file, however. In the file you’ll see the top left corners of each tile (xy) and the tile’s size and index values.
Creating the game map
Start up Tiled Map Editor and choose “New Map” in the File menu. Enter a map size at least a few times as wide as and a bit taller than your target screen, so you’ll have something to scroll around. I picked 60×15 (1920x480pixels) for the example map. Be sure to select “Orthogonal” under orientation and use the correct tile size (I’m using 32×32 as before).
Tiled Map Editor “New Map” dialog
In the Map menu, choose “New Tileset”. In the dialog that pops up, pick a name for the tiles (anything will do) and browse to your tiles. Leave the “Use transparent color” box unchecked — this tutorial is not using transparencies. Set your tile width and height (32 and 32 in this example) and set the spacing to 2.
Select a tileset
Now you’re ready to start drawing the map. Tiled Map Editor works just like a pixel image editor, with a standard paintbrush tool and a fill tool. It saves to a “TMX” file that contains instructions for rendering the tiled map. You can find my sample TMX file inside the project zip file (at the top of the page).
Screenshot of a map in Tiled Map Editor
Saving the map data to the projects
The file names and directory structure used for your tiled map assets are important. Create a “data” directory in your desktop project if you haven’t already. Inside “data” create “world” and a subdirectory “level1″. For now, this game will only have one level, but it will be easy to add another level should the time come. Copy your TMX file in to that “level1″ directory and name it “level.tmx”.
Inside “data” create a “packer” directory and save your tile image there as “level.png” and its pack file as “level packfile” (yes, with a space, required by libgdx).
The main project directory structure
Loading and viewing the map in-game: TiledMapHelper
I wrote a simple, reusable class to handle all of the map loading and framing of the map within the display (through positioning of the camera). This decouples the game code from the map code and makes it easy for the game to change from level to level. The class is based on code found in libgdx’s tiled map test suite, and it only works with single-layer maps. You can find it inside the zip file (beginning of the article).
Here’s some explanation about some of the class methods
45 46 47 48 49 50 51 52 53 54 | public void render() { tileMapRenderer.getProjectionMatrix().set(camera.combined); Vector3 tmp = new Vector3(); tmp.set(0, 0, 0); camera.unproject(tmp); tileMapRenderer.render((int) tmp.x, (int) tmp.y, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), layersList); } |
The camera’s position controls what is shown on the display. This method copies the camera’s combined projection and view matrix (in effect, its current position) to the tiled map library’s projection matrix and then sets the coordinates (x, y, w, h) that will be used to render the map to the screen.
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | public void loadMap(String tmxFile) { if (packFileHandle == null) { throw new IllegalStateException("loadMap() called out of sequence"); } map = TiledLoader.createMap(Gdx.files.internal(tmxFile)); tileAtlas = new TileAtlas(map, packFileHandle); tileMapRenderer = new TileMapRenderer(map, tileAtlas, 16, 16); camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); camera.position.set(0, 0, 0); } |
This method will be used when your player switches levels. It basically just takes care of things that you would otherwise have to worry yourself with, like preparing the camera and tile atlas and renderer. Note: The 16 used in the TiledMapRenderer constructor was picked arbitrarily.
Enable scrolling through the map by touch
The code in the project detects touch and drag events by recording where the event began and then measuring the horizontal and vertical distance from that point. The code will also ensure that the user cannot scroll outside of the map area. You’ll find this in the render() method of JumperTutorial.java.
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | if (tiledMapHelper.getCamera().position.x < screenWidth / 2) { tiledMapHelper.getCamera().position.x = screenWidth / 2; } if (tiledMapHelper.getCamera().position.x >= tiledMapHelper.getWidth() - screenWidth / 2) { tiledMapHelper.getCamera().position.x = tiledMapHelper.getWidth() - screenWidth / 2; } if (tiledMapHelper.getCamera().position.y < screenHeight / 2) { tiledMapHelper.getCamera().position.y = screenHeight / 2; } if (tiledMapHelper.getCamera().position.y >= tiledMapHelper.getHeight() - screenHeight / 2) { tiledMapHelper.getCamera().position.y = tiledMapHelper.getHeight() - screenHeight / 2; } |
This code is pretty self-explanatory. The main thing to consider, that might not be immediately obvious, is that the camera is pointed at the center of the screen. This means the camera’s position will need to be constrained within an imaginary rectangle inside of the map, inset by half the screen width and half screen height all around.
Summary
You should now have what you need to make a simple map and an application to navigate around that map using your finger or mouse. It’s not quite a game. Where to go from here? You could, if you like, make a few more levels and add some code that uses TWL to make a menu system of sorts. You could add an intermediate map screen that allows you to select which level you want to view. Or you could add detection for clickable regions on the map that will take you from level to level.
In part 2, I’ll describe how to integrate the box2d physics library, and I’ll include some code that will make adding collision detection to your map a whole lot easier.
This is a great example. I’m looking forward to the Box2D code.
Great tutorial! Eagerly awaiting part 2 :D
This is so inspirational! Thanks a lot for sharing,
Cheers
can you help me?!!for a android code of box2D in our proposal thesis
What sort of help are you looking for Jo-Ann?
It’s very useful!
Thanks for sharing!
I was wondering whether you could write a tutorial using isometric tileset especially with adding sprites dynamically to the map?? That would be awesome.
Totally love the tutorial.
Thank you for your comment Carl. I hope to finish it up, one of these days…
As to the isometric tilesets — unfortunately, at least at the time this tutorial was first started, libgdx did not support isometric maps. Maybe in the future, though!
This is a great example.But I want to know from where I can download the source code. Thank you!
Great tutorial, but I have some issues with the pack file. I don’t know why, but the index generate by the TexturePacker wasn’t right and i get the NullPointerException to load the map, so I create the pack file by my self and it works :)
Just wondering what version of libGDX you are using?
I’ve tried with the latest nightly build and the 0.9.1 build, and your examples fail to run.
It seems in your helper class you refer to com.badlogic.gdx.graphics.g2d.tiled.TiledMapRenderer, which doesn’t exist. TileMapRenderer does exist (without the d).
However if I change it to use that, some of the methods don’t exist such as getMapHeightPixels.
Also the constructor to TileAtlas only takes 2 arguments not 3??
Any hints??
These were based on 0.9.1. I had the same problems with newer nightlies (renamed classes, method changes), for what it is worth. The library that comes with the zip file ought to work, though. I’m really looking forward to the next release because it will make some of the code I wrote unnecessary.
Haven’t made any progress on part 3 yet. Got totally sidetracked.
Edited to add: I’m looking in to this further. Perhaps I was mistaken, maybe I used 0.9.0. Sorry about that, I am now migrating it to 0.9.1 for sure.
nvm fixed it
Do you know what the problem was?
I was using the nightlies and I was silly enough to not read the comments on the blog. It works now. My big problem now is that I have tiles labeled tile_01.png, tile_02.png, tile_03.png, ….etc and when the packer runs, the resulting pack file lists the images out of order. So if my images are 32×32 with a padding of 2, image with index of 1 will not have an xy coord of 2,2 but it may have 34,34. And the image at 2,2 will have an index of 26 or something. Which would be all good but when I load the tileset in the tiledmap editor, and grab the image in the top left corner, it says this as image 1. Unfortunately, image 1 was indexed to the image that may be at 34,34. So when I run the sample program code, I get the wrong tiles displayed! I’m not sure how to solve this problem without creating a pack file by hand. But I have 64 images so you can see the problem i’m having.
Did you figure out a resolution to this? I am having the same problems. I don’t want to manually redo the index myself as this could get tedious for a few hundred maps.
AAH! coworker just figured it out: in your tmx file change <tileset firstgid="1" to <tileset firstgid="0" – basically it was incorrectly applying the indices.
Not sure if this is a bug or just my not knowing how to use the tools.
Spent 2 days looking into this as I have very complex maps and this issue affects all tilesets. Basically the texture indices are all off by 1 in the packfile. Modify the writePacketEntry function and replace:
writer.write(” index: ” + index + “\n”);
with:
writer.write(” index: ” + (index-1) + “\n”);
That resolved it for me!
Hi, I kept trying to make the jar file (from the TexturePacker folder), but it kept asking for a launch configuration (which had nothing). How were you able to extract the jar? Can you upload it here?
Thanks.
I didn’t have to do anything special, interesting. You could try making a new project and then copy the files in to place. I’ll see if I can upload the .jar, though.
hi !
great tutorial, i wonder if there is an easy solution to just create an packfile from an already finished tileset(hundred of tiles) ?! :)
I don’t know of a great one, unfortunately. I made a script at one point that built the pack file for me, but it didn’t work very well. You might be able to try making a better one. The pack file format is easy to understand.
oh and i get a “unable to access jarfile TexturePacker” when starting the TexturePacker jar from the cmd prompt (java -jar TexturePacker.java inputdirectory outputdirectory level)
any ideas ?
Try “java -jar TexturePacker.jar”, in the project’s bin directory.
hi, thanks a lot. its so useful.
i have a wish. can you make a tutorial for box2d?
i know you explain box2d in chapter 2(i don’t read it, for now), but i need something like a reference. mario say examples in his tests. but it’s hard for me to understand it. i need something simple.
tnx.
Hi dpk,
It’s really helpful.
I’m stucked with an issue where I have to create grid of cubes eg. 32*32 grid. Here each cube has a different color and different height. So can you help me to sort it using libgdx.
Hi dpk,
I’m stucked with an issue where I have to create grid of cubes eg. 32*32 grid. Here each cube has a different color and different height. So can you help me to sort it using libgdx.
I just can’t get my transparent tiles to work. They always show a dark color regardles if I use proper PNG file, or fill the transparent part with pure green and then set it in tile editor… Any help? I’m actually growling at the screen right now!
I can not get the transparent tiles to work either. Transparency is working in the rest of my game, but not in the TileMapRenderer
Need to edit the tmx file and add the property defining which tiles need to be transparent. Here is an example from my own tmx file:
<tileset firstgid="1"
You can cut and paste that and then modify the value to define the transparent tiles. These values are the tile number references the tmx uses. Havent yet figured out an easy way to figure these values and I have a full mix of tiles that need to be transparent or not, so as you can see I just added them all.
That didnt paste right: took out the open braces so you can see.
map version=”1.0″ orientation=”orthogonal” width=”80″ height=”25″ tilewidth=”32″ tileheight=”32″>
properties>
property name=”blended tiles” value=”1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90″ type=”string”/>
/properties>
tileset firstgid=”1″ name=”levelblue” tilewidth=”32″
[...] http://dpk.net/2011/05/01/libgdx-box2d-tiled-maps-full-working-example-part-1/ [...]
I think this might be a bug, but whenever I run the TexturePacker GUI the images are reordered in a random way. For instance Tile_1 has an index of 1 but it might appear in the middle of the TextureAtlas. [ image | image | image | Tile_1 | image ]
Problem here is that Tiled uses the image’s location as the Grid number.
Any help?
tandblekninng med laser…
[...]v Dude.. I am not much into reading, but somehow I got to read lots of articl qa[...]…
I was wondering for a tutorial using isometric tileset especially with adding sprites dynamically to the map.Does libgdx support Isometric tiled map yet or not..As i have the carl reply of 2011 that libgdx does not support isometric yet..Kindly reply asap.thanks in advance
I downloaded the part 1 tutorial project and tried running it on the desktop. Unfortunately, I’m just getting a black screen. Any suggestions would be much appreciated.
First off great tutorial, it was very helpful in getting things ported from an C# game I was working on. Quick question for you, I’m using your TiledMapHelper class, and pulling the camera from there out into my scene class, where I have things like the hero sprite, enemies, pathfinding logic, etc. When I draw using the spritebatch though, my sprites are being drawn on the camera and not on the world map(when I move the camera the sprite stays in the same position on the screen, when it should be staying at the world coord). I’ve tried using unproject but I don’t think that is what I’m after.. It’s something to do with the camera only taking the map into account and not my other sprites..
This is really nice. I was just wondering if it’s possible to use the texture packer UI. Also, is it necessary to pack ur own tiles into a tile sheet or can I use any tile sheet I find out there?
I’m not sure about the UI but I don’t know of a reason it wouldn’t work. You should probably start with your own tiles, though, so that you can more easily build and rebuild them at a later time. It’s a pain to manually split out tiles.
Hey, I’m not sure if you still come back to this blog. But I’m having problems with the TexturePacker/TiledMapRendering.
Here’s the problem I’m having. http://badlogicgames.com/forum/viewtopic.php?f=11&t=4726&p=22660#p22660
Have you faced anything like this?
It’s been a while since I’ve worked on libgdx/TiledMap stuff unfortunately. Need to get back in to it one day.
I see a comment on that post suggesting that you may have found a solution though — the indexes needed updating. Is it working now? I definitely experienced some weirdness when it came to mapping pack indexes to tile indexes.
Hi, thanks for your usefull tutorials serie as it is helped me to get in using TMX file with LibGDX.
But I have a problem (and as i’m a beginner everything I tried failed to solve it).
So my problem is when I download your project, import it in Eclipse, it runs withtout problems and I can see your map on the screen with all your tiles in place.
So I tried to implement TMX files support in one of my own project using the TiledMapHelper you provide. But it always crashes when the render() method is called) !!
My code and yours are almost the same, the only differences are the “level.tmx” file, and so “level.png” and “level pack” are mines.
If you have some times, please take a look at the errors: http://stackoverflow.com/questions/11737426/libgdx-application-crashes-when-call-tiledmaprenderer-render
If you need more code please just let me know !
Thanks
So I can’t use your TexturePacker (NoClassDefFoundError when doing java -jar), and when using an other tool to do it called “TexturePacker GUI” the program doesn’t crash but the screen is fully black, and no tiles are displayed…
Any idea please ?
hi, thanks for the tutorial.
I tried to run the project in the zip file (http://dpk.net/android/jt/part1/JumperTutorialProjects.zip) using android 4.0.3, API 15, libgdx-0.9.6.
it compiled well, but it cannot run on emulator and device.
Any idea please ?
[...] found this tutorial to get me up and running: http://dpk.net/2011/05/01/libgdx-box2d-tiled-maps-full-working-example-part-1/#p1. Which I’ve followed (and made a few changes to) and I’ve got it up and running with my [...]
Hi,
I try to make a new map, with more and diferent tiles and there were some problems.
First, using texture packer indexs were all with the value -1.
After solving this problem, there was another one.
The map tiles do not appear on display, everything appears black.
Any idea about how to solve the problem?
Thanks ;)
Solved ;)
Hey, could you tell me how You solved the black screen problem? I’m having the same issue and I’m stuck :(
Ok, solved :)
For anyone that has a similar problem and uses TexturePackger GUI:
The indexes are wrong
The pack tileset names are wrong :)
can someone help me? i have this same problem, but i don’t know how to fix it. What indexes and pack tilesets should I put?
dude, great tutorial!
how is the part 3 coming along?
i have not succeeded in implementing the scoring system, so i am super interested!
nicomate3
[...] i want to use tiled for draw my maps. for use this map in libgdx i must build a level packfile, but i can’t build it. i use this ways for build it, but all of them has error in execute… this is my ways : Source for this way [...]
[...] http://dpk.net/2011/05/01/libgdx-box2d-tiled-maps-full-working-example-part-1/ a not yet finished tutorial, that will cover a complete example. Unknown to you should be the code from this passage on. [...]
I too ran into the problem with the tileset containing the improper index counts. I wrote a GUI wrapper around a copy of the TexturePacker class and fixed some of the issues. I have not tested this too much, but it has been working for me. Even though the GUI lets you set tile size it is hard coded for 32×32. I put it up at http://www.themanwithnolife.com/TilePacker.jar feel free to download a copy. It will output the packed file, the combined image, the tsx tileset and the tmx file for TileEditor (you can double click and start making your world). You should place all your output files to be in the same directory, then you can move them to required paths as described in this tutorial. This will solve the black screen issue. The black screen is due to TexturePacker placing the full path to the image in the output. This is fixed in the GUI version I posted.
Thank you,
William
Thanks William Whispell. You tile packer seems to be the only one which works for me. It’s not perfect, it has its own flaws, like having weird indices 0,1,2,1,2,3,2,3,4 etc. but it’s not a problem, I simply enumerate them from 1-n and it works perfectly.
All other tile packers, like the one in this tutorial or tile packer (deprecated) or tile packer 2. All of them messes ordering really bad. Indices are pretty correct, but they are not pointing to the right tile.
So everyone, I suggest using William’s tile packer.
By the way, great tutorial. Gave me a heads up.
For people who can’t get the TexturePacker to work see http://stackoverflow.com/questions/11737426/libgdx-application-crashes-when-call-tiledmaprenderer-render
I feel like I correctly placed the files, but whenever I try to run I get the following error message:
Exception in thread “Thread-2″ javax.media.opengl.GLException: com.badlogic.gdx.utils.GdxRuntimeException: File not found: data\packer\output\tiles1 packfile (Internal)
I’m not sure why its looking for an “output” folder under “packer”.
Has anyone had a similar problem or know what to do?
Thanks
I had the same problem – open your .tmx file in a text editor and find the <image source = "data\packer\output\tiles1"
Change it to "level.png" (or whatever your file is named)
That should fix that problem… but might just bring you to the next issue I'm trying to deal with, which is the .tmx file encoding seems to have changed.
When I open the .tmx file from this tutorial it has a long list of "” for data
When I open MY .tmx file it says and then has a huge string for the data.
No clue if there is a way to switch back to the old “” style or not, so I’m stuck here currently :(
Ok, may have fixed that problem (and run into another).
To fix the .tmx output file source code open Tiled and go to Edit >> Preferences >> Change to XML (new version is default 64bit zlib).
DO THIS BEFORE CREATING THE LEVEL. If you open a level you already created, change the output source formatting and save it IT WILL NOT CHANGE :(
I’m still getting a black screen though ;/
Woohoo, final fix!
Used Williams texture packer (above). I am using 16×16 and like everyone is saying, the default packer is hardcoded for 32×32.
So IN CONCLUSION:
1) Use William Whispell’s image packer to start (nice little UI too!). Note: you have to create your own output files beforehand, which the program then overwrites. After creating the files, open the “level packfile” in text editor and make sure the “index” field starts at 0 and increases by 1 each time (0,1,2,3…).
2) BEFORE CREATING YOUR MAP in “Tiled Map Editor”, set your output type to XML under the Edit >> Preferences settings. THEN do File >> New…
3) Open your .tmx file in text editor and make sure your is pointing to the correct file location (for this tutorial it should just be “level.png”).
William Whispell thankyou thankyou thankyou!!
I was trying to implement tilemap , its giving ” File not found(Internal)” exception while i hav loaded ma file in assets
solved!!