I'm following a course on Udemy, but sadly it is through Packt Publishing so they aren't very helpful. I was working on the Zombie Arena example and in the video when the author runs it it shows a black screen, requires user to press enter then number 1-6 before showing the player PNG that stars at the mouse pointer as you move it. I've used C++ for a couple of years and this is the first serious thing I've tried making so I feel slightly overwhelmed. The issue is that on my end it just displays a white screen and was wanting pointers on how to tweak the code so it isn't drastically different from the course. I've included all three source code files, but I suspect the issue is in Player.cpp in the player constructor..just confused as to how as I thought the data was held in memory until the object was destroyed.
Main.cpp
#include "Player.h"
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
sf::Vector2f resolution;
resolution.x = sf::VideoMode::getDesktopMode().width;
resolution.y = sf::VideoMode::getDesktopMode().height;
sf::RenderWindow window(sf::VideoMode(resolution.x, resolution.y), "Zombie Arena", sf::Style::Fullscreen);
// create a SFML view for the main action
sf::View mainView(sf::FloatRect(0, 0, resolution.x, resolution.y));
// here is our clock for timing everything
sf::Clock clock;
// how long has the PLAYING state been active
sf::Time gameTimeTotal;
// where is the mouse in relation to world coordinates
sf::Vector2f mouseWorldPosition;
// where is the mouse in relation to screen coordinates
sf::Vector2i mouseScreenPosition;
// create an instance of the Player class
Player player;
// the boundaries of the arena
sf::IntRect arena;
// the main game loop
while(window.isOpen()){
// handle input
sf::Event event;
while(window.pollEvent(event)){
if(event.type == sf::Event::KeyPressed){
// pause a game while playing
if(event.key.code == sf::Keyboard::Return && state == State::PLAYING){
state = State::PAUSED;
}else if(event.key.code == sf::Keyboard::Return && state == State::PAUSED){ // restart while paused
state = State::PLAYING;
// reset the clock so there isn't a frame jump
clock.restart();
}else if(event.key.code == sf::Keyboard::Return && state == State::GAME_OVER){ // start a new game while in GAME_OVER state
state == State::LEVELING_UP;
}
if(state == State::PLAYING){
}
}
} // end event polling
// handle the player quitting
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)){
window.close();
}
// handle controls while playing
if(state == State::PLAYING){
// handle the pressing and releasing of the WASD keys
if(sf::Keyboard::isKeyPressed(sf::Keyboard::W)){
player.moveUp();
}else{
player.stopUp();
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::S)){
player.moveDown();
}else{
player.stopDown();
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::A)){
player.moveLeft();
}else{
player.stopLeft();
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::D)){
player.moveRight();
}else{
player.stopRight();
}
} // end WASD while playing
// handle the leveling up state
if(state == State::LEVELING_UP){
// handlethe player leveling up
if(event.key.code == sf::Keyboard::Num1){
state =State::PLAYING;
}
if(event.key.code == sf::Keyboard::Num2){
state = State::PLAYING;
}
if(event.key.code == sf::Keyboard::Num3){
state = State::PLAYING;
}
if(event.key.code == sf::Keyboard::Num4){
state = State::PLAYING;
}
if(event.key.code == sf::Keyboard::Num5){
state = State::PLAYING;
}
if(event.key.code == sf::Keyboard::Num6){
state = State::PLAYING;
}
if(state == State::PLAYING){
// prepare the level
// we will modify the next two lines later
arena.width = 500;
arena.height = 500;
arena.left = 0;
arena.top = 0;
// we will modify this line of code later
int tileSize = 50;
// spawn the player in the middle of the arena
player.spawn(arena, resolution, tileSize);
// reset the clock so there isn't a frame jump
clock.restart();
}
} // end of LEVELING_UP
// update the frame
if(state == State::PLAYING){
// update the delta time
sf::Time dt = clock.restart();
// updte the total gmae time
gameTimeTotal += dt;
// make a decimal fraction of 1 from the delta time
float dtAsSeconds = dt.asSeconds();
// where is the mouse pointer
mouseScreenPosition = sf::Mouse::getPosition();
// convert mouse position to world coordinates of mainView
mouseWorldPosition = window.mapPixelToCoords(sf::Mouse::getPosition(), mainView);
// update the player
player.update(dtAsSeconds, sf::Mouse::getPosition());
// make a note of the player's new position
sf::Vector2f playerPosition(player.getCenter());
// make the view center around the player
mainView.setCenter(player.getCenter());
} // end updating the scene
// draw the scene
if(state == State::PLAYING){
window.clear();
// set the mainView to be displayed in the window
// and draw everything related to it
window.setView(mainView);
// draw the player
window.draw(player.getSprite());
}
if(state == State::LEVELING_UP){
}
if(state == State::PAUSED){
}
if(state == State::GAME_OVER){
}
window.display();
} // end of game loop
return 0;
}
Player.h
#ifndef PLAYER_H
#define PLAYER_H
#include <SFML/Graphics.hpp>
class Player
{
public:
Player();
virtual ~Player();
void spawn(sf::IntRect arena, sf::Vector2f resolution, int tileSize);
// call this at the end of every game
void resetPlayerStatus();
// handle the player getting hit by a zombie
bool hit(sf::Time timeHit);
// how long ago wasthe player last hit
sf::Time getLastHitTime();
// where is the player
sf::FloatRect getPosition();
// where is the center of the player
sf::Vector2f getCenter();
// which angle is the player facing
float getRotation();
// send a copy of hte sprite to main
sf::Sprite getSprite();
// the next four functions move the player
void moveLeft();
void moveRight();
void moveUp();
void moveDown();
// stop the player moving a specific direction
void stopLeft();
void stopRight();
void stopUp();
void stopDown();
// we will call this function once every frame
void update(float elapsedTime, sf::Vector2i mousePosition);
// give player a speed boost
void upgradeSpeed();
// give player some health
void upgradeHealth();
// increase the maximum amount of health the player can have
void increaseHealthLevel(int amount);
// how much health has the player currently got?
int getHealth();
private:
const float START_SPEED = 200;
const float START_HEALTH = 100;
// where is the player
sf::Vector2f m_Position;
// of course we will need a sprite
sf::Sprite m_Sprite;
// add a texture
// !! Watch this space!!
sf::Texture m_Texture;
// what is the screen resolution;
sf::Vector2f m_Resolution;
// what size is the current arena
sf::IntRect m_Arena;
// how big is each tile of the arena
int m_TileSize;
// which direction is the player currently moving in
bool m_UpPressed;
bool m_DownPressed;
bool m_LeftPressed;
bool m_RightPressed;
// how much health has the player got?
int m_Health;
// what is the maximum health the player can have
int m_MaxHealth;
// when was the player last hit
sf::Time m_LastHit;
// speed in pixels per second
float m_Speed;
};
#endif // PLAYER_H
Player.cpp
#include "Player.h"
#include <cmath>
Player::Player(){
//ctor
this->m_Speed = START_SPEED;
this->m_Health = START_HEALTH;
this->m_MaxHealth = START_HEALTH;
// Associate a texture with the sprite
this->m_Texture.loadFromFile("graphics/player.png");
this->m_Sprite.setTexture(this->m_Texture);
// set the origin of the sprite to the center for smooth rotation
this->m_Sprite.setOrigin(this->m_Texture.getSize().x / 2, this->m_Texture.getSize().y / 2);
}
Player::~Player(){
//dtor
}
void Player::spawn(sf::IntRect arena, sf::Vector2f resolution, int tileSize){
// place player in the middle of the arena
this->m_Position.x = arena.width / 2;
this->m_Position.y = arena.height / 2;
// copy the details of the arena to the player's m_arena
this->m_Arena.left = arena.left;
this->m_Arena.width = arena.width;
this->m_Arena.top = arena.top;
this->m_Arena.height = arena.height;
// remember how big the tiles are in this arena
this->m_TileSize = tileSize;
// store the resolution for future use
this->m_Resolution.x = resolution.x;
this->m_Resolution.y = resolution.y;
}
void Player::resetPlayerStatus(){
this->m_Speed = START_SPEED;
this->m_Health = START_HEALTH;
this->m_MaxHealth = START_HEALTH;
}
bool Player::hit(sf::Time timeHit){
if(timeHit.asMilliseconds() - this->m_LastHit.asMilliseconds() > 200){
this->m_LastHit = timeHit;
this->m_Health -= 10;
return true;
}else{
return false;
}
}
sf::Time Player::getLastHitTime(){
return this->m_LastHit;
}
sf::FloatRect Player::getPosition(){
return this->m_Sprite.getGlobalBounds();
}
sf::Vector2f Player::getCenter(){
return this->m_Position;
}
float Player::getRotation(){
return this->m_Sprite.getRotation();
}
sf::Sprite Player::getSprite(){
return this->m_Sprite;
}
void Player::moveLeft(){
this->m_LeftPressed = true;
}
void Player::moveRight(){
this->m_RightPressed = true;
}
void Player::moveUp(){
this->m_UpPressed = true;
}
void Player::moveDown(){
this->m_DownPressed = true;
}
void Player::stopLeft(){
this->m_LeftPressed = false;
}
void Player::stopRight(){
this->m_RightPressed = false;
}
void Player::stopUp(){
this->m_UpPressed = false;
}
void Player::stopDown(){
this->m_DownPressed = false;
}
void Player::update(float elapsedTime, sf::Vector2i mousePosition){
if(this->m_UpPressed){
this->m_Position.y -= this->m_Speed * elapsedTime;
}
if(this->m_DownPressed){
this->m_Position.y += this->m_Speed * elapsedTime;
}
if(this->m_RightPressed){
this->m_Position.x += this->m_Speed *elapsedTime;
}
if(this->m_LeftPressed){
this->m_Position.x -= this->m_Speed *elapsedTime;
}
this->m_Sprite.setPosition(this->m_Position);
// keep the player in the arena
if(this->m_Position.x > this->m_Arena.width - this->m_TileSize){
this->m_Position.x = this->m_Arena.width - this->m_TileSize;
}
if(this->m_Position.x < this->m_Arena.left + this->m_TileSize){
this->m_Position.x = this->m_Arena.left + this->m_TileSize;
}
if(this->m_Position.y > this->m_Arena.height - this->m_TileSize){
this->m_Position.y = this->m_Arena.height - this->m_TileSize;
}
if(this->m_Position.y < this->m_Arena.top + this->m_TileSize){
this->m_Position.y = this->m_Arena.top + this->m_TileSize;
}
// calculate the angle the player is facing
float angle = (atan2(mousePosition.y - this->m_Resolution.y / 2, mousePosition.x - this->m_Resolution.x / 2) * 180) / 3.141;
this->m_Sprite.setRotation(angle);
}
void Player::upgradeSpeed(){
// 20% speed upgrade
this->m_Speed += (START_SPEED * 0.2);
}
void Player::upgradeHealth(){
// 20% max health upgrade
this->m_MaxHealth += (START_HEALTH * 0.2);
}
void Player::increaseHealthLevel(int amount){
this->m_Health += amount;
// but not beyond the maximum
if(this->m_Health > this->m_MaxHealth){
this->m_Health = this->m_MaxHealth;
}
}
int Player::getHealth(){
return this->m_Health;
}