Sign in to follow this  

2D platformer and hit detection

This topic is 3034 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Well, here's the deal. I have some experience now with SDL, and have made some fairly small 2D projects. Aside from that, I am still a bit of a newbie. I have a function all made up that I use for simple hit detection, and that has been great thus far. However, now I am running into a snag. I now have a large world map, which is navigated by the player. There are also levels that the player can enter, which are sidescrolling 2D platformer types. My problem is this: How on earth do I handle hit detection for everything? First of all, what is a good way to let the game know my character is on the ground, or against a wall? Do I need to add in hundreds of hitboxes by hand? This is what I started to do, but it seems that there must be some FAR better approach that I simply cannot come up with. And then I need to detect whether or not my character has hit an enemy, or whether an enemy has hit him. I am a bit overwhelmed, and am hoping there is some relatively simple solution. For enemies, I figured I would make each enemy type a class. Each class would have a hitbox variable. Then, I could make an array of whatever enemy type I need a few (or a bunch!) of, and then have the player's hit detection function check each class in each array using for loops. Each enemy class could also have its own hit detection function included, and then another for loop could run each class in each array's hit detection function to see if they hit the player. I hope the above paragraph makes some sense. That is what I have come up with on my own, and I must admit I don't know a whole lot yet. Any light anyone could shed would be greatly appreciated.

Share this post


Link to post
Share on other sites
Quote:
For enemies, I figured I would make each enemy type a class. Each class would have a hitbox variable. Then, I could make an array of whatever enemy type I need a few (or a bunch!) of, and then have the player's hit detection function check each class in each array using for loops.


Sounds like you've pretty much got it. You have each enemy store its current position and collision rectangle, and each frame you just loop over every enemy and check against the player's collision rectangle.

With regards to the collisions with scenery: it depends on how all the backgrounds, etc, are stored. If you're using tiles then you can define some tiles as 'impassable' and the rest as 'passable' (or equivalent). Then you can just check against all the impassable tiles. Otherwise you'll have to create or make use of some form of level editor to define by hand where all the walls are, and check against all of them in the game. There are optimisations you can make to reduce the number of checks, but you probably don't need to worry about them at this stage.

EDIT: I hope I've understood your problem correctly!

Share this post


Link to post
Share on other sites
Quote:
Original post by Dark_Oppressor
First of all, what is a good way to let the game know my character is on the ground, or against a wall? Do I need to add in hundreds of hitboxes by hand? This is what I started to do, but it seems that there must be some FAR better approach that I simply cannot come up with.

You could generate those hitboxes from other, easier to create, data. Like, as shaolinspin already suggested, a tilemap.

Quote:
For enemies, I figured I would make each enemy type a class. Each class would have a hitbox variable. Then, I could make an array of whatever enemy type I need a few (or a bunch!) of, and then have the player's hit detection function check each class in each array using for loops. Each enemy class could also have its own hit detection function included, and then another for loop could run each class in each array's hit detection function to see if they hit the player.

Sounds like code duplication to me. All those enemies would have a hitbox and the same collision check function, so why not put that into a single base class? In fact, if your enemies only differ in data (different sprite, different walking speed, etc.) then you might as well just write one class for them.

Share this post


Link to post
Share on other sites
I'm in the middle of doing the same thing myself

At the moment my levels are images (ie not tile-based) and a simple level editor lets me drag either a rectangle collision box for walls, floors etc and a triangular one for slopes over each respective landscape feature in the image

the level editor when writing the data to an xml file splits the level into vertical sections

the game detects which section the player is in (is player's x co-ords between the start and end x values for that section) and only runs through the collision test loops for the collision boundaries in that section (each section is a node in an array with a vector of rectangles or triangles associated with it), just thought it'd worth mentioning that since you said you had large levels, might just speed things up a bit since you're not testing everything in the level against everything else each frame

Share this post


Link to post
Share on other sites
Ok, great! So it sounds like I actually have a clue when it comes to the enemies. Captain P, I am already making classes for each enemy type, and I guess making just one class is probably all I really need to do, I'll change that. The class has a collision detection function in it, and that is what I was trying to say in my first post.

So that part is starting to sound quite doable. I'm still a bit worried about the level part, though. Mantrid, are you saying you made a little level editor for your engine? That is an interesting idea. What do you all think? Which is the better approach, tiles or non-tiles?

One more question: If you make a level using tiles, the actual level is "drawn" in your code, and does not exist in any image file, right? (Other than the individual tiles, obviously)

Share this post


Link to post
Share on other sites
Quote:
So that part is starting to sound quite doable. I'm still a bit worried about the level part, though. Mantrid, are you saying you made a little level editor for your engine? That is an interesting idea. What do you all think? Which is the better approach, tiles or non-tiles?

One more question: If you make a level using tiles, the actual level is "drawn" in your code, and does not exist in any image file, right? (Other than the individual tiles, obviously)


Well, the 'better' approach depends on what you want to do in your levels. For platformers, tiles are probably the most-used approach, because it allows you to create a great variety of shapes, and vast levels, with only a few graphical elements.

There are tile editors out there, which you could use to create levels in your game if you don't mind a bit of extra coding to create the functions to load them in.

You are right about the last point; the level is assembled and drawn on-the-fly from the individual tile graphics and a tile map. Using a single image for the level would use up a huge quantity of memory for anything other than small levels (i.e. the size of a few screens).

Share this post


Link to post
Share on other sites
Quote:
Original post by Dark_Oppressor

So that part is starting to sound quite doable. I'm still a bit worried about the level part, though. Mantrid, are you saying you made a little level editor for your engine? That is an interesting idea. What do you all think? Which is the better approach, tiles or non-tiles?

One more question: If you make a level using tiles, the actual level is "drawn" in your code, and does not exist in any image file, right? (Other than the individual tiles, obviously)


yeah with tile-based you might have say 1 image of a set of blocks like in mario, and a seperate data file just saying which squares in the level grid to draw this one block to, so it looks like you've drawn loads of platforms etc but in reality it's just the same image being cloned as it were

so like:

111111111111111
100000000000001
100000000000001
111100001111111
100000000000001
111111111111111

could be your level grid in a tile-based level, where 1 is a block that a player can collide with (0 could be empty space), so you've got a ground, ceiling and walls there with two platforms, all using the same single block graphic so you're only storing that one tiny image in the memory instead of an image of the entire level

it all depends on the design of your game, my level design is basically making a level out of photographs of local landmarks so i had to be able to adapt collision to predefined terrain, but the theory of grouping a level into sections if you have lots of things that can collide with each other still stands (ie if you have player bullets, enemy bullets, player and enemies who can all collide with a large level)

Share this post


Link to post
Share on other sites
Ok, I think I'm starting to grasp all of this. It doesn't sound quite as scary now :-)

Another question: I know a fair amount of C++, but not all of it (for instance, I have tried on numerous occasions to figure out what the heck pointers do, without success). If I may refer you to the C++ language tutorial located at http://www.cplusplus.com/doc/tutorial/, I know everything up through Classes (II), except for pointers and dynamic memory. Thus far, this has not been a problem for me, but I am curious if it will eventually become one. As far as I can tell from thinking it all through, I should be able to write this current game with the knowledge that I have.

I have a partially completed roguelike that I started some time ago, and it had a little text file like the one you show, Mantrid. I guess a graphical tile-based level is about the same thing. I think that is the way I want to go. It definitely sounds doable.

Share this post


Link to post
Share on other sites
you can get away with not knowing about classes, inhertance etc. for a small enough game (for smaller games they just make things a lot easier and cleaner) but i think pointers would be really useful just to have a sit down and get out of the way first, once you get an idea they're really not that complicated

as it says on the tin, they just point to stuff.

when you send something to a function, eg

void dostuff(float number1, int number2)

number1 and number2 aren't actually sent to the function per se, but a copy of them is created just for that function each time it is called, and destroyed after the function ends.

so if you wanted to actually change number2 within the function you could send a pointer to 2, so the function is dealing with the original number2 you're sending

also, you're sending a float, which means at one point in our program there are two floats, whereas it's "cheaper" to send a pointer to the float, since a pointer is smaller in size than a float, so you can do that

it is incredibly useful for passing pointers to large arrays or structs so you're not cloning a massive struct and all its data each time you wanna do something to it, means if you definitely do NOT want anything within that struct (etc) to change then use const to ensure it isn't modified.

so i'd definitely suggest learning a thing or two about pointers even if you're only spending a day or two on them, if you can't get your head round that tutorial google for a few different ones, some tutorial series are great but one bit just doesn't do it the way you'd like, so it's always good to google round other tutorials to say if anyone else has a better way of explaining it to you, then when you go back to the first one you'll understand it

Share this post


Link to post
Share on other sites
About pointers, when I went from knowing how to use pointers to understanding the true nature of pointers, was when I started coding for Gameboy Advance. There, you don't have any operating system between you and the hardware, so all the RAM, cartridge ROM, control registers and stuff are just accessed directly by memory address.

For example, RAM starts at address 0x02000000, so you can just say

char *point = (char*)0x02000000;
*point = 50;

And now you've written the value 50 to the byte at memory address 0x02000000. It turns out all a pointer is, is a variable that contains a memory address.

Pointers themselves are 32 bits (4 bytes), and are basically the same as an unsigned int, regardless of the type that the pointer points to. The type only matters when you go to dereference it or add/subtract to it. In the example, the pointer points to a char, which is a 1 byte signed integer. So when you dereference it and write the value 50, it only changes one byte in memory. But if it was a pointer to a float, which is 4 bytes, then dereferencing would change 4 bytes in memory.

So, as Mantrid says, pointers are good for passing large structs to functions (just send the 32-bit address where the struct is in memory, rather than making a copy of all the variables in it), and for modifying the original struct (since the function has the address where the original is, it can then write to it).

Share this post


Link to post
Share on other sites
Quote:
Original post by Mantrid
also, you're sending a float, which means at one point in our program there are two floats, whereas it's "cheaper" to send a pointer to the float, since a pointer is smaller in size than a float, so you can do that

That's hardly ever true for primitives. If anything, passing a pointer to a float makes the code harder to understand and manage. But yes, for larger objects, passing a pointer (or often better, a reference) is often more efficient.


The concept behind pointers is indeed rather simple - they point to other objects - but their use can be quite tricky. For example, pointers can point to actual objects, but they can also just contain random addresses. Trying to dereference such pointers is asking for trouble.

Also, with regards to dynamic memory allocation, a pointer doesn't indicate whether it 'owns' the object it points at or not. What I mean is this: you can create a float on the stack (float a;) and make a pointer point to it (float* p = &a;). That's all fine. But if you dynamically allocate a float and make a float pointer point to it (that float is now on the heap, or freestore): (float* p = new float;), then you're responsible for cleaning up that float (delete p;). In both cases you're using pointers, but in one case you need to clean up what you're pointing at, yet in the other case you definitely shouldn't call delete on it: what's on the stack will be removed automatically when it goes out of scope.


It's usually better to use higher level constructions (smart pointers, standard library containers) to reduce the risks and automate the tedious parts of memory management.

Share this post


Link to post
Share on other sites
Ok, I have been working on learning some more stuff before moving on. I've learned about dynamic memory, and how to use vectors. Now, I can have dynamic arrays of classes. I would like to say that this may have been the most exciting discovery I have ever made while programming.

Anyway, today I've been working on learning how to use OpenGL with SDL. I've gotten a little pong game working with OpenGL, save one big problem. Apparently, alpha blending is really hard and complicated with OpenGL. So my ball and paddles (which are image files with some transparency around the edges to make them look round) now have black pixels in the corners of their textures.

I'm starting to wonder if using OpenGL is even worth the large amount of extra trouble. On the other hand, once I get it all figured out, I won't have to look at it again, since I'm putting all the OpenGL-related stuff in just a couple of functions (one to load image files to a SDL_surface and then a texture, and another to actually display textures). Could anyone clue me in to the actual advantages of OpenGL? I know that it allows hardware acceleration, which is why I originally started learning it. But is there anything I will want to do in my 2D game that will require hardware acceleration?

One other question: Should I keep asking my questions in here, or should I be making new threads for each topic I am asking about?

Share this post


Link to post
Share on other sites
OpenGL and Direct3D allow hardware acceleration, sure, but it's more than that: these APIs are your interface to the graphics card. You will have to use one of them, or some kind of library that makes use of them, in order to do any graphics output at all (unless you use the Windows GDI, which isn't that fast or capable). It's definitely worth sticking with it; it'll expand your horizons so much more in the future.

Rotating sprites is really much easier with hardware acceleration, and alpha blending may be hard with OpenGL but not as hard as trying to do it without! As you say, once you've got the hang of it, you can write a few functions you can use in the future and then you'll be flying along.

Hope this helps.

Edit: Oh, if you start new topics for specific problems, it may help others in future who are looking for answers to the same questions.

Share this post


Link to post
Share on other sites
Quote:
Original post by Dark_Oppressor
Ok, I have been working on learning some more stuff before moving on. I've learned about dynamic memory, and how to use vectors. Now, I can have dynamic arrays of classes. I would like to say that this may have been the most exciting discovery I have ever made while programming.

It sure makes things easier, doesn't it? ;)

Be aware of the subtle details though. For example, if you have a vector of objects (not classes - a class is a blueprint, an instance or object is an actual object created according to a given blueprint), and you start using pointers to those objects, things can go wrong once you modify that vector. It may resize itself after adding a new instance, invalidating any pointers to it's content. Another thing to keep in mind is that whenever you add an object to a vector, a copy is made (using the copy constructor) and stored in the vector, so you want to make sure your objects don't do weird things when they're being copied (which easily happens when they dynamically allocate resources).

Yay, C++. :)

Quote:
I'm starting to wonder if using OpenGL is even worth the large amount of extra trouble.

Personally I wouldn't put in the effort, because there are several alternatives. Take a look at Haaf's Game Engine, for example. OpenGL and DirectX, and SDL to some extend, are still rather low-level.

Share this post


Link to post
Share on other sites
Yes, I must say that I am regretting the entire day that I wasted trying to get OpenGL to work. After many hours of endless work, my 2 or 3 OpenGL related blocks of code continue to leak memory, even though I have carefully gone over the code a million times, making sure everything is cleaned up properly. I have absolutely no idea what could possibly be causing it to STILL leak. It certainly worked great before I attempted to use OpenGL.

EDIT: I have completely removed OpenGL from the code, and it is still leaking... I think. What exactly constitutes a memory leak? That simply means that the program continues to eat up more and more memory the longer it runs, right? Mine is definitely doing that. As I type here, I am removing almost all of the code, and it is still leaking. I am now down to a blank screen that doesn't calculate anything, and it is STILL leaking.

[Edited by - Dark_Oppressor on August 20, 2009 7:59:19 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Dark_Oppressor
EDIT: I have completely removed OpenGL from the code, and it is still leaking... I think. What exactly constitutes a memory leak? That simply means that the program continues to eat up more and more memory the longer it runs, right? Mine is definitely doing that. As I type here, I am removing almost all of the code, and it is still leaking. I am now down to a blank screen that doesn't calculate anything, and it is STILL leaking.

A memory leak is lost memory you can't account for. It could be possible that your game is eating up more and more memory because you continue to load more and more game data, which isn't necessarily a leak but rather just high memory usage. But if you're missing a few dozen megabytes and none of the memory you think you currently have allocated accounts for it, then it's very likely there's a leak somewhere. There are plenty of tools out there that can help you find leaks, such as this one.

Share this post


Link to post
Share on other sites
I actually looked at that tool, among others. I have Windows, though. Anyway, I figured it out on my own by the process of elimination and some luck. It was only happening in the drawing parts of my code, but I looked back and a previous game I made with just SDL had the same problem.

Turns out, it apparently has something to do with the stringstream I am using to display int's and such as text. So, I guess I'm looking for a better way (or the reason my stringstream usage is causing a problem). But, I blamed OpenGL unfairly, ha ha. My own lack of knowledge of how stringstreams work, I guess. I'm going to be reading up on how to use them properly now, but if anyone has a better solution for getting an int/float etc. into a string, please let me know.

Also, if anyone could recommend a good Windows-compatible memory leak detector (or whatever you want to call it), that would be swell.

EDIT: Alright, I figured out how to stop the leak :-)
I was displaying a string, "FPS: " and then an int, frame_rate both at once using a stringstream to make one string out of them. However, I was reusing the same stringstream over and over, and to do that you need to properly clear it out each time you reuse it. To do THAT, you must:
my_ss.clear();
my_ss.str("");
ss<<"FPS: ";
ss<<frame_rate;
msg=ss.str();

And after that, I simply passed msg along to my "write strings of text to the screen" function. The above code makes it work without any problems, and no memory is leaking.

I now have a new problem, but it is unrelated to stringstreams. My message writing function makes a new surface with the text I want, then makes a texture(I'm using OpenGL, remember) out of that. This is then rendered to the screen like any other texture using a "render textures to the screen" function. This uses way too much CPU power and drastically reduces the framerate(and the ms per frame, for you picky people). I am guessing the solution is to use a bitmap font instead of SDL_ttf, bypassing the whole surface/make a new texture each time something is written to the screen portion. This way, I could simply load the entire alphabet and such into memory when the game first starts, and never have to do that again.

So I guess I'm off to learn how to do bitmap fonts.

[Edited by - Dark_Oppressor on August 21, 2009 3:51:30 AM]

Share this post


Link to post
Share on other sites

This topic is 3034 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this