2D Platformer

Mar 10, 2009 at 10:00 PM
Hi!!

I´m making a game for a project at school, and by now i´ve implemented the levels and the collisions with the walls and blocks using Farseer Physics Engine and i think it´s awesome...
But i´m having some problems implementing my ideas, so i´ve got some questions:

  • I want to invert the gravity, so that my player could walk on the bottom of some platforms.
    • I´ve already implemented this, by multiplying by -1, the Y component o the gravity, but i wanted that to be applied only to my player, not to the objects and the enemies in the level.
    • Is it possible?
  • The game also have a small ball jumping around, and the way it´s is, after a while, the ball stops bouncing, i know it´s normal, i even reduced the ballGeom.RestitutionCoefficient = 0.0f, but even that way it doesn´t work.
    • Imagine something like Super Pang, where the balls never stop.
  • Other thing about my player, he also have a Body and a Geom, so that the collisions with the platform can be detected, but i need to constrain some of the movements of the player, like:
    • I dont want him to rotate when he hits a block with his head (he is a rectangle).
    • And i dont want him to Jump in the same way that the ball jumps, although the RestitutionCoefficient of the floor is the same for all the objects.

Well, if someone could give me a hand about all this question, i would be very thankfull.
I hope that i explained myself clearly, sorry for any writing mistake.
Mar 11, 2009 at 7:59 AM
Hello and welcome! About your questions:

 * That's really not easy unless you modify the engine to support a per-body gravity. Its pretty easy: you modify the body code to have an extra Vector2 then hunt down the gravity applying code (its somewhere in the main simulator code file) and modify it to use a per-body gravity if the body has it.
 * Try setting the restitution coefficient to 2 on your jumping ball (it might make the ball bounce out of control though, and in that case im not sure if theres anything that can be done)
 * Part 1: set an AngleLimitJoint on your body with a min and max angle of zero. It isn't perfoect, but it should do the job you want. Part 2:  i don't quite understand what you're asking, maybe you could clarify?
Coordinator
Mar 11, 2009 at 8:06 AM
RestitutionCoefficient is the "bouncyness" of your geometries.
If you want the ball to continue jumping forever, you will have to remove friction, lineardragcoefficient and adjust the restitutioncoefficient on both the ball and the platform the ball is bouncing on.

As for the gravity on one body only. Just manually apply some force on the geometry on each update (to cancel out the gravity). When the character jump, just apply some force downwards. But this all depends on how you would like the character to jump.

The rest is in RCIX's post.
Mar 11, 2009 at 9:33 AM
you could apply per-body gravity on every update cycle on the player. keep in mind however that gravity is a massLESS force (imagine a 1kg and a 5kg ball, the both fall with the SAME speed).

to prevent rotation set MomentOfInertia to float.PositiveInfinity. you could also reset the rotation on every update cycle.

you might have a look at this thread: http://farseerphysics.codeplex.com/Thread/View.aspx?ThreadId=44960 (i already found some issues however. it can't handle multiple collisions per frame and if you run down slopes the logic "flickers" between "sliping" and "floating". i can post an update if you want)

> Just manually apply some force on the geometry

genbox ... i'm disappointed. you don't apply forces to geometry ;)
Coordinator
Mar 11, 2009 at 11:05 AM
@yobiv - Argh damn it.
It's not the first time I've said something completely nonsense. ;)
Mar 11, 2009 at 11:41 AM
Edited Mar 11, 2009 at 12:17 PM
Hi, with some work, i´ve managed to:
  • The issues with the ball are solved, 2.0f for the RestitutionCoefficient is too much, but with 1.1f it gets the effect i wanted, thanks RogueCommanderIX.
  • The issues with the player rotation are solved as well, playerBody.MomentOfInertia = float.PositiveInfinity works like a charm ;), thanks yobiv.
  • The gravity is also solved, instead of modifying the engine, i´ve applied some force on the body of the Player to make him go up sky, for now serves its purpose, thanks genbox.
RogueCommanderIX - When i said that i didn´t wanted for the player to jump in the same way as the ball, imagine when i jump with the spacebar i apply an impulse upwards, when the player starts to come down to the floor, when it collides, jumps like the ball, (not that much!)<abbr></abbr> because i´ve set the playerGeom.RestitutionCoefficient = 0.0f; How do i prevent him of jumping on his own ?

yobiv - From what i´ve seen from the thread, you´ve implemented states to the player, stabilized, floats and slips, in my case my player only can Run and Jump, maybe i would need to implement something of that sort to check if the player is on air while jumping, because right now, if you jump, and even if the player is on air, you can jump again, and change his direction.

So is there some way to check if the player is not colliding with any other object, that way meaning he is on the air ?

Thanks for all the help.
Mar 11, 2009 at 12:18 PM
> So is there some way to check if the player is not colliding with any other object, that way meaning he is on the air ?

OnCollision, set a CollisionTime (from absolute time or just an update cycle interval)
OnSeparation, check if there has been a collision in the current cycle. when colliding with multiple Geoms, this will be false when separating from the last one.
to you have slopes? if so, you may need some threshold because else you will get some sort of flickering when bouncing down the slopes

> It's not the first time I've said something completely nonsense. ;)

well... i have merci. but it's just a matter of time until the creator will read this heretic gibberish... and i won't imagine what will happen then ;)
Mar 11, 2009 at 10:09 PM
@DavidJardim: So if i understand you correctly, you dont want the player to bounce when it hits something? then maybe a slight negative restitution coefficient (or hacking up an OnCollision event to make a temp PinJoint that breaks when you go to move) should work. If you use the MomentofInertia, then if you have slopes the player will appear to stand on air. If you use an AngleLimitJoint, however, you can change the requested angle to account for slopes that your player is on.
Mar 13, 2009 at 10:53 AM
Hi,

In my game i dont plan to have slopes, but i´ve already solved the problem of the bounciness of my player. I have different types of platforms, i´ve just forgot to
set the RestitutionCoefficient to zero of one of the platforms, so it wasnt working, but now its fine.

About seeing if the player is on air, i went for a very simple concept, that is checking if his linearVelocity on Y is diferent than zero, maybe not the best aproach but it works.

My game is going to be a fusion between Super Pang and Ikarura (the concept about polarity), so imagine there is a cloud dropping balls, some black and other white, my character must be able to shoot those balls while changing the polarity of his suit, he can absorb or destroy the balls.

The balls are already on the physics engine, having a body and a geom, they collide with the platforms and the player.

Now i need to implement the shooting, so i was wandering what could be the best aproach for this problem, and if you got some ideas, i could use some help.

Thanks ;)
Mar 13, 2009 at 8:14 PM
Just making sure i understand you here: You want your character to be able to absorb balls of one type and then shoot them back out? Well then what you need is a pool of those types of balls and when you shoot one you put it in the simulation with the proper speed and velocity, and when you destroy/absorb one, you dump it into a pool of those types of balls.
Mar 23, 2009 at 1:15 AM
Hi,

I´ve already solved the problem with my player shooting the bullets, and it´s works fine.
About the balls, i have an evil cloud dropping some balls, and the player must shoot them with the bullets.
I´ve already learned to register the collisions events, so when the ball collides with something i´m warned.
But i wanted the balls to collide with everything except the cloud, so i´ve put them in different collisions categories.

The thing is, that way it only tells me if there has been a collision, but it doesnt tell me with who it has collided ...
Imagine when i shot a bullet and it hits the ball, i want the ball to blow up, but if hits the player, he dies, but when it hits the wall, i dont want anything to happen...
I dont know if that is possible, but if is, i would thank a lot some help on a way to do that.

Cheers..
Mar 23, 2009 at 3:00 AM
Well if you're not already using the Tags, you can attach references to your game objects to the geoms and then retrieve them from the tag in your OnCollision events (via WhateverGameClassHere blah = (Geom.Tag as WhateverGameClassHere)), that can tell you what is colliding.
Apr 27, 2009 at 11:57 AM

Ok, the Tags solved my problem to identify the objects colliding, thanks ;).

My levels are being built from a txt file, initially each single block was an object with a body and a geom, but then in order to simplify, i created a method that counts the adjacent blocks
and then build a platform as an object with a single body and geom, reducing the amount of objects considerably.

The simplest way for me to check if the player was standing on the floor, was to check is his velocity in the Y axis was Zero, but sometimes when im walking around, in a linear platform
it seems that there is a variation of that speed, i think it has to do with the collision between the player and the platform.

When that variation of speed occurs, the Jump animation is played, and it´s weird...
How can I solve that problem ?

Thanks.

Apr 27, 2009 at 12:37 PM
Edited Apr 27, 2009 at 12:46 PM
With regards to the "can I jump or not" problem, what worked for me is this:

Start with yobiv's idea. That is, write an OnCollision event handler that sets a timer when the player collides with a platform (using tags to figure out if an object is a platform).

However, only set the timer if the collision occurred below the character. You use a square for your character (I highly recommend a circle myself, or an elipse), so you will be looking for a collision on the bottom edge. For a circle you can calculate the angle of the collision point, and only set the timer if the angle is in a certain range along the bottom (45 degrees on each side works good).

One of the advantages of using a circle over a square is that you can control the maximum angle of terrain on which the player can jump. Another is that on ledges, a square (if you limit rotation) will remain on the ledge until the right or left side is completely off, which looks a little fake. With a circle, your character will slide off the ledge when only halfway off of it - more realistic. Also I find the corners of the square tend to catch on things too often, bringing my character to a complete stop. For example, I made a rope bridge of sorts, and the square character couldn't go past one link in the rope bridge because the corner would catch on the edge of the next link. With a circle, the character can slide right onto the next link easily, even gradually pushing the link down (because of the curve of the circle), almost as if the character were taking a step onto the link and gradually shifting its weight. Ok maybe that's a stretch! :)
May 5, 2009 at 6:23 PM
Solved It.

Thanks, the idea to use an elipse instead of an rectangle is very good, and now my player slowly fall from a ledge ;)

For now i think the project is finished, thanks a lot for all the help from you guys.

;)