Game Development Community

Code Problem/Suggestions

by Jeffrey Sweeney · in Torque Game Builder · 06/17/2009 (3:44 pm) · 14 replies

Because if the varying results I've had when using the "castCollision()" and "onCollision" functions together on different Operating Systems, I'm now trying to make a platform game script that's movement is completely defined in the "onCollision" function.

Problems:
Jumpy on wall collisions (but at least not going through them ;) )
-any more?

Suggestions and problems with the following script would be appreciated. You're free to use and manipulate this code as well.





This assumes the player sends + receives collision (and nothing else) and the ground receives collision (and nothing else)


------------------------------------------------------------

function player::onCollision(%this, %dstObj, %srcRef, %dstRef, %time, %normal, %contactCount, %contacts) {  
   //-----For simplicity, I'm using local variables-----  
   %xvel = (%this.moveRight - %this.moveLeft) * %this.movespeed;          //the resulting x velocity
   %yvel = mTan(getWord(%normal, 0)) * %this.getLinearVelocityX();        //the resulting y velocity
   %angle = getWord(%normal, 1);                                          //the collision angle y (in radians)
   %jumpheight = %this.jump * -%this.jumpSpeed;                           //the height the player will jump

   //-----ceiling collision-----
   if(%angle > 0) {
	  %this.setPositionY(%this.getPositionY() + 1);
      %yvel = 4 - %jumpheight;
   }

   //-----wall collision (or too steep of a slope)-----  
   if(%angle > -0.3) {
      %yvel = %this.getLinearVelocityY();		
   
      if(%this.getLinearVelocityX() - %dstObj.getLinearVelocityX() < 0)
         %this.setPositionX(%this.getPositionX() + 1);
      if(%this.getLinearVelocityX() - %dstObj.getLinearVelocityX() > 0)
         %this.setPositionX(%this.getPositionX() - 1);

      %xvel = %dstObj.getLinearVelocityX();
      %jumpheight = 0;  
   }
		
   //-----if the player is on a rotating block-----  
   if(%dstObj.getAngularVelocity() != 0 && %this.getLinearVelocityX() == 0) 
      %yvel = ((%this.getPositionY() - %dstObj.getPositionX()) / %dstObj.getWidth() / 2);  
      
   //-----if the player is on a moving block-----  
      if(%dstObj.getLinearVelocityX() != 0)  
         %xvel = %dstObj.getLinearVelocityX() + %xvel;
      if(%dstObj.getLinearVelocityY() != 0)
         %yvel = %dstObj.getLinearVelocityY() + %yvel;
      
   //-----finally, set the speeds-----
   %this.setLinearVelocityX(%xvel);
   %this.setLinearVelocityY(%yvel + %jumpheight - 0.05);
}
------------------------------------------------------------



Oh, and if you want to use this code in a game, copy/paste this script in the same file:


------------------------------------------------------------



//----------start----------
function player::onLevelLoaded(%this) {
   %this.start();
   %this.loadAnimation();
}





//----------enablers----------
function player::start(%this) {

%this.gravity = 49.05; //gravitational effect on a 5N object
%this.setConstantForceY(%this.gravity);


   //-----variables-----
   %this.moveSpeed = 15;
   %this.jumpSpeed = 50;
   
   //---don't change---
   %this.jump = false;
   %this.moveLeft = 0;
   %this.moveRight = 0;


   //-----keybinds-----
   if(!isObject(moveMap)) {return;}
   moveMap.bindCmd(keyboard, "up", "player.Jump();", "player.stopJump();");
   moveMap.bindCmd(keyboard, "left", "player.left();", "player.stopLeft();");
   moveMap.bindCmd(keyboard, "right", "player.right();", "player.stopRight();");
   
   
   //-----collision-----
   %this.setCollisionActiveSend(true);
   %this.setCollisionActiveReceive(true);
   %this.setCollisionPhysics(false, false);
   %this.enableUpdateCallback();
   %this.setCollisionCallback(true);
}





//----------key commands----------
function player::Jump(%this) {
   %this.jump = true;
}
function player::stopJump(%this) {
   %this.jump = false;
}

function player::left(%this) {
   %this.moveLeft = 1;
   %this.setFlipX(1);
}
function player::stopLeft(%this) {
   %this.moveLeft = 0;
}

function player::right(%this) {
   %this.moveRight = 1;
   %this.setFlipX(0);
}
function player::stopRight(%this) {
   %this.moveRight = 0;
}





//----------movement code----------
function player::onUpdate(%this) {

   if((%this.moveRight - %this.moveLeft) == 0)
      %this.setAnimationFrame(0);
	  
   //%this.updateAnimation();
   
}

------------------------------------------------------------




Feedback would be greatly appreciated.

#1
06/18/2009 (1:55 am)
you could use [ code ][ /code ] tags on this forum :P
#2
06/18/2009 (12:40 pm)
Alright, sure.
(Ironically, I don't know much html)
#3
06/22/2009 (8:10 am)
It could use some improvement, but at the very least it's now impossible to get stuck in walls. BTW, I also added a variable called jumpSpeed so you can set that in the default properties.

function player::onCollision(%this, %dstObj, %srcRef, %dstRef, %time, %normal, %contactCount, %contacts) 
{  
    	//-----For simplicity, I'm using local variables-----  
    	%xvel = %this.moveRight - %this.moveLeft;                              //the resulting x velocity  
    	%yvel = -mAbs(mTan(getWord(%normal, 0)) * %this.getLinearVelocityX()); //the resulting y velocity  
    	%angle = getWord(%normal, 1);                                          //the collision angle y (in radians)  
    	%jumpheight = %this.jump * -%this.jumpSpeed;                           //the height the player will jump  
   
    	echo(%angle);  
      
    	//-----if the player is on a rotating block-----  
    	if(%dstObj.getAngularVelocity() != 0 && %this.getLinearVelocityX() == 0) 
	{  
       		%yvel = ((%this.getPositionY() - %dstObj.getPositionX()) / %dstObj.getWidth() / 2) * %dstObj.getAngularVelocity();  
    	}  
      
      
    	//-----if the player is on a moving block-----  
    	if(%dstObj.getLinearVelocityX() != 0)  
	{
       		%xvel = %dstObj.getLinearVelocityX() + %xvel;
	}  
    	if(%dstObj.getLinearVelocityY() != 0)  
	{
       		%yvel = %dstObj.getLinearVelocityY() + %yvel; 
	} 
      
      
    	//-----wall collision (or too steep of a slope)-----  
    	if(%angle > -0.3) 
	{
		%xvel = 1 / (mSin(getWord(%normal, 1)));
		//if(%this.xvel < 0)
		//{
		//	%this.setPositionX(%dstObj.getPositionX() + %dstObj.getWidth() + 1)
		//}
		//if(%this.xvel > 0)  
		//{
		//	%this.setPositionX(%dstObj.getPositionX() - %this.getWidth() - 1)
		//}
       		%this.setLinearVelocityX(0); //to play it safe  
       		%jumpheight = 0;  
    	}  
      
    	//-----finally, set the speeds-----  
    	%this.setLinearVelocityY(%yvel + %jumpheight - 0.05);  
    	%this.setLinearVelocityX(%xvel);  
}
#4
06/22/2009 (10:36 am)
Awesome, this looks great!
You fixed the going through wall glitch, but now the player gets caught up on some ramps and in the wall. Maybe it has to do with colliding with more than one object... not sure. I think you're on the right track with the commented speed checks there.

I'll update my first post with your code though. Thanks tons.
#5
06/22/2009 (11:01 am)
Thats the way I used to do this in flash, unfortunatley it seems to be returning errors every time I compile those checks in particular, is there any obvious thing I've missed there?
#6
06/22/2009 (11:43 am)
I think you just forgot a few semicolons ;)

I'll post my revisions right now so you can see what I changed.
#7
06/22/2009 (7:18 pm)
whoa, holy crap, DURRRR. I can't believe I missed that, I've gotta test this right away.
#8
06/26/2009 (10:24 am)
I guess I'm done updating this code for now. The only major problem is getting 'jumpy' when colliding with a wall.

Again, feel free to use it people. If I ever get it to work just right, I'll submit it as a resource.
#9
07/14/2009 (8:54 am)
I'm a little confused on your usage of %normal in the onCollision function. Isn't the normal a vector? You are treating it like two angles, but it is really the cosine and sine of one angle. Your usage of the second coordinate (%angle) is OK, but I particularly don't understand why you take the tangent of the first coordinate to compute %yvel. Can you please explain?
#10
07/15/2009 (10:42 am)
In that case, he's using the tangent of the normal in the x direction, as opposed to the y direction as in %angle, and since he doesnt use that variable again, hes using getWord directly.
#11
07/16/2009 (5:42 am)
Yeah, I did it like that so the necessary Y velocity for going up slopes would be calculated at the beginning of the function.
#12
07/16/2009 (6:02 am)
But how can you take the tangent of a normal? What does that quantity even mean? You can only take the tangent of an angle. I understand your use of the y direction, but not your use of the x direction.
#13
07/16/2009 (10:48 pm)
So where's the finished code?
#14
07/17/2009 (8:33 pm)
@James
It's been awhile since I worked on this, and while since I did pre-cal. I guess I did just treat it like an angle. Whatever the hell I did, it seems to work. :)
If I remember why I did it like this (I'm bad at leaving comments in my code), I'll get back to you.

@Fernando
I've been too busy procrastinating/doing other stuff to work on the code.