Jump physics easy fix
by Steven Hine · in Torque Game Builder · 11/04/2006 (8:35 am) · 7 replies
Ok... I've read all the threads on this and maybe I missed one that had an easy fix. I came up with this one.
The problem:
$pGuy would not jump every time I hit the jump key. I could here the jump happening, but he didn't jump.
It seemed that pGuy was stuck in the tile layer.
Here's the fix:
function playerJump()
{
if(!$pGuy.airBorne)
{
//move guy up to keep from getting stuck when jumping
%oldY = $pGuy.getPositionY();
%newY = %oldY - 1.0;
$pGuy.setPositionY(%newY);
$pGuy.setLinearVelocityY($pGuy.vJump);
$pGuy.airborne = true;
alxPlay(jumpAudio);
}
}
function playerJumpStop()
{
//limit jump when key is released
if($pGuy.getLinearVelocityY() < 0)
$pGuy.setLinearVelocityY(-50);
}
function playerClass::updateVertical(%this)
{
//if pGuy has collided with anything reset airborne
if(%this.getLinearVelocityY() == 0)
%this.airBorne = false;
}
pGuy's settings:
send and receive collisions turned on
send physics on
callback turned on(for spikes and enemies)
constant Y force set to 100.00
gravity on, force scale 4.0
vJump = -125
Easy just move pGuy up slightly to keep collision from registering. I don't seem to have any glitches from this, but if anyone has some let me know.
Steve
The problem:
$pGuy would not jump every time I hit the jump key. I could here the jump happening, but he didn't jump.
It seemed that pGuy was stuck in the tile layer.
Here's the fix:
function playerJump()
{
if(!$pGuy.airBorne)
{
//move guy up to keep from getting stuck when jumping
%oldY = $pGuy.getPositionY();
%newY = %oldY - 1.0;
$pGuy.setPositionY(%newY);
$pGuy.setLinearVelocityY($pGuy.vJump);
$pGuy.airborne = true;
alxPlay(jumpAudio);
}
}
function playerJumpStop()
{
//limit jump when key is released
if($pGuy.getLinearVelocityY() < 0)
$pGuy.setLinearVelocityY(-50);
}
function playerClass::updateVertical(%this)
{
//if pGuy has collided with anything reset airborne
if(%this.getLinearVelocityY() == 0)
%this.airBorne = false;
}
pGuy's settings:
send and receive collisions turned on
send physics on
callback turned on(for spikes and enemies)
constant Y force set to 100.00
gravity on, force scale 4.0
vJump = -125
Easy just move pGuy up slightly to keep collision from registering. I don't seem to have any glitches from this, but if anyone has some let me know.
Steve
About the author
#2
1. engine reads script
2. does collisions(which cancels any script velocity changes)
3. then updates velocity changes(only if they didn't collide with something)
So out of this came the idea to give pGuy a boost to make sure he wasn't colliding when the engine updated velocity changes. It's quite simple and doesn't cause collision problems, at least I hope. I haven't seen any. Putting in ramps may be a different story. I'll look in to that, when I can...
11/04/2006 (5:49 pm)
Lol... It's not a coincidence. I did read that thread, but thought it was a lot of work to fix my problem. That's why I came up with this fix. I did use some on the code from the tutorial. The problem seems to be the order the engine does the collision and update movements. I think it works like this: 1. engine reads script
2. does collisions(which cancels any script velocity changes)
3. then updates velocity changes(only if they didn't collide with something)
So out of this came the idea to give pGuy a boost to make sure he wasn't colliding when the engine updated velocity changes. It's quite simple and doesn't cause collision problems, at least I hope. I haven't seen any. Putting in ramps may be a different story. I'll look in to that, when I can...
#3
The updated tutorial code happens to be a lot more efficient, too. The castCollisions are reduced to one call per frame unless necessary... at which point I believe the function gets called a maximum of twice. It's also more expandable code than the original.
Also, some GG employees posted on some of the forums and have said that the wall-sticking is related to some collision bugs that are getting worked out for the next update of TGB. As such, the code you used above and the code implemented in the tutorial are actually work-arounds for those bugs. They make things work 'for the time being'. I'm not sure if it has anything to do with the order of operations you mention above... I think it's just bugs. For instance, the engine reads the script and if you say "cast collision-> oops, collision so set velocity to zero" then the velocity is immediately set to zero. Then the engine does collisions and updates stuff but it should never have collided in the first place. There's some question as to how setVelocity and getVelocity work, as well... but my understanding is that it should work as I have mentioned but engine-side bugs are causing funky 'functionality'.
If you continue with this path, though, please post what you come up with in terms of ramps and stuff! Always good to get a second opinion and a look into other means to an end!
11/04/2006 (5:58 pm)
Wow, that's funny. Same function and variable names! I guess when they describe what their doing and the fixes remain similar...The updated tutorial code happens to be a lot more efficient, too. The castCollisions are reduced to one call per frame unless necessary... at which point I believe the function gets called a maximum of twice. It's also more expandable code than the original.
Also, some GG employees posted on some of the forums and have said that the wall-sticking is related to some collision bugs that are getting worked out for the next update of TGB. As such, the code you used above and the code implemented in the tutorial are actually work-arounds for those bugs. They make things work 'for the time being'. I'm not sure if it has anything to do with the order of operations you mention above... I think it's just bugs. For instance, the engine reads the script and if you say "cast collision-> oops, collision so set velocity to zero" then the velocity is immediately set to zero. Then the engine does collisions and updates stuff but it should never have collided in the first place. There's some question as to how setVelocity and getVelocity work, as well... but my understanding is that it should work as I have mentioned but engine-side bugs are causing funky 'functionality'.
If you continue with this path, though, please post what you come up with in terms of ramps and stuff! Always good to get a second opinion and a look into other means to an end!
#4
Heres my version of the mini platform code:
Perhaps I should use triggers instead. But I'm thinking of writting my movement from scratch.
03/17/2007 (5:53 pm)
Sorry to bump this again, I tried doing this code but my character still get's stuck. I know it's from a function I'm doing that disallow movement mid air(Old School Castlevania style), I don't want to want to player to control movement in midair but I'm tired of the the character getting stuck all the time, but the rest of the code works great if take way the if (!%this airborne) trick.Heres my version of the mini platform code:
function playerClass::onLevelLoaded(%this, %scenegraph)
{
$pGuy = %this;
moveMap.bindCmd(keyboard, "left", "playerLeft();", "playerLeftStop();");
moveMap.bindCmd(keyboard, "right", "playerRight();", "playerRightStop();");
moveMap.bindCmd(keyboard, "space", "playerJump();", "");
%force = 20;
sceneWindow2D.mount($pGuy, "0 0", %force, true);
%this.setCollisionMaxIterations(2);
}
function playerLeft()
{
$pGuy.moveLeft = true;
}
function playerLeftStop()
{
$pGuy.moveLeft = false;
}
function playerRight()
{
$pGuy.moveRight = true;
}
function playerRightStop()
{
$pGuy.moveRight = false;
}
function playerJump()
{
if(!$pGuy.airborne)
{
$pGuy.setLinearVelocityY(-80);
$pGuy.airborne = true;
$pGuy.jump = true;
}
}
function playerClass::jump(%this)
{
if (!%this.airborne)
{
if(%this.moveLeft)
{
%this.jumpd=1;
}
if(%this.moveRight)
{
%this.jumpd=2;
}
if(!%this.moveLeft && !%this.moveRight)
{
%this.jumpd=3;
}
}
}
function playerClass::updateHorizontal(%this)
{
if(%this.jumpd==1)
{
%this.setLinearVelocityX(-30);
}
if(%this.jumpd==2)
{
%this.setLinearVelocityX(30);
}
if(%this.jumpd==3)
{
%this.setLinearVelocityX(0);
}
}
function playerClass::updateVertical(%this)
{
%yVelocity = %this.getLinearVelocityY();
if(%this.airborne)
{
%this.setLinearVelocityY(0);
%collision = %this.castCollision(0.005);
if(%collision !$= "")
%this.setLinearVelocityX(0);
}
%this.setLinearVelocityY(50);
%collision = %this.castCollision(0.005);
if(%collision $= "")
{
%this.airborne = true;
%this.setConstantForceY(50);
if(!%this.jump){
%this.jumpd=3;
}
}
else if(%yVelocity < 0 && %this.airborne)
{
%this.setConstantForceY(50);
}
else
{
if(%yVelocity > 0)
{
%this.airborne = false;
%this.jump = false;
%this.setConstantForceY(0);
}
}
%this.setLinearVelocityY(%yVelocity);
}
function playerClass::setCurrentAnimation(%this)
{
%xVelocity = %this.getLinearVelocityX();
%yVelocity = %this.getLinearVelocityY();
if(%xVelocity > 0)
{
%this.setFlip(false, false);
}
else if(%xVelocity < 0)
{
%this.setFlip(true, false);
}
if(%this.airborne)
{
if(%yVelocity < 0)
{
%this.playAnimation(playerJumpUp);
}
else
{
%this.playAnimation(playerJumpDown);
}
}
else
{
if(%xVelocity == 0)
{
%this.playAnimation(playerStand);
}
else
{
if(%this.getAnimationName() $= "playerRun")
{
if(%this.getIsAnimationFinished())
{
%this.playAnimation(playerRun);
}
}
else
{
%this.playAnimation(playerRun);
}
}
}
}
function playerClass::updateMovement(%this)
{
%this.jump();
%this.updateHorizontal();
%this.updateVertical();
%this.setCurrentAnimation();
}
function PlatformerSceneGraph::onUpdateScene()
{
if (isObject($pGuy))
$pGuy.updateMovement();
}Perhaps I should use triggers instead. But I'm thinking of writting my movement from scratch.
#5
[ code]
// insert code here
function blah()
{
echo('blah');
}
[ /code]
(just take out the space after the bracket)
which makes it look like
03/19/2007 (1:14 am)
A chime a bit off topic though think you will find it useful. When posting code in these forums just wrap them with:[ code]
// insert code here
function blah()
{
echo('blah');
}
[ /code]
(just take out the space after the bracket)
which makes it look like
// insert code here
function blah()
{
echo('blah');
}
#7
03/19/2007 (11:57 am)
I was wondering how it implement that. Let me correct that for a moment.
Torque Owner Eric Robinson
Though it does appear that you are using variables and functions from the overhauled tutorial... are you proposing a rewrite of the functions or is that just coincidence?