Advertisement

Help with Missile Command

Started by July 18, 2017 04:28 AM
43 comments, last by Glydion 7 years, 4 months ago
On 7/18/2017 at 0:28 AM, Glydion said:

Game.cpp



void Game::Update(float delta)
{
    // Game logic

    // Input, get mouse position to determine
    // the cannon pipe's angle for rendering
    int mX, mY;
    SDL_GetMouseState(&mX,&mY);

    // Create the target vector, normalize it
    // and pass it to the cannon to set the
    // current angle
    target = new Vector2(mX,mY);
    SetCannonAngle( target );

    ...
}

void Game::SetCannonAngle( Vector2* theVector )
{
    // Calculate arc tangent between the
    // the mouse's position and the center
    // axis of the cannon and convert to degrees

    double theAngle = atan2( theVector->x, theVector->y );
    theAngle = ConvertDegrees(theAngle);
    cannon->angle = theAngle;
}

double Game::ConvertDegrees(double radians)
{
    // Convert the angle from radians to
    // degrees and return the value
    return radians * ( 180 / 3.141592653589793238 );
}

 

 

Looks like you're assuming the cannon is at the world origin. You want to know the angle between the cannon and the mouse cursor, but you're testing the angle between the world origin and the mouse cursor. Subtract the cannon's position from "theVector" to get the displacement vector.

Additionally, you should store your conversion constants in variables or macros to prevent unnecessary arithmetic. Eg.


#define	MATH_180_OVER_PI	(57.295779513082320876798154814105f)
#define	MATH_PI_OVER_180	(0.01745329251994329576923690768489f)
#define	RAD_TO_DEG(rad)		(rad*MATH_180_OVER_PI)
#define	DEG_TO_RAD(deg)		(deg*MATH_PI_OVER_180)

 

Hi cmac,

Hmm, when you say "world origin", do you mean the video screen?

Yeah, I set the cannon position with a hardcoded x and y to denote where it is showing on the video screen, is that what you mean?

Hmm, I haven't tried subtracting theVector from the cannon position before calling atan2.

I will try that, thank you.

Macros sounds like a great idea, I will add more to it.

Advertisement

World origin is wherever (0,0) is in your window, which is typically the topleft or bottomleft corner. This is why your cannon is only rotating to the right - it's impossible for the cursor to be left of the world origin (assuming your camera is static).

Imagine an arrow extending from the bottom-left corner of your screen that ends at the mouse cursor. Your cannon is accurately being set to that angle, it's just not the angle you want. Subtracting a source point from a destination point is how you can calculate the displacement between two points, so that's the angle you'll want to use in this case (cursor - cannon = vector that extends from cannon to cursor).

 

 

Ohhhh that makes a lot more sense after seeing someone explaining it.

Yes, in my program (0,0) is in the top-left, that's right.  And yes the camera is static for this basic game.

To be honest, it never occurred to me that the cannon was trying to rotate about the world origin, which explains why it never turned "left" into negative space as it was impossible to reach it with the way I set up my logic.

So I'll set a new variable that calculates the angle between the cannon and cursor and then call atan2 to see what I get.

I'll keep you guys posted on the results.  Thanks again.

Note too that you'll need to invert y when you pass it in to atan2 since trig functions assume a bottom-left origin, and SDL uses top-left.

Invert?  Okay, so if the Y is negative, make it positive and vice versa?

Advertisement

 

f you want to go completely overboard, you may want use a rotation matrix like in my code below.

Mine is 3d and my current "exercise" is to build an algorithm that gives you the approriate rotation matrix for rotation around an arbitrary vector, but since your game is 2d you can do it with a 2x2 matrix I think (you just have to remove those row and column full of 0 from mine I think) and the formula also won't change since you're always rotating around the same vector so no extra work required xD

You would just need to implement vector*matrix multiplication which can be learned in 10 min from a random youtube video, but probably all this is only adding to problems, so ignore me :D


	//bottom left and top right points of a square
	Vector p1 = { -1, 0, -1 };
	Vector p2 = { 1, 0, 1 };

	//desired rotation angle from degree to radians
	double a = toRad(-30);
	
	//Hardcoded 3x3 matrix for rotation around Y axis
	Matrix R(3, 3, 
			{ cos(a), 0, -sin(a),
			
		     	   0    , 0,    0,

		          sin(a), 0,   cos(a) });
	//Rotation test -30° around Y axis
	//If correct, the new points will be:
	// p1 = {-0.36, 0 , -1.36}
	// p2 = {0.36, 0 , 1.36}
	//Write algorithm for rotation around an arbitrary axis


	p1 = p1*R;
	p2 = p2*R;

	cout << "p1: " << p1 << endl;
	cout << "p2: " << p2 << endl;

output:

Quote

p1: x,y,z{-0.366025, 0, -1.36603} 
p2: x,y,z{0.366025, 0, 1.36603} 

 

Hey Marcus, 

 

That matrix sounds like an interesting idea, but both you and cmac identified a grand problem with my logic, basically saying the same thing.

 

No matter how I call atan2 in my Game class, as long as I'm assuming that the cannon is in the world origin, the angling will never be what I'm expecting.

 

So after dinner, I'm going to calculate the dispersion between the cannon (I have to explicitly state it) and the current mouse position.

 

To my limited knowledge as a beginner so far, I believe this will rectify everything.

 

Wish me luck folks, I appreciate all the help.

SDL already does the rotation matrix math under the hood with RenderCopyEx from what I understand, but it's definitely worth understanding since you're doing this as an educational exercise.

You can invert a y-value by subtracting it from the screen height (both in screen coordinates) before converting to world coordinates. But if you're using a static camera you don't need to worry about screen->world conversions for now.

Hey guys,

Just wanted to update you on the posting.

Yesterday was pretty hectic so I never got around to working on my game last night, apologies.

So I'll be cranking away at it tonight.  I'll post new code snippets here to show you what has changed in my original code.

Be back in a bit.

This topic is closed to new replies.

Advertisement