1

I've searched high and low for an answer to this question and have attempted many solutions including forward declaration, pointers, and references. I'm sure I'm just using incorrect syntax somewhere. After many wasted hours, I've decided to turn to stack overflow.

I am attempting to code one of my first CPP applications as a learning experience. Right now I have a Player and a Ball object. My Ball object must be able to access some of the member variables and methods in my player object. I have been unable to figure out how to do this. Below is an extremely simplified version of my code. I've commented the code that is particularly important.

PlayState.hpp

#ifndef PLAYSTATE_HPP
#define PLAYSTATE_HPP
#include "Player.hpp"
#include "Ball.hpp"

class Player;
class Ball;

class PlayState
{
public:
    PlayState();
    Player player;
    Ball ball;
 };
#endif

PlayState.cpp

#include "PlayState.hpp"

PlayState::PlayState() {
}

void PlayState::update() {

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
    {
        ball.checkCollision();
        player.move(1);
    }
    ball.update();
}

void PlayState::draw()
{
    m_game.screen.clear();
    m_game.screen.draw( player.getSprite() );
    m_game.screen.draw( ball.getSprite() );
    m_game.screen.display();
}

Player.hpp

#ifndef PLAYER_HPP
#define PLAYER_HPP

class Player
{
public:
    Player();
    ~Player();

    void create();
    void setRotation(float);
    void setPosition(float, float);
};
#endif

Player.cpp shouldn't really be all that important to see.

Ball.hpp

#ifndef BALL_HPP
#define BALL_HPP

class Player; // I don't think forward declaration is what I need???

class Ball
{
public:
    bool picked_up;
    bool throwing;

    Player *player; // this isn't working

    Ball();
    ~Ball();

    bool checkCollision();
};
#endif

Ball.cpp

#include "Ball.hpp"

Ball::Ball() {
    Ball::picked_up = false;
    Ball::throwing = false;
}

Ball::~Ball() {
}

bool Ball::checkCollision()
{
    float ball_position_x = Ball::getPosition().x;
    float ball_position_y = Ball::getPosition().y;

    // I need to access the player object here.
    float x_distance = abs(player.getPosition().x - ball_position_x);
    float y_distance = abs(player.getPosition().y - ball_position_y);

    bool is_colliding = (x_distance * 2 < (player.IMG_WIDTH + Ball::width)) && (y_distance * 2 < (player.IMG_HEIGHT + Ball::height));

    return is_colliding;
}
Mayur Birari
  • 5,837
  • 8
  • 34
  • 61

1 Answers1

0

When you say player, do you mean the exact same player that is in the same playstate object as the current ball object? If so you want to first set up that link, it cannot be done automatically.

PlayState::PlayState() :ball(&player){ //pass pointer to ball of its player?
}

class Ball
...    
Ball(Player *myPlayer);
...

}

Ball::Ball(Player *myPlayer):player(myPlayer) {
...

// I need to access the player object here.
float x_distance = abs(player->getPosition().x - ball_position_x);

You also need to use a pointer to use the player since it is a pointer to a player object.

You do need the forward declaration to Player above the Ball class. The one above Playstate is unnecessary.

Also your player doesnt seem to have a GetPosition function, I am assuming it is a public member function you forgot to include above.

Karthik T
  • 31,456
  • 5
  • 68
  • 87
  • Thank you for the answer. You are correct in your assumption that player is the same player in PlayState. I didn't include some of the functions to try to cut down some space in the question I was asking :) I'm attempting to implement your solution right now. Could you explain the following syntax for me? `PlayState::PlayState() :ball(&player)` specifically the `:ball()` – user1881255 Dec 06 '12 at 05:36
  • Its a way of initializing members in constructor, necessary for invoking member/base class constructors, more information can be found at http://www.cprogramming.com/tutorial/initialization-lists-c++.html or at http://stackoverflow.com/a/8523361/1520364 – Karthik T Dec 06 '12 at 05:50
  • Okay thanks. May I ask if there is a way to do this without the use of an initialization list? The solution you provided initialized the ball object with the player. The problem with this set up is that the Ball object can sometimes exist without a player object attached to it. I'm looking for a solution that doesn't involve initializing either object with the other object. I think a better solution for me would be to pass the player reference into specific functions that need to use it, or perhaps to have a member variable that stores the player and I can set it when I need to. – user1881255 Dec 06 '12 at 06:31
  • I've fixed the problem. I believe my problem was my forward declaration. It declared but I failed to include the proper header files so my object was never defined. – user1881255 Dec 06 '12 at 07:18
  • @user1881255, yes you can do it as you suggest, basically you need the correct instance at the correct time in order to call functions, initialization list is what is needed to get your current design to work, but you can change that how ever you want. And yes includes to atleast player.hpp is needed in ball.cpp – Karthik T Dec 06 '12 at 07:23