In this game, we will need a slightly upgraded game engine in main
. In particular, we will have an enumeration called state
which will track what the current state of the game is. Then, throughout main
, we can wrap parts of our code so that different things happen in different states.
Right-click on the HelloSFML
file in the Solution Explorer and select Rename. Change the name to ZombieArena.cpp
. This will be the file that contains our main
function and the code that instantiates and controls all our classes.
We begin with the now familiar main
function and some include directives. Note the addition of an include directive for the Player
class.
Add the code following to the ZombieArena.cpp
file:
#include "stdafx.h" #include <SFML/Graphics.hpp> #include "Player.h" using namespace sf; int main() { return 0; }
The previous code has nothing new in it except that the #include "Player.h"
line means we can now use the Player
class within our code.
Let's flesh out some more of our game engine. This next code does quite a lot. Be sure to read the comments when you add the code to get an idea of what is going on. We will then go through it in detail.
Add the highlighted code at the start of the main
function:
int main()
{
// The game will always be in one of four states
enum class State
{
PAUSED, LEVELING_UP, GAME_OVER, PLAYING
};
// Start with the GAME_OVER state
State state = State::GAME_OVER;
// Get the screen resolution and create an SFML window
Vector2f resolution;
resolution.x = VideoMode::getDesktopMode().width;
resolution.y = VideoMode::getDesktopMode().height;
RenderWindow window(VideoMode(resolution.x, resolution.y),
"Zombie Arena", Style::Fullscreen);
// Create a an SFML View for the main action
View mainView(sf::FloatRect(0, 0, resolution.x, resolution.y));
// Here is our clock for timing everything
Clock clock;
// How long has the PLAYING state been active
Time gameTimeTotal;
// Where is the mouse in relation to world coordinates
Vector2f mouseWorldPosition;
// Where is the mouse in relation to screen coordinates
Vector2i mouseScreenPosition;
// Create an instance of the Player class
Player player;
// The boundaries of the arena
IntRect arena;
// The main game loop
while (window.isOpen())
{
}
return 0;
}
Let's run through each section of the code that we just entered. Just inside the main function we have this code:
// The game will always be in one of four states enum class State { PAUSED, LEVELING_UP, GAME_OVER, PLAYING }; // Start with the GAME_OVER state State state = State::GAME_OVER;
The previous code creates a new enumeration class called State
. Then the code creates an instance of State
called state
. The state
enumeration can now be one of four values, as defined in the declaration. Those values are PAUSED
, LEVELING_UP
, GAME_OVER
, and PLAYING
. These four values will be just what we need for keeping track and responding to the different states that the game can be in at any given time. Note that it is not possible for state
to hold more than one value at a time.
Immediately after, we add the following code:
// Get the screen resolution and create an SFML window Vector2f resolution; resolution.x = VideoMode::getDesktopMode().width; resolution.y = VideoMode::getDesktopMode().height; RenderWindow window(VideoMode(resolution.x, resolution.y), "Zombie Arena", Style::Fullscreen);
The previous code declares a Vector2f
called resolution
. We initialize the two variables of resolution
(x
and y
) by calling the VideoMode::getDesktopMode
function for both width
and height
. The resolution
object now holds the resolution of the monitor on which the game is running. The final line of code creates a new RenderWindow
called window
using the appropriate resolution.
This next code creates an SFML View
object. The view is positioned (initially) at the exact coordinates of the pixels of the monitor. If we were to use this View
to do some drawing in this current position it would have no effect whatsoever. However, we will eventually start to move this view to focus on the parts of our game world that the player needs to see. Then, when we start to use a second View
that remains fixed (for the HUD), we will see how this View
can track the action while the other remains static to display the HUD:
// Create a an SFML View for the main action View mainView(sf::FloatRect(0, 0, resolution.x, resolution.y));
Next, we create a Clock
to do our timing and a Time
object called gameTimeTotal
that will keep a running total of the game time that has elapsed. As the project progresses we will introduce more variables and objects to handle timing:
// Here is our clock for timing everything Clock clock; // How long has the PLAYING state been active Time gameTimeTotal;
The next code declares two vectors. One holding two floats, called mouseWorldPosition
, and one holding two integers, called mouseScreenPosition
. The mouse pointer is something of an anomaly because it exists in two different coordinate spaces. You could think of these as parallel universes if you like. First, as the player moves around the world we will need to keep track of where the crosshair is in that world. These will be floating point coordinates and will be stored in mouseWorldCoordinates
. Of course the actual pixel coordinates of the monitor itself never change. They will always be 0,0 to horizontal resolution-1, vertical resolution-1. We will track the mouse pointer position relative to this coordinate space using the integers stored in mouseScreenPosition
:
// Where is the mouse in relation to world coordinates Vector2f mouseWorldPosition; // Where is the mouse in relation to screen coordinates Vector2i mouseScreenPosition;
Finally, we get to use our Player
class. This line of code will cause the constructor function (Player::Player
) to execute. Refer to Player.cpp
if you want to refresh your memory about this function:
// Create an instance of the Player class Player player;
This IntRect
object will hold starting horizontal and vertical coordinates as well as a width and a height. Once initialized, we will be able to access the size and location details of the current arena with code such as arena.left
, arena.top
, arena.width,
and arena.height
:
// The boundaries of the arena IntRect arena;
The last part of the code that we added previously is, of course, our main game loop:
// The main game loop while (window.isOpen()) { }
You have probably noticed that the code is getting quite long. Let's talk about this inconvenience.
3.128.197.221