This project has moved and is read-only. For the latest updates, please go here.

# Jumping.

 Wiki Link: [discussion:64997]
 SlimeQ Aug 10, 2009 at 3:16 AM I'm making a 2d platformer/shooter (still) and I've hit yet another roadblock. Jumping. I decided to go with a completely physical method (one built with moving physics pieces) for a number of reasons: A) I couldn't figure out for the life of me a decent way to check if the player is on the ground B) I don't want jumping to be constrained to the ground. I want it possible for say, one player to jump off another's head. So, I made a small 10x10 "jumpbox" and attatched it to my player with a pin joint. The jumpbox's x position is constantly changed to that of the player torso. When the player clicks the left stick, the target distance is added to a constant value, forcing the jumpbox down quickly, launching the player skyward. When the distance between the jumpbox and the torso exceeds the constant, the target is reset. This works well in theory, but after a bit of toying with it, it became increasingly apparent that it is somewhat unreliable. The player sometimes jumps super high, and other times barely jumps at all. It's just not a good system. So I'm wondering, are there any tried and true methods for jumping and such? (or does anybody have an idea as to fix this one?) ladron Aug 10, 2009 at 4:55 AM I use a sensor geometry at the base of the player. Jumping is only allowed if that geometry is colliding. The actual jumping is done just by applying an impulse. Works quite well. SlimeQ Aug 10, 2009 at 5:07 AM Alright. So I can put a sensor geometry down there, but how would go about the actual checking for collision? pnikosis Aug 10, 2009 at 10:02 AM Edited Aug 10, 2009 at 10:03 AM SlimeQ wrote: Alright. So I can put a sensor geometry down there, but how would go about the actual checking for collision? Instead of checking when it is colliding for allowing the player jump, what I do is to check if it's not colliding with anything to avoid him to jump. I use Yobiv's method: http://farseerphysics.codeplex.com/Thread/View.aspx?ThreadId=56162 For jumping, I just apply impulse. ladron Aug 10, 2009 at 5:52 PM pnikosis wrote: SlimeQ wrote: Alright. So I can put a sensor geometry down there, but how would go about the actual checking for collision? Instead of checking when it is colliding for allowing the player jump, what I do is to check if it's not colliding with anything to avoid him to jump. I guess that would be more efficient if you are only using the collision information for jumping. I use it for applying different drag and changing character animations, so I already need to check it every frame. I just set a flag in the collision event handler. Nice and simple. SlimeQ Aug 10, 2009 at 7:06 PM I'm terribly sorry for the noob question, but I've looked at that code before and couldn't figure it out... Where does that go? How do I use it? Does all that stuff go in my main class, or is it a new one? How do I go about checking the collision of the object in relation to everything without using an array? Do I have to put everything in an array? pnikosis Aug 10, 2009 at 9:07 PM @SlimeQ: I guess you are asking for the yobiv's code :) In the example code, the class MyObject should be your character (with its geometries and bodies... or maybe only one geometry and body, however you designed your character). Your character should have an Update method, called each frame, and the OnCollision and OnSeparation methods are for the geometry you want to check if it collides or not. For example you character has a small geometry for its feet, you should check if that geometry collides with something or not to know if the character is standed on the ground or not. Let's suppose that that geometry is called geomFeet, so when you load or initialize your character you should tell to the system that you need to add special code for the OnCollision (called each time the geometry collides with something) and for the OnSeparation (called each time a geometry stops colliding with something) methods. For that you need to add the following code: geomFeet.OnCollision += OnCollision; geomFeet.OnSeparation += OnSeparation; Then you add the code for the OnCollision and OnSeparation methods as showed on yobiv's post, and that's it. When the HasCollision variable is set to false, means that the character is not touching ground :) SlimeQ Aug 13, 2009 at 10:42 PM Edited Aug 15, 2009 at 9:13 AM `` i'm getting this error with that code. (oh and by the way i'm using this with the bullets here... (i'm a very ADD-ish coder...)) but seeing as i'm not really entirely sure what yobiv's code is doing, i'm clueless as to what the problem is here. what's it mean? Cowdozer Aug 13, 2009 at 10:50 PM The error "not all code paths return a value" means that the stated method (in this case, Hyperinflation.Bullet.OnCollision) is not guaranteed to return a value. The method signature states that it will return a bool, so you need to make sure that any code path taken will end in either return true; or return false; ZachTheRiah Aug 15, 2009 at 1:40 AM pnikosis wrote: Then you add the code for the OnCollision and OnSeparation methods as showed on yobiv's post, and that's it. When the HasCollision variable is set to false, means that the character is not touching ground :) Yes, but there are some weird things that *could* happen (these may be rare, but probably worth noting). Say we were writing a Mario-like game and there was a block in mid-air. If you hit the block, there would be a collision, but you would also be in mid-air. Since there was a collision, if you hit the jump button on the collision, you could technically jump again according to this method (and you could perpetually jump as long as you collided with the block), right? How could you work around this? My first thought would be to use the contact points list and detect which edge you collided with. Maybe I misunderstand the method, but that's what seems to happen to me. genbox Aug 15, 2009 at 1:48 AM Edited Aug 15, 2009 at 1:49 AM I've not read this thread, but you will have to have a geometry as the ground (or several geometries) and check if it is the ground you collide with in the OnCollision event. If your player collides with the ground, he is able to jump again. The thing is that the OnCollision and also OnSeparation events fires whenever there is an collision, but since we use approximations of physics there is a small error involved that makes the whole physics world jitter (not normally seen by the user). To prevent this you can add a sensor geometry (an ordinary geometry with IsSensor = true) on the feet the player and update the position of the sensor to be the same place as the player. Whenever the sensor collides with the ground, he would be able to jump. @SlimeQ: Could you add a newline to the long error like you posted? it makes the site very wide and breaks word wrapping. SlimeQ Aug 15, 2009 at 9:40 AM @genbox: apologies. i feel like i'm doing something really stupid here. i'm still getting that "not all code paths return a value" thing,and i'm not quite sure why. i did what pnikosis said, and i put in yobiv's code verbatim, but... not sure what's going on here. ``` public void Update(GameTime time) { ++Ticks; } private bool OnCollision(Geom g1, Geom g2, ContactList contactList) { TicksCollision = Ticks; HasCollision = true; } private void OnSeparation(Geom g1, Geom g2) { if (TicksCollision < Ticks) { HasCollision = false; } } ``` ^^^ it looks like that.^^^ i'm fairly new to C# (and obviously farseer) so a lot of this more complex stuff is going right over my head. it'd be super cool if somebody could explain in the simplest terms what's happening here codewise. JellyStorage Aug 15, 2009 at 10:19 AM Edited Aug 15, 2009 at 10:53 AM @SlimeQ: OnCollision is a function of type Boolean, and yet you did not return anything. simply add "Return true" after the HasCollision= true line.   @ZachTheRiah You don't have to get into that, seeing how the sensor is in the player's feet. If the player's body (the top of the player) collides with anything, it wouldn't allow it to jump again.   edit: I need some help of my own as well. I tried to set the geometry on the player's feet to a sensor, after getting some weird results from a non-sensor geometry. However, when I set the geom to a sensor, the character will just hang in the air in its initial position, without being able to move. am I supposed to create a different body for the sensor? otherwise it's impossible to set the geometry to the body's position every step, since geom.position is read only. genbox Aug 15, 2009 at 3:47 PM Yes, the sensor geometry needs its own body for now. The IsSensor property set the body to be static and the geometry to not react to collisions. You set the body.position property each step. Cowdozer Aug 15, 2009 at 5:07 PM When I was figuring this out on my own, I didn't use a sensor geometry. I just had a second "foot" geometry below my character, and after associating it with the body of my character, I initialized it with this code: ```foot.CollisionResponseEnabled = false; foot.OnCollision = (a, b, c) => { this.IsStanding = true; return true; }; foot.OnSeparation = (a, b) => { //TODO: Fix the standing check methods so that it properly handles //recognizing standing on an object even if another object is separating this.IsStanding = false; }; ``` Note the big TODO... yobiv's code is an example of how to fix that issue. This code is just an alternative to using a sensor. SlimeQ Aug 15, 2009 at 8:23 PM Edited Aug 15, 2009 at 8:24 PM ```private bool OnCollision(Geom g1, Geom g2, ContactList contactList) { TicksCollision = Ticks; HasCollision = true; return true; } okay. no more errors, but HasCollision does nothing because no geometry is specified here... how would one specify the geometry that is to be checked?EDIT; do i need to somehow call this method for every geom in my game?``` genbox Aug 16, 2009 at 12:34 AM The OnCollision method is just an ordinary method. You can call it whatever you like. - But you also need the physics engine to call that method, so you will have to provide the engine with the name of your method. Just like this: ```//This is where you tell the geometry to call your method once it // collides with something. You do this inside the code where you // create the geometry. myGeometry.OnCollision += MyCollisionMethod; //Then you create the method that gets called: public bool MyCollisionMethod(Geom geomA, Geom geomB, ContactList list) { //Inside here geomA will be myGeometry. It is always the one you // told to call the method. //geomB will be whatever geometry myGeometry collided with. } ``` Cowdozer Aug 16, 2009 at 2:37 AM That got me thinking... genbox, is OnCollision called anywhere other than in the Arbiter class? I've been assuming that no other part of the framework will call it, but I guess it's good to know for sure. genbox Aug 16, 2009 at 3:30 AM Nope, it is the responsibility of the Arbiter to call the OnCollision delegate right before the physics response is calculated and applied. This makes it possible to cancel the collision response (by returning false in the OnCollision method) SlimeQ Aug 17, 2009 at 11:52 PM Alright, I couldn't quite get it to work, but I have a theory as to why. My map is concave, so the bounding rectangles of the 'ground' are always intersecting with the players feet, therefore not allowing the OnSeparation method to fire. Therefor, the hascollision bool is always true. Could this be happening, or is something else at play here? (btw the hascollision bool won't change to false) Dusho Aug 19, 2009 at 12:36 PM I'm not sure, but this may have some to do with what I observed when playing with collisions - OnSeparation triggered only when there is no contact with bounding box of geometry (and this will cause problems if you have concave geometry). But no one confirmed my observations. ( http://www.youtube.com/watch?v=-RX-Z76q0J0 ) SlimeQ Aug 21, 2009 at 4:30 AM SlimeQ wrote: @genbox: apologies. i feel like i'm doing something really stupid here.   ... the player's gun was intersecting with the feet. i fixed it. it was stupid. however, i couldn't get the IsSensor property to work right. it just sorta refused to detect collisions. i changed the jumpbox to a normal geom with collision response turned off, but this isn't really ideal (i don't think). what would have been wrong with the sensor? genbox Aug 21, 2009 at 3:18 PM Sorry, that is my fault. I forgot that your ground is probably static and thus a sensor geometry will not detect the geometry. A sensor geometry is defined static for performance reasons and static geometries  are not tested against other static geometries. A sensor is not supposed to be moved around - but if someone wants this functionality they can create a bug report to suggest this functionality. I have limited time, so I need to prioritize. SlimeQ Aug 21, 2009 at 6:12 PM It's not a huge deal. Disabling the CollisionResponseEnabled bool works just fine (tho the debug view shows the geom sinking all the time (tho the collision works fine)) Cowdozer Aug 23, 2009 at 7:41 PM What do you mean it shows it sinking all the time? Is your foot geometry not just associated with the player body? That'll keep it moving around with your player and you won't have to reposition it manually every frame or anything. SlimeQ Aug 24, 2009 at 2:08 AM I mean quite literally, the geom is sinking the collision still works fine tho. I think the jumpbox is just falling indefinitely so it goes farther and farther down. A simple dynamics reset will fix that. And I can't associate it to the body cuz it's rotating at high speeds. glopes Aug 24, 2009 at 10:29 PM Hmmm, I'm not sure if I'm being overly simplistic, but my jumping logic is working great with a very basic rule, which is a variation on Yobiv. Basically, just check for collisions with the player legs, but make sure the contact normal is facing up. If this is true, this means the legs have contacted a flat surface. This has stopped my character from jumping off vertical walls and other mischievous situations without adding additional geometries or sensors. Maybe I'm missing something... Cowdozer Sep 1, 2009 at 5:53 PM Nope, that sounds perfectly reasonable, and if it's working exactly how you want it, there's no need to change it!