Loading Levels and Basic Movement
First, change your window to be 448x512 in size.
Next, create an actor in LoadData
that’s centered in the window, has a SpriteComponent
, and uses the "Assets/Background.png"
texture.
You should see the window and a background:
For this game, we’re using a text-based level file format. Here’s what the provided Assets/Level.txt
file looks like:
......G......
...X.....Y...
.X...X....X..
......Z......
X...X...X....
....Y......Y.
.............
T....T....T..
..D.D...D.D..
.C..C..C..C..
B.....B.....B
...A.....A...
......F......
Each character represents a 32x32 square in a grid. The square in the top left corner is centered at (32, 80). A .
means there’s nothing at that square. A
, B
, C
, D
, and T
are vehicles, with A
-D
being four different types of cars and T
being a truck. X
, Y
, and Z
correspond to the logs floating in the river. F
is the starting position of the frog and G
is the goal.
You’ll need to make three Actor subclasses: Vehicle
, Log
, and Frog
. Right now the only components they need are SpriteComponent
s.
Frog’s sprite component will always use “Assets/Frog.png”
For Vehicle
, which texture you’ll use will depend on the letter:
A
–"Assets/CarA.png"
B
–"Assets/CarB.png"
C
–"Assets/CarC.png"
D
–"Assets/CarD.png"
T
–"Assets/Truck.png"
For Log
, the texture also depends on the letter:
X
–"Assets/LogX.png"
Y
–"Assets/LogY.png"
Z
–"Assets/LogZ.png"
Write code in Game
that loads in the text file and creates the correct actors with the correct textures. Ignore the G
letter for now (treat it like a .
or nothing at that square). You can use normal C++ file reading to read in the file (eg. std::ifstream
to open the file and std::getline
to read a line). For each square, if there’s an actor at that square, you’ll need to create it and set it to the correct position.
Once your actors are setup and you’re correctly creating them with the correct textures, your game should look like this:
Frog Movement
Since the Frog hops are instant and not a continuous motion, Frog
doesn’t need a MoveComponent
. Instead, we can just detect the leading edge and calculate the new position in an override of OnProcessInput
. You want to detect the leading edges of each of the four WASD keys: W for up, S for down, A for left, and D for right. On a leading edge, you want to move the Frog 32 units in the corresponding direction.
To save the “last frame” values, rather than using four separate bools, you should use a map where the key is an SDL_Scancode
and the value is a bool
.
You should also make it so the Frog
can’t hop off-screen by restricting the min/max x and y values of its position. You can use the Math::Clamp
to help do this.
Since Math::Clamp
is a template function, all arguments need to be the same type and it will return a value of that type. In this case, you want the type to be float
, because the x/y components of the Vector2
are float
s. If you use int
, you will truncate the position of the frog which will cause bugs later on, so don’t do this!
You should now hop in the four directions based on the WASD keys. Keep in mind that holding down a key should still only hop once, on the initial leading edge! Also verify that you can’t hop off-screen.
Vehicle and Log Movement
Since Vehicle
and Log
will move in the same way, it makes sense to make a component specifically for this. Make a new subclass of MoveComponent
called WrappingMove
. You need to add only a single member variable to the class, a Vector2
for the direction the owner should move in.
Instead of using the parent’s Update
function, we want to have a separate override in WrappingMove
. Inside here you want to move the owner in the direction specified by the direction member variable at the specified forward speed (don’t forget to multiply by delta time!). Remember that since WrappingMove
is a subclass of MoveComponent
, you already inherit the mForwardSpeed
variable, so you shouldn’t declare another variable. Just use the one you inherited.
You also want to make it so WrappingMove
will wrap the objects around the screen if their position moves off-screen. (You only need to worry about the x-component). For example, if x becomes less than 0 you will want to change the x to the screen width, which is 448).
Now add your WrappingMove
component to both Vehicle
and Log
. Vehicle
s should have a forward speed of 50 and Logs
a forward speed of 37.5. As for the direction, it should be based on the row in the file. Assume the first row of the file is row 0. Even rows should have a direction of <1, 0> (to the right) while odd rows should have a direction of <-1, 0> (to the left). This will give a desired alternating direction on each row.
Verify your logs and vehicles move to the left and right and wrap around screen, like in the original video. Note that the video shows the vehicles slow down and speed up in some cases, but your vehicles won’t behave that way just yet.
Once you’e pushed this code, you’re ready to move on to part 2.