Obstacles and Shooting
First, declare a new Actor
subclass called Block
with:
- A scale of
25.0f
- A
MeshComponent
using"Assets/Cube.gpmesh"
as the mesh - A
CollisionComponent
with size(1, 1, 1)
You’ll need to make a vector of Block*
pointers in Game
(and a getter that returns it by reference), and add/remove them from the vector in Block’s constructor/destructor.
In the Assets/Blocks
directory, there are 20 different text files. Each of these files represents an arrangement of smaller blocks that are obstacles for the player’s ship. The file format is the same ASCII style we used in some of the earlier 2D labs. In this case:
.
means an empty squareA
means a regular block - it should use texture index3
B
means an exploding block - it should use texture index4
Each of these files will spawn at 1000
x-position increments. So 1.txt
would be at x=1000, 2.txt
would be at x=2000, and so on. Once all 20 files have been shown in sequence, the game will keep going by picking a random file every time it needs a new set of obstacles.
As with the SideBlock
s, we don’t know how long the player will stay alive, so we can’t just load a fixed number of the files. Instead, like with the side blocks, we’ll load the files 4000 x-units in advance. So, when the game starts, we’ll load a file at x=1000, 2000, and 3000. Then when the player moves to x >= 0, we’ll load a file at x=4000, and so on.
First, make a LoadBlocks
function in Game
that takes in a file name. The basic idea of reading in the text, will be like you did it in Mario/Frogger.
What’s different is the coordinates of the Blocks. The x-position is based on the logic described earlier. The letter in the top left corner of the file corresponds to y=-237.5
and z=237.5
. As you increase the column, the y increases by 25
, and increasing the row decreases the z by 25
.
Next, implement the logic that dynamically loads the block files 4000 x-units in advance.
Then in Block::OnUpdate
, add the same code you did to SideBlock::OnUpdate
(e.g. destroy the Block
after it’s 2000 units behind the player). Without this, your game collision code will slow down dramatically over time because the blocks vector would get huge.
When the game starts, you should see the first couple of few set of obstacles, and as you advance you should see new ones come in (you don’t collide with them yet):
Now implement the code that after the initial sequence of 1 to 20 finishes, each subsequent obstacle layer picks a random file from 1.txt
to 20.txt
. Use Random.h
for the random numbers.
Verify that after you see 20.txt
(which is the one that says “DO A BARREL”), your game continues to create more obstacle layers at random:
Exploding Blocks and Shooting
In Block
, add a bool
to track whether a block is of the “exploding” type. Set this to true
for blocks of type 'B'
Next, we’ll add shooting of the exploding blocks. Make a new Actor
subclass called Bullet
, it needs:
· A scale of 5.0f
· A MeshComponent
using "Assets/Laser.gpmesh"
· A MoveComponent
set to an initial forward speed of 900.0f
· A CollisionComponent
with size (10, 10, 10)
Make it so the Bullet
gets destroyed if:
- It collides with a block
- It has been alive for more than 1 second
Because GetMinOverlap()
is not yet implemented for the 3D CollisionComponent
, you need to use Intersect()
to test the collision.
For regular blocks, getting hit by a bullet only destroys the bullet and not the block. However, when a bullet hits an “exploding” block it should destroy the block and also trigger an explosion:
- The explosion should destroy any other block within a radius of
50
units - If an exploding block gets destroyed via an explosion, then that exploding block should also explode
- This means that exploding blocks can set off a chain explosion where a lot of blocks get destroyed well beyond the initial 50 units
When implementing the explosion logic, think about how you can make sure your explosion chain reaction doesn’t get stuck in an infinite loop (or infinite recursion).
Now in PlayerMove
, add code that creates a Bullet
on a leading edge of the spacebar. Make sure you set the position of this Bullet
to the Player
’s current position.
Verify that you can shoot bullets (they just look like small green spheres). If a bullet hits a normal block or hits nothing for 1 second, it should just get destroyed. If it hits an exploding block, verify your explosion logic works. Here’s what the first few exploding obstacles should look like when you hit them with the bullet:
Shields and Damage
Give the Player
an integer to track their shield level, which starts at 3.
Then in PlayerMove::Update
, make it so if the player collides with any of the blocks, those blocks get destroyed (and explode) and the player takes 1 shield damage.
When the player takes shield damage, they should become invulnerable for 1 second so that they cannot take any additional shield damage for that second. This will mean that if the player hits several blocks over that one second, they will still only take 1 damage in total.
If the player’s shield level hits 0, set the player’s actor state to paused, which will end the game.
Verify that after colliding with three sets of blocks, the player stops moving:
Once you’ve pushed this code, you’re ready to move on to part 3.