Skip to main content Link Search Menu Expand Document (external link)

Theme: auto

Asteroids and Shooting

Now we’ll add asteroids moving around and the ability to shoot lasers at them.

Asteroid Basics

Create new Asteroid.h/cpp files and in these files declare a subclass of Actor called Asteroid. In the constructor, create the following components:

  • A SpriteComponent using the "Assets/Asteroid.png" texture
  • A MoveComponent with a hardcoded forward speed of 150.0f

We want to create asteroids with random positions and orientations so that they are different each time. To help with this, we have provided a basic random library in Random.h/cpp. To initialize this library, at the start of Game::Initialize, add a call to Random::Init().

All the Random functions are static, so you don’t need to create an instance of Random to use it. Furthermore, please don’t use rand() instead of the provided Random library because our library is way better than rand().

Then, back in the Asteroid constructor, initialize the rotation and position to random values:

  • Set mRotation to a Random::GetFloatRange between 0.0f and Math::TwoPi.
  • Set mPosition to a Random::GetVector. This takes in a min and max vector. In this case case, you want min/max to correspond to the coordinates for the top left corner and bottom right corners of the window, respectively.

Now in Game::LoadData, create 10 asteroids (please make a loop for this).

You should now see 10 asteroids on screen that fly around in different directions: Random asteroids flying around`

Asteroid Screen Wrapping

You may notoice now that the asteroids fly off screen quickly. As in the original Asteroids game, you should change it so the asteroids wrap around the screen. To do this, override the OnUpdate function in Asteroid. Then, add code that checks the position of the asteroid. If it moves off one of the sides of the screen, change its position to the other side. For example, if the x goes below 0, set x to 1023. Add similar logic for the three remaining sides of the screen.

When an asteroid reaches one side of the screen, it should now teleport to the other side of the screen rather than flying off.

Laser Shooting

Make a new subclass of Actor called Laser (again, in new files). It needs:

  • A SpriteComponent using "Assets/Laser.png"
  • A MoveComponent with a forward speed of 400.0f
  • An override of OnUpdate

Now in Ship::OnProcessInput, if the SDL_SCANCODE_SPACE key is pressed, dynamically allocate a new Laser. Set the position of the laser to the ship’s position, and the rotation of the laser to the ship’s rotation.

Now if you hold down the space bar, you should be able to create a ridiculous number of lasers: Infinite lasers

Laser Limiting

We want to make it so that you can only shoot one laser per second. To do this:

  • Add a float variable to Ship to track the “cooldown” of the laser, and initailize it to 0.0f
  • When you’re deciding whether to fire the laser, only fire the laser if the the cooldown is <= 0.0f. If you do fire a laser, set the cooldown to 1.0f
  • In Ship, add an override of OnUpdate and reduce the cooldown by delta time
  • Thus, when you fire a laser, you won’t be able to fire another one for a second

You should only be able to fire one laser per second.

Now make it so that lasers die after being alive for one second. To do this, add a variable to track the “lifetime” in Laser. When that lifetime reaches one second, set the state to ActorState::Destroy. You’ll want to use an approach very similar to the laser limiting.

Lasers Colliding with Asteroids

Now we’ll make it so that lasers can destroy asteroids. We haven’t talked about more complex collision yet, so we’ll keep it simple for now.

First, we need a way to track all the asteroids in the game world. So, add a std::vector of Asteroid* to Game, and corresponding AddAsteroid/RemoveAsteroid functions. The implementation of these two functions is very similar to AddActor/RemoveActor. Then, make the Asteroid constructor and destructor call the appropriate functions.

Then in Laser::OnUpdate, you’ll need to loop over the asteroid vector. Use Vector2::Distance to calculate the distance between the position of each asteroid and the position of the laser. If this distance is <= 70, then set both the laser and asteroid to ActorState::Destroy and break out of the loop.

You should now be able to shoot at and destroy asteroids.

Once you’ve pushed your code, you should review the grading specifications to confirm you’ve satisfied them.