New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
objects on moving platform "jump" if it changes direction to downward #8
Comments
Hi, I've not be able to reproduce this behavior. This is my GameState : override public function initialize():void {
} The moving platform doesn't change other objects velocity. However the Hero has some functions where a moving platform has an impact : protected function getSlopeBasedMoveAngle():b2Vec2 protected function updateCombinedGroundAngle():void
} |
I will try to give you simple game state code to reproduce this tomorrow (other pc here). However, this is fairly easy to understand. Imagine yourself in the elevator that accelerates downwards faster than 1g - the floor will basically say goodbye to your feet (and then the roof will hit your head). Now when moving platform reverses its direction and goes down - it does so instantly (basically infinite acceleration is applied, which sure is > 1g), so you see hero detached from platform for a short time. If the platform moves diagonally, this is enough for him to "jump" along the platform to one of edges and eventually fall off. |
Hi makc, Physics engines in the case of a platformer, are almost TOO close to reality in fact, like your example shows. So the laws must be broken when he is standing on a platform in one way or another to avoid this, I think that if "moving platforms" are part of the engine, then this behavior should also be taken care of inside of it. either this or maybe your gravity isn't high enough? but I haven't tested this as moving platforms are not yet implemented in nape apparently (and I would love to be able to contribute to this so this discussion may help). My main idea for your problem would be to "disable" the vertical velocity of the player (making it equal to the platform's at every update) only when he's in contact with it - that would involve using the onGround boolean I guess - and also this shouldn't prevent the player from voluntarily jumping off of the platform (because onGround would stop being true) or moving sideways on it by himself so long as the platforms friction is not equal to 0 i guess. |
Thanks for the explanation, I understand this physics problem :) For example, the Treadmill (which extends MovingPlatform) update function looks like this : override public function update(timeDelta:Number):void {
} In our case, it would be something close to (I didn't test it) : var newVelocity:b2Vec2 = passengers.GetLinearVelocity(); |
Here is a test state to reproduce this: package {
import com.citrusengine.physics.box2d.Box2D;
import com.citrusengine.objects.platformer.box2d.MovingPlatform;
import com.citrusengine.objects.platformer.box2d.Hero;
import com.citrusengine.core.StarlingState;
public class TestState extends StarlingState {
override public function initialize ( ) : void {
super.initialize();
var physics : Box2D = new Box2D("box2d");
physics.visible = true;
add(physics);
add(new MovingPlatform("moving", {x:200, y:600, width:140, height:95, startX:220, startY:600, endX:500, endY:170}))
add(new Hero("hero", {x:300, y:450, width:60, height:135}))
}
}
} Hero should land on very edge of the platform, and then fall off when it reverses the direction. The swf is set to 60fps, btw. As @gsynuh I would like to see this fixed in MovingPlatform itself ;) There is a number of ways you could do that, so just pick one that works and easy to hack in. |
Even though this might not be the best solution, it would be good to reset the passengers velocity to the new platform's velocity when it suddenly changes direction. for each (var passengers:b2Body in _passengers) { passengers.SetLinearVelocity(velocity); } does it, in the update loop of MovingPlatform, after line 161 ( _forward = !_forward; ) . I wish I knew how to attach a commit to a comment here, it would be easier to suggest larger changes. |
Hey, I've been able to reproduce the "bug". I changed the class as @gsynuh said, it works great the first time, but the second time it falls : else {
//Destination is very close. Switch the travelling direction
_forward = !_forward;
for each (var passengers:b2Body in _passengers)
passengers.SetLinearVelocity(velocity);
}
}
_body.SetLinearVelocity(velocity); I also tried to add this to the end of the update function, it was a bit better but not a success : var passengersVelocity:b2Vec2;
for each (var passengers:b2Body in _passengers) {
if (velocity.y > 0) {
passengersVelocity = passengers.GetLinearVelocity();
passengersVelocity.Add(velocity);
passengers.SetLinearVelocity(passengersVelocity);
}
} |
sorry I can't be much of help since I work with swc here. but why do you put it inside else {...} clause when the platform itself set velocity to its _body outside? apparently there is a number of cases where it is altered between lines 135 and 163, and passengers velocity change should be in sync with all of those cases, no? |
your second try is much more logical than mine in fact. Combining the two solutions, even if it sounds crazy, works nicely, I have been running the state for 4 minutes now, it doesn't look like it has moved at all. because I believe the conservation of momentum when it changes direction is still an issue unless for each (var passengers:b2Body in _passengers) passengers.SetLinearVelocity(velocity); } is still applied when _forward changes I guess. |
@makc the "else" is not a problem, as this is the special case when the moving platform changes direction. being a special case it should be handled differently. By the way, it's been running for a very long time now, still not out of the platform :D maybe we have a solution ! |
"changing direction" is only a special case as far as I noticed the effect in this case. however, the actual case is "changing platform velocity instantly" - i.e. if the platform could double its speed in the same direction. I did not aim to understand what lines 135-163 do, but if they change the velocity - they do all participate in this "special case". p.s.:
I'm quite happy if so. |
Right. For now MovingPlatform has linear speed so it may not be a solution if you create a moving platform that has easing effects on its velocity . |
sorry I think to be exact I should've said linear movement rather than linear speed. |
I've updated the class with @gsynuh code which combined both. I've to admit that combine both is a bit weird. I'm not sure to fully understand why it works. |
Our hero here, has a velocity relative to the world. What should really be happening is to have its velocity relative to the platform always. - this is exactly what your code attempts to replicate. if the platform moves up, we can jump in place, we land on the same spot However, when the platform moves down, the hero lands always slightly on the left. In an attempt to hack away some weird solution, this came up as "working" //prevent bodies to fall if they are on a edge. var passengerVelocity:b2Vec2; for each (passenger in _passengers) { if (velocity.y > 0) { passengerVelocity = passenger.GetLinearVelocity(); //passengerVelocity.Add(velocity); passengerVelocity.y += velocity.y; passenger.SetLinearVelocity(passengerVelocity); } } The Hero no longer drifts when jumping on the moving platform when its going down. Let's not forget that one is no longer a passenger when one is not touching (even slightly) the platform so the fact that we are supposed to be focused on vertical velocity causing the problem is right, however the code that does make it all work feels like a bit of nonsense. here I just had a feeling that adding in the velocity.x to the passengerVelocity was wrong in the first place. I still don't get most of it though. |
I don't want to go on about it for ages and spam your inboxes, but for future reference and other visitors that would come here, It's best to clarify what's happening as much as possible, also to help people that would try creating other types of platforms. What I did right after I took a look at this issue in the first place was set the passenger's velocity to the platform's velocity on every update using for each (passenger in _passengers) passenger.SetLinearVelocity(velocity); What happened then was that it fixed the problem but your jumping height was restricted and you would move very slowly left or right, because in fact your 'initial' velocity was the platform's velocity so in order to jump as you would on the floor you needed more velocity impulse to counter the platform's forces, and the same for moving left or right. Adding the velocity to the passengers velocity would fix the problem, but not for its passenger's x velocity because it would already be the same as the platform's velocity , and that's because of the friction ! That's why I think we only need to fix the y velocity on each frame to make the passenger "stick" to the platform on each frame, the physics engine then, thanks to the positive friction, will fix the x velocity by itself. If we would leave Add(velocity) then there would be twice as much x velocity to the hero than it's supposed to, and that's why he would drift left when jumping. problem solved? |
Firstly, don't worry about my inboxes. It's an amazing feeling to see people interested in this engine :) Setting a linear velocity on each update to the passenger, is very wrong because it would prevent objects to be able to move. I've made the update, so problem solved? ;) |
it could be argued that this is perfectly physical behavior, however, if I leave the hero standing on the moving platform and go for my coffee, I do not expect it to be dead after a while because he moved to the edge and fell off.
could there be some kind of hack implemented that will change the inertia of all the bodies that contact moving platform when it changes direction?
The text was updated successfully, but these errors were encountered: