Move a distance with sine affect

Started by
1 comment, last by Zakwayda 13 years, 11 months ago
Hi there! I've got a function that moves an object by a specified distance (moveAmt), at a speed of moveX, moveY, moveZ. I'd like to apply a sine effect to the movement. You know, starts out moving slowly, speeds up toward the middle, and slows down when reaching the destination. Given an internal game clock of 60Hz, how can I determine how much to modify useMoveX,useMoveY,useMoveZ at a particular tick during the movement? Or maybe I should always set the position relative to the origX,origY,origZ. I'm cool with either way, but don't know how to calculate. :) Assume that the game clock starts at counter 0 when this function is first run. Any ideas would be really helpful. Thanks so much!

//
// Move
//
// Moves an object in a specified direction
// by a specified distance, at a specified speed
//
// 0 - Move amount
// 1 - move X (per tic)
// 2 - move Y (per tic)
// 3 - move Z (per tic)
// 4 - tag of object to affect
// 5 - option:
//		1 - Use a sine effect
//
boolean Move(Object::object_t *obj, Object::object_t *hitobj, scriptparams_t *p)
{
#define moveAmt (p->numdata[0])
#define moveX (p->numdata[1])
#define moveY (p->numdata[2])
#define moveZ (p->numdata[3])
#define tag (p->numdata[4])
#define sine (p->numdata[5])
#define origX (p->numdata[8])
#define origY (p->numdata[9])
#define origZ (p->numdata[10])
#define first (p->numdata[11])

	Object::object_t *object;

	object = GetObjectFromParamTag(obj, hitobj, (int)tag);

	if (!object)
		return true;

	// On first run, record our original position
	// so we know when we've gone far enough.
	if (first == 0.0f)
	{
		first = 1.0f;
		origX = object->x;
		origY = object->y;
		origZ = object->z;
	}

	float useMoveX = moveX;
	float useMoveY = moveY;
	float useMoveZ = moveZ;

	// Move using a sine effect,
	// making it more smooth
	if (sine == 1.0f)
	{
		// Here, we want to clamp
		// the tics of our movement
		// to a 0-180 range.
		// But since the movement is going to be altered
		// with a sine movement, how do we figure out
		// how long it's going to take??
	}

	Blockmap::UnSetThingPosition(obj);
	object->x += useMoveX;
	object->y += useMoveY;
	object->z += useMoveZ;

	float dist = U_GetDistance(origX, origY, origZ, object->x, object->y, object->z);
	boolean result = false;

	// We've gone far enough, so snap to our destination
	if (dist > moveAmt)
	{
		Vector::vector_t finalPos;
		Vector::Load(&finalPos, moveX, moveY, moveZ);
		Vector::Normalize(&finalPos);
		Vector::Mul(&finalPos, moveAmt);

		object->x = origX + finalPos.x;
		object->y = origY + finalPos.y;
		object->z = origZ + finalPos.z;
		result = true;
	}

	Blockmap::SetThingPosition(object);
	return result;
#undef moveAmt
#undef moveX
#undef moveY
#undef moveZ
#undef tag
#undef sine
#undef origX
#undef origY
#undef origZ
#undef first
}
Advertisement
Hi,

If you want the object to move in a sinusoidal path, just set the object's position to a given sample. E.g., for 70 frames, a full sine wave displacing [-1,1]:
X(frame) = sin(2.0*pi*(frame/70.0))

If you want to do this by altering the object's speed, take the derivative of X(frame) with respect to frame:
V(frame) = (1.0/35.0)*pi*cos(2.0*pi*(frame/70.0))

Sine and cosine are standard in basically any math library.

-G

[size="1"]And a Unix user said rm -rf *.* and all was null and void...|There's no place like 127.0.0.1|The Application "Programmer" has unexpectedly quit. An error of type A.M. has occurred.
[size="2"]

Quote:Original post by Geometrian
Hi,

If you want the object to move in a sinusoidal path, just set the object's position to a given sample. E.g., for 70 frames, a full sine wave displacing [-1,1]:
X(frame) = sin(2.0*pi*(frame/70.0))

If you want to do this by altering the object's speed, take the derivative of X(frame) with respect to frame:
V(frame) = (1.0/35.0)*pi*cos(2.0*pi*(frame/70.0))

Sine and cosine are standard in basically any math library.

-G
I think the OP is asking how to implement an 'ease in, ease out' animation effect rather than how to move an object along a sinusoidal path. (If I'm wrong about that, please ignore the rest of this post :)

@The OP: Say you have a starting point, a unit-length direction vector, a distance to be traveled, and a time interval in which to travel that distance.

One way to move an object to the goal with linear speed would be as follows (pseudocode typed into post, so no guarantee of correctness):
elapsed_time += time_step; // time_step would be 1/60 in your casefloat t = elapsed_time / travel_time;if (t >= 1) {    t = 1;    arrived_at_destination = true;}position = start_position + direction * travel_distance * t;
To get the 'sine effect' to which you refer, simply add the following lines (in bold):
float t = elapsed_time / travel_time;t = sin(-pi_over_2 + t * pi);t = .5 + t * .5;
This is an example of an 'ease in, ease out' function (you can find other, similar 'ease' functions if you look around online a bit).

This topic is closed to new replies.

Advertisement