Scrolling and Enemies
Now that the basic platforming works, you’re going to add a camera and enemies.
Scrolling Camera
You’re going to implement a 2D camera as described in lecture.
- Add a private
Vector2
for the camera position to game and a publicVector2& GetCameraPos()
function that returns the camera position (the reference for the return type of the function is important) - In
SpriteComponent::Draw
, before theSDL_RenderCopyEx
call, we want to adjustr.x
andr.y
by the camera position x/y, respectively. Remember thatScreenPos = WorldPos – CameraPos
and you still want to keep the half width/height subtractions. - At the end of
PlayerMove::Update
, set thecamera.x
equal to the player’sposition.x
(leave thecamera.y
as 0)
Now the player will start at the leftmost edge on the screen, and you should be able to move through the level. For now, the player will always remain on the leftmost edge on screen.
You may notice that if you’re standing right next to a tall green pipe, start running into the pipe, and try to jump, you won’t be able to jump over the pipe. This is a bug because the pipe is made of multiple “blocks.” You do not need to fix this in the lab, but if you’re curious how to fix it, we discuss in “Taking it Further!”
Next, we want to horizontally center the player on screen. To do this, should subtract 300
(half the screen width) when calculating the new camera.x
value in PlayerMove
Now the player is centered when you move through. Though now you’ll see the area to the left of the level when the game starts (which we’ll fix in a second).
In the original Super Mario Bros., you can’t move the camera backwards, and you can’t move the player off the screen to the left. You can only scroll forward. We want this, so:
- Don’t let the
player.x
ever be less than thecamera.x
- Don’t change
camera.x
if you would decreasecamera.x
- Don’t let the
camera.x
go below 0 (to fix the problem at the start)
Your scrolling camera should now work as described. If you’re not sure if your camera’s working to specification, watch the final video. (Unlike the video, you will be able to run past the end of the level, because we haven’t added the win condition yet.)
Creating Enemies
The Y
letter in the level file corresponds to the location of an enemy. However, we do not want to simply create all the enemies as the game first loads, because then they will have moved out of position by the time the player gets close.
Instead, we’re going to make a Spawner
actor that doesn’t do anything other than wait for the player to get close enough, at which point the spawner will create one enemy, and then get destroyed.
Goomba
The “goomba” is one of Mario’s enemies. Make a new Actor
subclass called Goomba
with:
- A
SpriteComponent
using the"Assets/Goomba/Walk0.png"
texture, and a draw order of150
- A
CollisionComponent
with size 32x32 - A new
MoveComponent
subclass calledGoombaMove
(we’ll implement the movement a bit later)
Just like with the blocks, you’ll want to keep track of all the enemies in the Game
class with a separate vector. This means also, just like with Block
, your Goomba
constructor should add to your enemy vector, and the destructor should remove from the enemy vector
Spawner
Now make another Actor
subclass called Spawner
. It doesn’t need any components, but it does need an OnUpdate
override function.
In OnUpdate
, you want to spawn a Goomba
if the x-distance between the spawner and the player is less than 600
. In this case:
- Create a Goomba, and set its position to the Spawner’s position
- Set the Spawner’s state to ActorState::Destroy (so it’ll be destroyed and can’t spawn anything anymore)
Now in your level loading code, whenever you see a Y
, create a Spawner
object.
Now when you move through the level, you should see various Goombas positioned slightly above blocks (where their spawn spots are):
Making the Goombas Move
Now it’s time to implement GoombaMove::Update
. Unlike the earlier parts of this lab, the instructions for this are less detailed. You should apply the techniques you’ve already learned to implement the behaviors as described.
- Goombas should begin moving to the left at a speed of 100 units/second
- If while moving left, they run into a block or another goomba, they should start moving to the right. Hint: Think about which
CollSide
s this means…
Hint 2: Don’t forget that a goomba should not be able to collide with itself! - Similarly, if they’re moving to the right and run into a block or another goomba, they should start moving left again.
- On any collisions, you should “fix” the position so the goomba is no longer overlapping
- If a goomba isn’t standing on any blocks, it should fall with the same gravity as the player does (but they would continue moving left/right as needed)
- If a goomba’s y-position places them below the bottom of the screen, destroy them (because this means they fell into a pit).
If your goombas seem to turn at incorrect times, it’s because the goomba falling slightly into the platform is sometimes a MinOverlap
of left or right. To fix this, check block collision in two consecutive loops. In the first loop, only care about “top”. Then in the second loop, look for “left/right” overlaps, but don’t count it as a collision unless the block.y
is approximately the same as the goomba.y
.
As you move through the level, you should see goombas moving to the left initially. You should see that goombas that hit a wall or each other should switch their horizontal direction. Watch the two goombas in between the pipes near the beginning of the level, as they should change directions back and forth on account of each other and the walls. If you move a bit further, you should see two goombas fall from a high platform to a middle platform and then to the ground. As before, watch the video if you’re not sure if it’s working properly.
Stomping
Now you’ll add the ability for Mario to jump on and “stomp” the goombas. You should add a bool
to Goomba
to track whether it’s been stomped.
Mario successfully stomps a goomba if one these is true:
-
Mario hits the top of the goomba
OR
-
Mario hits the left/right of the goomba AND
mInAir
istrue
If a goomba gets stomped, it should:
- Change its texture to
"Assets/Goomba/Dead.png"
- No longer move in
GoombaMove
- Not be able to collide with Mario anymore
- Get destroyed after 0.25 seconds
When Mario stomps a goomba, he should also do a “half jump”, which just means:
- Set
mYSpeed
inPlayerMove
to-350.0f
(half of the normal jump velocity) - Set
mInAir
totrue
, since you’re in the air now
If Mario collides with a goomba but does NOT satisfy the “stomping” conditions, Mario should die. When Mario dies you should:
- Change his texture to
"Assets/Mario/Dead.png"
- Set him to
ActorState::Paused
(so you can see him dead for all of eternity, or at least until you close the game window)
Keep in mind that if the goomba in question has already been stomped, then a collision against should do nothing.
You should be able to stomp goombas now by jumping on them. You should die if you just run into them when not in the air.
Once you’e pushed this code, you’re ready to move on to part 3.