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 aRandom::GetFloatRange
between0.0f
andMath::TwoPi
. - Set
mPosition
to aRandom::GetVector
. This takes in amin
andmax
vector. In this case case, you wantmin
/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: `
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 of400.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:
Laser Limiting
We want to make it so that you can only shoot one laser per second. To do this:
- Add a
float
variable toShip
to track the “cooldown” of the laser, and initailize it to0.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 to1.0f
- In
Ship
, add an override ofOnUpdate
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.