1

so i've been working on a game system/engine, for my 2D Platformer, and when i press the w, a, s, or d keys it won't move when called in the main loop event.

Here is all of my project files and everything that i've written: main.cpp:

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#include <vector>

#include "RenderWindow.hpp"
#include "Entity.hpp"
#include "Utils.hpp"

int main(int argc, char const *argv[])
{
    
    if (SDL_Init(SDL_INIT_VIDEO) > 0)
        std::cout << "ERROR: SDL_Init() HAS FAILED: SDL_ERROR => " << SDL_GetError() << std::endl;

    if (!(IMG_Init(IMG_INIT_PNG)))
        std::cout << "ERROR: IMG_Init() HAS FAILED: SDL_ERROR => " << SDL_GetError() << std::endl;

    RenderWindow window("GAME v1.0", 1280, 720);

    SDL_Texture* grassTexture = window.loadTexture("res/gfx/ground_grass.png");
    SDL_Texture* playerTexture = window.loadTexture("res/gfx/ghost.png");

    std::vector<Entity> platforms = {Entity(Vector2f(0, 30), grassTexture),
                                     Entity(Vector2f(30, 30), grassTexture),
                                     Entity(Vector2f(30, 30), grassTexture),
                                     Entity(Vector2f(60, 30), grassTexture)};

    Entity player(Vector2f(30, 8), playerTexture);

    bool gameRunning = true;

    SDL_Event event;

    const float timeStep = 0.01f;
    float accumulator = 0.0f;
    float currentTime = utils::hireTimeInSeconds();



    while(gameRunning)
    {

        int startTicks = SDL_GetTicks();

        float newTime = utils::hireTimeInSeconds();
        float frameTime = newTime - currentTime;

        currentTime = newTime;
        accumulator += frameTime;

        while(accumulator >= timeStep)
        {
            // Get out controls and events
            while(SDL_PollEvent(&event))
            {
                if (event.type == SDL_QUIT)
                {
                    gameRunning = false;
                    break;

                    // window.freeTexture(grassTexture);
                    // window.freeTexture(playerTexture);
                }
                
                // Add code to move the player texture
                const Uint8* currentKeyStates = SDL_GetKeyboardState(NULL);
                Vector2f& playerPos = player.getPos();
                if(currentKeyStates[SDL_SCANCODE_W]) {
                    playerPos.y -= 1;
                    break;
                }
                if(currentKeyStates[SDL_SCANCODE_S]) {
                    playerPos.y += 1;
                    break;
                }
                if(currentKeyStates[SDL_SCANCODE_A]) {
                    playerPos.x -= 1;
                    break;
                }
                if(currentKeyStates[SDL_SCANCODE_D]) {
                    playerPos.x += 1;
                    break;
                }
            }

            window.clear();

            for (Entity& e : platforms)
            {
                window.render(e);
                window.render(player);
            }
            window.display();

            // // Add code to move the player texture
            // const Uint8* currentKeyStates = SDL_GetKeyboardState(NULL);
            // Vector2f& playerPos = player.getPos();

            // if(currentKeyStates[SDL_SCANCODE_W]) {
            //     playerPos.y -= 1;
            // }
            // if(currentKeyStates[SDL_SCANCODE_S]) {
            //     playerPos.y += 1;
            // }
            // if(currentKeyStates[SDL_SCANCODE_A]) {
            //     playerPos.x -= 1;
            // }
            // if(currentKeyStates[SDL_SCANCODE_D]) {
            //     playerPos.x += 1;
            // }

            //playerPos.print();

            accumulator -= timeStep;
            // std::cout << accumulator << std::endl;
        }

        // const float alpha = accumulator / timeStep; // 50%?

        // window.freeTexture(grassTexture);
        // window.freeTexture(playerTexture);

        int frameTicks = SDL_GetTicks() - startTicks;

        if (frameTicks < 1000 / window.getRefreshRate())
            SDL_Delay(100 / window.getRefreshRate() - frameTicks);
    }

    window.cleanUp();
    SDL_Quit();

    return 0;
}

renderwindow.hpp:

#pragma once
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

#include "Entity.hpp"

class RenderWindow
{
public:
    RenderWindow(const char* p_title, int p_w, int p_h);
    SDL_Texture* loadTexture(const char* p_filePath);

    int getRefreshRate();

    void cleanUp();
    void clear();
    void render(Entity& p_entity);
    //void freeTexture(SDL_Texture* p_tex);
    void display();
private:
    SDL_Window* window;
    SDL_Renderer* renderer;
};

renderwindow.cpp:

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>

#include "RenderWindow.hpp"
#include "Entity.hpp"

RenderWindow::RenderWindow(const char* p_title, int p_w, int p_h)
    :window(NULL), renderer(NULL)
{
    window = SDL_CreateWindow(p_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, p_w, p_h, SDL_WINDOW_SHOWN);

    if (window == NULL)
    {
        std::cout << "ERROR: Window has failed to init! SDL_Error: " << SDL_GetError() << std::endl;
    }

    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

}

SDL_Texture* RenderWindow::loadTexture(const char* p_filePath)
{
    SDL_Texture* texture = NULL;
    texture = IMG_LoadTexture(renderer, p_filePath);

    if (texture == NULL)
        std::cout << "ERROR: Failed to load texture! SDL_Error: " << SDL_GetError() << std::endl;

    return texture;
}

int RenderWindow::getRefreshRate()
{
    int displayIndex = SDL_GetWindowDisplayIndex(window);

    SDL_DisplayMode mode;

    SDL_GetDisplayMode(displayIndex, 0, &mode);

    return mode.refresh_rate;
}

void RenderWindow::cleanUp()
{
    SDL_DestroyWindow(window);
}

void RenderWindow::clear()
{
    SDL_RenderClear(renderer);
}

void RenderWindow::render(Entity& p_entity)
{
    SDL_Rect src;
    src.x = p_entity.getCurrentFrame().x;
    src.y = p_entity.getCurrentFrame().y;
    src.w = p_entity.getCurrentFrame().w;
    src.h = p_entity.getCurrentFrame().h;

    SDL_Rect dst;
    dst.x = p_entity.getPos().x * 4;
    dst.y = p_entity.getPos().y * 4;
    dst.w = p_entity.getCurrentFrame().w * 4;
    dst.h = p_entity.getCurrentFrame().h * 4;

    SDL_RenderCopy(renderer, p_entity.getTex(), &src, &dst);
}

// void RenderWindow::freeTexture(SDL_Texture* p_tex) {

//     SDL_DestroyTexture(p_tex);
// }

void RenderWindow::display()
{
    SDL_RenderPresent(renderer);
}

Entity.hpp:

#pragma once
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

#include "Math.hpp"

class Entity
{
public:
    Entity(Vector2f p_pos, SDL_Texture* p_tex);
    Vector2f& getPos()
    {
        return pos;
    }
    void setPos(Vector2f p_pos)
    {
        pos = p_pos;
    }
    SDL_Texture* getTex();
    SDL_Rect getCurrentFrame();
private:
    Vector2f pos;
    SDL_Rect currentFrame;
    SDL_Texture* tex;
};

entity.cpp:

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

#include "Entity.hpp"
#include "Math.hpp"

Entity::Entity(Vector2f p_pos, SDL_Texture* p_tex)
:pos(p_pos), tex(p_tex)
{
    currentFrame.x = 0;
    currentFrame.y = 0;
    currentFrame.w = 32;
    currentFrame.h = 32;
}

SDL_Texture* Entity::getTex()
{
    return tex;
}

SDL_Rect Entity::getCurrentFrame()
{
    return currentFrame;
}

math.hpp:

#pragma once

#include <iostream>

struct Vector2f
{
    Vector2f()
    :x(0.0f), y(0.0f) 
    {}

    Vector2f(float p_x, float p_y)
    :x(p_x), y(p_y)
    {}

    void print()
    {
        std::cout << x << ", " << y << std::endl;
    }

    float x, y;
};

Utils.hpp:

#pragma once
#include <SDL2/SDL.h>

namespace utils
{
    inline float hireTimeInSeconds()
    {
        float t = SDL_GetTicks();
        t *= 0.001f;

        return t;
    }
}

Thanks!

  • You might consider trimming this down to something much more minimal. You might even figure out what the issue is yourself in the process. – Retired Ninja Jan 21 '23 at 18:43
  • I don't actually know, because i've been trying now for the past 3 days – Ralph Turner Jan 21 '23 at 18:45
  • Remove everything you do not need to duplicate the problem. Do you need grass? Nope. Do you need platforms? Nope. Did you realize you're rendering the player once per platform? Maybe not. Could that be related to the issue? Maybe. Do you need the commented out code? Nope. – Retired Ninja Jan 21 '23 at 18:50
  • I actually tried without rendering it once per platform, and didn't succeed – Ralph Turner Jan 21 '23 at 18:53
  • Note: the player can move when hey held down, but once lifted, you can't move it then even if you pressed it – Ralph Turner Jan 21 '23 at 18:54

1 Answers1

0

This is an updated version of my code, i've figured it out.

It turns out the problem was:

if (frameTicks < 1000 / window.getRefreshRate())
            SDL_Delay(100 / window.getRefreshRate() - frameTicks);

was actually delaying it by 100 instead of 1000.