PDA

View Full Version : 2d-platforms game



patroclus02
16-02-2003, 10:12 PM
I'm making a 2d-platforms game, and I already made the engine, with paralax scrolling, three layers, some sprites and colisions.

The problem is the colision with the platforms (ground, walls, etc.). I already made it, I check 2 or 3 points on each side of the sprite to see if it collides with any wall. If it does, I do not let it go any further. The problem is...

Do you know this platforms you can jump from below??
How can I manage the collisions with this kind of platforms efficently.

thank you
:)

Crisp_N_Dry
17-02-2003, 06:50 PM
I think you would have to have a boolean like TopSideCollide: Boolean in the platform object which says:

If (Player is falling) then (engage collision detection on platform object) else (Let him through)

I'm going to assume that the player has x and y velocities, so when the players Y velocity is positive (going down the screen i.e falling) then make the collision detection effective. I think I understood your question correctly but it took me a few passes before I got it. Let me know if this is or isn't helpful.

patroclus02
17-02-2003, 10:33 PM
Thank you, your're very kind.
You understood perfectly what I was trying to ask.

Anyway, I already considered that solution. But there's a big problem.

Speed movement here is not framerate based (I don't use a fixed frame rate and move the sprites each frame at a fixed speed).
I use speed based on how fast the frames are beeing rendered. If at a certain point the framerate drops, the speed per frame raises, and the other way round. this way, the objects move always at the same speed independent of the FPS and the CPU.

And here is the problem.
If I do what you say, in a certain point, imagine I'm about to land on a platform (5 pixels above), the movement for that frame could be bigger (imagine the FPS drops), so the sprite falls 10 pixels that frame (imagine), and passes by the ground, so it does not collide with its feet on the platform.

I don't know If I explained myself clearly.. (hope so)

Crisp_N_Dry
18-02-2003, 08:18 PM
Yes, I understand what you mean and is a common problem with collision detection. What I would suggest is that instead of suddenly moving the sprite 10 pixels or however many,you do a loop and test each fraction of the movement of the sprite from 1 to HoweverManyPixels for collisions, then if there are no collisions you move the sprite the required amount of pixels otherwise you store the loop counter value at the point of collision and only move the sprite that far. This will mean that when the sprite moves it only moves as far as it can before colliding instead of passing through a solid object. This would only be a check loop and machine would not update the screen during this loop and should happen very fast and so shouldn't affect speed too much. I hope this helps, if your still having real trouble then you might be able to twist my arm into writing some example code but see how you get on with explanation. Good Luck.

patroclus02
18-02-2003, 09:53 PM
Thank you once again ;)

No, there's no need for it, I understood what you said, and I think it is a great solution.
Now that I see you know a lot of this, jejej, I would like to ask you another simple question if you don't mind (i find so little help around).

Remember what I said in the first message? :
"for collision.. I check 2 or 3 points on each side of the sprite to see if it collides with any wall. If it does, I do not let it go any further".
I check right collisions when the sprite moves right (only in that case, not in other), the same with the left direction. I always check the down collision, and only check up collision when the sprite goes up (jumps)...

Is this ok? Should I have to check collisions in all directions always?

I thank you very much for your help, really.

Alimonster
19-02-2003, 11:33 AM
I find so little help around
I've spotted some of your posts in other forums (Turbo, Delphi Sanctuary...) and you do seem to get few responses. If I could be so bold, I'd ask whether you'd be willing to write a small tutorial (http://terraqueous.f2o.org/dgdev/viewforum.php?f=20) on collision detection for a 2d platformer once you've solved all your issues. I know that this seems like you're doing the grunt work, but you'd be helping a lot of people who might find themselves in the same position (having questions, but having a hard time getting answers, about 2d platformers).

patroclus02
19-02-2003, 03:12 PM
Yes.

I'm thinking of writing a tutorial not only for collision, but for making a 2d platforms game. If I manage to finish the game (or if I get a good Beta version), I'll try to write about how I implemented the engine, what features it has, how I manage movements, timers, colisions, paralax scrolling, sounds and level desings.
As I'm very busy, I don't think I could wirte a very detailed tutorial, but I'll try to do something useful.

Anyway, I still have several problems, and need the help of people like Crisp_N_Dry.

Crisp_N_Dry
19-02-2003, 09:44 PM
I think the best way of doing collision detection for a game like yours is to use a bounding box. I don't know whether you're familiar with the term so I'll explain. A bounding box is a set of coordinates that specifies the left, right, top and bottom extremes of your sprite. This is effectively a TRect. Using a bounding box and an easy collision function as shown below, you can check for collisions on all sides of the object at every pass. This saves you applying different collision detection rules for every possible direction. All you do is check whether the sprites bounding box is overlapping with the bounding box of another object.

function Collision(Rect1,Rect2: TRect): Boolean;
begin
Collision:=False;
//If top left corner of bounding box 1 (Rect1) is in bounding box 2 (Rect2) then make Collision=True
If ((Rect1.Left>=Rect2.Left) and (Rect1.Top>=Rect2.Top) and
(Rect1.Left<=Rect2.Right) and (Rect1.Top<=Rect2.Bottom)) or
//...bottom right corner of bounding box 1(Rect1) is in bounding box 2 (Rect2) Then...
((Rect1.Right>=Rect2.Left) and (Rect1.Bottom>=Rect2.Top) and
(Rect1.Right<=Rect2.Right) and (Rect1.Bottom<=Rect2.Bottom)) Then
//...Collision detected
Collision:=True;
end;

Now just apply this to to yur sprite(Rect1) and every active enemy/object(Rect2) on screen/level and hopefully you will have working collision detection that can stll be aplied to the methods I showed you in previous posts.

I hope this helps you and you don't have to change too much code, but I know having to redo certain parts of code can often affect the rest of the code and means a hell of a lot of work so if you don't wanna use this idea then just stick to you current method. As always, if you don't think this is suitable or need anymore help then just post a message to that effect and I'll see what we can do.

P.S. In answer to your original question, I can't think of any reason why your current method shouldn't work but, this method will make sure that you are always checking for collisions on the whole sprite and not just one side and so may be more definitive.

patroclus02
19-02-2003, 10:13 PM
Yes, that solution will require a lot of changes.

I use 2 different collision detection methods.
What I do is this :
1) I'm using Borland Delphi and Omega/DelphiX, so for enemy colision detection I use Omega's function (it automatically detect collision with other sprites, so it saves a lot of work).

2) Platforms and walls are the real problem :)
Here I need more information than just knowing that there's been a collision. I need directions. What I do is use 4 functions, one for left collision, another for right, up and down.
Example :
When the sprite moves right, I calculate the current speed and the pixels that are going to be "walked", then I call the right_collison function, that cheks that there are no walls or obstacles. If there are, then it returns the maximun numer of pixel that can be walked before we have to stop (colision). Same applies to left side, botton side, and top side. Botton side is always checked cause os gravity.

What do you think?
Today I've been working on diagonal platforms (45 degrees). I managed to do something, but I'm finding that it is quite difficult task. (i don't know really if finally i'll go on with it). Anyway, I need to definetly implement my collision detection method for platforms.

Thanks man!

patroclus02
24-02-2003, 10:50 PM
Crisp_n_Dry are you there?

Crisp_N_Dry
25-02-2003, 07:53 PM
Sorry Partoclus, not been able to find the time but I am here now. Anyway, I read your last message where you said that a bounding box would not be best and that your current method is causing you problems with diagonal movement. I thought this might cause you problems but I because I don't know exactly how you've coded it, it is hard to find a suitable solution. Could you explain in as much detail as possible how it is going wrong and I'll see if I can come up with an answer.

patroclus02
25-02-2003, 11:17 PM
Glad to see you again :)

Well, I already solved some problems and now I have a pretty good 45 AČ? diagonal platforms collision detection.
Anyway, what I said in my last message is that I use 2 different methods for collision (for collsions between sprites I use a DelphiX/Omega function, hope you know this libraries). But I made my own method for platform collision. And I explained how I do this in the second point of my last message. I only wanted to know if it is a good way of doing it.

Now I'm wondering how to "create" the enemy sprites. Create all of them at the begining of the level? or create them as they appear on the screen?

DooMeeR
01-06-2003, 05:09 PM
Hi :)

I tried to build a pinball once, and I never made it because of the collisions problems. Sometimes the ball rolled fine, sometimes it went through walls... Now I've been thinking this more, but anyway, here is how I would do it now:

The main ideas has already been discussed:
- have a bounding rect for your sprite, or another shape like circle for a ball but it costs more time to calculate.
- have a loop which tests whether you collided something or not.

But for my pinball I had other problems:
- walls can be VERY thin, thus allowing the ball to get through them very easily
- walls can have random angles

So I had to find maths formula. Actually I changed the loop system, and I replaced it with the calculation of the intersection between two segments: [AB], where A is the ball position before it moves, and B the ball position after it moved, and [CD] which is the segment symbolizing the wall.
This can handle every angle and "go through" issue.

But then you have to figure out what to do with the moving sprite, so as to prevent it from going through the wall, AND to prevent it from being stuck. This is done by stopping the sprite right before the collision, as with the loop method. It's not too hard to find this position if you know [AB] and P where P is the collision point.
Then you need to modify the speed. It's hard, because it depends on the collision angle. For a platform game, you don't want the player to be stopped whenever he collides something, as he always collide the ground when walking.
But I have no solution for these problems.

It might be interesting to discuss this in a tutorial if you manage to use it. I realize that I don't really help here, I just highlight some possible collision problems ;)

patroclus02
18-07-2003, 11:00 PM
Thanks for your ideas :)
Anyway, they don't fit my purposes.
I'll try to get on and see what can I do.