Search code examples
c++sdl

Why isn't my C++ code rendering an SDL rectangle?


I'm new to using SDL with C++ and was trying to create a little Pong game as a project, too bad I can't actually render a rectangle! I have tried to figure out whats wrong, but I need somebody who actually knows SDL in depth help me. This is the code I am working with:

SystemManager.h

#pragma once
#include <SDL.h>
#include <cstdio>

class SystemManager {
const int SCREEN_WIDTH = 1000;
const int SCREEN_HEIGHT = 800;

public:
SDL_Window* m_window = nullptr;
SDL_Renderer* m_window_renderer = nullptr;

bool running = true;



bool Initialize() {
    SDL_Init(SDL_INIT_VIDEO);

    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        printf("SDL could not initialize! SDL Error: %s \n", SDL_GetError());

        return false;
    }
    else {
        m_window = SDL_CreateWindow("Pong", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_BORDERLESS);
        m_window_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_PRESENTVSYNC);

        if (m_window == NULL) {
            printf("SDL Window could not be constructed! SDL Error: %s \n", SDL_GetError());

            return false;
        }
    }



    return true;
}


void Render() {
    SDL_SetRenderDrawColor(m_window_renderer, 0, 0, 0, 255);
    SDL_RenderPresent(m_window_renderer);
}
};

Player.h

#pragma once

#include "SystemManager.h"



class Player : public SystemManager {
int y_axis = 400;

public:
void Player_Draw() {
    SDL_SetRenderDrawColor(m_window_renderer, 0, 0, 0, 255);
    SDL_RenderClear(m_window_renderer);



    SDL_Rect pong1;

    pong1.w = 30;
    pong1.h = 50;
    pong1.x = 970;
    pong1.y = 400;

    SDL_SetRenderDrawColor(m_window_renderer, 255, 255, 255, 255);
    SDL_RenderFillRect(m_window_renderer, &pong1);
}



void Inputs() {

}
};

And Main.cpp

#include <SDL.h>

#include "Player.h"



int main(int argc, char* argv[]) {
SystemManager System;
Player PlayerPong;

Might somebody help explain to me what I'm doing wrong?

System.Initialize();

if (System.Initialize() == false) {
    return -1;
}



while (System.running == true) {
    PlayerPong.Player_Draw();
    System.Render();
}



SDL_DestroyWindow(System.m_window);
SDL_DestroyRenderer(System.m_window_renderer);
SDL_Quit();

return 0;
}

Solution

  • First, if you do not understand my written explanation, I can create video and explain line by line how to fix your code.

    So, there are many errors with your code. In the first part of the explanation I will explain why it does not work. In the second part, I will show you the correct way of writing your header files as well as some other problems. In the third part I will give you the code to make it work.

    PART 1: Why your code isn't working

    The first thing I noticed is that you are calling some functions twice on accident. If you check the return value of a function in a conditional, the function is called.

    SDL_Init(SDL_INIT_VIDEO);
    if (SDL_Init(SDL_INIT_VIDEO) != 0) 
    

    For instance in this code you call SDL_Init(SDL_INIT_VIDEO) twice. Instead delete the first and just call the function in the conditional. You also do that here:

    System.Initialize();
    if (System.Initialize() == false)
    

    Keep in mind, as of now, if your code were to run you would not be able to exit the window, because you are not checking if the window should be closed.

    You also need to go back and learn how inheritance. When you draw the rectangle you pass in the window pointer from the inherited SystemManager. The problem is that this is a copy of the window pointer. Instead you should pass in the render pointer when you call the player render function. If you look at my example code at the bottom I do this.

    Define the function like this:

    void Player_Draw(SDL_Renderer* render) {
        SDL_SetRenderDrawColor(render, 255, 255, 255, 255);
        SDL_RenderFillRect(render, &pong1);
    }
    

    Call the function like this:

    SDL_RenderClear(System.m_window_renderer);
    

    PART 2: Other things you happen to be doing incorrectly

    First fix the issues I described previously.

    You are using header files in a way that most people say you shouldn't. You are defining the class function inside the header. Instead, you should create a second file with the .c extension that defines the class functions.

    Here is a link that will show you the proper way to write header fies: https://www.learncpp.com/cpp-tutorial/89-class-code-and-header-files/

    Also, when you init sdl, you should check the if the return value is less than zero instead of !0. It's a little nit picky so you can ignore this if you want.

    Example:

    if (SDL_Init(SDL_INIT_VIDEO) < 0)
    

    PART 3: The fixed code

    I fixed your code and put it all into one c file. Here is the fixed code:

    #include <iostream>
    #include <SDL2/SDL.h>
    
    class SystemManager {
        const int SCREEN_WIDTH = 1000;
        const int SCREEN_HEIGHT = 800;
    
        public:
        SDL_Window* m_window = nullptr;
        SDL_Renderer* m_window_renderer = nullptr;
    
        bool running = true;
        bool Initialize() {
    
            if (SDL_Init(SDL_INIT_VIDEO) != 0) {
                printf("SDL could not initialize! SDL Error: %s \n", SDL_GetError());
    
                return false;
            }
            else {
                m_window = SDL_CreateWindow("Pong", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
                m_window_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_PRESENTVSYNC);
    
                if (m_window == NULL) {
                    printf("SDL Window could not be constructed! SDL Error: %s \n", SDL_GetError());
                    return false;
                }
            }
    
            return true;
        }
    
    
        void Render() {
            SDL_SetRenderDrawColor(m_window_renderer, 0, 0, 0, 255);
            SDL_RenderPresent(m_window_renderer);
        }
    };
    
    class Player : public SystemManager {
        int y_axis = 400;
        SDL_Rect pong1;
    
        public:
    
        Player(){
            pong1.w = 100;
            pong1.h = 100;
            pong1.x = 100;
            pong1.y = 100;
        }
    
        void Player_Draw(SDL_Renderer* render) {
            SDL_SetRenderDrawColor(render, 255, 255, 255, 255);
            SDL_RenderFillRect(render, &pong1);
        }
    
    
    
        void Inputs() {
    
        }
    };
    
    int main(int argc, char* argv[]) {
        SystemManager System;
        Player PlayerPong;
    
        if (System.Initialize() == false) {
            return -1;
        }
    
    
    
        while (System.running == true) {
            SDL_SetRenderDrawColor(System.m_window_renderer, 0, 0, 0, 255);
            SDL_RenderClear(System.m_window_renderer);
            PlayerPong.Player_Draw(System.m_window_renderer);
            System.Render();
        }
    
        SDL_DestroyWindow(System.m_window);
        SDL_DestroyRenderer(System.m_window_renderer);
        SDL_Quit();
    
        return 0;
    }
    

    If you are using linux, you can compile with:

    g++ Main.cpp -lSDL2