Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Displaying a white screen  (Read 3023 times)

0 Members and 1 Guest are viewing this topic.

SpecterPhoenix

  • Newbie
  • *
  • Posts: 4
    • View Profile
Displaying a white screen
« on: January 01, 2018, 01:15:43 pm »
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;
}

 

NGM88

  • Full Member
  • ***
  • Posts: 162
    • View Profile
Re: Displaying a white screen
« Reply #1 on: January 01, 2018, 06:57:19 pm »
I tested the code, the player sprite is drawn when I call state = State::PLAYING; right before the "// draw the scene" part. The game logic is a mess though, I can't blame anyone for getting lost in this. Your game starts at the game over state.

SpecterPhoenix

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Displaying a white screen
« Reply #2 on: January 01, 2018, 09:19:51 pm »
Thanks. I also noticed, after sleeping, that I goofed the event code as I did state == State::LEVELING_UP; instead of assigning it to state. This goof raised a question for me though. Is there no way to check, later in the code after loading an image into sf::Texture, to see if it still holds the data (ie print out the string, in my case 'graphics/player.png')?

NGM88

  • Full Member
  • ***
  • Posts: 162
    • View Profile
Re: Displaying a white screen
« Reply #3 on: January 01, 2018, 10:27:25 pm »
By "data" do you mean the player texture? It will be held in the gpu memory until player falls out of scope.

SpecterPhoenix

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Displaying a white screen
« Reply #4 on: January 02, 2018, 12:48:10 am »
I'm not sure how to word it. Just for debugging purposes, I was curious what method should be used, when you get white screen, to check if Texture is still pointing to a valid location/file. I know mine isn't going out of scope, but in the chance it was a scope issue. That is what I meant by "data". loadFromFile loads player.png into GPU memory, is there a way to check if that memory location or data it holds is the same as when you assigned it or if it went out of scope due to a mishap? I'm so sorry if I'm not being clear as I'm not 100% positive myself how to word the question properly.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Displaying a white screen
« Reply #5 on: January 02, 2018, 06:40:00 am »
I don't know if it is related to your problem, but you're using "event" outside the event loop, which is undefined behaviour.
Laurent Gomila - SFML developer

NGM88

  • Full Member
  • ***
  • Posts: 162
    • View Profile
Re: Displaying a white screen
« Reply #6 on: January 02, 2018, 02:20:19 pm »
I'm not sure how to word it. Just for debugging purposes, I was curious what method should be used, when you get white screen, to check if Texture is still pointing to a valid location/file. I know mine isn't going out of scope, but in the chance it was a scope issue. That is what I meant by "data". loadFromFile loads player.png into GPU memory, is there a way to check if that memory location or data it holds is the same as when you assigned it or if it went out of scope due to a mishap? I'm so sorry if I'm not being clear as I'm not 100% positive myself how to word the question properly.

Assigning the texture to a sprite won't change its address. The only problem I can think of that comes close to this is that the sprite will lose the reference to its texture if you copy player somehow, like a push_back to a vector. Otherwise everything should be fine.

NGM88

  • Full Member
  • ***
  • Posts: 162
    • View Profile
Re: Displaying a white screen
« Reply #7 on: January 02, 2018, 02:21:57 pm »
I don't know if it is related to your problem, but you're using "event" outside the event loop, which is undefined behaviour.

Speaking of the code in general, I will also add that you should always call clear on the window, it should not be in some game state.

SpecterPhoenix

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Displaying a white screen
« Reply #8 on: January 05, 2018, 09:02:36 pm »
Well, it's a shame to know I wasted money on a set of videos that do a terrible job at teaching game development, C++, and SFML.