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;
}
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.
Related
So, I'm using SFML and I'm trying to setup an entity class and a player sub-class that inherits from it, but this is my first time working with inheritance and I'm having issues:
First, I have an AssetManager class that I cobbled together from different sources, since I don't quite understand how they work yet:
AssetManager.h:
class AssetManager {
public:
AssetManager();
static sf::Texture& LoadTexture(std::string const& path);
static sf::SoundBuffer& LoadSoundBuffer(std::string const& path);
static sf::Font& LoadFont(std::string const& path);
private:
std::map<std::string, sf::Texture> m_Textures;
std::map<std::string, sf::SoundBuffer> m_SoundBuffers;
std::map<std::string, sf::Font> m_Fonts;
static AssetManager* sInstance;
};
But you can only need to see the part relating to textures, here is that part from AssetManager.cpp:
AssetManager* AssetManager::sInstance = nullptr;
AssetManager::AssetManager() {
assert(sInstance == nullptr);
sInstance = this;
}
sf::Texture& AssetManager::LoadTexture(std::string const& path) {
auto& texMap = sInstance->m_Textures;
auto pairFound = texMap.find(path);
if (pairFound != texMap.end()) {
return pairFound->second;
}
else {
auto& texture = texMap[path];
texture.loadFromFile(path);
return texture;
}
}
Then an object of that class is included inside a Sprite class, that facilitates declaring sprites for me.
Sprite.h:
class Sprite {
public:
AssetManager manager;
sf::Texture m_Texture;
sf::Sprite m_Sprite;
sf::Vector2f sprite_scale;
sf::Vector2u original_size;
sf::Vector2f texture_size;
Sprite(std::string path,sf::IntRect rect,sf::Vector2f size);
};
Sprite.cpp:
Sprite::Sprite(std::string path, sf::IntRect rect, sf::Vector2f size) {
m_Texture = sf::Texture(AssetManager::LoadTexture(path));
m_Sprite.setTextureRect(rect);
m_Sprite.setTexture(m_Texture);
original_size = m_Texture.getSize();
texture_size.x = static_cast<float>(original_size.x);
texture_size.y = static_cast<float>(original_size.y);
sprite_scale.x = size.x / texture_size.x;
sprite_scale.y = size.y / texture_size.y;
m_Sprite.setScale(sf::Vector2f(sprite_scale.x, sprite_scale.y));
m_Sprite.setOrigin(sf::Vector2f(original_size.x / 2, original_size.y / 2));
}
Then, an object of the Sprite class is itself included within an Entity class.
Entity.h:
class Entity {
public:
Sprite entity_sprite;
int health;
float speed;
bool collision = false;
bool entity_collision(sf::Sprite entity2_sprite);// Entity.cpp only contains the declaration of this function so far so no need to post it.
};
Now, for a reason I don't understand, I'm not able to directly assign any arguments to the entity_sprite object when declaring it, and I'm only able to declare it with no arguments, despite the class having not a default constructor.
However I am able to get around it using assignment:
Entity entity_sprite = Entity("res/wildcard.png", { 0,0,36,63 }, { 36,63 });
But this isn't the main issue, and using the Entity class directly is not what I'm trying to do, I'm trying to write the Player sub-class and use that instead:
Player.h:
class Player:public Entity {
Player() {
entity_sprite = Sprite("res/wildcard.png", { 0,0,36,63 }, { 36,63 });
}
};
Now I'm once again not able to directly assign arguments to the object directly, because the call of an object of a class type without appropriate operator() or conversion function to pointer-to-function type (Interestingly enough if I go back to the Entity object and assign the arguments there and pretend the errors don't exist, the error produced by the Player class changes to Too many arguments' and 'Too many initializers
This is getting too confusing.
Nonetheless, I am once again able to get around it using assignment, exactly the same as before, except this time I get an error saying the default constructor "Entity" cannot be referenced -- its a deleted function., so I go back to the Entity class and add an empty constructor like this: Entity() { } but then this constructor gives me another error saying no default constructor exists for class "Sprite", even though the Entity class doesn't exactly inherit from the Sprite class, so I go back even further to the Sprite class and give that an empty constructor: Sprite(){}, and the errors seemingly disappear, that is until I declare a Player object in the main.cpp file and try to compile and get a debug error pointing to the following line in AssetManager.cpp: assert(sInstance == nullptr);
So many problems for such a seemingly simple task, how do I pull myself out of this?
Ok, after consulting the SFML Forums, I have refactored the code to the following:
Sprite.h:
#include "AssetManager.h"
class Sprite{
public:
sf::Sprite m_sprite;
sf::Vector2f sprite_scale;
sf::Vector2u original_size;
sf::Vector2f texture_size;
Sprite(){}
sf::Sprite set_sprite(sf::Texture& tx, sf::IntRect rect, sf::Vector2f size);
};
Sprite.cpp:
#include "Sprite.h"
sf::Sprite Sprite::set_sprite(sf::Texture& tx, sf::IntRect rect, sf::Vector2f size) {
sf::Sprite spr(tx);
spr.setTextureRect(rect);
original_size =tx.getSize();
texture_size.x = static_cast<float>(original_size.x);
texture_size.y = static_cast<float>(original_size.y);
sprite_scale.x = size.x / texture_size.x;
sprite_scale.y = size.y / texture_size.y;
spr.setScale(sf::Vector2f(sprite_scale.x, sprite_scale.y));
spr.setOrigin(sf::Vector2f(original_size.x / 2, original_size.y / 2));
return spr;
}
Entity.h:
#pragma once
#include "Sprite.h"
#include "collision.h"
#include "Timer.h"
class Entity {
public:
Sprite spr;
sf::Sprite entity_sprite;
int health;
float max_speed;
sf::Vector2f speed;
sf::Vector2f direction;
float acceleration;
bool collision = false;
timer t;
float acc_time;
};
Player.h:
#pragma once
#include "Entity.h"
class Player:public Entity {
public:
Player();
float acc_time = t.accumulate_time();
void keyboard_controls();
void mouse_controls(sf::Vector2f cursor);
};
Player.cpp:
#include "Player.h"
#include <math.h>
Player::Player() {
speed = { 0,0 };
acceleration = 2;
max_speed = 500 + acceleration;
entity_sprite = spr.set_sprite(AssetManager::LoadTexture("res/wildcard.png"), { 0,0,60,63 }, { 60,63 });
}
In short, the Sprite class' constructor is replaced with a method that has the same exact role, that way I can simply declare a Sprite object with no parameters inside the Entity class, and I won't have any issues with the derived Player class since I won't be asked to create default constructors for both the Sprite and Entity classes.
I don't know if my question title makes sense, so apologies in advance for that. so... I'm trying to implement a state machine for a little game I'm trying to make using C++ and SFML.
I have a GameLoopObject abstract class which needs a renderwindow argument and has these virtual methods: update, draw, handleinput and reset.
Then I have a GameState abstract class which inherits from GameLoopObject, but doesnt add anything new yet so its basically the same as GameLoopObject, for now.
Last, I have a GameStateManager class which also inherits from GameLoopObject and should handle my gamestates.
Now my problem is that I want to use a GameState currentState and a nextState member variable in my GameStateManager, but I can't seem to find the correct way/syntax to declare these and use them afterwards. I'd prefer leaving them empty (if that's possible in C++), as GameState objects are being stored inside of them immediately after making a GameStateManager object.
Basically, what I'm trying to do is something along the lines of this:
GameStateManager(sf::RenderWindow & w) :
GameLoopObject(w),
currentState(new GameState(w)),
nextState(new GameState(w));
Which gives me a "no default constructor exists for class "GameLoopObject" "
This is the rest of my code:
/*
* GameStateManager.hpp
*/
#ifndef GameStateManager_HPP
#define GameStateManager_HPP
#include "stdafx.h"
#include "GameLoopObject.hpp"
#include "GameState.hpp"
#include<string>
#include<map>
class GameStateManager : GameLoopObject {
private:
GameState currentState;
GameState nextState;
public:
std::map<std::string, GameState> gameStates{}; // list where all known gamestates are stored.
// methods
GameStateManager(sf::RenderWindow & w);
void AddGameState(std::string name, GameState * state);
void SetNext(std::string name);
void SwitchState();
void HandleInput();
void Update();
void Draw();
void Reset();
};
#endif //GameStateManager_HPP
/*
* GameStateManager.cpp
*/
#include "stdafx.h"
#include "GameStateManager.hpp"
GameStateManager::GameStateManager(sf::RenderWindow & w)
// : GameLoopObject(w)
{
GameState currentState(w);
GameState nextState(w);
}
void GameStateManager::AddGameState(std::string name, GameState * state)
{
gameStates.insert(std::make_pair(name, * state));
}
void GameStateManager::SetNext(std::string name)
{
//check if user wants to exit (close window with X)
if (gameStates.count(name))
{
nextState = gameStates[name];
}
}
void GameStateManager::SwitchState()
{
if (currentState != nextState)
{
currentState = nextState;
}
}
void GameStateManager::HandleInput()
{
// if(currentState != null)
currentState.HandleInput();
}
void GameStateManager::Update()
{
// if(currentState != null)
currentState.Update();
}
void GameStateManager::Draw()
{
// if(currentState != null)
currentState.Draw();
}
void GameStateManager::Reset()
{
// if(currentState != null)
currentState.Reset();
}
I see you have two issues here, both stemming from the fact that you can't declare an instance of an abstract class. The members of the class should be GameState pointers. You also face the same issue when you call new GameState, there is no constructor available here as GameState is abstract.
I'm not sure whether your GameStateManager is the owner of the current and next state. In the case that it is, you should change the type of your members to std::unique_ptr<GameState>, otherwise just use a GameState*.
Your constructor doesn't need to create a new GameState object to initialise these members if they don't own the states, in this case you would pass a pointer to an existing GameState. However if they do, you must call new ConcreteGameState where ConcreteGameState is some derived class of GameState that is not abstract.
EDIT:
Looking at your member functions, you almost definitely want to a raw pointer.
EDIT 2:
Noticed you are currently privately inheriting from GameLoopObject, you should change that to public by adding the keyword:
class GameStateManager: public GameLoopObject
I apologize if this is a lot of code to read, if I can simplify with explanations please let me know, also if you'd like to comment on my design/practices feel free.
So my Player is being deleted twice, I'm not sure why. If you look at the call stack, you'll see that GameEventManager is actually calling the Player destructor before the GameState destructor, even though GameState is the one with the pointer to Player. I'm thinking maybe this is because it's also destroying the vector first, so it finds Player in the vector and tries to destroy it. I don't know why it would try to destroy the Player though, since there is still a reference to Player that the GameState object knows about. The shared pointer functionality should prevent the Player from being destroyed.
Maybe I am going about it the wrong way, if so could someone point me in the correct direction for best practices here? Thanks
Call stack:
GameState.h
#ifndef _level
#define _level
#include <vector>
#include "Player.h"
#include <memory>
using namespace std;
class GameState // A representation of the Level/Game/Scene
{
public:
GameState();
virtual ~GameState() {}
//Keep track of the game's state
//Maybe get rid of the Level class, and make this a class, and move the Level functionality here?
static void EndGame(const bool & b) { mbEndGame = b; }
static const bool & EndGame() { return mbEndGame; }
private:
void SetPlayer(shared_ptr<Player> sptrPlayer) { msptrPlayer = sptrPlayer; }
static bool mbEndGame;
shared_ptr<Player> msptrPlayer;
vector<shared_ptr<Player>> msptrMob; // Representation of all the NPCs in the game. Eventually make a Mob class but for now just use Player
// shared_ptr<LevelMap> mMap // Representation of what the game looks like visually
// Renderer // Should the level have the renderer to create the graphics? Or should this be handled by another "GUI Layer" and interact with this layer as little as possible ?
};
#endif
GameState.cpp
#include "stdafx.h"
#include "GameState.h"
bool GameState::mbEndGame(false);
GameState::GameState() : msptrPlayer(NULL)
{
shared_ptr<Player> sptrPlayer(new Player);
SetPlayer(sptrPlayer);
}
GameObject.h
#ifndef _game_object
#define _game_object
#include <memory>
// Game Object Classes inherit this so they are registered with GameEventManager.
using namespace std;
class GameObject{
public:
GameObject();
virtual ~GameObject() {}
virtual void Update() = 0;
virtual void Start() = 0;
};
#endif
GameObject.cpp
#include "stdafx.h"
#include "GameObject.h"
#include "GameEventManager.h"
GameObject::GameObject()
{
shared_ptr<GameObject> ptr(this);
GameEventManager::GetGameEventManager()->RegisterGameObject(ptr);
}
Player.h
#ifndef _player
#define _player
#include "GameObject.h"
//A representation of the Player. Used by Level.
class Player : public GameObject
{
public:
Player();
virtual ~Player() {}
private:
virtual void Update();
virtual void Start();
int miMaxHealth;
};
#endif
Player.cpp
#include "stdafx.h"
#include "Player.h"
#include "GameState.h"
Player::Player() : miMaxHealth(100) {};
void
Player::Start()
{
}
void
Player::Update() // reimplement GameObject::Update(), which is called by the GameEventManager
{
--miMaxHealth;
if (miMaxHealth <= 0)
{
GameState::EndGame(true);
}
}
GameEventManager.h
#ifndef _game_event_manager
#define _game_event_manager
#include "stdafx.h"
#include <memory>
#include <vector>
#include "GameObject.h"
#include "GameState.h"
using namespace std;
class GameEventManager{
//Object which inherit from GameObject are automatically registered with GameEventManager when they are constructed.
// GameEventManager creates the level object to represent the game, and then runs Start() on all registered GameObjects
// and then continually runs Update() on all registered game objects until the GameState is set to EndGame.
public:
virtual ~GameEventManager(){} // This gets called at the end of the program (I guess whne static variables are destroyed), and crashes during vector<shared pointer <GameObject>> destruction, probably because
// Player already destroyed it. So... not sure what to do. If I make it non-static
void StartGameEvents();
const static shared_ptr<GameEventManager>& GetGameEventManager();
const shared_ptr<GameState>& GetLevel();
void RegisterGameObject(shared_ptr<GameObject> sptrGameObject);
const shared_ptr<vector<shared_ptr<GameObject>>>& GetRegisteredGameVector() const { return mvecRegisteredGameVector; }
private:
GameEventManager(); //singleton
void AddGameObject(shared_ptr<GameObject>);
shared_ptr<GameState> mLevel;
shared_ptr<vector<shared_ptr<GameObject>>> mvecRegisteredGameVector; //Reference because shared pointer will double delete otherwise. ~Level() still deletes it but this way I guess it doesn't try to delete again? but...
//Now I'm trying it as a shared_ptr, but it's not working. ~Level() still deletes it even though there is a shared pointer to a vector pointing to the Player. Why is ~Level() doing this?
static shared_ptr<GameEventManager> msptrGameEventManager;
};
#endif
GameEventManager.cpp
#include "stdafx.h"
#include "GameEventManager.h"
#include "GameState.h"
shared_ptr<GameEventManager> GameEventManager::msptrGameEventManager(new GameEventManager);
void
GameEventManager::StartGameEvents()
{
//run once
int size = GetRegisteredGameVector()->size();
vector<shared_ptr<GameObject>> & vecsptrRegisteredGameVector = (*GetRegisteredGameVector());
for (int i = 0; i < GetRegisteredGameVector()->size(); ++i)
{
vecsptrRegisteredGameVector[i]->Start(); //nothing for now
}
//keep running
while (GetLevel()->EndGame() != true)
{
for (int i = 0; i < GetRegisteredGameVector()->size(); i++)
{
(*GetRegisteredGameVector())[i]->Update(); //Player's life goes from 100 to zero, see Player::Update
}
}
return;
// GameState destructor is called and destroys player for some reason, even though it's still being referenced by the GameEventManager's vector.
}
GameEventManager::GameEventManager() : mvecRegisteredGameVector(new vector<shared_ptr<GameObject>>) , mLevel(NULL) //Instantiating the level before the GameEventManager is fully instantiated causes an infinite recursion.
{
return;
}
const shared_ptr<GameEventManager>&
GameEventManager::GetGameEventManager()
{
if (!msptrGameEventManager)
{
msptrGameEventManager.reset(new GameEventManager);
}
return msptrGameEventManager;
}
const shared_ptr<GameState>&
GameEventManager::GetLevel()
{
if (!mLevel)
{
mLevel.reset(new GameState);
}
return mLevel;
}
void
GameEventManager::RegisterGameObject(shared_ptr<GameObject> sptrGameObject)
{
GetGameEventManager()->AddGameObject(sptrGameObject);
}
void
GameEventManager::AddGameObject(shared_ptr<GameObject> sptrGameObject)
{
GetRegisteredGameVector()->push_back(sptrGameObject);
}
GameObject::GameObject()
{
shared_ptr<GameObject> ptr(this);
GameEventManager::GetGameEventManager()->RegisterGameObject(ptr);
}
The ptr in this function does not share ownership with any other shared_ptr constructed independently, like the one declared at shared_ptr<Player> sptrPlayer(new Player);. Creating two shared_ptr from raw pointers, rather than copying the first one, generally leads to a double delete.
Instead, you could do something like this:
class GameObject :
public std::enable_shared_from_this<GameObject>
{
protected:
GameObject(); // creates the original shared_ptr
virtual ~GameObject();
};
class Player : public GameObject
{
public:
static std::shared_ptr<Player> create();
private:
Player() : GameObject() {}
virtual ~Player() {}
};
std::shared_ptr<Player> Player::create() {
return dynamic_pointer_cast<Player>((new Player)->shared_from_this());
}
A player is inherited from a GameObject (class Player : public GameObject). During the gamestate construction, it is set as the player.
GameState::GameState() : msptrPlayer(NULL)
{
shared_ptr<Player> sptrPlayer(new Player);
SetPlayer(sptrPlayer);
}
You add the object to a std::shared_ptr object. But, the parent class GameObject also creates a std::shared_ptr object, and adds the same pointer:
GameObject::GameObject()
{
shared_ptr<GameObject> ptr(this);
GameEventManager::GetGameEventManager()->RegisterGameObject(ptr);
}
The same pointer is added to two separate std::shared_ptr objects. So both shared pointer objects will delete the object, causing your problem.
I have a Weapon.h/cpp class. thats has an enum
Weapon.h
enum WEAPONTYPE {
LASER,
ROCKET
}
and I have a variable that I'd like to use to track the current enum.
WEAPONTYPE currentWeapon;
I have a function that will be called to change the currentWeapon value. The declaration in the header file is:
void weaponSelect(WEAPONTYPE choice);
and the declaration in the .cpp file is
void Weapon::weaponSelect(Weapon::WEAPONTYPE enumChoice)
{
currentWeapon = enumChoice;
}
Now the error I recieve is:
error C2511: 'void Weapon::weaponSelect(Weapon::WEAPONTYPE)' : overloaded member function not found in 'Weapon'
Any help is appreciated.
Edit 1:
Weapon.h
#ifndef WEAPON_H_
#define WEAPON_H_
class Weapon
{
public:
Weapon(Ogre::SceneManager* localManager);
virtual ~Weapon(void);
void createBullet(Ogre::Vector3 cameraPosition); //Create bullet nodes/entities.
void weaponSelect(WEAPONTYPE enumChoice); //Function to select weapon type. Tried to have "WeaponType enumChoice" as parameter but would produce error.
void updateBullet(); //Update bullet logic.
enum WEAPONTYPE {
LASER = 0,
ROCKET = 1
};
private:
WEAPONTYPE currentWeapon; //Enum var to track weapon selected.
Ogre::SceneManager* localBulletSceneManager; //Pointer to our application's scene manager
std::vector<Ogre::SceneNode*> bullets; //List of pointers to the bullet nodes.
};
#endif
Weapon.cpp
#include "Weapon.h"
#include <OgreStringConverter.h>
using Ogre::SceneNode;
using Ogre::Entity;
using Ogre::String;
using Ogre::Vector3;
Weapon::Weapon(Ogre::SceneManager* localManager)
: localBulletSceneManager(nullptr)
, currentWeapon(LASER)
{
this->localBulletSceneManager = localManager;
}
Weapon::~Weapon(void)
{
}
void Weapon::weaponSelect(WEAPONTYPE enumChoice)
{
this->currentWeapon = enumChoice;
}
void Weapon::createBullet(Vector3 cameraPosition)
{
//Pointers to use for Quick Node and Entity Creation - Get Reused once object is attached to scene.
SceneNode* tempNode = nullptr;
Entity* tempEntity = nullptr;
//All our Objects are spheres, so create one mesh and reuse it with each entity.
String bulletMesh = "Bullet";
//Procedural::SphereGenerator().setRadius(1.f).setUTile(5.).setVTile(5.).realizeMesh(bulletMeshName);
Procedural::ConeGenerator().setRadius(0.5F).setHeight(3.0F).realizeMesh(bulletMesh);
for (int bulletAmount = 0; bulletAmount < 10; ++bulletAmount)
{
tempNode = this->localBulletSceneManager->getRootSceneNode()->createChildSceneNode("RocketNode" + Ogre::StringConverter::toString(bulletAmount));
tempEntity = this->localBulletSceneManager->createEntity("RocketEntity" + Ogre::StringConverter::toString(bulletAmount), bulletMesh);
//tempEntity->setMaterial(
tempNode->attachObject(tempEntity);
tempNode->setPosition(0,0,100 + (bulletAmount * 10));
}
switch (this->currentWeapon)
{
case LASER:
break;
case ROCKET:
break;
}
}
Edit 2:
Reverted declaration for void weaponSelect in both .h and .cpp to the original version without any changes suggested by other posters.
Move your WEAPONTYPE declaration on the top of the class:
class Weapon {
public:
enum WEAPONTYPE {
LASER = 0,
ROCKET = 1
};
Weapon(Ogre::SceneManager* localManager);
// ...
The error was cause by the fact that when the compiler read the line:
void weaponSelect(WEAPONTYPE enumChoice);
it couldn't figure out what WEAPONTYPE is. That happened because the declaration of the enum comes later in the class.
Also, I see you are using C++11: use enum class instead:
enum class weapon {
laser,
rocket
};
If WEAPONTYPE is declared outside the class use this syntax:
void Weapon::weaponSelect(WEAPONTYPE enumChoice)
{
currentWeapon = enumChoice;
}
If this enum is declared within the class:
void Weapon::weaponSelect(Weapon::WEAPONTYPE enumChoice)
{
this->currentWeapon = enumChoice;
}
You must declare the enum before using it.
try moving the enum, WEAPONTYPE to be before the deceleration of weaponSelect
Also, I dont understand your API:
On one hand, you declare weaponSelect as public. But, it's parameter is a protected enum. how cau users of your class can use it? this should all have the same accessibility/.
I'm trying to structure my code like this main <- game <- player.
IF I write in main:
player* P;
P = new player;
P->move();
Everything works but when trying to move this code in to the game component I run in to problems.
Here is the parts of game.cpp I need help with.
#include "game.h"
#include <string>
using namespace std;
game::game(){
player* P;
P = new player;
};
void game::playerStuff(){
P->move(); //c2227+C2065
};
Here is a part of game.h
#include "player.h"
class game {
public:
game();
void playerStuff();
The issue is rather simple. Your pointer to the player (P) is a local variable only visible/existing within your constructor. Add it as a class member instead to use it everywhere in your game class:
class game
{
private:
player *P;
public:
game();
// other stuff ...
}
P needs to be a member of the game class.
Currently, in your constructor here:
game::game(){
player* P;
P = new player;
};
P is local to the ctor and disappears as soon as this function ends.
Solution
Make P a member of game:
class game {
private:
player * P;
public:
game();
~game(); // NOTE: I have added a destructor
void playerStuff();
}
And change the contructor:
game::game(){
P = new player;
};
Remembering of course, to delete it in the destructor:
game::~Game(){
delete P;
};
Of course, because you include <player.h>, you don't need to allocate this object on the heap at all, and can use the stack instead, thereby negating the need to delete P in the destructor.
EDIT: Here is an example showing using the stack, rather than allocating on the heap:
#include "player.h"
class game
{
private:
player P; // Note, we're not declaring a pointer.. we have a complete type here.
public:
game();
~game();
void playerStuff();
}; // eo class game
game.cpp
game::game()
{
// No need to allocate, it's already allocating on the stack
}; // eo ctor
game::~game()
{
// No need to delete, P will be deallocated along with this game class.
}; // eo dtor
void game::playerStuff()
{
P.move(); // note we're not using -> (pointer to member) here
} // eo playerStuff
Move #include "player.h" to game.cpp if you need only pointers or references on game.h. If you need to reference Player on game.h to declare a pointer, you can use a forward declaration, like:
class Player;
class game
{
Player *myPlayer;
};