Solution for "riding up the walls" in Mini Platform Tutorial
by Vern Jensen · in Torque Game Builder · 09/11/2006 (4:53 pm) · 40 replies
After many hours experimeting, I have found a solution to the "riding up the walls" problem in the Mini Platform Tutorial. I've posted this in a new thread, so that other threads can reference this thread, and people wont' have to dig down to the 30th message to find this.
The solution is to change the custom collision poly just before doign castCollision, insetting the left/right sides somewhat, so that castCollision won't detect walls to our left or right. The restore the custom collision poly when done.
[code]
// Inset the collision poly's left/right sides a little bit before doing castCollision, so
// that castCollision truly is checking for something BELOW us.
$pGuy.setCollisionPolyCustom( 4, "-0.80 -0.358", "0.60 -0.358", "0.60 0.975", "-0.80 0.975" );
%collision = $pGuy.castCollision(0.005);
// Restore original values after castCollision
$pGuy.setCollisionPolyCustom( 4, "-0.910 -0.358", "0.678 -0.358", "0.678 0.975", "-0.910 0.975" );
[\code]
This would go in the updateMovement function() and should also probably go in the jump() function too.
The solution is to change the custom collision poly just before doign castCollision, insetting the left/right sides somewhat, so that castCollision won't detect walls to our left or right. The restore the custom collision poly when done.
[code]
// Inset the collision poly's left/right sides a little bit before doing castCollision, so
// that castCollision truly is checking for something BELOW us.
$pGuy.setCollisionPolyCustom( 4, "-0.80 -0.358", "0.60 -0.358", "0.60 0.975", "-0.80 0.975" );
%collision = $pGuy.castCollision(0.005);
// Restore original values after castCollision
$pGuy.setCollisionPolyCustom( 4, "-0.910 -0.358", "0.678 -0.358", "0.678 0.975", "-0.910 0.975" );
[\code]
This would go in the updateMovement function() and should also probably go in the jump() function too.
#23
thanks agine.
Firas
10/09/2006 (11:36 pm)
Eric I will check your replay in my post now, and let me thank you alot for your (courtesy) and your interest to help us solve this problem.thanks agine.
Firas
#24
1) No riding up walls.
2) Appropriate jumping while hugging a wall (this is a special case).
3) Smooth movement while running up ramps/slopes (running down slopes is another issue altogether. I'm not sure how you would go about this with the simple physics engine place - unless you set the gravity to something ridiculous and removed it on jumping/falling).
4) No need to worry about pointy collision polygons.
Here's how the code works.
There are a few stipulations/caveats:
1) You must exercise extreme caution when setting up your ramps. If you do not set the collision polygons properly you will get weird functionality. You might set the polygon to look perfect in the editor from the normal perspective but what's actually going on is there's some decimal value pushing the top of your ramp over the platform (noticeable to the engine but not your eye)... in this case, running into the platform while trying to go down it will result in you getting stuck against that wall (no matter how tiny the wall is). A similar issue can occur when approaching the base of a platform. Watch out.
2) Your character will hop at the top of any ramp. This is due to the Y linear velocity resulting from going up the platform. Note that you can kill this by calling "%this.setLinearVelocityY(0);" after "%this.setConstantForceY(0);" in the else-block of updateMovement. A side effect is that you'll move slower up the ramp.
3) Movement down ramps is not clean. We constantly push the player away from the ramp, popping them off of it. Gravity then kicks in and brings you back to the platform. Looks weird but it works.
4) That weird functionality while holding down both direction keys on a ramp. This is mentioned in the comments to the code in the third code block but I figured I'd mention it down here for those who skimmed the code. Watch for slight vertical hopping if both buttons are pressed on the ramp in certain cases.
5) Jumping while running up a ramp/sloped surface is touchy. Not sure exactly what's going on here but it seems like the collision check in the jump may occasionally miss the ramp.
6) Running while against a wall still animates. We continue to set the horizontal velocity even though the player doesn't move anywhere. When we apply animations we base them off the stored value... which we just set. This could potentially be solved by having another flag akin to "airborne". Be careful, though, because it would be difficult to test wall versus ramp (without specifying the platform type of course). Beginning to see a theme here with the the platform types...
Proposed fix for ramp-related issues.
Define a ramp-type platform separate from your usual tile layers. These will allow you to fix special cases (like the slowing down caused by calling %this.setLinearVelocityY(0);" in the second stipulation mentioned above). Much more involved but also clearer and easier to futz with using the editor.
Hope that helps. I'll add some stuff if I find better ways to fix the issues...
EDIT 1: Fixed egregious spacing in code by replacing tabs with spaces.
EDIT 2: Clarity in first code block comment. Fixes for width of third code block.
EDIT 3: Added the third and fourth stipulations/caveats.
EDIT 4: Re-added bold to the third block of code.
EDIT 5: Added the fifth and sixth bullets to the stipulations/caveats. Also added the fourth code block (fixes for animation) which I forgot to add in subsequent edits.
EDIT 6: Replaced redundant call to getLinearVelocityY(0) in else-if statement with cached value.
10/10/2006 (8:15 pm)
@Dan: I have produced a working fix. You get:1) No riding up walls.
2) Appropriate jumping while hugging a wall (this is a special case).
3) Smooth movement while running up ramps/slopes (running down slopes is another issue altogether. I'm not sure how you would go about this with the simple physics engine place - unless you set the gravity to something ridiculous and removed it on jumping/falling).
4) No need to worry about pointy collision polygons.
Here's how the code works.
// The tutorial uses $pGuy instead of %this. I opt for the latter.
function playerClass::onLevelLoaded(%this, %scenegraph)
{
...
%this.airborne = false;
...
}// We have just jumped so we need to set the flag!
function playerJump()
{
...
if(%collision !$= "")
{
$pGuy.setLinearVelocityY(-225);
$pGuy.airborne = true;
}
...
}// Lots edited here. For clarity I put my entire function and bold the new parts.
// I have also added some comments for 'odd functionality' within the code, too.
function playerClass::updateMovement(%this)
{
[b]// ODD FUNCTIONALITY FIX FOR BOTH BUTTON HOLD HERE.
// PUT IF STATEMENT TO SEE IF BOTH ARE DOWN.[/b]
if(%this.moveLeft)
{
%this.setLinearVelocityX(-%this.runSpeed);
}
if(%this.moveRight)
{
%this.setLinearVelocityX(%this.runSpeed);
}
[b]// COULD FIX FOR BOTH BUTTON HOLD HERE TOO.
// WOULD CONSIST OF: "HOLDING BOTH DOWN ALSO STOPS MOVEMENT."[/b]
if(!%this.moveLeft && !%this.moveRight)
{
%this.setLinearVelocityX(0);
[b]// New: Stops the small hopping effect that can occur on ramps/sloped platforms.
// The issue occurs because you gain some linearVelocityY while going up a ramp.
// Letting go of the arrow keys kills the X but not the Y. Here we fix that.
// NOTE: This does not fix a hopping effect that can occur if you press the
// [downhill key] while holding the [uphill key]. Implementing the comment above
// this if-block would be one way to fix the issue.
if(!%this.airborne)
%this.setLinearVelocityY(0);[/b]
}
// Begin checking for objects around the player
%yVelocity = %this.getLinearVelocityY();
%this.setLinearVelocityY(0);
%collision = %this.castCollision(0.005);
[b]// WALL CLIMBING FIX HACK.
if(%collision !$= "")
{
if(%this.airborne) // NEW: Only kill the X-Velocity if we're flyin'.
%this.setLinearVelocityX(0);
}[/b]
// Check for ground beneath the feet.
%this.setLinearVelocityY(100);
%collision = %this.castCollision(0.005);
// Before we move further, restore the previous velocity.
%this.setLinearVelocityY(%yVelocity);
if(%collision $= "")
{
[b]%this.airborne = true; // NEW: Case that ensures falling == airborne.[/b]
%this.setConstantForceY(100);
}
[b]// NEW: Fixes the following:
// A) Case where you're moving into a wall while you jump. Without this, a player can
// bound over any wall around simply by holding the arrow key. A special case of
// wall-climbing.
// B) Case for moving UP ramps / sloped platforms. Does not really fix this issue,
// just allows for the case to be handled separately. (This is actually handled in the
// final else-statement below).
else if(%yVelocity < 0 && %this.airborne)
{
// We are in the special case where we are jumping while colliding against a wall.
%this.setConstantForceY(100);
}
else
{
%this.airborne = false; // NEW: Default for being on the ground!
%this.setConstantForceY(0);
}[/b]
// Make sure we're animationg properly
%this.setCurrentAnimation();
}// Make sure that you're only playing the jumping animations when airborne.
function playerClass::setCurrentAnimation(%this)
{
...
// Jumping.
if(%yVelocity < 0 [b]&& %this.airborne[/b])
{
%this.playAnimation(playerJumpUp);
}
else if(%yVelocity > 0 [b]&& %this.airborne[/b])
{
%this.playAnimation(playerJumpDown);
}
...
}Read through the bold parts to get an idea of how stuff works. Things seem to be working well enough (minus the little hop when heading downhill if both keys are temporarily pressed (or held down, given the order of if-statements in setting horizontal speed).There are a few stipulations/caveats:
1) You must exercise extreme caution when setting up your ramps. If you do not set the collision polygons properly you will get weird functionality. You might set the polygon to look perfect in the editor from the normal perspective but what's actually going on is there's some decimal value pushing the top of your ramp over the platform (noticeable to the engine but not your eye)... in this case, running into the platform while trying to go down it will result in you getting stuck against that wall (no matter how tiny the wall is). A similar issue can occur when approaching the base of a platform. Watch out.
2) Your character will hop at the top of any ramp. This is due to the Y linear velocity resulting from going up the platform. Note that you can kill this by calling "%this.setLinearVelocityY(0);" after "%this.setConstantForceY(0);" in the else-block of updateMovement. A side effect is that you'll move slower up the ramp.
3) Movement down ramps is not clean. We constantly push the player away from the ramp, popping them off of it. Gravity then kicks in and brings you back to the platform. Looks weird but it works.
4) That weird functionality while holding down both direction keys on a ramp. This is mentioned in the comments to the code in the third code block but I figured I'd mention it down here for those who skimmed the code. Watch for slight vertical hopping if both buttons are pressed on the ramp in certain cases.
5) Jumping while running up a ramp/sloped surface is touchy. Not sure exactly what's going on here but it seems like the collision check in the jump may occasionally miss the ramp.
6) Running while against a wall still animates. We continue to set the horizontal velocity even though the player doesn't move anywhere. When we apply animations we base them off the stored value... which we just set. This could potentially be solved by having another flag akin to "airborne". Be careful, though, because it would be difficult to test wall versus ramp (without specifying the platform type of course). Beginning to see a theme here with the the platform types...
Proposed fix for ramp-related issues.
Define a ramp-type platform separate from your usual tile layers. These will allow you to fix special cases (like the slowing down caused by calling %this.setLinearVelocityY(0);" in the second stipulation mentioned above). Much more involved but also clearer and easier to futz with using the editor.
Hope that helps. I'll add some stuff if I find better ways to fix the issues...
EDIT 1: Fixed egregious spacing in code by replacing tabs with spaces.
EDIT 2: Clarity in first code block comment. Fixes for width of third code block.
EDIT 3: Added the third and fourth stipulations/caveats.
EDIT 4: Re-added bold to the third block of code.
EDIT 5: Added the fifth and sixth bullets to the stipulations/caveats. Also added the fourth code block (fixes for animation) which I forgot to add in subsequent edits.
EDIT 6: Replaced redundant call to getLinearVelocityY(0) in else-if statement with cached value.
#25
Eric could you please suggest somthing about stucking in the ciling when pGuy jump while moving left or right?
I notic that if you jump straight up pGuy will not stuck on the ciling.
10/11/2006 (2:42 am)
Eric nice workEric could you please suggest somthing about stucking in the ciling when pGuy jump while moving left or right?
I notic that if you jump straight up pGuy will not stuck on the ciling.
#26
It's certainly happening because of the following code:
There's hacks that you could do to get around the issue... but they're a bit more involved. If your ceilings are only flat then you might be able to test the collision normal. Or you could just move on and work on other things until the bugs are fixed in the source.
@Dan: What do you think about the above code? Is it worth adding to the tutorial? It makes platforms somewhat viable as well as fixes the wall climbing issue...
10/11/2006 (8:36 pm)
@Firas: I have tried with all my might to get him stuck in the ceiling using my code. I changed the collision polygon to make it pointy again and even that didn't do the trick. I increased the speed of my collision to no affect. I honestly can't figure out why it's not happening for me but it is for you.It's certainly happening because of the following code:
// WALL CLIMBING FIX HACK.
if(%collision !$= "")
{
if(%this.airborne) // NEW: Only kill the X-Velocity if we're flyin'.
%this.setLinearVelocityX(0);
}You're experiencing the same issue that everyone did when they got stuck on the ground, just the reverse. We can't test for velocity or anything because that would nullify the climbing fix.There's hacks that you could do to get around the issue... but they're a bit more involved. If your ceilings are only flat then you might be able to test the collision normal. Or you could just move on and work on other things until the bugs are fixed in the source.
@Dan: What do you think about the above code? Is it worth adding to the tutorial? It makes platforms somewhat viable as well as fixes the wall climbing issue...
#27
10/11/2006 (10:59 pm)
I like it! I wont have a chance to re-visit in the short term. If you would like to edit the descriptions and incorporate your changes I'm more then happy for you to do it. Seems like you've done a lot of good work here.
#28
my platforms/Tiles is not slanted at all, they are entirely horizontal, (the same environment we build in miniPlatformerTutorial).
for the tiles there is no custom collision for them.
but for the pGuy yes there is a custom collision polygon and I show it to you and we fix it together and here is it a gine:
CollisionPolyList = "0.900 0.418 0.486 1.000 -0.699 1.000 -0.910 0.129 -0.910 0.024 0.185 -0.550 0.241 -0.550 0.900 0.265";
this is working perfectly with the ciling if you colide with the ciling vertically there will be no stucking at all but the problem is when you jump while pressing left or right movemnet key your player will stuck in the ciling, please note that you can move horizontally after you stcuk in the ciling but you can't get back to the ground.
here is a pic. descripe the problem:
img214.imageshack.us/img214/3100/stuckmv1.jpg
10/12/2006 (12:14 am)
Eric:my platforms/Tiles is not slanted at all, they are entirely horizontal, (the same environment we build in miniPlatformerTutorial).
for the tiles there is no custom collision for them.
but for the pGuy yes there is a custom collision polygon and I show it to you and we fix it together and here is it a gine:
CollisionPolyList = "0.900 0.418 0.486 1.000 -0.699 1.000 -0.910 0.129 -0.910 0.024 0.185 -0.550 0.241 -0.550 0.900 0.265";
this is working perfectly with the ciling if you colide with the ciling vertically there will be no stucking at all but the problem is when you jump while pressing left or right movemnet key your player will stuck in the ciling, please note that you can move horizontally after you stcuk in the ciling but you can't get back to the ground.
here is a pic. descripe the problem:
img214.imageshack.us/img214/3100/stuckmv1.jpg
#29
@Firas: I tested your polygon in my code again and have not once gotten stuck. Could you send me your project code to look over? Or at least post the updateMovement and jump functions? The project folder would be best because it might be a glitch in something else...
10/12/2006 (12:25 am)
@Dan: Excellent. I've gone through and cleaned up the tutorial a bit (at least through player movement). Spelling and punctuation mostly. I'm going to look into turning the setting of 'airborne' into a separate function that gets called before the if statements. Hopefully this will make it clearer and move the castCollision tests to a separate, isolated function.@Firas: I tested your polygon in my code again and have not once gotten stuck. Could you send me your project code to look over? Or at least post the updateMovement and jump functions? The project folder would be best because it might be a glitch in something else...
#30
you should recive now a message called "Project files from Firas"
please check it and tell me what up?
thanks in advance
Firas
10/12/2006 (3:19 am)
Eric I'm sending the project files to your email (I take it from your profile) you should recive now a message called "Project files from Firas"
please check it and tell me what up?
thanks in advance
Firas
#31
Rebuild your level.
Start over with a new t2dTileLayer and then get the t2dTileMap setup properly again. You might be able to get away with just changing the TileMap.
Why? I dropped my tileMap into your project's directory and ran the game. Using my tileMap (nothing special, as far as I know), the problem went away. I suspect that something's busted in the tileMap. Unfortunately, I do not know what format the file is saved in and have had no luck dropping the tileMap into a simple editor.
This is unrelated to the issue but, as for the code, there are a lot of bugs related to implementation that are gone in my project. I'm planning on updating the miniPlatformerTutorial to include most, if not all, of the fixes that I made, including the fixes mentioned in this forum. An example of something that's fixed is the "moonwalking" effect you can get if you press the keys a certain way.
Let me know if you have any luck with recreating the tileMap.
10/12/2006 (6:35 pm)
@Firas: I received your project and took a look at it. There really isn't any single setting or line of code that can fix the problem, it seems. I did get your project working without issue, however. Here's what you need to do:Rebuild your level.
Start over with a new t2dTileLayer and then get the t2dTileMap setup properly again. You might be able to get away with just changing the TileMap.
Why? I dropped my tileMap into your project's directory and ran the game. Using my tileMap (nothing special, as far as I know), the problem went away. I suspect that something's busted in the tileMap. Unfortunately, I do not know what format the file is saved in and have had no luck dropping the tileMap into a simple editor.
This is unrelated to the issue but, as for the code, there are a lot of bugs related to implementation that are gone in my project. I'm planning on updating the miniPlatformerTutorial to include most, if not all, of the fixes that I made, including the fixes mentioned in this forum. An example of something that's fixed is the "moonwalking" effect you can get if you press the keys a certain way.
Let me know if you have any luck with recreating the tileMap.
#32
it's work like a charm, I just create a new level and drop my tileLayer and it's work perfectly.
I don't know why this happen, but anyway thanks alot.
and I'm waiting you update on miniPlatformTutorial
Best Regards
Firas
10/12/2006 (10:25 pm)
Thanks alot Ericit's work like a charm, I just create a new level and drop my tileLayer and it's work perfectly.
I don't know why this happen, but anyway thanks alot.
and I'm waiting you update on miniPlatformTutorial
Best Regards
Firas
#33
10/13/2006 (12:12 am)
Odd... I replaced my update movement fuction with the one above and replaced what was needed for the code change. It got rid of the hop in my movement. but my player still rides up walls. I guess thats alright because hes a bar of soap. (my main character)
#34
I edited the Movement and Animation sections. As I went I refined my code from above, making it shorter and much easier to follow. I think it's better organized, too. Anyone who used the animation code unmodified will notice much more precise animation (no moonwalking and such anymore!).
Thoughts?
@Matthew: Give the updated tutorial a shot. Maybe you're bar of soap will adhere to the laws of gravity after you've gone through it :)
10/13/2006 (2:02 am)
@All: I have just completed my overhaul of the miniPlatformerTutorial. Give it a try and let me know if you come across any problems.I edited the Movement and Animation sections. As I went I refined my code from above, making it shorter and much easier to follow. I think it's better organized, too. Anyone who used the animation code unmodified will notice much more precise animation (no moonwalking and such anymore!).
Thoughts?
@Matthew: Give the updated tutorial a shot. Maybe you're bar of soap will adhere to the laws of gravity after you've gone through it :)
#35
One nit pick... the format of
and for some reason you brain can't see that AnotherLineOfCode() is executing every time because white space does not determin scope!
So as a practice I always do...
Then when someone comes along and adds another line there's no qustion if it belongs to the "if" statement or not.
This becomes really important on larger projects where you can have one or more people touching the same code.
Overall though, very nice work. You did a lot of legwork on this and I know a lot of people are going to benefit.
10/14/2006 (1:16 am)
Good changes, especially the animation code. I thought you might have dropped a little too much on the player at once with the vertical movement function, but you broke out each section nicely and explained it pretty well.One nit pick... the format of
if( something )
OneLineOfCode();the curly brackets aren't nessisary, but man, their a good idea. I don't know how many times i've come across code where the bug is something like this.if( something )
OneLineofCode();
AnotherLineofCode();and for some reason you brain can't see that AnotherLineOfCode() is executing every time because white space does not determin scope!
So as a practice I always do...
if( something )
{
OneLineOfCode();
}Then when someone comes along and adds another line there's no qustion if it belongs to the "if" statement or not.
This becomes really important on larger projects where you can have one or more people touching the same code.
Overall though, very nice work. You did a lot of legwork on this and I know a lot of people are going to benefit.
#36
Further, I felt that some of the functions were a little long in the tooth and removing some braces made them seem a bit less intimidating.
I agree completely, however, about the coding style in general. Feel free to add the braces back in if you like. I'm going to try to add a section about "Further Direction" or, as I did above "Stipulations and Caveats" to further explain the goal of the tutorial and give people a few hints on directions to go in and where to start looking...
10/14/2006 (7:11 pm)
Thanks! For the most part I agree about the if-statement braces. As a rule I do it for the functions myself. I just figured that it would cut back on length a bit. Also, and this may not have been you as it was added later, there was a one line function already in the tutorial with:function t2dSceneGraph::onUpdateScene()
{
if (isObject($pGuy))
$pGuy.updateMovement();
}I took that as a layout example and ran with it. Removing braces can sometimes add to readability as well, particularly when you hit a bunch of one-liners.Further, I felt that some of the functions were a little long in the tooth and removing some braces made them seem a bit less intimidating.
I agree completely, however, about the coding style in general. Feel free to add the braces back in if you like. I'm going to try to add a section about "Further Direction" or, as I did above "Stipulations and Caveats" to further explain the goal of the tutorial and give people a few hints on directions to go in and where to start looking...
#37
This would seem to me (despite being a check that happens in the air) to be a horizontal check, I probably would have placed it in ithe updateHorizontal( ) function.
EDIT:
I guess i see why you did it there, because we dont store the yVelocity in the updateHorizontal() method and we would have to add that to restore it after this check.
10/14/2006 (7:34 pm)
One thing that had me curious though, at the beginning of the updateVertical( ) function.. you haveif(%this.airborne)
{
%this.setLinearVelocityY(0);
%collision = %this.castCollision(0.005);
if(%collision !$= "")
%this.setLinearVelocityX(0);
}This would seem to me (despite being a check that happens in the air) to be a horizontal check, I probably would have placed it in ithe updateHorizontal( ) function.
EDIT:
I guess i see why you did it there, because we dont store the yVelocity in the updateHorizontal() method and we would have to add that to restore it after this check.
#38
I left it where I did because we could then sandwich the function with %yVelocity storing and setting, cutting back on one call to "getLinearVelocityY()".
I was toying with using a vector to store the data and pass-to/get-back-from the functions (something like "return %xVelocity SPC %yVelocity;") but that would have required calls to getWord to implement properly, negating the readability / admitedly-teenie-weenie performance gain. I figured it only happens in relation to vertical movement so it would be okay in either... :)
A do call getLinearVelocityY and getLinearVelocityX to determine animations but I figured that was exceptable, all things considered.
10/14/2006 (8:12 pm)
That's exactly why I did it, actually. I tried to keep it simple and not go into too much detail and simply pointed out that the location of the code was important. It needs to come after the horizontal stuff (so that we are no longer setting the horizontal velocity and tossing the player into a wall) but before the other code so that the next collision check occurs properly.I left it where I did because we could then sandwich the function with %yVelocity storing and setting, cutting back on one call to "getLinearVelocityY()".
I was toying with using a vector to store the data and pass-to/get-back-from the functions (something like "return %xVelocity SPC %yVelocity;") but that would have required calls to getWord to implement properly, negating the readability / admitedly-teenie-weenie performance gain. I figured it only happens in relation to vertical movement so it would be okay in either... :)
A do call getLinearVelocityY and getLinearVelocityX to determine animations but I figured that was exceptable, all things considered.
#39
10/15/2006 (6:10 pm)
@Dan: I added a seventh section to the tutorial entitled "Stipulations, Caveats, and Where to go from here". It incorporates some of the stuff I mentioned in the big code update in this thread and kind of summarizes what the tutorial is about (at least as I understand it). What do you think? Of course edit/delete it at your own leisure... ;D
#40
10/18/2006 (12:57 pm)
I think you hit it right on the head :)
Torque Owner Eric Robinson