Advertisement

rotate a sprite

Started by July 16, 2020 02:33 AM
15 comments, last by Alberth 4 years, 4 months ago

I am still working on a slot car simulation game. I have got the car to move up the track to the bend in the track. My question is how do I get the car sprite to move around the bend in the track while the sprite rotates from going up to going to the left. my code moves the center of the sprite in a curve like fashion but it does not rotate the sprite. I am using the sin and cos functions. here is the code I am working with.

void rotateSprite()
{
	x = cos(i);
	y = sin(i);

	i += PI / 16.0f;

	if (i >= PI / 2.0f)
	{
		i = PI / 2.0f;
	}
}

void move_up(int val)
{
	up+=5.0f;
	if (up >= 70.0f)
	{
		up = 70.0f;
		rotateSprite();
	}
	glutPostRedisplay();
	glutTimerFunc(500, move_up, 0);
}

void drawSlotcar()
{
	glEnable(GL_TEXTURE_2D);
	glPushMatrix();
	glBindTexture(GL_TEXTURE_2D, texture[0]);
	glTranslatef(20.0f, 0.0f, 0.0f);
	glBegin(GL_POLYGON);
	glTexCoord3f(0.0f, 0.0f, 0.0f);

	glVertex3f(5.0f+x, -10.0f+up+y, 0.0f);
	glTexCoord3f(1.0f, 0.0f, 0.0f);

	glVertex3f(5.0f+x, 10.0f+up+y, 0.0f);
	glTexCoord3f(1.0f, 1.0f, 0.0f);

	glVertex3f(-5.0f+x, 10.0f+up+y, 0.0f);
	glTexCoord3f(0.0f, 1.0f, 0.0f);

	glVertex3f(-5.0f+x, -10.0f+up+y, 0.0f);
	glEnd();
	glPopMatrix();
	glDisable(GL_TEXTURE_2D);
}

Start the other way around, and with paper and pencil.

Draw a car near the center on paper (doesn't need to be realistic, a rectangle is sufficient). With another sheet, draw a viewport (a bigger rectangle), and cut out that area.

Now put the hole on your car so you can see it, and mark the corners of the cut-out area on the paper with the car. Rotate the sheet with the hole, and do it again.

You can do it several times, or even all around, but the result is that you will get positions of the corners relative to your car sprite. If you keep the car in the center of the hole, you will find that all marked positions are at a circle from the center of the car.

Pick one of the sets of 4 corners, and draw that on the paper of the car. Now the question is, how do you compute those corners? Hint: Draw lines from the center to the corners. What are the angles of those lines?

Advertisement

Make your life easier by introducing complex numbers! No, really.

Instead of keeping track of coordinates with two numbers, (x,y), use a single complex number z = x+y*i. It doesn't look like we've gained much, but now there is a magical formula that says that multiplying z times (cos(alpha)+sin(alpha)*i) yields a point that is the rotation of z around the origin by an angle of alpha. Now, throw away the angle alpha, and think of rotations as being complex numbers with length 1.

In your current code, think of the four corners of your sprite as being z+v1, z+v2, z+v3 and z+v4. Now just take your rotation (remember, just a length-1 complex number) r and compute z+r*v1, z+r*v2, z+r*v3 and z+r*v4. Done.

I can post some code if that description is not clear enough.

@Alberth I did what you said to do, I hope I am correct. For a car at a 45 degree angle I get angles of 300 degrees, 330 degrees, 120 degrees and 150 degrees.

Good.

So how do you compute the position of those corner points? Those 4 points are the vertex corners at your car sprite for rotating the car. I do hope your car sprite is big enough, not sure what happens if a corner point is outside the sprite.

What you're doing now for 45 degrees needs to be done for every angle of the car that you want to show. You can do this manually for each angle, which is quite feasible if there are only a few angles you want to display.

If you have many angles, or when you are lazy and don't want to do the manual work, you need to find a relation between your ‘45’ of the car, and the corner angles. In other words, if you don't have 45, but for example 55 (10 degrees more), what are the corner angles then? From that result, can you predict what will be the result for a car rotated 65 degrees? and 100? and 180?

When you can do that, what's the general formula if you have a ‘car_rotation’ variable?

@Alberth well here is my angles and car rotation

car rotation 0 45 90

angle 1 120 150 150

angle 2 60 120 30

angle 3 240 300 210

angle 4 300 300 330

I am trying to notice a pattern but I am still not seeing it yet.

Advertisement

I don't see it either, it's weird, you would expect an equal amount of increase in angles everywhere wouldn't you? Perhaps it is because you wrap around at 360 degrees. Another option is that you made an error somewhere and switched some angles at some point by accident.

To get a better chance at a pattern you could try making much smaller steps, eg 5 or 10 degrees increment. Then angles don't jump so much. Also, computing just 1 angle is sufficient for each car rotation to see a pattern.

Instead of trying to find a pattern, the other option is to accept the values as they are, and build a lookup table (I am assuming you use C++), so you can actually see stuff.

static const float angle1[] = {120f, 150f, 150f};
static const float angle2[] = {60f, 120f, 30f};
static const float angle3[] = {240f, 300f, 210f};
static const float angle4[] = {300f, 300f, 330f};

int car_orientation = 0; // 0=0 degrees, 1=45 degrees, 2=90 degrees
float cx = 0.5f; // center horizontal position of the car sprite.
float cy = 0.5f; // center vertical position of the car sprite.
float length = ...; // distance between (cx, cy) and a vertex corner position.

// first vertex
float x1 = cx + length * cos(deg_to_rad(angle1[car_orientation]));
float y1 = cy + length * sin(deg_to_rad(angle1[car_orientation]));

// second vertex
float x2 = cx + length * cos(deg_to_rad(angle2[car_orientation]));
float y2 = cy + length * sin(deg_to_rad(angle2[car_orientation]));

// and so on for the other vertices

// then draw the sprite to check if the angles are correct.

Code is far from optimal, but you have variables for all the various key points, so it's easy to modify and experiment.

For production, it's better to fold the ‘deg_to_rad’ conversion into the table.

Eventually, you may like to stop using degrees and use radians by default everywhere. Radians are the better way to express angles in math, it's just that we all ran into degrees first, so we see radians as weird, and degrees as normal. If you switch however you will quickly catch on to seeing 0.5*π as 90 degrees etc, it's just a matter of getting used to it.

I would expect that some orientations will look wrong, but at least by displaying them, you can actually see what you're doing, and correct the faulty entries.

well I stubbed out some code and a screen shot of the output. I am looking for a pattern.

https://imgur.com/y8FtQnm

#include<iostream>
#include<math.h>

using namespace std;

const float PI = 3.1415926;

int main()
{
	static const float angle1[] = { 2.0f*PI / 3.0f,5.0f*PI / 6.0f,5.0f*PI / 6.0f };
	static const float angle2[] = { PI / 3.0f,2.0f*PI / 3.0f,PI / 6.0f };
	static const float angle3[] = { 4.0f*PI / 3.0f,5.0f*PI / 3.0f,7.0f*PI / 6.0f };
	static const float angle4[] = { 5.0f*PI / 3.0f,5.0f*PI / 3.0f,11.0f*PI / 6.0f };

	int car_orientation = 0;
	float cx = 5.0f;
	float cy = 10.0f;
	float length = sqrt((5.0f - 0.0f)*(5.0f - 0.0f) + (10.0f - 0.0f)*(10.0f - 0.0f));

	float x1 = cx + length * cos(angle1[car_orientation]);
	float y1 = cx + length * sin(angle1[car_orientation]);

	float x2 = cx + length * cos(angle2[car_orientation]);
	float y2 = cx + length * sin(angle2[car_orientation]);

	float x3 = cx + length * cos(angle3[car_orientation]);
	float y3 = cx + length * sin(angle3[car_orientation]);

	float x4 = cx + length * cos(angle4[car_orientation]);
	float y4 = cx + length * sin(angle4[car_orientation]);

	cout << "x1: " << x1 << " y1: " << y1 << endl;
	cout << "x2: " << x2 << " y2: " << y2 << endl;
	cout << "x3: " << x3 << " y3: " << y3 << endl;
	cout << "x4: " << x4 << " y4: " << y4 << endl;

	cout << endl;
	car_orientation = 1;
	x1 = cx + length * cos(angle1[car_orientation]);
	y1 = cx + length * sin(angle1[car_orientation]);

	x2 = cx + length * cos(angle2[car_orientation]);
	y2 = cx + length * sin(angle2[car_orientation]);

	x3 = cx + length * cos(angle3[car_orientation]);
	y3 = cx + length * sin(angle3[car_orientation]);

	x4 = cx + length * cos(angle4[car_orientation]);
	y4 = cx + length * sin(angle4[car_orientation]);

	cout << "x1: " << x1 << " y1: " << y1 << endl;
	cout << "x2: " << x2 << " y2: " << y2 << endl;
	cout << "x3: " << x3 << " y3: " << y3 << endl;
	cout << "x4: " << x4 << " y4: " << y4 << endl;

	cout << endl;
	car_orientation = 2;
	x1 = cx + length * cos(angle1[car_orientation]);
	y1 = cx + length * sin(angle1[car_orientation]);

	x2 = cx + length * cos(angle2[car_orientation]);
	y2 = cx + length * sin(angle2[car_orientation]);

	x3 = cx + length * cos(angle3[car_orientation]);
	y3 = cx + length * sin(angle3[car_orientation]);

	x4 = cx + length * cos(angle4[car_orientation]);
	y4 = cx + length * sin(angle4[car_orientation]);

	cout << "x1: " << x1 << " y1: " << y1 << endl;
	cout << "x2: " << x2 << " y2: " << y2 << endl;
	cout << "x3: " << x3 << " y3: " << y3 << endl;
	cout << "x4: " << x4 << " y4: " << y4 << endl;

	system("pause");
	return 0;
}

Since the input angles that you found don't have a pattern, I wouldn't expect the coordinates to be much better.

I don't know if you saw anything, but x3/y3, and x4/y4 with car-orientation 1 are at the same spot, so that's definitely not a rectangle.

actually they make a rectangle there is a bug in the code.

This topic is closed to new replies.

Advertisement