I'm making an asteroids clone game, using GDI+ in C#. I don't understand why the asteroids wont move. They are supposed to rotate based on a member indicating rotation angle, and move in a direction based off of a member that indicates movement angle. But they don't do anything at all! It doesn't make any sense, because the space ship and the bullets work perfectly fine!! And they are more complex than the asteroids! I must have missed something somewhere in the code, hopefully someone is willing to look through it and help me find my problem :) . I should mention, the entire game is driven off of a 60ms timer which raises the event timer1_Tick().
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;
namespace Space
{
public partial class Form1 : Form
{
#region structs
struct Bullet
{
public Point pnt;
public double dBulletAngle;
public double dBulletVel;
public int iTick;
public Bullet(Point point, double dA, double dV)
{
pnt = new Point(point.X, point.Y);
dBulletAngle = dA;
dBulletVel = dV;
iTick = 0;
}
public void Clear()
{
pnt = new Point();
dBulletAngle = 0;
dBulletVel = 0;
iTick = 0;
}
};
public struct Asteroid
{
public enum Size { Huge, Medium, Small, Tiny };
public GraphicsPath _gp;
public double _dX;
public double _dY;
public double _dMovementAngle;
public double _dRotationAngle;
public Size _size;
public double _dVel;
public void TickAngle()
{
_dRotationAngle += 0.2;
if ((_dRotationAngle > Math.PI * 2 ))
_dRotationAngle = 0;
if (_dRotationAngle < -0.01)
_dRotationAngle = 0;
}
public void SetX(double X)
{
_dX = X;
}
public void SetY(double Y)
{
_dY = Y;
}
public Asteroid(GraphicsPath gp,double dX, double dY, double dMA, double dRA, Size sz)
{
_dX = dX;
_dY = dY;
_gp = gp;
_dMovementAngle = dMA;
_dRotationAngle = dRA;
_size = sz;
_dVel = 0.5;
}
}
#endregion
#region members
const int MAX_BULLETS = 15;
const int BULLET_DISTANCE = 10;
const int BULLET_TICKS = 50;
int iSpaceYAccel = 1,
iSpaceYVel = 0;
const int iMaxYVel = 15;
const double BULLET_VEL = iMaxYVel * 1.5;
double dShipAngle = 0,
dAngularVelocity = Math.PI / 32,
dShipX = 125,
dShipY = 125;
bool bKeyDown = false,
bKeyUp = false,
bKeyLeft = false,
bKeyRight = false,
bKeyFire = false;
Bullet[] Bullets = new Bullet[MAX_BULLETS];
List<Asteroid> Asteroids = new List<Asteroid>();
int iActiveBullets = 0;
#endregion
public Form1()
{
InitializeComponent();
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
dShipX = this.ClientRectangle.Width / 2;
dShipY = this.ClientRectangle.Height / 2;
InitNewAsteroids();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
DrawGame(ref e);
}
void InitializeBoundary(ref GraphicsPath gpBoundary)
{
gpBoundary.AddRectangle(new Rectangle(this.ClientRectangle.Left - 25,
this.ClientRectangle.Top - 25,this.Width+ 25, this.Height + 25));
}
public Asteroid.Size GetRandomSize()
{
Random rand = new Random();
switch (rand.Next(4))
{
case 0:
return Asteroid.Size.Huge;
case 1:
return Asteroid.Size.Medium;
case 2:
return Asteroid.Size.Small;
case 3:
return Asteroid.Size.Tiny;
default:
return Asteroid.Size.Tiny;
}
}
public int GetSize(Asteroid.Size _size)
{
switch (_size)
{
case Asteroid.Size.Huge:
return 50;
case Asteroid.Size.Medium:
return 40;
case Asteroid.Size.Small:
return 20;
default:
return 10;
}
}
void InitializeShipGraphics(ref GraphicsPath gpSpaceShip)
{
Point[] pntSpaceShip = new Point[3];
pntSpaceShip[0].X = -15;
pntSpaceShip[1].X = 15;
pntSpaceShip[2].X = 0;
pntSpaceShip[0].Y = 15;
pntSpaceShip[1].Y = 15;
pntSpaceShip[2].Y = -15;
gpSpaceShip.AddPolygon(pntSpaceShip);
}
void InitNewAsteroids()
{
Random rand = new Random();
Asteroids.Clear();
for (int i = 0; i < 8; i++)
{
GraphicsPath gp = new GraphicsPath();
Point[] pnts = new Point[8];
Asteroid.Size siz = new Asteroid.Size();
siz = GetRandomSize();
gp.AddEllipse(0, 0, GetSize(siz), GetSize(siz));
Asteroid asAst = new Asteroid(gp,
(double)rand.Next(ClientRectangle.Width),
(double)rand.Next(ClientRectangle.Height),
(double)rand.Next((int)((2 * Math.PI) * 100.0)) / 100.0,
(double)rand.Next((int)((2 * Math.PI) * 100.0)) / 100.0,
siz);
Asteroids.Add(asAst);
}
}
void InitAsteroids()
{
for (int i = 0; i < 8; i++)
{
Asteroids[i]._gp.Reset();
Asteroids[i]._gp.AddEllipse(0, 0, GetSize(Asteroids[i]._size), GetSize(Asteroids[i]._size));
}
}
void InitializeNewAsteroid(ref GraphicsPath gpAsteroid, Asteroid.Size sz)
{
Random rand = new Random();
Point[] pntAsteroid = new Point[8];
for (int i = 0; i < 8; i++)
{
pntAsteroid[i].X = GetSize(sz);
pntAsteroid[i].Y = GetSize(sz);
}
gpAsteroid.AddPolygon(pntAsteroid);
}
void UpdateAsteroids()
{
for (int i = 0; i < Asteroids.Count; i++)
{
Asteroids[i].TickAngle();
Asteroids[i].SetX(Asteroids[i]._dX + (
Math.Sin(Asteroids[i]._dMovementAngle) * Asteroids[i]._dVel));
Asteroids[i].SetY(Asteroids[i]._dY + (
Math.Cos(Asteroids[i]._dMovementAngle) * Asteroids[i]._dVel));
if (!(Asteroids[i]._dMovementAngle >= -0.03 && Asteroids[i]._dMovementAngle <= 0.03))
{
if (Asteroids[i]._dY < -15.0)
{
Asteroids[i].SetY((double)this.ClientSize.Height);
Asteroids[i].SetX((double)Math.Abs(this.ClientSize.Width * Math.Sin(Asteroids[i]._dMovementAngle)));
}
if (Asteroids[i]._dY > this.ClientSize.Height + 15.0)
{
Asteroids[i].SetY(0);
Asteroids[i].SetX((double)Math.Abs(this.ClientSize.Width * Math.Sin(Asteroids[i]._dMovementAngle)));
}
}
else
{
if (Asteroids[i]._dY < -15.0)
{
Asteroids[i].SetY((double)this.ClientSize.Height);
}
if (Asteroids[i]._dY > this.ClientSize.Height + 15.0)
{
Asteroids[i].SetY(0);
}
}
if (!((Asteroids[i]._dMovementAngle >= 1.5 - 0.1 && Asteroids[i]._dMovementAngle <= 1.5 + 0.1)
|| (Asteroids[i]._dMovementAngle >= -1.5 - 0.1 && Asteroids[i]._dMovementAngle <= -1.5 + 0.1)
|| (Asteroids[i]._dMovementAngle >= 4.7 - 0.1 && Asteroids[i]._dMovementAngle <= 4.7 + 0.1)
|| (Asteroids[i]._dMovementAngle >= -4.7 - 0.1 && Asteroids[i]._dMovementAngle <= -4.7 + 0.1)))
{
if (Asteroids[i]._dX < -15.0)
{
Asteroids[i].SetY((double)Math.Abs(this.ClientSize.Width * Math.Cos(Asteroids[i]._dMovementAngle)));
Asteroids[i].SetX((double)this.ClientSize.Width);
}
if (Asteroids[i]._dX > this.ClientSize.Width + 15.0)
{
Asteroids[i].SetY((double)Math.Abs(this.ClientSize.Width * Math.Cos(Asteroids[i]._dMovementAngle)));
Asteroids[i].SetX(0);
}
}
else
{
if (Asteroids[i]._dX < -15.0)
{
Asteroids[i].SetX((double)this.ClientSize.Width);
}
if (Asteroids[i]._dX > this.ClientSize.Width + 15.0)
{
Asteroids[i].SetX(0);
}
}
}
}
void DrawGame(ref PaintEventArgs e)
{
GraphicsPath gpSpaceShip = new GraphicsPath();
InitializeShipGraphics(ref gpSpaceShip);
InitAsteroids();
//some info in the title bar
this.Text = ((int)dShipX).ToString() + ", " + ((int)dShipY).ToString() + ": "
+ dShipAngle.ToString().Substring(0, dShipAngle.ToString().Length > 4 ? 4 :
dShipAngle.ToString().Length) + " rads @ "
+ iSpaceYVel.ToString() + " pixels per "
+ timer1.Interval.ToString() + "ms";
Pen p1 = new Pen(Color.White,3);
BufferedGraphicsContext bgc = new BufferedGraphicsContext();
BufferedGraphics bg1 = bgc.Allocate(e.Graphics, this.DisplayRectangle);
//erase the old space ship
//bg1.Graphics.DrawPath(new Pen(Color.Black, 3), gpSpaceShip);
bg1.Graphics.Clear(Color.Black);
Matrix matTrans = new Matrix();
matTrans.Translate((float)dShipX, (float)this.ClientRectangle.Height - (float)dShipY);
matTrans.RotateAt((float)((180 / Math.PI) * dShipAngle), new PointF(0, 5));
gpSpaceShip.Transform(matTrans);
bg1.Graphics.DrawPath(p1, gpSpaceShip);
for (int i = 0; i < iActiveBullets; i++)
{
bg1.Graphics.FillRectangle(Brushes.White, new Rectangle(new Point(Bullets[i].pnt.X, this.ClientRectangle.Height - Bullets[i].pnt.Y), new Size(4, 4)));
}
for (int i = 0; i < Asteroids.Count; i++)
{
Matrix matTrans2 = new Matrix();
matTrans2.Translate((float)Asteroids[i]._dX, (float)this.ClientRectangle.Height - (float)Asteroids[i]._dY);
matTrans2.Rotate((float)(Asteroids[i]._dRotationAngle * (180 / Math.PI)));
GraphicsPath tmp = new GraphicsPath();
tmp = (GraphicsPath)Asteroids[i]._gp.Clone();
tmp.Transform(matTrans2);
bg1.Graphics.DrawPolygon(p1, tmp.PathPoints);
}
bg1.Graphics.Flush();
bg1.Render();
}
void UpdateBullets()
{
for (int i = 0; i < iActiveBullets; i++)
{
Bullets[i].iTick++;
if (Bullets[i].iTick < BULLET_TICKS)
{
Bullets[i].pnt.X = (int)(Bullets[i].pnt.X +
Math.Sin(Bullets[i].dBulletAngle) * Bullets[i].dBulletVel);
Bullets[i].pnt.Y = (int)(Bullets[i].pnt.Y +
Math.Cos(Bullets[i].dBulletAngle) * Bullets[i].dBulletVel);
double dAngle = Bullets[i].dBulletAngle;
double dX = Bullets[i].pnt.X;
double dY = Bullets[i].pnt.Y;
if (!(dAngle >= -0.03 && dAngle <= 0.03))
{
if (dY < -15.0)
{
dY = this.ClientSize.Height;
dX = Math.Abs(this.ClientSize.Width * Math.Sin(dAngle));
}
if (dY > this.ClientSize.Height + 15.0)
{
dY = 0;
dX = Math.Abs(this.ClientSize.Width * Math.Sin(dAngle));
}
}
else
{
if (dY < -15.0)
{
dY = this.ClientSize.Height;
}
if (dY > this.ClientSize.Height + 15.0)
{
dY = 0;
}
}
if (!((dAngle >= 1.5 - 0.1 && dAngle <= 1.5 + 0.1)
|| (dAngle >= -1.5 - 0.1 && dAngle <= -1.5 + 0.1)
|| (dAngle >= 4.7 - 0.1 && dAngle <= 4.7 + 0.1)
|| (dAngle >= -4.7 - 0.1 && dAngle <= -4.7 + 0.1)))
{
if (dX < -15.0)
{
dY = Math.Abs(this.ClientSize.Width * Math.Cos(dAngle));
dX = this.ClientSize.Width;
}
if (dX > this.ClientSize.Width + 15.0)
{
dY = Math.Abs(this.ClientSize.Width * Math.Cos(dAngle));
dX = 0;
}
}
else
{
if (dX < -15.0)
{
dX = this.ClientSize.Width;
}
if (dX > this.ClientSize.Width + 15.0)
{
dX = 0;
}
}
Bullets[i].pnt.X = (int)dX;
Bullets[i].pnt.Y = (int)dY;
}
else
{
ClearBullets();
iActiveBullets = 0;
}
}
}
void ClearBullets()
{
for (int i = 0; i < MAX_BULLETS; i++)
{
Bullets[i].Clear();
}
}
private void timer1_Tick(object sender, EventArgs e)
{
MoveShip();
if (iActiveBullets != 0)
UpdateBullets();
UpdateAsteroids();
this.Refresh();
}
void MoveShip()
{
dShipY += (Math.Cos(dShipAngle) * iSpaceYVel);
dShipX += (Math.Sin(dShipAngle) * iSpaceYVel);
if (!(dShipAngle >= -0.03 && dShipAngle <= 0.03))
{
if (dShipY < -15.0)
{
dShipY = this.ClientSize.Height;
dShipX = Math.Abs(this.ClientSize.Width * Math.Sin(dShipAngle));
}
if (dShipY > this.ClientSize.Height + 15.0)
{
dShipY = 0;
dShipX = Math.Abs(this.ClientSize.Width * Math.Sin(dShipAngle));
}
}
else
{
if (dShipY < -15.0)
{
dShipY = this.ClientSize.Height;
}
if (dShipY > this.ClientSize.Height + 15.0)
{
dShipY = 0;
}
}
if (!((dShipAngle >= 1.5 - 0.1 && dShipAngle <= 1.5 + 0.1)
|| (dShipAngle >= -1.5 - 0.1 && dShipAngle <= -1.5 + 0.1)
|| (dShipAngle >= 4.7 - 0.1 && dShipAngle <= 4.7 + 0.1)
|| (dShipAngle >= -4.7 - 0.1 && dShipAngle <= -4.7 + 0.1)))
{
if (dShipX < -15.0)
{
dShipY = Math.Abs(this.ClientSize.Width * Math.Cos(dShipAngle));
dShipX = this.ClientSize.Width;
}
if (dShipX > this.ClientSize.Width + 15.0)
{
dShipY = Math.Abs(this.ClientSize.Width * Math.Cos(dShipAngle));
dShipX = 0;
}
}
else
{
if (dShipX < -15.0)
{
dShipX = this.ClientSize.Width;
}
if (dShipX > this.ClientSize.Width + 15.0)
{
dShipX = 0;
}
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Up || bKeyUp == true)
{
iSpaceYVel += iSpaceYAccel;
bKeyUp = true;
}
if (e.KeyCode == Keys.Down || bKeyDown == true)
{
iSpaceYVel -= iSpaceYAccel;
bKeyDown = true;
}
if (e.KeyCode == Keys.Right || bKeyRight == true)
{
dShipAngle += dAngularVelocity;
bKeyRight = true;
}
if (e.KeyCode == Keys.Left || bKeyLeft == true)
{
bKeyLeft = true;
dShipAngle -= dAngularVelocity;
}
if (e.KeyCode == Keys.Space || bKeyFire == true)
{
bKeyFire = true;
if (iActiveBullets < MAX_BULLETS)
{
if (iActiveBullets != 0)
if (Math.Abs(Bullets[iActiveBullets - 1].pnt.X - dShipX) > BULLET_DISTANCE ||
Math.Abs(Bullets[iActiveBullets - 1].pnt.Y - dShipY) > BULLET_DISTANCE)
Bullets[iActiveBullets] =
new Bullet(new Point((int)dShipX,
(int)dShipY),
dShipAngle,
BULLET_VEL);
else { }
else
Bullets[iActiveBullets] =
new Bullet(new Point((int)dShipX,
(int)dShipY),
dShipAngle,
BULLET_VEL);
iActiveBullets++;
}
}
if (e.KeyCode == Keys.Escape)
Close();
DoNormalize();
}
void DoNormalize()
{
if (iSpaceYVel > iMaxYVel)
iSpaceYVel = iMaxYVel;
else if (iSpaceYVel < (-iMaxYVel))
iSpaceYVel = -iMaxYVel;
if (dShipAngle > (2 * Math.PI))
dShipAngle = 0;
else if (dShipAngle < -(2 * Math.PI))
dShipAngle = 0;
}
private void Form1_Shown(object sender, EventArgs e)
{
timer1.Enabled = true;
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Up)
{
bKeyUp = false;
}
if (e.KeyCode == Keys.Down)
{
bKeyDown = false;
}
if (e.KeyCode == Keys.Right)
{
bKeyRight = false;
}
if (e.KeyCode == Keys.Left)
{
bKeyLeft =false;
}
if (e.KeyCode == Keys.Space)
bKeyFire = false;
}
}
}
Sorry if it's a bit long, I can post more specific portions if i need to. There's not many comments, but its not very complex right now and the variables are self explanitory.