0
\$\begingroup\$

I am making a game with SDL and C++. I am trying to render simple image to the screen but I can't. I am not getting any error but I see only black screen.

I think because the renderer in player is not the same in game they do not have the same memory address.

**my question **: is how to pass the renderer?

I have tried passing it through init() in player directly but it didn't work then.

game.h

#ifndef GAME_H
#define GAME_H

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

using namespace std;

class game
{
public:

    game();
    ~game();

    void init(char *title,int xpos, int ypos ,int xsize ,int ysize ,bool fullscreen);
    void loop();
    void input();
    void update();
    void render();
    SDL_Renderer* renderer;
    SDL_Window* window;

private:

    const int target_Fps = 60;
    const float TFEF = 1000/60; // time for each frame
    int delta;
    long int start_time;
    bool isrunning = true;
    int fps_counter = 0;
    unsigned int counter = 1;
};

#endif

game.cpp


#include "game.h"
#include "player.h"

player* pla;

game::game()
{
    cout << "something"<<endl;
    if (SDL_Init(SDL_INIT_EVERYTHING) == 0)
    {
        cout << "another thing" << endl;
        init("game",10,15,500,500,false);
    }

    loop();
}

game::~game()
{
}

void game::init(char *title,int xpos, int ypos ,int xsize ,int ysize ,bool fullscreen)
{
    window = SDL_CreateWindow(title, xpos,  ypos , xsize , ysize , fullscreen);
    renderer = SDL_CreateRenderer(window,-1,0);
    //SDL_SetRenderDrawColor(renderer, 0, 0,0, 255);
    SDL_RenderClear(renderer);
    SDL_RenderPresent(renderer);

    cout << "another another something" << endl;

    pla = new player(renderer,32,32);
    pla->init();

    //SDL_Texture* tex = IMG_LoadTexture(renderer,"res/pss.png");
}

void game::loop()
{
    while(isrunning)
    {
        start_time = SDL_GetTicks();

        input();
        update();
        render();

        delta = SDL_GetTicks() - start_time;
        if (delta < TFEF)
            SDL_Delay(TFEF - delta);

        fps_counter++;

        if (start_time >= 1000 * counter)
        {
            //cout <<"the FPS is : "<< fps_counter << endl;
            counter++;
            fps_counter = 0;
        }
    }
}

void game::input()
{
    SDL_Event e;
    SDL_PollEvent(&e);
    if (e.type == SDL_QUIT)
        SDL_Quit();
}

void game::update(){}

void game::render()
{
    SDL_RenderClear(renderer);
    pla->render(renderer);
    SDL_RenderPresent(renderer);
}

gameobject::~gameobject(){};

player.h


#ifndef PLAYER_H
#define PLAYER_H

#include "gameobject.h"

class gameobject;

class player : public gameobject
{
public:

    void init() override;
    void tick() override;
    void render(SDL_Renderer* renderer) override;
    SDL_Renderer* renderer;
    player(SDL_Renderer* renderer,int pwidth,int pheight);
private:

    ~player() override;
    SDL_Texture* playertex;
};

#endif // PLAYER_H

player.cpp


#include "player.h"

player::player(SDL_Renderer* renderer,int pwidth, int pheight)
{
   this->pos.w = pwidth;
   this->pos.h = pheight;
   this->pos.x = 0;
   this->pos.y = 0;

   this->renderer = renderer;
}

void player::init()
{
    this->playertex= IMG_LoadTexture(renderer,"res/pss.png");
    cout<<"int in player \n"<<endl;

    crop.x = 0;
    crop.y = 0;
    crop.w = 32;
    crop.h = 32;

    cout<<"pos x :"<<this->pos.x<<endl;
    cout<<"pos y : "<<this->pos.y<<endl;
    cout<<"pos w : "<<this->pos.w<<endl;
    cout<<"pos h : "<<this->pos.h<<endl;
    cout<<"crop x :"<<this->crop.x<<endl;
    cout<<"crop y :"<<this->crop.y<<endl;
    cout<<"crop w :"<<this->crop.w<<endl;
    cout<<"crop h : "<<this->crop.h<<endl;
}

void player::tick()
{
}

void player::render(SDL_Renderer *renderer)
{
/*
    cout<<"pos x :"<<this->pos.x<<endl;
    cout<<"pos y : "<<this->pos.y<<endl;
    cout<<"pos w : "<<this->pos.w<<endl;
    cout<<"pos h : "<<this->pos.h<<endl;
    cout<<"crop x :"<<this->crop.x<<endl;
    cout<<"crop y :"<<this->crop.y<<endl;
    cout<<"crop w :"<<this->crop.w<<endl;
    cout<<"crop h : "<<this->crop.h<<endl;
*/
    SDL_RenderCopy(renderer,playertex,&crop,&pos);
}

player::~player(){};

\$\endgroup\$
0
\$\begingroup\$

You should look at C++ language concepts, such as passing by reference, address, and value.

If I have a class, Foo, and another, Bar:

class Bar
{
public:
    int num;
};

class Foo
{
public:
    void doSomethingV(Bar bar);
    void doSomethingR(Bar& bar);
    void doSomethingA(Bar* bar);
};

Look at the doSomething* member functions: the first one passes the object by value, which means inside the function, a copy (new instance) is made of the Bar object. Typically we do not do this.

The second version is passing by reference. This is basically a pointer, but it has the extra safety of not allowing null values:

foo.doSomethingR(NULL); //generates a compiler error
foo.doSomethingR(bar); //works, as long as bar is an instance of an object(not pointer)

Do this when you can. Function definitions can treat the variable as an instance of an object instead of a pointer, but what really gets passed is the address of the object.

The final version, is passing by address, or pointer. As above, the calling convention is as follows:

foo.doSomethingA(NULL); //valid
foo.soSomethingA(&bar); //valid. '&' means "address of"

Use this when you have to.

Now to your case:

If you wish to store a copy of the renderer, then pass by value, or reference. Preferably reference.

If you wish to use the renderer, pass by reference only.

If you wish to store the address of the renderer, pass by pointer, or reference;

If you pass by pointer, your storing class must have a pointer member variable to receive the address like Renderer* m_renderer; which is then assigned like so:

player::player(SDL_Renderer* renderer,int pwidth, int pheight)
{
    pos.w = pwidth;
    pos.h = pheight;
    pos.x = 0;
    pos.y = 0;
    m_renderer = renderer;
}

If you pass by reference:

player::player(SDL_Renderer& renderer,int pwidth, int pheight)
{
    pos.w = pwidth;
    pos.h = pheight;
    pos.x = 0;
    pos.y = 0;
    m_renderer = &renderer;
}

Also, as a side note: the keyword this is only necessary when the argument name is the same as the member variable, which is whilst syntactically correct, considered poor practice. See my examples above for a better way to do it. Another use for this is when a class instance wishes to pass itself as an argument, like so:

Bar::doSomething(Foo& foo)
{
    foo.doSomethingA(this); //passes itself by pointer
    foo.doSomethingR(*this); //pass itself by reference. 
    // '*' is opposite of '&' operator and is called de-referencing a pointer
}
\$\endgroup\$
  • \$\begingroup\$ still didn't work this is my code they didn't let me to paste it here so i will just do it on paste online websitepastebin.com/MLL6jrbb \$\endgroup\$ – younlok Nov 11 at 13:41
  • \$\begingroup\$ I'm sorry, but you need to debug your own code. Stack Overflow is for asking specific questions. explore the concepts I described, until you understand them completely, then you should be able to solve your own problem. If not, you will be able to ask a more detailed, and specific question. \$\endgroup\$ – Ian Young Nov 11 at 13:49
  • \$\begingroup\$ iask a detailed about my code i tried what u said but nothing \$\endgroup\$ – younlok Nov 11 at 14:03
  • \$\begingroup\$ You asked about passing an object to another object: " **my question ** : is how to pass the renderer " ,which I answered. If that did not solve your problem, then update your question with what you have tried, and try to be more specific about what you want help with. \$\endgroup\$ – Ian Young Nov 11 at 14:55
  • \$\begingroup\$ now its the same memory-adress but still doesn't render \$\endgroup\$ – younlok Nov 11 at 15:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.