My console game doesn't accept keypresses until I hit the space bar once (VS 2022, C++)

61 Views Asked by At

I am just starting with coding and I am following the book "Beginning C++ Game Programming Second Edition" by John Horton, and so far everything works more or less as I expect, apparently there are some mistakes in the book, but nothing I couldn't handle so far.
Some info: The project is a c++ console app in Visual Studio 2022. Solution platform x86.
The main functions lets the game start out in a paused state called "GAME_OVER".

enum class State { PAUSED, LEVELING_UP, GAME_OVER, PLAYING };

State state = State::GAME_OVER;

How I expected things to work according to the code: You are in game over. You press "return" to enter the "LEVELING_UP" state. Then you press any NUM button from 1 to 6 to enter the "PLAYING" state, at which point the game is drawn.
Right now neither game over nor leveling up will draw anything, so the screen is black, but that's okay.
This should be the relevant code:

while (window.isOpen())
{
    /*
    *************
    HANDLE INPUT 
    *************
    */
    //handle events by polling
    Event event;
    while (window.pollEvent(event))
    {
        if (event.type == Event::KeyPressed)
        {
            //start game while in GAME_OVER state
            if (event.key.code == Keyboard::Return && state == State::GAME_OVER)
            {
                state = State::LEVELING_UP;
            }
        }
    }//end event polling
    
    //handle LEVELING_UP state
    if (state == State::LEVELING_UP)
    {
        if (event.key.code == Keyboard::Num1)
        {
            state = State::PLAYING;
        }
        if (event.key.code == Keyboard::Num2)
        {
            state = State::PLAYING;
        }
        if (event.key.code == Keyboard::Num3)
        {
            state = State::PLAYING;
        }
        if (event.key.code == Keyboard::Num4)
        {
            state = State::PLAYING;
        }
        if (event.key.code == Keyboard::Num5)
        {
            state = State::PLAYING;
        }
        if (event.key.code == Keyboard::Num6)
        {
            state = State::PLAYING;
        }
    }
}

What actually happens: Game starts in black screen. I need to press the "return" key. So far nothing happens (as it should). Pressing Num1 through 6 now doesn't do anything, although it should return the state to "PLAYING".
The game only starts when pressing space. Why space? The word "space" is in this class exactly once, at the very beginning outside main in "namespace". Any other event is either "return" or Num 1 through 6.

Why do I need to press space after pressing enter, and why do the Num keys not work?

I tried searching my code for instances of "space" in case I had just forgotten it somewhere, but the only instances of "space" in any classes or headers are "namespace".
I tried using the Num keys with Numlock on and off, makes no difference.
I tried using all kinds of other keys after pressing "enter" the first time, the game only starts when pressing space.
At this point I am out of ideas. Maybe this is a Visual Studio quirk? Or a console game quirk? I have no idea, and googling hasn't helped me, so far.

Thank you for reading, I am hoping someone can explain to me what is happening.

As requested, the full code for the main class:

#include <SFML/Graphics.hpp>
#include "Player.h"
#include "ZombieArena.h"
#include "TextureHolder.h"
#include "Bullet.h"
using namespace sf;

int main()
{
    TextureHolder holder;
    //the game will always be in on of four stages
    enum class State { PAUSED, LEVELING_UP, GAME_OVER, PLAYING };

    State state = State::GAME_OVER;
    //get 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 SFML window for main action
    View mainView(sf::FloatRect(0, 0, resolution.x, resolution.y));
    //clock for timing
    Clock clock;
    //how long PLAYING has been active
    Time gameTimeTotal;
    //where the mouse is in relation to world
    Vector2f mouseWorldPosition;
    //where the mouse is in relation to screen
    Vector2i mouseScreenPotition;
    //create player
    Player player;
    //boundaries of arena
    IntRect arena;
    //create background
    VertexArray background;
    Texture textureBackground = TextureHolder::GetTexture("graphics/background_sheet.png");
    //prepare horde
    int numZombies;
    int numZombiesAlive;
    Zombie* zombies = nullptr;
    //100 bullets array should do
    Bullet bullets[100];
    int currentBullet = 0;
    int bulletSpare = 24;
    int bulletsInClip = 6;
    int clipSize = 6;
    float fireRate = 1;
    //when was fire button last pressed?
    Time lastPressed;
    //hide mouse pointer and replace with crosshair
    window.setMouseCursorVisible(true);
    Sprite spriteCrosshair;
    Texture textureCrosshair = TextureHolder::GetTexture("graphics/crosshair.png");
    spriteCrosshair.setTexture(textureCrosshair);
    spriteCrosshair.setOrigin(25, 25);

    //main game loop
    while (window.isOpen())
    {
        /*
        *************
        HANDLE INPUT 
        *************
        */

        //handle events by polling
        Event event;
        while (window.pollEvent(event))
        {
            if (event.type == Event::KeyPressed)
            {
                //Pause game
                if (event.key.code == Keyboard::Return && state == State::PLAYING)
                {
                    state = State::PAUSED;
                }
                //restart while paused
                else if (event.key.code == Keyboard::Return && state == State::PAUSED)
                {
                    state = State::PLAYING;
                    //reset clock so there is no frame jump
                    clock.restart();
                }
                //start game while in GAME_OVER state
                else if (event.key.code == Keyboard::Return && state == State::GAME_OVER)
                {
                    state = State::LEVELING_UP;
                }

                if (state == State::PLAYING)
                {
                    //reloading
                    if (event.key.code == Keyboard::R)
                    {
                        if (bulletSpare >= clipSize)
                        {
                            //enough bullets
                            bulletsInClip = clipSize;
                            bulletSpare -= clipSize;
                        }
                        else if (bulletSpare > 0)
                        {
                            //not a full clip left
                            bulletsInClip = bulletSpare;
                            bulletSpare = 0;
                        }
                        else
                        {
                            //out of bullets
                        }
                    }
                }
            }
        }//end event polling
        //handle quitting
        if (Keyboard::isKeyPressed(Keyboard::Escape))
        {
            window.close();
        }

        //handle wasd while playing
        if (state == State::PLAYING)
        {
            if (Keyboard::isKeyPressed(Keyboard::W))
            {
                player.moveUp();
            }
            else
            {
                player.stopUp();
            }
            if (Keyboard::isKeyPressed(Keyboard::S))
            {
                player.moveDown();
            }
            else
            {
                player.stopDown();
            }
            if (Keyboard::isKeyPressed(Keyboard::A))
            {
                player.moveLeft();
            }
            else
            {
                player.stopLeft();
            }
            if (Keyboard::isKeyPressed(Keyboard::D))
            {
                player.moveRight();
            }
            else
            {
                player.stopRight();
            }
            //fire
            if (Mouse::isButtonPressed(sf::Mouse::Left))
            {
                if (gameTimeTotal.asMilliseconds() - lastPressed.asMilliseconds() > 1000 / fireRate && bulletsInClip > 0)
                {
                    //pass center of player and center of crosshair to shoot function
                    bullets[currentBullet].shoot(player.getCenter().x, player.getCenter().y, mouseWorldPosition.x, mouseWorldPosition.y);
                    currentBullet++;
                    if (currentBullet > 99)
                    {
                        currentBullet = 0;
                    }
                    lastPressed = gameTimeTotal;
                    bulletsInClip--;
                }
            }//end fire bullet
        }//end wasd handling while playing
        //handle LEVELING_UP state
        if (state == State::LEVELING_UP)
        {
            if (event.key.code == Keyboard::Num1)
            {
                state = State::PLAYING;
            }
            if (event.key.code == Keyboard::Num2)
            {
                state = State::PLAYING;
            }if (event.key.code == Keyboard::Num3)
            {
                state = State::PLAYING;
            }if (event.key.code == Keyboard::Num4)
            {
                state = State::PLAYING;
            }if (event.key.code == Keyboard::Num5)
            {
                state = State::PLAYING;
            }if (event.key.code == Keyboard::Num6)
            {
                state = State::PLAYING;
            }
            if (state == State::PLAYING)
            {
                //prepare the level
                arena.width = 500;
                arena.height = 500;
                arena.left = 0;
                arena.top = 0;

                //pass vertex array by reference to createBackground function
                int tileSize = createBackground(background, arena);
                player.spawn(arena, resolution, tileSize);
                //create horde
                numZombies = 10;
                //delete previous memory of horde
                delete[] zombies;
                zombies = createHorde(numZombies, arena);
                numZombiesAlive = numZombies;
                //frame jump
                clock.restart();
            }
        }//end LEVELING_UP

        /*
        *****************
        UPDATE THE FRAME
        *****************
        */
        if (state == State::PLAYING)
        {
            //update delta time
            Time dt = clock.restart();
            //update total game time
            gameTimeTotal += dt;
            //make a decimal fraction of 1 from the delta time
            float dtAsSeconds = dt.asSeconds();
            //where is the mouse
            mouseScreenPotition = Mouse::getPosition();
            //convert mouse position to coordinates of mainView
            mouseWorldPosition = window.mapPixelToCoords(Mouse::getPosition(), mainView);
            //set crosshair to mouse world location
            spriteCrosshair.setPosition(mouseWorldPosition);
            //update player
            player.update(dtAsSeconds, Mouse::getPosition());
            //make note of player new position
            Vector2f playerPosition(player.getCenter());
            //make view centre around player
            mainView.setCenter(player.getCenter());
            //loop through zombies and update
            for (int i = 0; i < numZombies; i++)
            {
                if (zombies[i].isAlive())
                {
                    zombies[i].update(dt.asSeconds(), playerPosition);
                }
            }
            //loop through bullets and update
            for (int i = 0; i < 100; i++)
            {
                if (bullets[i].isInFlight())
                {
                    bullets[i].update(dtAsSeconds);
                }
            }
        }//end updating scene
        /*
        ***************
        DRAW THE SCENE
        ***************
        */
        if (state == State::PLAYING)
        {
            window.clear();
            //set mainView and draw
            window.setView(mainView);
            //draw background
            window.draw(background, &textureBackground);
            //draw zombies
            for (int i = 0; i < numZombies; i++)
            {
                window.draw(zombies[i].getSprite());
            }
            for (int i = 0; i < 100; i++)
            {
                if (bullets[i].isInFlight())
                {
                    window.draw(bullets[i].getShape());
                }
            }
            //draw player
            window.draw(player.getSprite());
            //draw crosshair
            window.draw(spriteCrosshair);
        }
        if (state == State::LEVELING_UP)
        {

        }
        if (state == State::PAUSED)
        {

        }
        if (state == State::GAME_OVER)
        {

        }
        window.display();
    }//end game loop
    //delete memory
    delete[] zombies;
    return 0;
}
0

There are 0 best solutions below