Click here to Skip to main content
13,149,099 members (56,434 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

59K views
10.4K downloads
57 bookmarked
Posted 30 Dec 2011

A Basic 3D Asteroid Game in openGL with C#

, 30 Dec 2011
Rate this:
Please Sign up or sign in to vote.
A Basic 3D Asteroid Game in openGL with C#
image001.jpg

Introduction

This article is intended for beginners who want to start with 3D game programming and don’t know where to start. It is programmed in Opengl using VS 2008 and a small graphic engine I made myself called Shadowengine. It has the basics of what a game should have: a Score, levels of difficulty and a life counter. All this is written in a small number of code lines, with the objective of being simple and understandable.

The first problem I had to achieve is the scene to look like outer space. For that issue, I set the background color to black. In opengl, it is set this way:

Gl.glClearColor(0, 0, 0, 1);//red green blue alpha 

The other problem were the stars and I solve it by drawing random white points on the screen. The algorithm is more or less this way. I generate a random point and measure the distance to the spaceship, and if it is less than a predefined number, I discard it and repeat the process until it creates the desired stars. Look at the code:

public void CreateStars(int cantidad)
        {
            Random r = new Random();
            int count = 0;
            while (count != cantidad)
            {
                Position p = default(Position);
                p.x = (r.Next(110)) * (float)Math.Pow(-1, r.Next());
                p.z = (r.Next(110)) * (float)Math.Pow(-1, r.Next());
                p.y = (r.Next(110)) * (float)Math.Pow(-1, r.Next());
                if (Math.Pow(Math.Pow(p.x, 2) + Math.Pow(p.y, 2) +
    Math.Pow(p.z, 2), 1 / 3f) > 15)
                {
                    stars.Add(p);
                    count++;
                }
            }
        }

The score is a number which increases over time and it grows faster everytime I pass a level. The level increases every 450 frames.

The last issue I had to address is the problem of asteroid collision. I make for the ship three positions (one for the ship and two for the wings) and every once in a while, I check the distance between all the asteroids and those three positions. If it is under a predefined value, I execute the collision event.

The project has 6 classes:

  • AsteroidGenerator.cs - It handles the creation of asteroids in random places and with random sizes and speeds. It also has the method to query whether or not there has been a collision between the spaceship and an asteroid.
  • Asteroid.cs - It handles all concerning an asteroid such as the movement, texture selection, drawing, among others.
  • Star.cs - It has a method to create random white points and to draw them.
  • Camera.cs - It handles the selection of the user camera and to set the right perspective view of the scene.
  • SpaceShip.cs - This class contains all methods and attributes regarding the spaceship, such as movement, drawing, etc.
  • Controller.cs - This class manages the game creation, game logic and contains all the classes needed to run the game. Here is a portion of code:
using System;
using System.Collections.Generic;
using System.Text;

namespace Naves
{
    public class Controller
    {
        Camera camara = new Camera();
        Star star = new Star();
        SpaceShip spaceShip = new SpaceShip();
        public SpaceShip Nave
        {
            get { return spaceShip; }set { spaceShip = value; }
        }
        public Camera Camara
        {
            get { return camara; }
        }
        public void BeginGame()
        {
            AsteroidGenerator.GenerateAsteroid(35, false);
        }
        public void ResetGame()
        {
            AsteroidGenerator.GenerateAsteroid(35, true);
            spaceShip.Reiniciar();
        }
        public void CreateObjects()
        {
            star.CreateStars(450);
            spaceShip.Create();
            Asteroid.Crear();
        }
        public void DrawScene()
        {
            star.Draw();
            AsteroidGenerator.DrawAsteroids();
            spaceShip.Dibujar();
        }
    }
}

Main.cs - This is the form which contains this visual components of the game. It contains the controller class and gives the player information through proper windows controls. It has a timer to periodically draw the scene and has the code for texture and object loading.

If you want to add sound to the project, uncomment the commented lines and press Ctrl+Alt+E and under managed debugging assistants, uncheck the loaderlock exception.

I am hoping to receive feedback from this example. If you like it, you can visit my blog at www.vasilydev.blogspot.com for more stuff like this. I’ll try to make a version where the spaceship can shoot at the asteroids.

History

  • 28th December, 2011: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Vasily Tserekh
Software Developer
United States United States
Born on 86, had my first computer at the age of 8, wrote my first code at the age of 15(pascal), began to study software engineering at 2005 and graduated in 2010. Now I am currently developing software for ERP systems in "Michell Consulting, LLC" . I have a dev blog www.vasilydev.blogspot.com. My real passion is 3D game programming and playing guitar. I've programmed stuff in C#, python, Delphi, PHP, C++, JS, QT and others...

You may also be interested in...

Comments and Discussions

 
QuestionHow is the texturas mapped to the nave.3ds? Pin
bitzhuwei15-Jun-13 21:30
memberbitzhuwei15-Jun-13 21:30 
AnswerRe: How is the texturas mapped to the nave.3ds? Pin
Vasily Tserekh16-Jun-13 5:10
memberVasily Tserekh16-Jun-13 5:10 
GeneralRe: How is the texturas mapped to the nave.3ds? Pin
Vasily Tserekh16-Jun-13 5:14
memberVasily Tserekh16-Jun-13 5:14 
GeneralRe: How is the texturas mapped to the nave.3ds? Pin
bitzhuwei15-Jul-13 17:28
memberbitzhuwei15-Jul-13 17:28 
GeneralRe: How is the texturas mapped to the nave.3ds? Pin
Vasily Tserekh17-Jul-13 4:25
memberVasily Tserekh17-Jul-13 4:25 
SuggestionLittle Tidbit/Suggestion Pin
Death2592-May-12 8:12
memberDeath2592-May-12 8:12 
I downloaded your code, because I've always wanted to do some game programming, but didn't know where to start. You've done a fabulous job for laying everything out in a nice and neat format that's easy to understand. One tip/suggestion that I have, is that you might want to change how you are doing the controls. Currently you can only move in one direction up, down, left or right. You cannot do a combination of them, diagonal. This, however, has a simple fix.

In the Main.cs:
Instead of having moviendo be an integer, make it a system.drawing.point. You can then keep track of 2 directions at once, up/down and left/right. Within your keydown event, you can then change the code to have moviendo be a new point in correlation to what key is down.

Ex. The A key would be:
moviendo = new Point(-1, moviendo.Y)


In your keyup event you will then have it stop the direction that is let go.

Ex. The A key would be:
moviendo = new Point(0, moviendo.Y)


Main_KeyDown
private void Main_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.A)
    {
        moviendo = new Point(-1, moviendo.Y);
    }
    if (e.KeyCode == Keys.D)
    {
        moviendo = new Point(1, moviendo.Y);
    }
    if (e.KeyCode == Keys.W)
    {
        moviendo = new Point(moviendo.X, 1);
    }
    if (e.KeyCode == Keys.S)
    {
        moviendo = new Point(moviendo.X, -1);
    }
    if (e.KeyCode == Keys.A || e.KeyCode == Keys.D || e.KeyCode == Keys.W || e.KeyCode == Keys.S)
    {
        if (pressed == false)
        {
            // AudioPlayback.PlayOne("mover.wav");
        }
    }
    pressed = true;
}


Main_KeyUp
private void Main_KeyUp(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.A)
    {
        moviendo = new Point(0, moviendo.Y);
    }
    if (e.KeyCode == Keys.D)
    {
        moviendo = new Point(0, moviendo.Y);
    }
    if (e.KeyCode == Keys.W)
    {
        moviendo = new Point(moviendo1.X, 0);
    }
    if (e.KeyCode == Keys.S)
    {
        moviendo = new Point(moviendo.X, 0);
    }
    pressed = false; 
}


In the SpaceShip.cs:
Since moviendo is a point and no longer just an integer, we need to make the necessary changes here as well for the movement of the ship. In order to keep the ship from going off of the screen, I added the bounds as you see with the < 3 and > -3. You already had half of the bounds put in, I just added the other 2. With the code below, we are just taking the distance we want to move and multiply it by the amount we are moving. A negative distance in the X direction means we are moving left, an negative distance in the Y direction means we are moving down, just like in a X,Y coordinate graph. First you will have to get rid of the switch statement within the Dibujar() method. Then you can add the code below within the initial if statement.

Dibujar() method
if (Main.Moviendo != new Point(0,0))
{
    if ((p.x + (Main.Moviendo.X * 0.08f)) < 3 && (p.x + (Main.Moviendo.X * 0.08f)) > -3)
    {
        p.x += (Main.Moviendo.X * 0.08f);
    }
    if ((p.y + (Main.Moviendo.Y * 0.08f)) < 3 && (p.y + (Main.Moviendo.Y * 0.08f)) > -3)
    {
        p.y += (Main.Moviendo.Y * 0.08f);
    }
}


I left out the little things that I figured were easy to catch on with (making sure to change the moviendo to a point in both files, etc.). When all of this is said and done, the players should now be able to freely move left, right, up, down or even in a diagonal direction. Hope this helps someone out a little. I appreciate the groundwork that was laid with this awesome tutorial!

modified 2-May-12 14:37pm.

GeneralRe: Little Tidbit/Suggestion Pin
Vasily Tserekh5-May-12 17:48
memberVasily Tserekh5-May-12 17:48 
GeneralRe: Little Tidbit/Suggestion Pin
Death2597-May-12 6:52
memberDeath2597-May-12 6:52 
GeneralRe: Little Tidbit/Suggestion Pin
Vasily Tserekh7-May-12 9:11
memberVasily Tserekh7-May-12 9:11 
GeneralRe: Little Tidbit/Suggestion Pin
Death2597-May-12 9:17
memberDeath2597-May-12 9:17 
GeneralRe: Little Tidbit/Suggestion Pin
Vasily Tserekh8-May-12 6:03
memberVasily Tserekh8-May-12 6:03 
GeneralRe: Little Tidbit/Suggestion Pin
Death2598-May-12 6:04
memberDeath2598-May-12 6:04 
QuestionIs source code available? Pin
Perry217-Apr-12 8:08
memberPerry217-Apr-12 8:08 
AnswerRe: Is source code available? Pin
Death2592-May-12 8:16
memberDeath2592-May-12 8:16 
QuestionThis is really cool! Pin
Larry Boeldt22-Mar-12 16:33
memberLarry Boeldt22-Mar-12 16:33 
AnswerRe: This is really cool! Pin
Vasily Tserekh23-Mar-12 8:39
memberVasily Tserekh23-Mar-12 8:39 
GeneralMy vote of 5 Pin
fredatcodeproject31-Dec-11 14:41
memberfredatcodeproject31-Dec-11 14:41 
QuestionWhat .NET OpenGL Library Are You Using? Pin
BlazeCell30-Dec-11 5:38
memberBlazeCell30-Dec-11 5:38 
AnswerRe: What .NET OpenGL Library Are You Using? Pin
J4$PER30-Dec-11 8:46
memberJ4$PER30-Dec-11 8:46 
GeneralRe: What .NET OpenGL Library Are You Using? Pin
GL_Terminator30-Dec-11 10:03
memberGL_Terminator30-Dec-11 10:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.170924.2 | Last Updated 30 Dec 2011
Article Copyright 2011 by Vasily Tserekh
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid