I'm having trouble testing if variables with the same name are unique to seperate classes.
This is my example:
class Sprite
{
public
int maxHP;
virtual void setup()=0
};
class Hero : public Sprite
{
void setup(){maxHP = 100;}
};
class Monster : public Sprite
void setup(){maxHP = 60;}
};
Do both of my sprites have 0 hp? Do the variables override each other?
Do I have to use this-> keyword to make them all specific?
Thanks.
If you create a variable type of Sprite and do not specialize it (like Hero or Monster), yes it has 0 HP. But If you create a pointer which is type Sprite and which holds the adress of specific type; then its HP is speciliazed too. I mean:
Sprite *S; //the pointer
Hero Johny;
S = &Johny;
S->setup(); // Johny's HP is updated to 100
Related
(sorry for my bad english)
I have a base class with vector of pointers on Drawable objects in it and method draw() that uses data from this vector.
class GameObject
{
protected:
std::vector<Drawable*> drawable;
...
void GameObject::draw() { for (const auto& object : drawable) window.draw(*object); }
In the derived classes I want to have an ability to add some Drawable objects
class Player : public GameObject
{
protected:
RectangleShape shape;
...
Player::Player(float x, float y, float z)
{
shape.setPosition [...]
drawable.push_back(&shape);
...
and draw them using method of base class pointer
std::vector<GameObject*> gameObjects;
...
for (auto& gameObject : gameObjects) gameObject->draw();
The program crashes (I think because the base class don't know anything about vector data in derived class).
I understand that I could make this method pure virtual and define it in the derived classes, but it's not that convenient. Maybe there is another way more similar to this?
upd:
Level::Level()
{
player = Player(500.f, 500.f); //Player player; in header file
gameObjects.push_back(&player);
}
void Level::display()
{
for (auto gameObject : gameObjects) gameObject->draw();
}
The problem is in the code added by your edit -- it looks like my crystal ball is working today.
You're creating a temporary Player and moving it into the player member variable. That ends up with a vector holding the address of the shape inside the temporary Player, which is immediately destroyed, leaving a dangling pointer.
Use a ctor-initializer-list to avoid the move:
Level::Level()
: player(500.f, 500.f /* where did Z go? */)
{
gameObjects.push_back(&player);
}
And disable the assignment operators to prevent doing this by accident in other places:
class Player
{
// ...
Player& operator=(const Player&) = delete;
Player& operator=(Player&&) = delete;
};
C++ (Arduino wrapper) question: This is related to this thread on double pointer member access regarding a shoot em up game.
I have a base class (Sprite), and from this other classes are derived - Alien and Player. For collision detection I want to pass pointers to Alien and Player, then access coordinates as in:
void Collision( Alien *pAlien, Player *pPlayer )
{
// obtain alien and player's (x,y) and do collision check here
pAlien->getX();
pPlayer->getX();
}
But after declaring the above function after the class I get this:
error: variable or field 'Collision' declared void
My question is: How can I resolve this? streamlined code and a screen shot are shown below.
/*****************************************************************************************/
// Bass class - has a form/shape, x and y position also has a method of moving
class Sprite
{
public:
Sprite(unsigned char * const spacePtrIn, unsigned int xInit, unsigned int yInit);
protected:
};
/*****************************************************************************************/
// Derived class "Alien" - has a specific form/shape, and specific (x,y) position
class Alien : public Sprite
{
public:
Alien();
virtual void Move();
};
/*****************************************************************************************/
// Derived class "Player" - has a specific form/shape, and specific (x,y) position
class Player : public Sprite
{
public:
Player(): Sprite(&spaceShip[0], xPlayer(), yPlayer()) {}
virtual void Move();
};
/*****************************************************************************************/
/*****************************************************************************************/
void Collision( Alien *pAlien, Player *pPlayer )
{
// obtain alien and player's (x,y) and do collision check here
pAlien->getX();
pPlayer->getX();
}
/*****************************************************************************************/
/*****************************************************************************************/
I've been coding a simple board game to learn concepts of C++ in practice. I have implemented the board: it consists of tiles, each of which is a child class inheriting from a parent class. The board is a class that has a vector of the tiles.
There are several kinds of tiles. Some of them can be bought by players. There are several different kinds of buyable tiles as well with different properties, so I deemed it cute to make a base class TileOnSale for tiles that can be bought and make child classes of the actual types, two of which I have provided in the below code.
Now my problem is that how can I access the child members' functions not defined within the parent class (TileOnSale)? Board gets initialized with all kinds of different tiles, so I can extract a Tile from there using getTile(int location) function. However, this gets interpreted as just a Tile, not a TileOnSale or a StreetTile. I know of no way to grasp StreetTile's buildHouses function this way.
So, is there a robust, or even better, a neat way of doing this? Can I make a template or something to hold Tile objects that might be StreetTiles or StationTiles or something else that is a Tile?
Or should I just redesign the class structure?
Here's a bare bones code. I have tried to provide only what is needed for understanding the question. Also, originally Tile and Board were in their own header files. I decided it not necessary to show the Player class that has a vector of owned TileOnSale objects but which retains the exact same access problem as Board.
// Board.h
#include "Tile.h"
typedef vector<Tile> Tiles;
class Board
{
public:
Board();
~Board();
Tile getTile(int location);
private:
Tiles tiles;
};
// Tile.h
class Tile
{
public:
Tile();
~Tile();
protected:
tileType tile_type; // this is enum containing unique type
string description;
};
class TileOnSale : public Tile
{
public:
TileOnSale();
~TileOnSale();
virtual int getRent() const { return 0; };
};
class StreetTile : public TileOnSale
{
public:
StreetTile();
~StreetTile();
int getRent() override;
void buildHouses(int number);
private:
int houses;
};
class StationTile : public TileOnSale
{
public:
StationTile();
~StationTile();
int getRent() override;
};
EDIT: added a potentially clarifying comment to code.
You might want to take a look at the visitor pattern.
In essence, the visitor allows one to add new virtual functions to a family of classes without modifying the classes themselves; instead, one creates a visitor class that implements all of the appropriate specializations of the virtual function. The visitor takes the instance reference as input, and implements the goal through double dispatch.
The double dispatch means you are actually calling a virtual function twice: first on the subject which in turn polymorphically calls the visitor.
In your case there is just one method, namely building houses, but you might want to add others later (like drawing them on a screen for example). Given your current example you should add this method to Tile and StreetTile:
virtual void accept(Visitor& v) { v.visit(*this); }
This is the Visitor base class implementation:
class Visitor {
public:
virtual void accept(Tile& t) = 0;
virtual void accept(StreetTile& t) = 0;
};
After that you can implement a Builder class:
class Builder: public Visitor {
private:
int numberOfHouses;
public:
Builder(int n): numberOfHouses(n) {}
virtual void accept(Tile& t) {}
virtual void accept(StreetTile& t) {
t.buildHouses(numberOfHouses);
}
};
After that all you have to do is construct such a builder, and call it on every tile in your vector of tiles:
Builder b(10);
for (Tile tile : tiles) {
tile.accept(b);
}
A Simple way is to add a unique id (enum or string) to each type. The player class can ask for the type (defined in the base class) and cast to the derived class accordingly.
Since it needs to call a function on the derived (e.g. specialized) class it has the knowledge to perform the cast.
Having a type ID is also nice for debugging purposes.
I'm continuing with a game for an embedded microcontroller (Arduino), and I have a question on class interaction -- this question continues from my previous question here and I have based my code on the suggestion of sheddenizen (see response to the given link in 'here'):
I have three classes that inherit from a base class-
(i) class Sprite - (bass class) has a bitmap shape and (x,y) position on an LCD
(ii) class Missile : public Sprite - has a specific shape, (x,y) and also takes a obj
(iii) class Alien : public Sprite - has specific shape and (x,y)
(iv) class Player : public Sprite - ""
They all have different (virtual) method of moving and are shown on the LCD:
My streamlined code is below - specifically, I only want the missile to fire under certain conditions: when missile is created it takes an objects (x,y) value, how can I access a passed objects value within an inherited class?
// Bass class - has a form/shape, x and y position
// also has a method of moving, though its not defined what this is
class Sprite
{
public:
Sprite(unsigned char * const spacePtrIn, unsigned int xInit, unsigned int yInit);
virtual void Move() = 0;
void Render() { display.drawBitmap(x,y, spacePtr, 5, 6, BLACK); }
unsigned int X() const { return x; }
unsigned int Y() const { return y; }
protected:
unsigned char *spacePtr;
unsigned int x, y;
};
// Sprite constructor
Sprite::Sprite(unsigned char * const spacePtrIn, unsigned int xInit, unsigned int yInit)
{
x = xInit;
y = yInit;
spacePtr = spacePtrIn;
}
/*****************************************************************************************/
// Derived class "Missile", also a sprite and has a specific form/shape, and specific (x,y) derived from input sprite
// also has a simple way of moving
class Missile : public Sprite
{
public:
Missile(Sprite const &launchPoint): Sprite(&spaceMissile[0], launchPoint.X(), launchPoint.Y()) {}
virtual void Move();
};
void Missile::Move()
{
// Here - how to access launchPoint.X() and launchPoint.Y() to check for
// "fire conditions"
y++;
Render();
}
// create objects
Player HERO;
Alien MONSTER;
Missile FIRE(MONSTER);
// moving objects
HERO.Move();
MONSTER.Move();
FIRE.Move();
Since Missile is a subclass of Sprite you can access Sprite::x and Sprite::y as if they were members of Missile. That is by simply writing x (or this->x if you insist).
The launchpoint reference that you got in the constructor is gone by now, so your Missile::Move memfunction cannot access it any more.
If in the meantime the members x and y changed, but you want the original value, you can either save a reference to launchpoint (which might be dangerous, it is destroyed) or you have to keep a copy of the original coordinates.
I have an Entity baseclass which the classes Player and Enemy Inherit.
class Entity
{
public:
virtual void Update(sf::RenderWindow &window) {};
virtual void Draw(sf::RenderWindow &window) {};
};
Both player and enemy contain a sprite object that looks like this:
class Player : Entity
{
public:
sf::Sprite sprite
void Update(sf::RenderWindow &window);
void Draw(sf::RenderWindow &window)
}
Player and Enemy are created inside a vector which is set up like this:
class EntityManager
{
public:
void CollisionCheck();
private:
std::vector<Entity*> entityVector;
}
I'm looking to use a collision detection function of this form:
bool Collision::CircleTest(const sf::Sprite& Object1, const sf::Sprite& Object2)
So I'm trying to do something like this:
void EntityManager::ColCheck()
{
if (Collision::CircleTest(entityVector[0]->sprite, entityVector[1]->sprite))
{
cout << "COLLISION\n";
}
}
This results in the following compile error:
‘class Entity’ has no member named ‘sprite’
I'm unsure how to create a dummy sprite in Entity so that I can access the player and enemy sprites using the above method. Is this possible?
I'm stumped and would greatly appreciate any help anyone can offer!
If everything in your code that derives from Entity has a sprite object, then you should declare that object in the base class.
Not declaring the object in the base class means that there could be a class inheriting from Entity that does not have a sprite object, which means that ColCheck has no valid basis for assuming that elements of entityVector point to something that has a variable called sprite. Make sense?
You probably shouldn't create a dummy unless having a sprite is something ALL entities have.
What you might want is to use a visitor pattern or possibly one of the many multiple-dispatch implementations. Which and what will end up having to be up to you.
If both Player and Enemy classes contain sprite, why not declare it inside Entity? This should solve your problem.
You could make a member function sprite() that is declared as a pure virtual function inside Entity:
class Entity {
public:
virtual void Update(sf::RenderWindow &window) {};
virtual void Draw(sf::RenderWindow &window) {};
virtual sf::Sprite& sprite() = 0;
};
Then, the Player and Enemy implementations would return the sf::Sprite instance variables each has. However, the other posters bring up a valid point; it might make sense to have the sprite be in the base class if all derived classes are going to have one.