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

Theme: auto

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 square
  • A means a regular block - it should use texture index 3
  • B means an exploding block - it should use texture index 4

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 SideBlocks, 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: 20 and beyond

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.