Question

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.

Was it helpful?

Solution

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).

OTHER TIPS

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.

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

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.

One thing you haven't yet mentioned is that in the Asteroids(R) brand arcade machine and video games derived therefrom, the player's ship has inertia. Consequently, you need to keep track of the ship's velocity. Each frame you should do something like:

if (thrusting)
{
  XVelocity += (XVelocity - Math.Cos(Heading)*MAX_SPEED) * (1/INERTIA_CONSTANT);
  YVelocity += (YVelocity - Math.Sin(Heading)*MAX_SPEED) * (1/INERTIA_CONSTANT);
}
else
{
  XVelocity -= XVelocity * (1/FRICTION_CONSTANT);
  YVelocity -= YVelocity * (1/FRICTION_CONSTANT);
}

XPosition += XVelocity; // Do twice--once before and once after speed adjust
YPosition += YVelocity;

Note that some games simply add to the velocity some constant times the cosine/sine. Doing that will have the unfortunate consequence that if a player points his ship in some direction and starts thrusting continuously, the distance traversed by the ship each frame may grow to absurd limits. The code as shown will cause the acceleration to diminish as the ship's velocity asymptotically approaches the maximum.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top