Level, Player, and Jumping
This lab uses a background texture just like the previous one did, but it’s much bigger, so you need to position the background actor to (3392, 224)
Next, make a Block
actor subclass that has a SpriteComponent
and a CollisionComponent
:
- Much like
Log
orVehicle
from Lab 3, the texture it uses will depend on a letter (A
-I
are the valid block letters). The textures are all with file names like"Assets/BlockX.png"
, whereX
is the letter of the block - The
CollisionComponent
forBlock
should be 32x32
In Game
, you need a vector of Block*
and AddBlock
/RemoveBlock
functions, as well as a public getter that returns a const reference to the vector. Use the pattern where the Block
constructor calls AddBlock
and destructor RemoveBlock
The level loading is like Lab 3, but there are some changes:
- For now, load the
Assets/Level0.txt
file - The top left corner of the file is centered at (16, 16)
- Each block is 32x32 in size
- The letters
A
throughI
should spawn aBlock
with the corresponding texture - Don’t do anything for all other letters (and
.
) for now
You should see the new background texture and some platforms made of blocks:
The Player
Make a subclass of Actor
called Player
- Give the
Player
aSpriteComponent
and use the"Assets/Mario/Idle.png"
texture. When constructing theSpriteComponent
, use a draw order of 200 (so the player is in front of the blocks) - Give your
Player
aCollisionComponent
with dimensions 32x32.
Next, make a subclass of MoveComponent
called PlayerMove
.
- Create a
PlayerMove
in thePlayer
constructor - In the level file, the character
P
represents the player spawn position. Modify the level loader inGame::LoadData()
to create a newPlayer
at this location. When you create the player, save its pointer in a member variable inGame
.
You should see the player on the bottom left part of the window, hovering above a block:
Player Controls
Now let’s add player controls. We’ll implement this in the PlayerMove
class. Begin by adding overrides for ProcessInput
and Update
. As we go along, you’ll need to add member variables to support these.
PlayerMove::ProcessInput
Use the A
and D
keys to modify the forward speed. For now, just set it to 300.0f
for D
and -300.0f
for A
, and 0 if either both or neither keys are pressed.
PlayerMove::Update
This won’t use the base MoveComponent::Update
, so don’t call that. For now, move the x-position according to forward speed and delta time.
You should now be able to move left and right with A
/D
keys.
Add a float member variable mYSpeed
to track the vertical velocity. In Update
, move the Actor
’s y-position according to mYSpeed
and delta time
mYSpeed
should default to0.0f
mYSpeed
is a velocity, so it is in units/second- To change the velocity you need an acceleration, which is in units/second2
- We will use an acceleration of
2000.0f
for gravity - You need to incrementally update
mYSpeed
every frame using the Euler integration formula. Make sure you do this at the end ofUpdate
.
Your character will now rapidly fall off the bottom of the screen.
Next, add a check that prevents the player y-value from increasing past 448.0f
. Now your player will fall through the platform and stop halfway off the bottom of the screen.
Now it’s time to check if the player overlaps with blocks using the GetMinOverlap
function implement in Lab 3. You should do this after you update the player’s position, but before you update mYSpeed
. Loop over the blocks and check the CollSide
:
- If it’s
CollSide::None
, then Mario didn’t collide with the block, so move on - If it’s
CollSide::Top
and mYSpeed > 0.0f, Mario is landing on top of block, so setmYSpeed = 0
, which stops Mario from moving down - For anything other than
CollSide::None
, you also must adjust the player’s position by theoffset
vector you get fromGetMinOverlap
- Because the collision components require the most up-to-date position information to work correctly, you should call
SetPosition
to update player’s position each time you detect a block collision - Mario can collide with more than one block on any given frame, so you should NOT quit the loop on the first collision
Rather than calling GetComponent<CollisionComponent>()
on every block every frame, you could cache this in a member variable in Block
.
You should now be able to slide back and forth along the starting platform smoothly without falling through it. If you walk off the edge, the player should fall to the bottom of the screen.
Making the Player Jump
Now let’s make the player jump!
PlayerMove variables
Create two new bool
s in PlayerMove
, both initialized to false
: mSpacePressed
and mInAir
PlayerMove::ProcessInput
We need to detect the leading edge of the spacebar, like in Lab 3. If so, set mYSpeed
to -700.0f
(this means the player’s y-velocity has them moving upwards)
You should now be able to jump only on the leading edge of the space bar. However, you can jump again while in the air, which we don’t want to support. There are also some glitches to fix.
Preventing Multiple Jumps
- In
PlayerMove::ProcessInput
code for jumping, only setmYSpeed
ifmInAir
isfalse
(meaning, don’t start a new jump ifmInAir
istrue
). Then, setmInAir
totrue
when the player starts jumping - Back in
Update
, before you loop over all the blocks, first setmInAir
totrue
– that is, we are assuming we are in the air. Then, when you detect that the player collided with the top of a block, setmInAir
tofalse
. This way, the player will properly “land” on the ground when colliding with the top of a block. If the player doesn’t collide with the top of any block,mInAir
will betrue
since we set it to that before the loop.
With this change, you will no longer be able to jump out of the pits in the level. However, ultimately this will kill Mario anyway, so it’s fine.
Fixing Floating
Back in Update
, change it so that if the player collides with the bottom of a block, and the mYSpeed
is negative, set it to 0.0f
. This allows gravity to immediately take over and the player will start falling correctly.
The basics of the platformer should now be setup. You should be able to make your way up to the top platform. Verify that the player behaves correctly when you bump into a platform from the side.
Now change your level file to "Assets/Level1.txt"
. There is an additional letter, Y
that you should ignore for now.
You should now see the beginning of the level on screen (and verify that jumping and such still works).
Once you’e pushed this code, you’re ready to move on to part 2.