Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411281 Posts in 69324 Topics- by 58380 Members - Latest Member: bob1029

March 28, 2024, 10:16:26 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Platforming tutorial
Pages: [1]
Print
Author Topic: Platforming tutorial  (Read 5983 times)
ImaginaryThomas
Level 1
*


Reor, Creo, Incito


View Profile WWW
« on: July 15, 2008, 04:43:36 AM »

Hi all, a long time coder taking his first stab at game programming.  Gentleman

I've chosen Pygame for my first code platform and so far all is going well. I plan to continue to make a platforming type game but I am at a loss of how to handle the floor. The best example of the type of floor I'm looking to do is Super metroid. Sort of a slopey floor with little hills and uneven areas.

Could someone kindly point me in the right direction?
Logged

muku
Level 10
*****


View Profile
« Reply #1 on: July 15, 2008, 09:36:32 AM »

Couldn't find any pygame tutorials specifically on platformers. Basically you could do something tile-based where you have some ground tiles which are flat, some which rise in a 45 degree angle and some which fall with that same angle. The math is very simple then, shouldn't be too hard to handle.

But to tell the truth, I'd say a platformer is rather tricky as a first game project, you have to deal with lots of stuff like collision detection, sprite animation and so on that's not trivial. Have you considered starting with something simpler? Or have you already done some simple stuff like a Tetris, Pong or Snake clone and want to take the next step now?

Just in case you haven't seen it, this looks like a nice tutorial on game programming in pygame: http://lorenzod8n.wordpress.com/category/pygame-tutorial/ (no offense if this is beneath your level, it's hard to judge what you've done so far).
Logged
Ryan
Level 1
*



View Profile
« Reply #2 on: July 15, 2008, 01:38:11 PM »

Going through this tutorial will get you up and running quickly, especially since you stated you were a long-time programmer (this site uses flash, but the concepts work in any language). The tutorial covers everything from jumping to slope tiles, ladders, scrolling the screen, and enemies.

Basically, you're going to have a map that's a 2D array of tiles. For example, a tile could be something like this (I don't know python, so here's c):

Code:
typedef enum {
  TYPE_BLOCK,
  TYPE_LSLOPE_45,
  TYPE_RSLOPE_45
} TileType;

typedef struct {
  TileType type;
  Texture  texture;
} Tile;

You would have a 2D array of these tiles to represent your map. The tile type dictates the collision, and the texture dictates what the tile will look like. This is how you get your bumps and rocky terrain without using complex collision detection techniques.



If you have any other questions, let us know, otherwise I think those tutorials will pretty much give you (almost) all the knowledge you need. Beer!
« Last Edit: July 15, 2008, 01:43:16 PM by Ryan » Logged
ImaginaryThomas
Level 1
*


Reor, Creo, Incito


View Profile WWW
« Reply #3 on: July 15, 2008, 03:46:06 PM »

Thanks for the help!

I've coded a pong clone long long ago when I was in a flash phase so I'm not a complete stranger.

So am I right in assuming the best way to map a platformer is with a 2d array? I understand how it would be read into a game but would that mean each tile is an object? wouldn't that slow down things considerably on large maps?
Logged

Ryan
Level 1
*



View Profile
« Reply #4 on: July 15, 2008, 06:51:14 PM »

Well, I was coming from the standpoint that you wanted to make something like Metroid, 2D array would be quick and easy.

A way to optimize the technique is to decide what type of tiles you need before hand. You could have two 2D-arrays per map. One would contain the collision blocks, and another array could contain what you're drawing on the screen. I think a diagram would be better than me trying to explain things:

Code:
KEY FOR COLLISION MAPS:      0 - empty space
                             1 - full tile
                             2 - slope left
                             3 - slope right

COLLISION MAP (as an array): 0000000
                             0021300
                             1111111
---

KEY FOR TILE MAP (textures): 0 - empty space
                             1 - rocky tile
                             2 - slope left, rocky
                             3 - slope right, rocky
                             4 - lava pit

TILE MAP (as an array):      0000000
                             0021300
                             1444411

This way you could use only a byte for each tile entry (or an integer depending on what python has). If everything in python is an object and you don't want to waste memory, could you use NULL instead of 0?

If you are doing something with a lot more space involved, then you can use geometry. It gives you more flexibility, but harder to program. If that's the route you want to go (which I don't recommend for your first platformer) then I can explain more stuff as needed.

(Also, just trying to help. I don't consider myself a "master" or anything, just giving my opinions in hope they help you out in some way. Programmers are opinionated beasts, it's good to get a lot of opinions.) Gentleman
Logged
Ivan
Owl Country
Level 10
*


alright, let's see what we can see


View Profile
« Reply #5 on: July 15, 2008, 08:13:33 PM »

Here's the tilemap code for the platforming engine I wrote. It's all pure C, but I hope it helps. It has tilemap loading/saving and collision stuff in there.

http://code.google.com/p/librgs/source/browse/trunk/src/rgs_tilemap.c
Logged

http://polycode.org/ - Free, cross-platform, open-source engine.
Wilson Saunders
Level 5
*****


Nobody suspects the hamster


View Profile WWW
« Reply #6 on: July 16, 2008, 10:22:58 AM »

It is good to hear you coded pong first, most beginners want to jump into their final fantasy clone without understanding how to render and update. I advise you redo the pong thing in Pygame to make sure that you know all the render and input commands before you get too deep into a platformer.

While I am too selfish to share my C++ code here are a list of concepts that will probably help you:
Camera:
If you plan on having the ability to scroll in your world like Super Mario Brothers you will need a camera point. If however you want to play the game on one screen like Donky Kong a camera is unnecessary. Usually the camera is centered on the player but it gives you the flexibility to display whatever you want to the user.
Camera related members usually are
float camCenterx;
float camCentery;
float zoom; // optional and a lot of hard work
Camera related methods are:
float worldToScreenX(float x);
float worldToScreenY(float y);
float screenToWorldX(float x);
float screenToWorldY(float y);
Since I use these functions a lot I usually shorten them to WTSx(float x) to save on typing. The important thing to realize is that there is a difference between world space and screen pixel location. I have seen many programmers learn this the hard way with baffling bugs such as, why is the character not on the screen, or why is he running into invisible walls or passing through solid blocks.

I usually store my levels in an int array but nothing stops you from using an object to represent one node. Only the objects’ member components are stored in memory, the function calls will be added and removed from the stack as they are used.

You will also need some means of figuring out which block a particular point in space rests inside. If you go with a one dimensional array of blocks to represent your level you will need a function to return and index of the block you are inside:
int getBlockIndex(float x, float y);

Once you have this function you can start checking for collisions. While you will most likely will apply player movement to one point in space to denote where your character is it helps to use at least four points to resolve collisions in a 2d world. These points should be placed at the min/max of the x and y values of the character. Meaning the lowest and highest y values should be placed at the bottom of the foot and top of the head.

Every time you update a character’s position set these four points relative to the character’s new location. Then run their x,y values through getBlockIndex(). If it returns an empty square they life is good and no collision has occurred. If it returns an impassable square then you need to resolve the collision fortunately you know which of the four points caused the collision. For example if it was the high y point your character obviously moved too high and the center y value for the character needs to be adjusted accordingly.
Logged

Play my games at http://monkeydev.com/
bateleur
Level 10
*****



View Profile
« Reply #7 on: July 16, 2008, 10:49:58 PM »

So am I right in assuming the best way to map a platformer is with a 2d array?

Not necessarily "best" in general, but it's a very widely used method which is very easy to use, so definitely a good choice for what you're doing.

Quote
I understand how it would be read into a game but would that mean each tile is an object? wouldn't that slow down things considerably on large maps?

Tiles need not be objects. An array of integers is often fine, with each integer acting as an index into a tile descriptor table. You then have one tile description object for each type of tile rather than for each tile.

That said, using an object per tile wouldn't slow things down anyway. Rather than performing collision detection on every tile, you instead exploit the grid structure to narrow down the set of tiles you might have collided with to a small rectangular region around the character. You then perform proper collision detection only against those tiles. (This approach is sometimes called "broad phase" collision detection.)
Logged

Cymon
Level 9
****


Computer Kid


View Profile WWW
« Reply #8 on: July 17, 2008, 08:19:09 AM »

So am I right in assuming the best way to map a platformer is with a 2d array?


work pretty good.
Logged

Cymon's Games, free source code, tutorials, and a new game every week!
Follow me on twitter
muku
Level 10
*****


View Profile
« Reply #9 on: July 17, 2008, 09:07:04 AM »

So am I right in assuming the best way to map a platformer is with a 2d array?


work pretty good.
Hm, somehow I doubt that's implemented as a 3D array. Memory usage would be through the roof for large levels as you'd have to store all those empty cells. Could be wrong, of course.
Logged
ImaginaryThomas
Level 1
*


Reor, Creo, Incito


View Profile WWW
« Reply #10 on: July 17, 2008, 04:06:36 PM »

Quote
I understand how it would be read into a game but would that mean each tile is an object? wouldn't that slow down things considerably on large maps?

Tiles need not be objects. An array of integers is often fine, with each integer acting as an index into a tile descriptor table. You then have one tile description object for each type of tile rather than for each tile.

That said, using an object per tile wouldn't slow things down anyway. Rather than performing collision detection on every tile, you instead exploit the grid structure to narrow down the set of tiles you might have collided with to a small rectangular region around the character. You then perform proper collision detection only against those tiles. (This approach is sometimes called "broad phase" collision detection.)


You will also need some means of figuring out which block a particular point in space rests inside. If you go with a one dimensional array of blocks to represent your level you will need a function to return and index of the block you are inside:
int getBlockIndex(float x, float y);

This is exactly what I was looking for, that was my understanding of how it would work but it just sounded like there was an easier way I just couldn't wrap my mind around.

I probably should revisit the pong clone idea, it's been a while since I've done anything that's not web programming (if anyone needs a web dev, I do freelance Tongue)

Thanks for the great advice from such a friendly community!
Logged

muku
Level 10
*****


View Profile
« Reply #11 on: July 17, 2008, 04:21:28 PM »

This is exactly what I was looking for, that was my understanding of how it would work but it just sounded like there was an easier way I just couldn't wrap my mind around.

Also, if you want to keep it simple, start with a non-scrolling platformer, i.e. one screen per level. That way your conversion from your grid indices to screen coordinates and vice versa is basically just a multiplication by your tilesize or a division by it, respectively. In other words,

screenX = gridX * tilesize
screenY = gridY * tilesize

You might have to adjust for sign depending on whether your y axis points up or down. Generally I'd recommend always having y point up, it's just less confusing in the long run. Depends on the framework though, with OpenGL it's trivial to do, with purely framebuffer-based libraries it's a bit more work, but still quite easy.
Logged
cmspice
Level 1
*


View Profile
« Reply #12 on: July 20, 2008, 11:29:31 AM »

http://lazyfoo.net/SDL_tutorials/index.php has some nice tutorials for SDL but they generalize to platformers in any language.

For handling a tiled floor, the tutorial suggests using a 1D array of tiles and checking for collision with every single tile (this takes a lot less processing power than you think with square tiles because collision is just 4 comparisons). It makes sense to me so it'll be the system I'm using for my platformer.

BTW, I don't think there's anything wrong with a platformer as your 'first' game (discounting the pong clone) because that's precisely what I'm doing. But be warned a platformer is BIG. Probably a lot bigger than you think it is. I'm not sure how much programming experience you have but I'll say this anyways. A strong grasp in object oriented programming will be very useful. You can't really get away with tackling a platformer like you would a pong clone. You can sort of grasp a pong clone entirely in your head since it's small. A platformer has so many elements that all need to work together. Of course you can do each part in your head but then when it comes to interfacing all these parts, you'll find inconsistencies that are just a pain to fix. So make sure you plan a few steps ahead.

Goodluck.
Logged
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic