Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411490 Posts in 69371 Topics- by 58428 Members - Latest Member: shelton786

April 24, 2024, 04:22:18 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Level generation in a tile based platformer?
Pages: [1]
Print
Author Topic: Level generation in a tile based platformer?  (Read 2944 times)
Ember
Level 0
*



View Profile
« on: November 05, 2010, 07:38:23 PM »

I've been working on a small platformer engine. I've gotten  basic player movement, and a tile class that works with collision. However, I seem to be stuck on making a level without resorting to just creating a whole lot of tile objects manually.(A more automated process, if you will)

Most tutorials I look up appear to be saving "tilemaps" in arrays. However, most are written in actionscript (I'm using Java) and I can't figure out what they're doing to automate tile creation based on a text tilemap. Can anyone add some advice to my predicament?
Logged
gwar
Level 0
***


View Profile
« Reply #1 on: November 05, 2010, 11:42:51 PM »

On disk or in memory? Well im using python but my tiler tries to read .tmx files. They are a xml file with a gziped tile array, the editor is even written in java so you could have a read of it. http://www.mapeditor.org/

How do I store my tiles? A list of lists (yay python) and a dict to relate any properties a tile has tile has that i'd want to look at later.
Logged
mcc
Level 10
*****


glitch


View Profile WWW
« Reply #2 on: November 06, 2010, 12:54:14 PM »

Are you asking about how to build levels or how to make procedurally generated levels?

For procedural generation, what a lot of games do is create kind of a "bag" of little fragments of levels and then combine them randomly. So like you yourself would create five or six 8x8 chunks of a level and then fit together the chunks at random. It's not the most creative thing but it works and it's simple to implement.

If you're wanting to make your own levels, you can use my trick: Just make a PNG. Tile-based maps and images have this nice 1:1 correspondence in that they both basically consist of discrete identifiers on a grid, and PNGs are easy to parse (Java will surely have a standard class for this). So like here's level 1 from Jumpman:



The game loads that image out of the program data, anywhere it sees a black pixel it places a wall, anywhere it sees a red pixel it places an enemy, anywhere it sees a blue pixel it places an exit, etc. I originally drew this in just an image editor. Doing things this way can save a lot of time until you write your own tile editor.

I believe I have seen posted in this forum in the past a couple of people who have made sort of abstract tile-layout editors that will integrate well with any project, but I don't remember the names of these projects. When I search on google for "java tile editor" however I see this, which seems promising.
Logged

My projects:<br />Games: Jumpman Retro-futuristic platforming iJumpman iPhone version Drumcircle PC+smartphone music toy<br />More: RUN HELLO
Ember
Level 0
*



View Profile
« Reply #3 on: November 06, 2010, 04:26:22 PM »

Perhaps I should have been more specific. This is purely reading a file and loading it in the engine. Not procedural generation(I'm definitely not ready for that!)

After reading up on two dimensional arrays, I found that you can iterate through them, and I tried doing that with drawing tiles.

My temporary system, a 2d array with 1s and 0s:
Code:
	int level[][] = 
{
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
};
My paint method:
Code:
	public void paint()
{
Graphics g = (Graphics) buffer.getDrawGraphics();
g.setColor(Color.black);
g.fillRect(0,0,800,600);
p1.draw(g);
//draw tiles
g.setColor(Color.blue);
{
//set i to 0, when it finishes all the columns in a row, increment the row
//stop when you run out of rows
for(int i = 0;i < level.length; i++)
{
//set j to 0, when it finished all the columns in a row, loop back and increase the row number
for(int j = 0; j < level[ 0] .length; j++)
{
if(level[i][j] == 1)
{
//draw a 32x32 tile
g.drawRect(j*32, i*32, 32, 32);
}
}
}
}
Which does work...
However the problem is, its really taxing to do this every frame. What can I do to optimize this? Is there a better way?

Also, the image trick is neat, but I don't understand how I would read an image's per pixel color values from the standard Image class. Would I have to write code to separate the image into pixels, read the values, then blit it back together again?
« Last Edit: November 06, 2010, 04:49:54 PM by Ember » Logged
Aquin
Level 10
*****


Aquin is over here.


View Profile WWW
« Reply #4 on: November 06, 2010, 04:49:27 PM »

For Java, I tended to only look at what was around the player character.  I remember doing that for a project in J2ME anyway, but I'm surprised you need that kind of optimization.

How many tiles are on-screen at once?  Or are you going through the whole level? 
Logged

I'd write a devlog about my current game, but I'm too busy making it.
Ember
Level 0
*



View Profile
« Reply #5 on: November 06, 2010, 04:51:59 PM »

I only drew one screen in that example, 25x18 32 pixel tiles, which is 450 tiles.
Logged
gwar
Level 0
***


View Profile
« Reply #6 on: November 06, 2010, 05:08:37 PM »

I'd like to know too, other than language specific things, like using numpy arrays for me. What I thought would be good is using a surface to blit to and move around. So the best case would be just 1 blit and no for loops, and worst for 32x32 tiles on a 800x600 display would be about 44 + what ever it takes to subsurface, move and reblit the part of the screen that didnt change. Dunno if that makes sense to anyone else, still it seems better than 475 odd.
Logged
mcc
Level 10
*****


glitch


View Profile WWW
« Reply #7 on: November 06, 2010, 06:02:47 PM »

However the problem is, its really taxing to do this every frame. What can I do to optimize this? Is there a better way?

If your grid of tiles is sparse-- that is, many or a majority of the tiles are "blank"-- one thing you can do is instead keep an array of objects each describing {x position, y position, tile} and then iterate over the array. It is easy to start with a "grid of tiles" like you've got in your big 2D array there and build your array of tiles from that. This sounds like what your actionscript tutorials were probably describing. The downside is it then becomes a little tricky to do what Aquin describes and draw only the tiles immediately around the player.

However, this is way overkill for what you are doing. Iterating over a 25x18 array is simply not going to be taxing, in any programming language. Even in your best case scenario, switching to the array-of-items idea will mean you're iterating over about 50 or items rather than iterating over 400 items. This isn't much of a gain, plus given your sample code, in those 350 "extra" cells you're just moving to the next cell. Checking an few hundred empty array indexes and then doing nothing is not expensive.

Another simple trick, which only really works with the "array of objects to draw" technique, is that you can try to break down your tiles into larger blocks. So if you have a rectangular block of 10x10 tiles that are all the same, instead of drawing 100 individual tiles you could draw 1 large block with a tile "texture". Again this may be overkill for what you are doing.

Quote
Also, the image trick is neat, but I don't understand how I would read an image's per pixel color values from the standard Image class. Would I have to write code to separate the image into pixels, read the values, then blit it back together again?

Unfortunately I am not familiar enough with with Java to really help you here. A cursory google check suggests you want to use something from the standard library called "PixelGrabber"
Logged

My projects:<br />Games: Jumpman Retro-futuristic platforming iJumpman iPhone version Drumcircle PC+smartphone music toy<br />More: RUN HELLO
Ember
Level 0
*



View Profile
« Reply #8 on: November 06, 2010, 08:22:44 PM »

Well, what I thought was being intensive was eclipse being silly and not closing at least a good 100 instances of "javaw.exe". After closing all those it ran reasonably well.
Logged
mimimimi
TIGBaby
*


View Profile
« Reply #9 on: July 22, 2014, 06:02:42 PM »

Well, what I thought was being intensive was eclipse being silly and not closing at least a good 100 instances of "javaw.exe". After closing all those it ran reasonably well.

glad you finally solved this problem. but i still can't figure out how this gonna happen after closing all this. i am a java programmer but in java class on barcode generation, sorry can't be more helpful.
Logged
diegzumillo
Level 10
*****


This avatar is so old I still have a some hair


View Profile WWW
« Reply #10 on: July 22, 2014, 06:08:38 PM »

Seems like you want some sort of autotile algorithm, like this: http://www.saltgames.com/2010/a-bitwise-method-for-applying-tilemaps/
Logged

Ky.
Level 0
***


Programmer & Web Slinger


View Profile WWW
« Reply #11 on: July 23, 2014, 10:02:36 AM »

just jumping in to say that you may want to change IDEs from Eclipse.

Eclispe used to be great (imo) but it has been far surpassed by tools like IntelliJ (arguably I guess, but Eclipse is just bad now)
Logged

gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #12 on: July 23, 2014, 04:36:43 PM »

http://tinysubversions.com/spelunkyGen/
Logged

Geti
Level 10
*****



View Profile WWW
« Reply #13 on: July 23, 2014, 05:42:13 PM »

Quote
Perhaps I should have been more specific. This is purely reading a file and loading it in the engine. Not procedural generation(I'm definitely not ready for that!)
Consider reading the thread first folks to avoid overwhelming a new programmer Smiley

Quote
Also, the image trick is neat, but I don't understand how I would read an image's per pixel color values from the standard Image class. Would I have to write code to separate the image into pixels, read the values, then blit it back together again?
For reading pixels out of an image in Java it's usually simplest to use a BufferedImage and getRGB

Here's an untested example that should work or at least be helpful for reading the pixels of an image.
You'll have to import the correct packages but your IDE should handle that.
Code:
BufferedImage bi;

try{
bi = ImageIO.read("./path/to/image.png");
} catch(Exception e) { /*handle errors properly children*/ }

//loop over all the pixels
int w = bi.getWidth(null);
int h = bi.getHeight(null);
for(int y = 0; y < h; y++)
{
for(int x = 0; x < w; x++)
{
//pixel is in 0xaarrggbb format
int pixel = bi.getRGB(x,y);
//you can compare directly with if(pixel == 0xffRRGGBB)
//assuming a full alpha image

//do something with pixel here
if(pixel == 0xff000000) //black
{
//wall?
}
else
{
//empty space
}
}
}
Logged

Actionman
Level 0
***


ermm...


View Profile
« Reply #14 on: July 24, 2014, 08:48:17 PM »

When I was doing something similar i just used a comma separated file. The code for a level would look like this:

Code:
0,0,3000,0,1
0,1500,3000,1500,1
0,400,900,410,1
500,359,550,401,1
550,301,600,401,1
200,359,700,401,1
0,0,600,10,1
400,340,600,350,1
0,0,40, 300,1

The first two values were where to begin drawing the tile, the second two the size and the last value the type of tile, so that a texture and collisions could be applied
Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic