Sign in to follow this  
Attala101

Sprite movement

Recommended Posts

Hi I've googled around to find information about sprite movement. I'm now able to do just about everything I could want with my sprites, but one problem eludes me. I cannot get the sprite to move in the direction it is "facing". Ok, I've made some testcode to make the sprite rotate and face the mousecursor when it moves around. This works like a charm, but now I want it to move towards the mousecursor. Here's the code i use to rotate:
float x = (sprTestSprite->XPOS + (sprTestSprite->width / 2)) , y = (sprTestSprite->YPOS + (sprTestSprite->height / 2)), x2, y2, x3, y3;

		POINT lpPoint;
		GetCursorPos(&lpPoint);
		x2 = lpPoint.x;
		y2 = lpPoint.y;

		x3 = (x2 - x);
		y3 = (y2 - y);

		
		float radians = atan2(x3, y3);

		sprTestSprite->desiredangle = D3DXToDegree(radians);
		sprTestSprite->angledegrees = D3DXToDegree(sprTestSprite->angle);

		float difference;

			difference = (180 - sprTestSprite->desiredangle);
	
		if(sprTestSprite->angledegrees < difference)
		{
		sprTestSprite->angle += 0.001 * Mtimer->DTime();
		}
		if(sprTestSprite->angledegrees > difference)
		{
		sprTestSprite->angle -= 0.001 * Mtimer->DTime();
		}
		
		sprTestSprite->SetPos(sprTestSprite->XPOS, sprTestSprite->XPOS);
		sprTestSprite->Drawtransformed(sprTestSprite->fXscale, sprTestSprite->fYscale, sprTestSprite->opacity, sprTestSprite->angle);

I've learned from googling that I should do something like: position += direction * speed * time_step. So I tried:
sprTestSprite->XPOS += (0.01 * Mtimer->DTime()) * cosf(sprTestSprite->angle);
sprTestSprite->YPOS += (0.01 * Mtimer->DTime()) * sinf(sprTestSprite->angle);

This did not give the desired effect at all :) I've tried both radians and degrees in the last mentioned code, but nothing has come close. The sprite reacts to the cursors position, but does not close the distance between them. Can anybody see what is wrong with my code? The "difference" variable is there to make sure the sprite knows that 0 degrees is up and 180 degrees is down. A

Share this post


Link to post
Share on other sites
Quote:
The sprite reacts to the cursors position, but does not close the distance between them.


If I understand this correctly, then what you're missing is calculating the velocity at which the sprite is moving at.

Here's some code (C# and made for PDA's, sorry :D):


public class Ball : Sprite
{
private float yVel = 0.0f;
private float xVel = 0.0f;

private float accelX = 0.0f;
private float accelY = 0.0f;

public Ball(Display display)
: base(display)
{
// not important ...
}

public void UpdateMovement(Point target)
{
if (this.Contains(target.X, target.Y))
return;

this.Top += yVel;
this.Left += xVel;

xVel += accelX;
yVel += accelY;

xVel *= 0.8f;
yVel *= 0.8f;
}

// getters/setters for each member
// ...
}







public void NewTarget(Point p)
{
target = p;

// Calculate deltas (used later for the Atan2 function)
float dX = (float)p.X - (ball.Left + (ball.Surface.Width / 2));
float dY = (float)p.Y - (ball.Top + (ball.Surface.Height / 2));

// Calculate angle in degrees
ball.AccelerationX = (float)Math.Cos(Math.Atan2(dY, dX));
ball.AccelerationY = (float)Math.Sin(Math.Atan2(dY, dX));
}





How this code is used:

Each frame, I call UpdateMovement from the ballsprite, and pass the target member. The target is set each time the stylus hits the screen by calling NewTarget and thereby also setting the sprites' direction. Im sure you can make this work for the mouse cursor instead :)

The speed the ball will travel at is determined by the amount you lessen the velocity with each UpdateMovement call, in this case 0.8.

Good luck :)

Share this post


Link to post
Share on other sites
Thanks for your reply.

I think maybe I wasn't clear enough in my first post. The sprite does move, but not necessarily in the direction of the mousecursor. (Follows its own strange pattern).

The sprite is supposed to have a fixed velocity, 0.01 pixel pr. millisecond, (which is used in the movement code I've tried). There is no acceleration involved.

Your movement code:
Quote:

ball.AccelerationX = (float)Math.Cos(Math.Atan2(dY, dX));
ball.AccelerationY = (float)Math.Sin(Math.Atan2(dY, dX));

...looks a lot like mine from where I'm sitting. I can't understand why mine is not working.

A

Share this post


Link to post
Share on other sites
sprTestSprite->SetPos(sprTestSprite->XPOS, sprTestSprite->XPOS);


Do you really want to call Set pos with sprTestSprite->XPOS used for both arguments, or should the second one be sprTestSprite->YPOS ?

Share this post


Link to post
Share on other sites
Quote:

Do you really want to call Set pos with sprTestSprite->XPOS used for both arguments, or should the second one be sprTestSprite->YPOS ?


Good point :) Yes, the second one is supposed to be sprTestSprite->YPOS. (I must be blind :))

After correcting this the sprite does not move right though. Now it moves in a circular notion around the cursor, like the angle of movement is 90 degrees off or something. I guess I can hardcode my way out of this, but I wish I understood why my code behaves like this.

Thanks for your help.

A

Share this post


Link to post
Share on other sites
Hehe - X and Y look almost the same, could have happened to anyone.

I'm suprised it still doesn't work, but I'm not exactly sure what you're trying to do. Can you post a screen shot and maybe draw an arrow point where it should move as opposed to where does move? The way you handle your angles isn't the way I'd do it, but I'm not exactly sure what you're trying to accomplish. Do you want it to turn and head straight towards the mouse cursor?



Share this post


Link to post
Share on other sites
Quote:
Original post by Attala101
Quote:

Do you really want to call Set pos with sprTestSprite->XPOS used for both arguments, or should the second one be sprTestSprite->YPOS ?


Good point :) Yes, the second one is supposed to be sprTestSprite->YPOS. (I must be blind :))


Uh... does that actually *do* anything, anyway (assuming SetPos does what it sounds like)? :s

Share this post


Link to post
Share on other sites
Quote:
Original post by syph
Hehe - X and Y look almost the same, could have happened to anyone.

I'm suprised it still doesn't work, but I'm not exactly sure what you're trying to do. Can you post a screen shot and maybe draw an arrow point where it should move as opposed to where does move? The way you handle your angles isn't the way I'd do it, but I'm not exactly sure what you're trying to accomplish. Do you want it to turn and head straight towards the mouse cursor?


Oh, didn't see that someone had answered :)

I'm still having problems with this. I tried hardcoding the angles and movement and it worked up to a certain point :) When it was time to implement a particle engine, things didn't work so well after all, so I went back to my original rotation/move-code.

This is what my last attempt looks like:

float x = sprTestSprite->XPOS , y = sprTestSprite->YPOS, x2, y2, x3, y3;

POINT lpPoint;
GetCursorPos(&lpPoint);
x2 = lpPoint.x;
y2 = lpPoint.y;

x3 = (x2 - x);
y3 = (y2 - y);

float radians = atan2(x3, y3);

sprTestSprite->desiredangle = D3DXToDegree(radians);
sprTestSprite->angledegrees = D3DXToDegree(sprTestSprite->angle);

sprTestSprite->XPOS += cosf(sprTestSprite->angledegrees) * 0.09 * Mtimer->DTime();
sprTestSprite->YPOS += sinf(sprTestSprite->angledegrees) * 0.09 * Mtimer->DTime();

if((180 - sprTestSprite->desiredangle) > sprTestSprite->angledegrees)
{
sprTestSprite->angledegrees += 0.1 * Mtimer->DTime();
}
if((180 - sprTestSprite->desiredangle) < sprTestSprite->angledegrees)
{
sprTestSprite->angledegrees -= 0.1 * Mtimer->DTime();
}

sprTestSprite->angle = D3DXToRadian(sprTestSprite->angledegrees);

sprTestSprite->SetPos(sprTestSprite->XPOS, sprTestSprite->YPOS);
sprTestSprite->Drawtransformed(sprTestSprite->fXscale * RESOLUTIONX, sprTestSprite->fYscale * RESOLUTIONY, 255, sprTestSprite->angle, false);



Now the sprite moves in the general direction of the cursor, but it seems to miss more or less depending on the angle its traveling. And it also stays in one spot and "stutter" while it rotates to the desired angle.

Can anybody see what I'm doing wrong here?

Quote:
Original post by Zahlman
Uh... does that actually *do* anything, anyway (assuming SetPos does what it sounds like)? :s


Not sure what you are saying here. The SetPos memberfunction tells the sprite its position. (Should have been included in the Drawtransformed function though).

A

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this