So I have three classes
class Map that stores objects of class Recty
class Map : public GameObject, public InCollisionMap
{
public:
void Setup();
private:
Recty *tile[24][32];
};
class InCollisionMap //interface for map
{
InCollisionRect *tile[24][32];
public:
virtual InCollisionRect* Tile(int n, int m){
int n = 0;
int m = 0;
return tile[n][m]; //returns object of class Recty
}
InCollision();
~InCollision();
};
class Recty that stores variable type
class Recty : public GameObject, public InCollisionRect
{
private:
int type;
public:
Recty();
~Recty();
};
class InCollisionRect //interface for class Recty
{
private:
int type;
public:
virtual int get_number(char num);
InCollisionRect();
~InCollisionRect();
};
and finally class GameObject
class GameObject : public InCollisionObject
{
public:
GameObject(const char* textureSheet, SDL_Renderer* ren, int x, int y);
GameObject();
~GameObject();
private:
int xpos;
int ypos;
int way;
SDL_Texture* objTexture;
SDL_Rect srcRect, destRect;
SDL_Renderer* renderer;
};
class InCollisionObject // interface for GameObject
{
int xpos;
int ypos;
int way;
SDL_Texture* objTexture;
SDL_Rect srcRect, destRect;
SDL_Renderer* renderer;
public:
virtual void Collision_Loop(InCollisionMap* target){
if (target->Tile(i, j)->get_number('t') == 0 {
^
/*{Tile(i,j) returns nullptr}*/
cout<<"NO<<endl;"
}
InCollisionObject();
~InCollisionObject();
};
and main
GameObject* player;
Map map;
int main(){
map.Setup();
player->Collision_Loop(&map);
}
I kind of simplified the code but that every object in array *tile is initialized properly. Array is full of objects.
I am getting this error in Collision_Loop()
Exception thrown: read access violation.
InCollision::Tile[virtual](...) returned nullptr.
Why does it returns a nullptr? And how do I fix this?
Related
class Entity
{
private:
//Functions
void initiVariables();
protected:
//Variables
float velocity;
sf::Sprite sprite;
sf::Texture* texture;
MovementComponent* movementComponent;
AnimationComponent* animationComponent;
HitboxComponent* hitboxComponent;
//Component Functions
void setTexture(sf::Texture& texture);
void **strong text**MovementComponent(float maxVelocity, float acceleration, float deacceleration);
void AnimationComponent(sf::Sprite& sprite, sf::Texture& texture);
void HitboxComponent(sf::Sprite& sprite, sf::Color wireColor, float wireThickness);
public:
//Constructor & Deconstructor
Entity();
virtual~Entity();
//Accessor
const sf::FloatRect& getGlobalBounds() const;
//when I check for Collsion sprite.getGlobalBounds().intersect(sprite.getGlobalBounds())
//it remains true for the entire time what am doing wrong?
//Funtions
void setPosition(const float x, const float y);
virtual void move(const float x, const float y, const float& dt);
virtual void update(const float& dt);
virtual void render(sf::RenderTarget* target);
};
You can do simple inheritance from the Entity class. I don't know why your program crashes when returning sf::FloatRect objects. This should also be the correct solution to this problem.
#include <SFML/Graphics.hpp>
#include <iostream>
class Entity : public sf::RectangleShape {
public:
bool isColliding(Entity const& other) {
return this->getGlobalBounds().intersects(other.getGlobalBounds());
}
};
class Player : public Entity {};
class Zombie : public Entity {};
int main() {
Player player;
player.setPosition({ 200, 200 });
player.setSize({ 100, 100 });
Zombie enemy;
enemy.setPosition({ 151, 151 });
enemy.setSize({ 50, 50 });
std::cout << player.isColliding(enemy);
}
Someone recommended me to use boost::variant as shape variable to store different types of shapes in it. But, when implemented boost::variant to my code, I got an error while compiling. Error says: 'Shape': base class undefined and more errors.
Here is my code (Object.h):
using Shape = boost::variant<Rectangle, Circle>;
enum Shape_Type
{
RECTANGLE,
CIRCLE
};
struct Position
{
float x, y;
Position(float position_x, float position_y)
{
x = position_x;
y = position_y;
}
};
class Object : private Shape
{
private:
std::string name;
public:
Object() = default;
Object(std::string name, Rectangle rectangle) : name(name), Shape(rectangle)
{
}
Object(std::string name, Circle circle) : name(name), Shape(circle)
{
}
void setPosition(float, float);
void setAngle(float);
Shape* getShape()
{
Shape* shape = this;
return shape;
}
Position getPosition();
const std::string* getName()
{
return &name;
}
};
class Rectangle
{
private:
sf::RectangleShape rectangleshape;
public:
Rectangle() = default;
Rectangle(float width, float height)
: rectangleshape(sf::RectangleShape(sf::Vector2f(width, height)))
{
}
void setPosition(float position_x, float position_y)
{
rectangleshape.setPosition(position_x, position_y);
}
void setAngle(float angle)
{
rectangleshape.setRotation(angle);
}
sf::RectangleShape* getRectangleShape()
{
return &rectangleshape;
}
Position getPosition()
{
return Position(rectangleshape.getPosition().x,
rectangleshape.getPosition().y);
}
};
class Circle
{
private:
sf::CircleShape circleshape;
public:
Circle() = default;
Circle(std::string name, float radius)
: circleshape(sf::CircleShape(radius))
{
}
void setPosition(float position_x, float position_y)
{
circleshape.setPosition(position_x, position_y);
}
void setAngle(float angle)
{
circleshape.setRotation(angle);
}
sf::CircleShape* getCircleShape()
{
return &circleshape;
}
Position getPosition()
{
return Position(circleshape.getPosition().x,
circleshape.getPosition().y);
}
};
And btw is getShape() function good?
Variants are used for static polymorphism, so you don't need the base class at all (that's dynamic - or virtual - polymorphism).
The members in a variant typically do not share a common base class, so you wouldn't have the getShape function, or you'd need to template it:
template <typename T>
T const& getShape() const { return boost::get<T>(_shape); }
I want to go from this:
To this:
How would I do this? How would the functions of subclasses square and rectangle know to use the variable of the parent class shape?
How would I set length and width from main?
#include <iostream>
#include <cmath>
using namespace std;
class SHAPES
{
public:
class SQUARE
{
int perimeter(int length, int width)
{
return 4*length;
}
int area(int length, int width)
{
return length*length;
}
};
public:
class RECTANGLE
{
int perimeter(int length, int width)
{
return 2*length + 2*width;
}
int area(int length, int width)
{
return length*width;
}
};
};
I recommend other (better?!) format:
class Shape
{
protected:
int length,width;
public:
Shape(int l, int w): length(l), width(w){}
int primeter() const
{
return (length + width) * 2;
}
int area() const
{
return length * width;
}
};
class Rectangle : public Shape
{
public
Rectangle(int l, int w) : Shape(l,w){}
};
class Square : public Shape
{
public:
Square(int l): Shape(l,l){}
};
int main()
{
Rectangle r(5,4);
Square s(6);
r.area();
s.area();
}
Or use interface with virtual function.
Those are not subclasses (i.e. derived classes), but rather nested classes (as the title of your question says).
I don't think I would answer your real question if I were to tell you how to make those variables visible in nested classes. Based on what I can understand from the names of your classes, you should rather use inheritance to model the IS-A relation between them:
class SHAPE
{
public: // <-- To make the class constructor visible
SHAPE(int l, int w) : length(l), width(w) { } // <-- Class constructor
...
protected: // <-- To make sure these variables are visible to subclasses
int length;
int width;
};
class SQUARE : public SHAPE // <-- To declare public inheritance
{
public:
SQUARE(int l) : SHAPE(l, l) { } // <-- Forward arguments to base constructor
int perimeter() const // <-- I would also add the const qualifier
{
return 4 * length;
}
...
};
class RECTANGLE : public SHAPE
{
// Similarly here...
};
int main()
{
SQUARE s(5);
cout << s.perimeter();
}
I'm writing a simple game in SDL. I have a class heirarchy that I am constructing for any sprite I use in the game. The base class is Sprite, which contains data abstractions for the collision box and the spritesheet. Directly below that are two abstract classes, Character and MapObject.
I am currently implementing the Player class which is derived from Character (Enemy and NPC will also be derived from the abstract Character class).
Anyway, hopefully that makes sense. My problem is this:
When I try and use the player class in the engine, I cannot access any of the Sprite functions.
I get the following error:
'Sprite' is not an accessible base of 'Player'
Here are the header files:
Sprite.h:
class Sprite{
public:
virtual ~Sprite() = 0; //I want this to be an abstract class and yes this is defined in the cpp
//Initialization functions - MUST be called before anything else in the class can be used.
void setupCollider(int xo, int yo, int ho, int wo);
void setupSheet(SDL_Surface* dest, std::string file, int numClips, int ac, int _res, int sr);
//SpriteSheet functions
void setActiveClip(int a);
int getActiveClip() const;
void draw() const;
int getResolution() const;
SDL_Surface* getDest();
//Collider functions
void updateCollider();
SDL_Rect box() const;
bool collision(SDL_Rect other) const;
//Access and Modify coordinates of the sprite
void setLoc(int x, int y) { _x = x; _y = y; }
int getX() const { return _x; }
int getY() const { return _y; }
private:
struct Collider{
SDL_Rect _box;
int x_offset,
y_offset;
};
struct SpriteSheet{
SDL_Surface* destination;
SDL_Surface* sheet;
SDL_Rect* clips;
int _numClips;
int active;
int res;
int sheetrows;
};
Collider collisionAttributes;
SpriteSheet spriteSheetAttributes;
int _x, _y;
};
Character.h:
class Character : public Sprite{
public:
virtual void move(Direction direction_input, const TileMap& currentlevel) = 0;
virtual void animate() = 0;
virtual void setAttributes( int h, int sp, int ad, int d, int m, int md, int l, std::string n){
hearts = h; speed = sp; attackdamage = ad;
defense = d; magicdamage = m; magicdefense = md;
level = l; name = n;
}
bool isDead() const{
return hearts == 0;
}
void heal(int heartsup){
hearts += heartsup;
}
void dealDamage(int heartsDown){
hearts -= heartsDown;
}
protected:
int hearts;
int speed;
int attackdamage;
int defense;
int magicdamage;
int magicdefense;
int level;
std::string name;
};
Player.h:
//Not fully finished yet, but should work for the purposes of this question
class Player : protected Character{
public:
~Player(){
if(heart) SDL_FreeSurface(heart);
}
static const int HEART_WIDTH;
void move(Direction direction_input, const TileMap& currentlevel);
void animate();
void updateCamera(TileMap& currLevel);
private:
SDL_Surface* heart;
enum ClipFace
{
UP1,
UP2,
DOWN1,
DOWN2,
LEFT1,
LEFT2,
RIGHT1,
RIGHT2
};
static const std::string HEART;
static const int HEART_RES;
};
I get the first error in my engine when I try to call the setup functions from Sprite in player, the first one being:
player.setLoc(levels[0].startX(), levels[0].startY());
Any and all help is appreciated.
[SOLVED] EDIT: An alternative solution to the comments: The character class didn't inherit anything from the Sprite class, so it didn't technically have to be derived from it. Instead of having Character inherit from Sprite, I had Player inherit from BOTH Sprite and Character and that also worked. I'm not sure what is better design though.
I think you need to change
class Player : protected Character{
to
class Player : public Character{
That way you can access Character and Sprite's functions on a Player object from an instance of Player created anywhere in your program.
If a Player should be able to do anything a Character can do, public inheritance makes sense. There's no reason to hide something in Player that would be freely accessible in Character or Sprite objects.
Always use public inheritance to represent an "is-a" relationship. It sounds like Player is a Character, so that inheritance should be public, not protected.
protected inheritance and private inheritance are more like "has-a" (and in most cases, a member subobject is an easier way to deal with that relationship).
I'd bet that since Character is a protected base class, its restricting the access to Sprite.
For the below code snippet, how do I initialize instances of class Enemy with variables (such as x, y, type)? I have it working correctly, it triggers the instances no matter how many of them I insert... I just need to know the best way of creating an enemy with certain variables that will differ for each of my instances... particularly when some of those variables are in the base class and others are not.
class BaseObject
{
public:
virtual void Render() = 0;
int x;
int y;
};
class Enemy : public BaseObject
{
public:
Enemy() { }
virtual void Render()
{
cout << "Render! Enemy" << endl;
}
typedef std::set<BaseObject *> GAMEOBJECTS;
GAMEOBJECTS g_gameObjects;
int main()
{
g_gameObjects.insert(new Enemy());
g_lootObjects.insert(new Loot());
for(GAMEOBJECTS::iterator it = g_gameObjects.begin();
it != g_gameObjects.end();
it++)
{
(*it)->Render();
}
for(GAMEOBJECTS::iterator it = g_lootObjects.begin();
it != g_lootObjects.end();
it++)
{
(*it)->Render();
}
return 0;
}
Include the arguments in the enemy constructor and Base constructors. You can then use those to initialize the member variables.
class BaseObject
{
public:
BaseObject(int x, int y) : x(x), y(y){ }
virtual void Render() = 0;
int x;
int y;
};
and
class Enemy : public BaseObject
{
public:
Enemy(int x, int y, int foo) : BaseObject(x,y), foo(foo) { }
int foo;
...
};