views:

198

answers:

5

I am trying to make the game Asteroids. My issue I have right now, is if you press the UP Arrow key, it will move the "ship" 10 pixels up. And if you hit the LEFT Arrow key, it will turn the "ship" 5 degrees to the left, the issue I have comes into play when you turn left, or right. And then try to move up. It won't move into the turned direction. It will just move the turned "ship" 10 degrees in the Y direction.

What I am thinking of doing is having a variable called direction, think of this variable as a circle with 360 degrees. What I am trying to do is everytime I hit the Left Arrow, it will subtract 5 from direction, which started at 0 and goes backwards from 360 and thus set it to 355. I would then divide 355 by 10 and get 35.5. Then I would divide 10 by 35.5 and get .355. I would then subtract .355 from 10 (moving up in the Y). And subtract it from 0 (moving left in the X). So I would be moving 9.645 up in the Y and moving 0.355 left in the X.

The issue I'm having is the "ship" in Asteroids I have is a Graphics.FillPie, which needs Ints to use as the Start Angle and Sweep angle, However as you can see I would have to be working with doubles or floats. I'm pretty sure I'm overcomplicating this and am pretty sure there is something 100 times simpler, I'm thinking something along the lines of Bresenham's Line Algorithm. If anyone could help by suggesting something easier or a fix to my problem, it would be much appreciated. Thanks in advance.

+1  A: 

I don't want to take your fun away, but you can always download someone else's code and look at it to figure out how to do it in your own. You can get one implementation here: http://www.c-sharpcorner.com/UploadFile/dannaboneheart/Asteroids11292005064500AM/Asteroids.aspx

ans here: http://www.codeproject.com/KB/game/hucsharpasteroids.aspx

David Stratton
+1  A: 

There is no problem using floats internally and converting them to ints when you need to use them that way:

double angle = ...;
int angleAsInt = (int)Math.Round(angle);

I suggest you look into using trigonometric functions like sin and cos for determining the X and Y components of velocities and accelerations.

Kristopher Johnson
A: 

What I am thinking of doing is having a variable called direction, think of this variable as a circle with 360 degrees. What I am trying to do is everytime I hit the Left Arrow, it will subtract 5 from direction, which started at 0 and goes backwards from 360 and thus set it to 355. I would then divide 355 by 10 and get 35.5. Then I would divide 10 by 35.5 and get .355. I would then subtract .355 from 10 (moving up in the Y). And subtract it from 0 (moving left in the X). So I would be moving 9.645 up in the Y and moving 0.355 left in the X.

So if the direction is 270, you will move 9.730 up in the Y direction and 0.270 in the X direction? I think your algorithm is broken. Try using trigonometry.

Brian
+2  A: 

You're over thinking it. ;> Just use matrix transforms to rotate and move the ship. When the ship is pointed "northwest" and the user pushes the UP key, you adjust the ship's translation matrix by 10 units in the ship's Y axis. You apply the rotation and translation matrixes to convert the ship's coordinate system to the screen coordinate system. Order of operations is critical - if you apply translation before rotation, the ship will go swinging around a center point instead of rotating around the ships origin and then translating to its new "forward" direction.

Since you can use the same matrix transforms for drawing, you can just draw the ship in the same fixed orientation (nose pointing "up" the positive Y axis) relative to its local coordinate system. The rotation of the image will be taken care of by the matrix transform.

dthorpe
+1 though this solution is more complex, it will make the transition to 3D games a lot easier. Note that the matrices will have a lot of zeros and transforms will in one way or another result in the exact same simple equations as listed in the accepted solution.
m_oLogin
Well, this approach requires/assumes that you have a good transformation engine available in whatever framework or environment you're working in. If you have to implement everything from scratch, it would be quicker to directly calc the rotations yourself (as in other answers) than to implement your own world transform layer. But if you have a good transform stack already (as in WinGDI, DirectX, OpenGL), dealing with (moving, drawing) the ship relative to its own cordinates is much easier, IMO. Everything is relative to something. Ender Wiggin's orientation rule: "The enemy's gate is down".
dthorpe
+11  A: 

It sounds like you need to calculate heading vectors for the ship based on the its current orientation in radians. For example:

double xVector = Math.Sin(orientationInRadians);
double yVector = Math.Cos(orientationInRadians);

Then use the left and right arrows to control the ship's current orientation. Once you have the vector you can calculate the location of the ship that is 10 units away from its current position along the heading vector. First you need to scale the vector to a unit (length of 1) vector.

double magnitude = sqrt(xVector*xVector + yVector*yVector);
double unitVectorX = xVector/magnitude;
double unitVectorY = yVector/magnitude;

Now you have a vector that is 1 unit long but still points in the ship's current orientation. Next move the ship with positionX and positionY as current its coordinates.

double distanceToTravel = 10;
double newPositionX = positionX + unitVectorX*distanceToTravel;
double newPositionY = positionY + unitVectorY*distanceToTravel;

You'll want to track the ship's position and orientation with doubles or floats even if you end up rendering with a system that only allows ints. You shouldn't store the current position and orientation using the rendering engine's precision or you will start to see strange jumps and pauses as you move and rotate. Also, using the above you can make distanceToTravel non-constant (imagine accelerating while the key is pressed instead of moving a fixed distance from a key press).

Peter
+1 for mentioning trigonometry as a way to calculate orientation.
Brian
Beat me to it :)+1 For simplicity and yay for vectors.
bearcdp
Am I missing something or is 'magnitude' always going to be 1? Math.Sin and Math.Cos certainly return values on the unit circle, don't they?
dash-tom-bang
@dash-tom-bang - you are correct, in this case that magnitude portion is unnecessary.
Peter
I've always used something like `newPositionX = positionX + Math.Sin(orientationInRadians)*distanceToTravel;` worked the exact same way.
Ivo Wetzel
Thanks for this, I'll see if I can get it to work :)
Cistoran