![]() |
|
platformer tutorial/guide in c |
_jagged
Member #17,124
September 2019
|
Hello everyone, I'm interested in making a simple tile based 2d platformer in the style of ghouls n ghosts. But i'm having trouble finding information on how to begin. I've found tutorials on youtube that use c++ but nothing using plain c. I know I could probably adapt the info from one of these c++ tutorials into c, but they all tend to go straight into classes and inheritance and all the garbage of c++ that i'm not interested in. Does anybody know of a tutorial or guide that could at least point me in the right direction? I know enough allegro and c to make simple shmups that constantly scroll, with parallax backgrounds and animations but I have no idea how to set up a tile based map, make tiles solid etc... Cheers!
|
MikiZX
Member #17,092
June 2019
|
Possibly these pages can help you a little (please note I've never used these and they are mostly Allegro5 related): https://github.com/dradtke/allegro_tiled |
DanielH
Member #934
January 2001
![]() |
Try yourself *This is a basic example, from memory* 1//1. determine how many tiles will fit on your display at one time
2#define GRID_WIDTH 40
3#define GRID_HEIGHT 30
4
5//2. determine cell size
6#define CELL_WIDTH 32
7#define CELL_HEIGHT 32
8
9//3. determine how big the overall map is
10//will it scroll horizontally or vertically or both
11#define MAP_WIDTH 400
12#define MAP_HEIGHT 30 // same as grid height if not scrolling vertically
13
14int camera_x = 0
15int camera_y = 0
16int map[MAP_WIDTH * MAP_HEIGHT];
17
18// for this example I'm using an array of bitmaps for tile
19// ALLEGRO *tile[];
20void draw_map
21{
22 int i, j, x, y, sx, sy, c;
23
24 x = camera_x / CELL_WIDTH;
25 y = camera_y / CELL_HEIGHT;
26 sx = camera_x - (x * CELL_WIDTH);
27 sy = camera_y - (y * CELL_HEIGHT);
28 c = map[x + (y * MAP_HEIGHT)];
29
30 // draw grid height + 1
31 for (j = 0; j <= GRID_HEIGHT; ++j)
32 {
33 // draw grid width + 1
34 for (i = 0; i <= GRID_WIDTH; ++i)
35 {
36 // draw tile at pos
37 al_draw_bitmap(tile[c], 0, 0, (i * CELL_WIDTH) - sx, (j * CELL_HEIGHT) - sy);
38 }
39 }
40}
All you have to do is adjust camera_x and camera_y. You can adjust by pixel amount or whole tile size; What I do is put player in the middle. If the player crosses an imaginary boundary then adjust the camera to counter movement; example: The map above is for a 640x480 grid. You can put boundary at 80 and 560; if (player_x < 80) { camera_x -= (80 = player_x); if (camera_x < 0) camera_x = 0; // keep in check player_x = 80; } if (player_x >= 560) { camera_x += (player_x - 560); if (camera_x >= (MAP_WIDTH - (GRID_WIDTH * CELL_WIDTH))) camera_x = (MAP_WIDTH - (GRID_WIDTH * CELL_WIDTH))); player_x = 559; }
|
RmBeer2
Member #16,660
April 2017
![]() |
It has no secret, it's just about printing a mesh of images based on a double index vector. πππ π BlackRook WebSite (Only valid from my installer) π C/C++ π GNU/Linux π IceCream/Cornet π πππ Rm Beer for Emperor 2021! Rm Beer for Ruinous Slave Drained 2022! Rm Beer for Traveler From The Future Warning Not To Enter In 2023! Rm Beer are building a travel machine for Go Back from 2023! Rm Beer in an apocalyptic world burning hordes of Zombies in 2024! |
_jagged
Member #17,124
September 2019
|
Thank you all for your replies, I think there's enough here to get started. I'm now realising I actually know less about game design than programming. It's just
|
MikiZX
Member #17,092
June 2019
|
If you were making a game as 'Ghosts 'n Goblins' then movement would be somewhat easier to make as 'Ghosts 'n Goblins' does not have slanted surfaces to walk over like 'Ghouls n Ghosts' does. Slanted surfaces would slightly increase complexity of your collision detection algorithm. It is 'collision detection algorithms' that help us define which part of the map is solid or ethereal. An oversimplified version of collision detection you could use follows but please note that it is just a suggestion of a direction you might take: I'm not sure if I'm explaining this well. If I should explain better please let me know. And, as an advanced programming task, and possibly not needed for your project, if you were to expand the collision detection further you could look into using Box2D which is a library that can help with collision detection problems - though you would need to write a parser for your tilemap that would transcribe your tilemap into objects that Box2D understands and likely learning a new library might not be something you've really planned on. P.S. For ease of understanding collision detection I would say that 'Ghouls n Ghosts' maps actually have two layers (one layer is the actual game-field that is considered when collision detection is done, and the second layer is drawn behind and is just a background - a decorative one, not considered when collision detection is processed). The enemies in that game would be taken in account when collision detecting though the player-enemy collision is likely done using rectangle-rectangle collision detection algorithm. To understand collision better try searching on the Internet using these keywords: "2d platformer collision detection algorithm" |
Mark Oates
Member #1,146
March 2001
![]() |
There are no tilemap classes in AllegroFlare yet for me to share, so my apologies on that. Right now I have 7 different tile map projects, each implementation is different so there are a lot of approaches that can work depending on your needs. I'm in the process of consolidate them all into a single one, Tileo being the most consolidated one so far. It does lack a simple renderer like the one DanielH sketched out. I should probably add that next before anything else. The more advanced renderer is a mesh renderer (the tiles in the tilemap are placed on a single 2 dimensional 3d mesh of squares, each square is a tile in the map). One version also uses a custom ALLEGRO_PIXEL_FORMAT which includes normal data for each pixel, so dynamic lighting effects can be added via shaders. I have a couple screenshot of that: {"name":"612202","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/1\/a\/1a581cc2b8faecb4db7cb3c0646e0fec.png","w":894,"h":552,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/1\/a\/1a581cc2b8faecb4db7cb3c0646e0fec"} _jagged said: So, does the player just float a certain tile height? as in there's no coding of solid/ethereal for the ground? Collision for tile maps is another topic. -- |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Hey baby, nice tiles. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
DanielH
Member #934
January 2001
![]() |
I spent a couple hours and made this code as a simple example of what I was talking about. I don't do plain c, so I tried my best not to overcomplicate it. Any questions, just ask. This is a simple horizonally scrolling tilemap. There are layers &background, solid, foreground, items, etc). At the moment there is only drawing layers and no collision checking. Only boundary checking. The "player" is the red rectangle. With the left and right keyboard buttons you can move left and right. The camera will scroll accordingly. The tile bitmap is pretty empty at the moment, but enough for example. You might have to adjust location of where to load the tiles. |
_jagged
Member #17,124
September 2019
|
Thanks everyone! DanielH, I created something similar to what you posted only my version is much more simple using primitive rectangles. I now have boundary detection and left/right collision detection, and a jump. Thanks again.
|
Ariesnl
Member #2,902
November 2002
![]() |
This is a GREAT resource : http://www-cs-students.stanford.edu/~amitp/gameprog.html#tiles I hope this is in a book someday Perhaps one day we will find that the human factor is more complicated than space and time (Jean luc Picard) |
Chris Katko
Member #1,881
January 2002
![]() |
Mark Oates: That's great! I am all about some 2-D bump mapping. -----sig: |
Audric
Member #907
January 2001
|
There is one thing that sometimes takes time to realize / re-invent, when you see how platform games work : Some tiles have to count as "soft" platforms. A completely "solid" tile will resist player movement from every direction. As a result, the player always stays 'outside' of it:
"soft" platforms only apply ruler nΒ°3). Most platform games have such. If the player has no jump-down controls that lets them fall through them voluntarily, the level design has to take it into account (there are holes or designated ladders, or no need to go back down). |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
All you really need is Line Segment vs Line Segment collision detection. Then you can do anything you want. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
DanielH
Member #934
January 2001
![]() |
Yes, but that's not "simple" |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
I coded my own AABB intercept routines, which account for velocity and acceleration. Once you know a collision has taken place, you can do anything with it. Stop movement. Bounce. Let it pass through, whatever. And velocity based line segment collision is not hard. It's adding in things like rotation and acceleration that make it hard. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
_jagged
Member #17,124
September 2019
|
I'd just like to thank you all again for the info in this thread, I appreciate all the responses even if I haven't acknowledged everyone, I have absorbed your wisdom. This whole endeavour of game making has been overwhelming. Making games is damn hard. I've battled with so many collision detection and response problems over the last week. But I feel they've really strengthened my understanding of C. Thanks everyone.
|
DanielH
Member #934
January 2001
![]() |
Here is a "simple" point collision for the code above. This uses a mask for collision. I created a bitmap the same size as the tiles. Black is open, White is closed. 1 bool collide(int x, int y)
2 {
3 static int tx = 0;
4 static int ty = 0;
5 static int sx = 0;
6 static int sy = 0;
7 static int px = 0;
8 static int py = 0;
9 static int value = 0;
10 static ALLEGRO_COLOR p;
11
12 tx = (x >> TileShiftX);
13 ty = (y >> TileShiftY);
14 sx = x - (tx << TileShiftX);
15 sy = y - (ty << TileShiftY);
16
17 // returns value of cell at specified x, y, layer
18 value = getValue(tx, ty, LayerSolid1);
19
20 px = (value % TileAcross) << TileShiftX;
21 py = (value / TileAcross) << TileShiftY;
22
23 p = al_get_pixel(MaskBitmap, px + sx, py + sy);
24
25 return (p.r != 0 || p.g != 0 || p.b != 0);
26 }
27
28// call it
29bool hit = collide(x - camera.x, y - camera-y);
|
|