Game Development Community

Better method for sinusoidal movement?

by Christopher Gu · in Torque Game Builder · 09/23/2005 (12:49 pm) · 9 replies

Hey guys. I'm trying to create some enemies and items in my game that move in a sinewave pattern. My current method for doing so looks like this:

function Oscillate(%object, %direction, %upAmount, %downAmount, %frequency)
{
	
	if(!isObject(%object))
		return;
		
	
	if(%direction $= "up")
	{
		%object.setConstantForce(0 SPC %upAmount, false);
		
		schedule(%frequency, 0, "Oscillate", %object, "down", %upAmount, %downAmount, %frequency);
	}
	if(%direction $= "down")
	{	

		
		%object.setConstantForce(0 SPC %downAmount, false);
		schedule(%frequency, 0, "Oscillate", %object, "up", %upAmount, %downAmount, %frequency);
	}

}

This sometimes creates some weird behavior though. Does anyone have a better method or any ideas on how I can improve upon this one?

#1
09/23/2005 (1:12 pm)
If you want sinusoidal movement, why not use a sine function?:)

Try this out:
$frequency= 10;
$amplitude = 10;
$wavelength = 10;
$yPosition = 0;

$object.setLinearVelocityX($frequency);

// Put this in onUpdateScene or a repeatedly scheduled function or some such.
%object.setPositionY($yPosition + ($amplitude * mSin(%object.getPositionX() / $wavelength)));
#2
09/23/2005 (1:34 pm)
SetPosition can make the collision slip however so if this were for an object that didn't demand a lot of collision then would be a much better solution though I could see problems if it demanded a lot of collisions.
#3
09/23/2005 (2:02 pm)
Yeah, the objects which I'm applying this to definately deal with a lot of collisions....

Any other suggestions?
#4
09/23/2005 (4:09 pm)
Does it deal with collisions in which it needs to respond (like running into a wall for instance) or merely need to detect collisions (like getting hit by a bullet)? If it's the latter, it should work fine. If there is any of the former, though, it won't work. Basically, if the objects position will ever be affected by something other than the sine pattern, you'll have to figure something else out.

What is the wierd behavior you're experiencing with your implementation?
#5
09/23/2005 (4:21 pm)
Probably the inaccuracy of schedules?
#6
09/24/2005 (2:00 pm)
Yeah, the schedules create problems. Sometimes my whole scene will explode and objects will fly off the screen.
#7
09/26/2005 (12:43 pm)
Hey Adam,

I tried implementing your suggestion:

function fxSceneGraph2D::onUpdateScene(%object)
{
	if(%object.type $= "sharkplane")
	{
		%yPos = getWord(%object.getPosition(), 1);
		%xPos = getWord(%object.getPosition(), 0);
		
		%object.setPositionY(%yPos + (100 * mSin(%xPos / 100)));
	}
}

It seems to compile just fine, but my ships designated as sharkplane only fly straight (linear velocity X is designated when the object is created). I'm sure I'm doing something wrong here...just not sure what :(
#8
09/26/2005 (1:01 pm)
A couple of problems:

First, $yPosition in my first post should be the y position you want the wave to be centered at, not the current y position of the object. Also, onUpdateScene isn't called for objects, it's called once for the entire scene (sorry about the confusion there). So, your object would need to be saved as a global - or alternatively, added to a SimGroup if you want to do this to multiple objects.

The SimGroup would be something like:
// Initialization
new SimGroup(OscillateGroup);

// Create your object, then...
%object.startYPos = %object.getPositionY();
OscillateGroup.add(%object);

// Scene update
function onUpdateScene()
{
   %count = OscillateGroup.getCount();
   for (%i = 0; %i < %count; %i++)
   {
      %object = OscillateGroup.getObject(%i);
      %xPos = %object.getPositionX();
      %object.setPositionY(%object.startYPos + (100 * mSin(%xPos / 100)));
   }
}

With this, every object you add to the OscillateGroup will oscillate.
#9
09/26/2005 (1:05 pm)
Thanks for the great info! I'll give it a try!