I'm trying to code a simple game, where the main.cpp file instantiates the Game class, and the Game class instantiates the Player class. I want the Player class to have access to the Game class' variables, so I guess the best way to do that is to have the Game class pass itself to the Player class:
game.h
#pragma once
#include <raylib.h>
#include "player.h"
class Game
{
public:
Game();
void run();
private:
void update();
void draw();
Player player;
};
game.cpp
#include "game.h"
Game::Game() : player(this, { 0, 0, 0 })
{
}
void Game::run()
{
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "teste");
SetTargetFPS(60);
while (!WindowShouldClose())
{
update();
draw();
}
CloseWindow();
}
void Game::update()
{
player.update();
}
void Game::draw()
{
BeginDrawing();
ClearBackground(RAYWHITE);
EndDrawing();
}
player.h
#pragma once
#include <raylib.h>
#include "game.h"
class Player
{
public:
Player(Game* game, Vector3 pos);
void update();
void draw();
Game* game;
Vector3 pos;
};
player.cpp
#include "player.h"
Player::Player(Game* game, Vector3 pos)
{
this->game = game;
this->pos = pos;
speed = .1;
}
void Player::update()
{
if (IsKeyDown(KEY_D)) pos.x += 1;
if (IsKeyDown(KEY_A)) pos.x += -1;
if (IsKeyDown(KEY_S)) pos.z += 1;
if (IsKeyDown(KEY_W)) pos.z += -1;
}
void Player::draw()
{
}
The code seems fine to Intellisense, but the compiler just throws a bunch of errors.
I tried passing this as an argument to the Player class constructor, but it didn't work out, as the compiler doesn't accept it.
You have a circular dependency between your header files.
game.h depends on player.h, because the Game::player member is a Player instance, not a Player* pointer or Player& reference, so the complete Player class declaration is needed. This is fine.
However, player.h depends on game.h, but Game hasn't been declared yet (because of the header guard in game.h) when the Player class declaration is compiled.
Since the Player::game member is just a Game* pointer, you can use a forward declaration to break that header dependency, eg:
game.h
#pragma once
//#include <raylib.h> // <-- game.h doesn't use anything from this, so move it to game.cpp
#include "player.h" // <-- needed here because of Game::player
class Game
{
public:
Game();
void run();
private:
void update();
void draw();
Player player;
};
game.cpp
#include "game.h"
#include <raylib.h> // <-- move here
Game::Game() : player(this, { 0, 0, 0 })
{
}
...
player.h
#pragma once
#include <raylib.h> // <-- leave here if it declares Vector3
//#include "game.h" // <-- move to player.cpp
class Game; // <-- use this forward declaration instead
class Player
{
public:
Player(Game* game, Vector3 pos);
void update();
void draw();
Game* game;
Vector3 pos;
};
player.cpp
#include "player.h"
#include "game.h" // <-- move here
Player::Player(Game* game, Vector3 pos)
{
this->game = game;
...
}
...
In short, a header file should #include only the things it actually uses directly. Anything else should be #include'd in the .cpp file instead. But, anything in a header file that is just a pointer or reference can be forward-declared without using an #include. Keep your #includes to a minimum in header files. The compilation process will be cleaner and more efficient because of it.
Related
I have three classes, 2 of which rely on the functionality of each other, and one which contains pointers to and is included in both:
Player:
#pragma once
#include <SFML\Graphics.hpp>
#include "RenderableObject.h"
//#include "Renderer.h"
class Renderer;
class Player : public RenderableObject
{
public:
Player(int size, Renderer* renderer);
~Player();
void render();
void setX(int x);
void setY(int y);
int getX();
int getY();
void setVelX(float x);
void setVelY(float y);
float getVelx();
float getVely();
int getSize();
private:
int size;
int x;
int y;
float velx;
float vely;
Renderer* ren;
};
GameManager:
#pragma once
#include "Player.h"
class Renderer;
class GameManager
{
public:
GameManager(Renderer* r);
~GameManager();
Player* getBall();
private:
Player* ball;
};
Renderer:
#pragma once
#include <SFML\Graphics.hpp>
#include "GameManager.h"
#include "Player.h"
class Renderer
{
public:
Renderer(GameManager* game);
~Renderer();
sf::RenderWindow* getWindow();
void draw();
void renderCircle(int size, int x, int y);
void renderSquare(int size, int x, int y);
private:
sf::RenderWindow* win;
GameManager* game;
Player* ball;
};
I suspect there is some sort of circular dependency going on here. I managed to reduce the 60 odd errors down to 3, by adding "class Renderer;" to the Player header file. However, I'm now receiving "Use of undefined type" errors.
It might help to give a higher level view of what I want to achieve:
The GameManager object should hold an instance (maybe more) of player. This GameManager object is shared between subsystems such as Renderer so they all have access to the same resources.
The Renderer object should be able to call the Player object's (retrieved from the GameManager object) render() function, which in turn should call back to the Renderer object's renderCircle() object.
I'm hoping this is a simple case of re-arranging the includes, without having to re-design what I've already done.
In a header file, where you only declare variables that are pointers or references, all the compiler needs to know is that a class exists, nothing more. It doesn't need to know how big it it, or what members the class have. Therefore it's enough with a forward declaration.
However, in the source files where the variable is used, objects are created, and member functions are called, then the compiler need the full definition which means you have to include your whole header file.
Taking your code, simplified:
Player.h
#pragma once
class Renderer;
class Player
{
public:
Player(Renderer*);
private:
Renderer* ren;
};
GameManager.h
#pragma once
class Renderer;
class GameManager
{
public:
GameManager(Renderer*);
private:
Renderer* ren;
};
Renderer.h:
#pragma once
class Player;
class GameManager;
class Renderer
{
public:
Renderer(GameManager*);
private:
GameManager* game;
Player* ball;
};
The above header files are about the same that you already have, with the exception that I used forward declarations in Renderer.h instead.
Now the Renderer.cpp source file, where the Player and GameManager objects are actually created and used, we need the full definition from the header files:
#include "Renderer.h"
#include "Player.h"
#include "GameManager.h"
Renderer::Renderer(GameManager* game)
: game(game), ball(new Player)
{
}
// Other functions that calls member function in the `man` and `ball` objects
Of course, you need to #include "Renderer.h" in the Player.cpp and GameManager.cpp source files.
If you have other errors, they are because of other things you done, not because of the circular dependencies, as those have been solved with the forward declarations.
In SFML I wanted to have a sprite but with other functions and variables so i decided to create a class that inherits the sprite class like this:
1. Player.hpp
#pragma once
#include <stdio.h>
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
class Player : sf::Sprite{
public:
void setup();
void input();
private:
int direction;
void moveRight();
void moveLeft();
sf::Texture textures[8];
};
2(WIP). Player.cpp
void Player::setup(){
direction = 0;
textures[0].loadFromFile("images/player_right_still.png");
textures[1].loadFromFile("images/player_right_jump.png");
textures[2].loadFromFile("images/player_right_walk1.png");
textures[3].loadFromFile("images/player_right_walk2.png");
textures[4].loadFromFile("images/player_left_still.png");
textures[5].loadFromFile("images/player_left_jump.png");
textures[6].loadFromFile("images/player_left_walk1.png");
setTexture(textures[0]);
}
void Player::input(){
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right) || sf::Keyboard::isKeyPressed(sf::Keyboard::D)){
moveRight();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Keyboard::isKeyPressed(sf::Keyboard::A)){
moveLeft();
}
}
void Player::moveRight(){
}
void Player::moveLeft(){
}
game.cpp (picture because SO is being weird on me)
But when I compile it I get this error:
game.cpp: In function ‘int main()’:
game.cpp:23:27: error: ‘sf::Drawable’ is an inaccessible base of ‘Player’
window.draw(player);
class Player : sf::Sprite means that inheritance is private, that is code using instances of Player class won't be able to cast it to Sprite or access methods inherited from Sprite class. You should change inheritance to public:
class Player: public sf::Sprite
I'm making a game in C++. I have a player and enemy class that inherit my mob class. I would like my constructor in the enemy class to have a different constructor than my mob class, but it doesn't seem to work.
Mob.h
#pragma once
#include <SFML/Graphics.hpp>
class Mob
{
public:
Mob();
~Mob();
void update();
void render();
protected:
static sf::Sprite mSprite;
static float mSpeed;
};
Mob.cpp
#include <SFML/Graphics.hpp>
#include "Enemy.h"
#include "Player.h"
Mob::Mob()
{
}
Mob::~Mob() {
}
Enemy.h
#pragma once
#include <SFML/Graphics.hpp>
#include "Mob.h"
class Enemy : public Mob
{
public:
Enemy(sf::Sprite sprite);
~Enemy();
void update(float delta, Player player);
void render(sf::RenderWindow& window);
};
Enemy.cpp
#include <SFML/Graphics.hpp>
#include "Enemy.h"
#include "Player.h"
Enemy::Enemy(sf::Sprite sprite)
{
mSprite = sprite;
mSpeed = 150.0f;
}
Enemy::~Enemy() {
}
void Enemy::update(float delta, Player player) {
}
void Enemy::render(sf::RenderWindow& window) {
window.draw(mSprite);
}
Player.h
#pragma once
#include <SFML/Graphics.hpp>
#include "Mob.h"
class Player : public Mob
{
public:
Player(sf::Sprite sprite);
~Player();
void update(float delta);
void render(sf::RenderWindow& window);
};
Player.cpp
#include <SFML/Graphics.hpp>
#include "Player.h"
Player::Player(sf::Sprite sprite)
{
mSprite = sprite;
mSpeed = 150.0f;
}
Player::~Player() {
}
void Player::update(float delta) {
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
{
mSprite.move(0, -mSpeed * delta);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
{
mSprite.move(-mSpeed * delta, 0);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
{
mSprite.move(0, mSpeed * delta);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
{
mSprite.move(mSpeed * delta, 0);
}
}
void Player::render(sf::RenderWindow& window) {
window.draw(mSprite);
}
Forgot to add my errors:
Error 3 error C2511: 'void Enemy::update(float,Player)' : overloaded member function not found in 'Enemy' c:\dev\c++\sven\sven\enemy.cpp 16 1 Sven
Error 1 error C2061: syntax error : identifier 'Player' c:\dev\c++\sven\sven\enemy.h 12 1 Sven
Error 2 error C2061: syntax error : identifier 'Player' c:\dev\c++\sven\sven\enemy.h 12 1 Sven
In Enemy.h you have void update(float delta, Player player);. How does the compiler know what a play is? It cant since you never included the player.h file in enemy.h. You have to options to fix this you can either include player.h or you could forward declare player and change the function to take a pointer to a player.
OK so i have a few problems.
1. I need to be able to register the childclass when its created with game for broadcasting.
2. I need to be able to call the child class's method from an array of GameObject Pointers.
3. I need it to be the actual classes, not just copys of them.
In the file systemvars.h i have my global methods and some variables.
#pragma once
//=================================
// include guard
#ifndef _SYSTEMVARS_H_
#define _SYSTEMVARS_H_
//=================================
// forward declared dependencies
class Game;
//=================================
// included dependencies
#include <iostream>
using namespace std;
//global enums
const enum CLASSTYPE{CLASSTYPE_NULL,CLASSTYPE_PLAYER,CLASSTYPE_DUNGION,CLASSTYPE_ENTITY,CLASSTYPE_MAP,CLASSTYPE_MENU};
//Global methods
void setGameRefrence(Game*);
Game* getGameRefrence();
systemvars.cpp: definitions
#include "SystemVars.h"
static Game* curentgame;
void setGameRefrence(Game* mygame)
{
curentgame = mygame;
}
Game* getGameRefrence()
{
return curentgame;
}
In my Game.h: a holder for gameobjects
#pragma once
//=================================
// include guard
#ifndef _GAME_H_
#define _GAME_H_
//=================================
// forward declared dependencies
class GameObject;
//class Player;
//=================================
// included dependencies
#include "SystemVars.h"
#include "GameObject.h"
//#include "Player.h"
#include <iostream>
using namespace std;
//=================================
// the actual class
class Game
{
public:
Game(void);
void registerGameObject(GameObject*);
void unregisterGameObject(GameObject*);
void sendMessageToAllObjects(string message,CLASSTYPE recipeint);
~Game(void);
private:
GameObject *gameobjects2[1000];
int numberofobject;
};
#endif
the game.cpp gameclass definition
#include "Game.h"
//#include "Player.h"
Game::Game(void)
{
setGameRefrence(this);
//logHelperMessage(INFO,1,"Registerd game");
numberofobject = 0;
}
void Game::registerGameObject(GameObject* newobj)
{
//logHelperMessage(INFO,1,"Registerd");
newobj->setId(numberofobject);
gameobjects2[numberofobject] = newobj;
numberofobject++;
//gameobjects.push_back(newobj);
}
void Game::unregisterGameObject(GameObject* objtodie)
{
//logHelperMessage(INFO,1,"Unregister");
for(int i = objtodie->getId();i < numberofobject - 1;i++)
{
gameobjects2[i] = gameobjects2[i+1];
gameobjects2[i]->setId(i);
}
gameobjects2[numberofobject-1] = nullptr;
numberofobject--;
}
void Game::sendMessageToAllObjects(string message,CLASSTYPE recipeint)
{
for(int i = 0; i < numberofobject;i++)
{
cout << "Sent the message from game");
//((Player *)gameobjects2[i])->sendMessage(message);
//static_cast<Player*>(gameobjects2[i])->sendMessage(message);
}
}
Game::~Game(void)
{
}
Gameobject.h: the parent of my inner game classes.
#pragma once
//=================================
// include guard
#ifndef _GAMEOBJECT_H_
#define _GAMEOBJECT_H_
//=================================
// forward declared dependencies
enum CLASSTYPE;
//=================================
// included dependencies
#include <iostream>
#include "SystemVars.h"
using namespace std;
//=================================
// the actual class
class GameObject
{
public:
GameObject();
GameObject(CLASSTYPE mytype);
~GameObject(void);
virtual void sendMessage(string data);
virtual CLASSTYPE getMyClassType();
virtual void setMyClassType(CLASSTYPE newrecip);
void setId(int val);
int getId();
protected:
CLASSTYPE _MYCURRENTCLASSTYPE;
int myid;
};
#endif
Gameobject.cpp
#include "GameObject.h"
GameObject::GameObject() : _MYCURRENTCLASSTYPE(CLASSTYPE_NULL)
{
//do not register
}
GameObject::GameObject(CLASSTYPE mytype): _MYCURRENTCLASSTYPE(mytype)
{
//register this object into the gameobject list.
getGameRefrence()->registerGameObject(this);
}
GameObject::~GameObject(void)
{
getGameRefrence()->unregisterGameObject(this);
}
void GameObject::sendMessage(string data)
{
//logHelperMessage(INFO,1,"Recived te message in GameObject");
cout << "Recived te message in GameObject";
}
CLASSTYPE GameObject::getMyClassType()
{
return _MYCURRENTCLASSTYPE;
}
void GameObject::setMyClassType(CLASSTYPE newrecip)
{
}
void GameObject::setId(int val)
{
myid = val;
}
int GameObject::getId()
{
return myid;
}
Player.h:
pragma once
//=================================
// include guard
#ifndef _PLAYER_H_
#define _PLAYER_H_
//=================================
// forward declared dependencies
//=================================
// included dependencies
#include "SystemVars.h"
#include "GameObject.h"
//=================================
// the actual class
class Player : public GameObject
{
public:
Player();
void sendMessage(string data) override;
void test();
}
Player.cpp:
Player::Player() : GameObject(CLASSTYPE_PLAYER)
{
}
void Player::sendMessage(string data)
{
//logHelperMessage(INFO,1,"Recived the message in Player");
cout << "Recived the message in Player";
//logHelperMessage(INFO,1,data.c_str());
cout << data;
}
void Player::test()
{
cout << "Sent message";
getGameRefrence()->sendMessageToAllObjects("Test",CLASSTYPE_PLAYER);
}
main.cpp
#pragma once
#include "SystemVars.cpp"
#include "Player.h"
#include "Game.h"
Game mygame;
int main(int argc, char **argv)
{
setGameRefrence(&mygame);
Player newplayer = Player();
newplayer.test();
}
Now that that is all out of the way.
The expected output is:
Sent message
Sent message from game
Recived message in Player
but insted i get:
Sent message
Sent message from game
Recived message in Gameobject
Im pretty sure i have a sliceing problem, but im not sure what to do about it, or where it is.
So, any ideas gents?
ALso, i tried to cut back the classes a bit so im not posting 2000~ lines of code. So if anyhting missing let me know.
About a dozen classes inherit from gameobject. and i need them all to talk to eachother in one way or another.
Just by having CLASSTYPE_PLAYER, etc. makes me concerned that you're trying to subvert/reinvent C++ OOP. You already have the concept of 'class' in the language, why re-invent it? Forgive me if I'm wrong. Aside from this, I suggest you look up publisher-subscriber frameworks to do the kind of thing you're after, or implement your own. I'm sure somebody will answer your C++ issue more directly.
Edit: tone of first comment.
I had a problem with an illegal access error and I have removed the default constructor from Player.h as I deduced that the problem was due to it. The problem I am having now is that the Level.cpp wanted a default constructor so I edited the Level.h file as shown. That problem was resolved but now I am not being able to return a pointer to the player. The error 'illegal operation on bound member function' is being shown. Any ideas please? I'm a beginner in C++ and any help would be appreciated.
Player.h:
#ifndef _TAG_PLAYER
#define _TAG_PLAYER
#pragma once
#include "Tile.h"
#include "Point.h"
class CGame;
class CPlayer : public CTile
{
public:
CPlayer(Point pos, CGame* game);
~CPlayer();
char getDisplay() ;
virtual bool canMove(const Direction direction, Point p) ;
virtual void move(const Direction direction, Point p);
bool CheckForHome() ;
};
#endif _TAG_PLAYER
Player.cpp:
#include "Box.h"
#include "Level.h"
#include "Tile.h"
CPlayer::CPlayer(Point pos, CGame* game)
{
this->game=game;
Point p;
p.x=0;
p.y=0;
setPosition(p);
}
CPlayer::~CPlayer()
{
}
bool CPlayer::CheckForHome() {
Point p = getPosition();
bool OnHomeTile;
if(game->getLevel()->getTiles()[p.y][ p.x] == GOAL)
{
OnHomeTile = true;
} else {
OnHomeTile = false;
}
return OnHomeTile;
}
char CPlayer::getDisplay()
{
if (CheckForHome())
{
return SOKOBANONGOAL_CHAR;
}
else
{
return PLAYER_CHAR;
}
}
Level.h:
#pragma once
#include "Point.h"
#include "Tile.h"
#include "Player.h"
#include "Box.h"
#include <list>
#include <string>
class CGame;
class CLevel
{
private:
list<CBox> boxes;
TileType tiles[GRID_HEIGHT][GRID_WIDTH];
CPlayer player(Point p, CGame* game); -> new declaration
//CPlayer player; -> old declaration
protected:
CGame* game;
public:
CLevel();
~CLevel();
CPlayer* getPlayer();
list<CBox>* getBoxes();
TileType (*getTiles())[GRID_WIDTH];
};
Constructor of Level.cpp
CLevel::CLevel()
{
this->game=game;
Point p;
p.x=0;
p.y=0;
player(p,game);
memset(tiles, GROUND, sizeof(TileType)*GRID_HEIGHT*GRID_WIDTH);
}
The function with the error in Level.cpp:
CPlayer* CLevel::getPlayer()
{
return &player;
}
Currently you've declared player as a member function not a member variable, which is why you're getting the weird error message. You can't mix the declaration and the initialisation of member variables like this.
You declaration should just be
CPlayer player;
But your CLevel constructor needs to initialise it, for example like:
CLevel() : player(Point(0, 0), game) { }
The problem with that though is that currently CLevel doesn't have a game to initialise the player with. Perhaps you could pass the game to the constructor of CLevel?
I think you need to read up on constructors and initialisation of members a bit more.