Search code examples
c++classsdlinstantiationgame-development

Player classes instantiated by argument C++ SDL


So, again, making a pong clone, and run into a bump. I'm creating the game class gamestate for my state machine and in the definition, I instantiate two classes of the class I've created for the the different player paddles and I give them two different arguments that will decide if the class becomes the player one or player two object.

But it seems like the program won't allow me to pass an argument in the class definition. I've tried to put the class instantiation in the game class constructor but then the events/logic/render functions don't have access to the paddle classes. That leads me to think it has to be in the game class definition. Here's the code presenting the problem.

class Ball
{
public:
    void events();
    void logic();
    void render();
    Ball(int server);
    ~Ball();
};

class Paddle
{
private:
    SDL_Rect Paddle_Bound;
    int yVel;
    SDL_Rect *clip;
    int player_key;
public:
    void events();
    void logic();
    void render();
    Paddle(int player);
    ~Paddle();
};

class Game : public GameState
{
private:
    int server;
    TTF_Font *score = NULL;
    Paddle PlayerOne(1);
    Paddle Playertwo(2);
    Ball Ball(2);
public:
    void events();
    void logic();
    void render();
    Game();
    ~Game();
};

The lines that say

Paddle PlayerOne(1);
Paddle Playertwo(2);
Ball Ball(2);

Are the ones raising errors that say "expected a type specifier". Now I know that means it wants something like int player but I need to pass a number so that the constructor can decide which player it'll be, which ultimately decides what keys move the class up and down the screen. So to be perfectly clear, I want to be able to pass an argument to a class instantiation so that the class constructor can turn the class into the left OR the right paddle. So how do I go about instantiating a class, inside another class, using arguments?

Thanks!

EDIT: For the constructor problem I have another example that is fully coded where I can't put the class initializer in the constructor. So basically in the title screen there is one button, and it has properties stored in a Button class that I create to manage buttons.

class GameState
{
public:
    virtual void events() = 0;
    virtual void logic() = 0;
    virtual void render() = 0;
    virtual ~GameState(){};
};

class Button
{
public:
    SDL_Rect button_clip[2];
    SDL_Rect button;
    SDL_Surface *button_sprite = NULL;
    Button();
};

class Title : public GameState
{
private:
    SDL_Surface *Title_Message = NULL;
    SDL_Rect *clip;
    // THIS IS WHERE I HAVE TO PLACE THIS LINE 
    //Button Title_Button;
public:
    void events();
    void logic();
    void render();
    Title();
    ~Title();
};

Title::Title()
{
    //THIS IS WHERE IT SHOULD BE ACCORDING TO WHAT YOU'RE TELLING ME
    Button Title_Message;
    //text/sprites
    Title_Message = TTF_RenderText_Solid(font, "PONG", color);
    Title_Button.button_sprite = load_image("Start.png");
    //region for button
    Title_Button.button.x = 200;
    Title_Button.button.y = 350;
    Title_Button.button.w = 100;
    Title_Button.button.h = 50;
    //clips not hover
    Title_Button.button_clip[0].x = 0;
    Title_Button.button_clip[0].y = 0;
    Title_Button.button_clip[0].w = 100;
    Title_Button.button_clip[0].h = 50;
    //clips hover
    Title_Button.button_clip[1].x = 0;
    Title_Button.button_clip[1].y = 50;
    Title_Button.button_clip[1].w = 100;
    Title_Button.button_clip[1].h = 50;
}

Title::~Title()
{
    SDL_FreeSurface(Title_Message);
    SDL_FreeSurface(Title_Button.button_sprite);
}

void Title::events()
{
    int x = 0;
    int y = 0;
    while (SDL_PollEvent(&event))
    {
        if (event.type == SDL_MOUSEMOTION)
        {
            x = event.motion.x;
            y = event.motion.y;
            if ((x > Title_Button.button.x) && (x < (Title_Button.button.x + Title_Button.button.w)) && (y > Title_Button.button.y) && (y < (Title_Button.button.y + Title_Button.button.h)))
            {
                clip = &Title_Button.button_clip[1];
            }
            else
            {
                clip = &Title_Button.button_clip[0];
            }
        }
        if (event.type == SDL_QUIT)
        {
            quit = true;
        }
        if (event.type == SDL_MOUSEBUTTONDOWN)
        {
            if (event.button.button == SDL_BUTTON_LEFT)
            {
                if ((x > Title_Button.button.x) && (x < (Title_Button.button.x + Title_Button.button.w)) && (y > Title_Button.button.y) && (y < (Title_Button.button.y + Title_Button.button.h)))
                {
                    set_next_state(GAME);
                }
            }
        }
    }
}

void Title::logic()
{

}

void Title::render()
{
    apply_surface(Title_Button.button.x, Title_Button.button.y, Title_Button.button_sprite, screen, clip);
    apply_surface((SCREEN_WIDTH - Title_Message->w) / 2, 100, Title_Message, screen);
}

The problem here is that the events/logic/render functions have no clue that Title_Message exists when I put it in the void Title::Title() constructor. But when I put it in the class definition, I can't pass an argument through it.


Solution

  • The values should be initialized in the constructor definiton: not in the class definition.

    class Game : public GameState
    {
    private:
        int server;
        TTF_Font *score;
        Paddle PlayerOne;
        Paddle Playertwo;
        Ball ball;  // same class name and variable name won't work
    public:
        void events();
        void logic();
        void render();
        Game();
        ~Game();
    };
    ...
    Game::Game()
    :   score(NULL)
    ,   PlayerOne(1)
    ,   PlayerTwo(2)
    ,   ball(2)
    {
    ...
    }
    

    EDIT: For the Title message stuff

    class Title : public GameState
    {
    private:
        SDL_Surface *Title_Message = NULL;
        SDL_Rect *clip;
        // THIS IS WHERE I HAVE TO PLACE THIS LINE 
        Button Title_Button;
        Button Title_Message;
    public:
        void events();
        void logic();
        void render();
        Title();
        ~Title();
    };
    
    Title::Title()
    {
        //text/sprites
        Title_Message = TTF_RenderText_Solid(font, "PONG", color);
        Title_Button.button_sprite = load_image("Start.png");