I'm trying to code a game with Allegro 4 and I've hit a weird bump. The linker is claiming an undefined reference to the destructor in two of my classes, but I've done nothing with it. What could be the issue? Here is my code:
Entity.h:
#pragma once
#include <allegro.h>
struct Rectangle
{
int x;
int y;
int w;
int h;
};
typedef enum {
FACE,
POOP
} EntityType;
class Entity
{
private:
EntityType m_EntityType;
BITMAP *m_Sprite;
int m_Score;
int m_X;
int m_Y;
Rectangle *m_Hitbox;
public:
Entity();
virtual ~Entity() {destroy_bitmap(m_Sprite);}
BITMAP *GetSprite() {return m_Sprite;}
int GetScore() {return m_Score;}
int GetX() {return m_X;}
int GetY() {return m_Y;}
Rectangle GetHitbox() {return *m_Hitbox;}
void SetSprite(EntityType type);
void SetScore(int value) {m_Score = value;}
void SetX(int value) {m_X = value;}
void SetY(int value) {m_Y = value;}
void SetHitbox(EntityType type);
};
Entity.cpp:
#include "Entity.h"
void Entity::SetSprite(EntityType type)
{
if (type == FACE)
m_Sprite = load_bitmap("face.bmp", NULL);
else if (type == POOP)
m_Sprite = load_bitmap("poop.bmp", NULL);
}
void Entity::SetHitbox(EntityType type)
{
if (type == FACE)
{
GetHitbox().x = m_X;
GetHitbox().y = m_Y;
GetHitbox().w = m_X + 32;
GetHitbox().h = m_Y + 32;
}
else if (type == POOP)
{
GetHitbox().x = m_X;
GetHitbox().y = m_Y;
GetHitbox().w = m_X + 16;
GetHitbox().h = m_Y + 16;
}
}
Related
I have tried to make it look like falling snow but snow is coming from everywhere and I have to make falling snow from library graphics.h. I don't know how to make it move but I already add x and y. For int speed I don't know to use it I see from other code which is from movement of the ball. This code is for my assignment, can you guys help me?
#include <graphics.h>
class Snow
{
private:
int x,y;
int color;
int speed;
public:
Snow(int _x, int _y, int _color, int _speed)
{
x=_x;
y=_y;
color=_color;
speed=_speed;
}
int getColor()
{
return color;
}
int getSpeed()
{
return speed;
}
int getX()
{
return x;
}
int getY()
{
return y;
}
void setX(int value)
{
//x=rand();
x=value;
}
void setY (int value)
{
//y=rand();
y=value;
}
void setColor(int value)
{
color=value;
}
void setSpeed(int value)
{
speed=value;
}
void draw()
{
setcolor(color);
setfillstyle(SOLID_FILL,color);
fillellipse(x,y,2,2);
}
void undraw()
{
setcolor(BLACK);
fillellipse(x,y,2,2);
}
void move()
{
undraw();
x=rand() % getmaxwidth();
y=rand() % getmaxheight();
draw();
}
};
int main()
{
int screenWidth = getmaxwidth();
int screenHeight = getmaxheight();
initwindow(screenWidth, screenHeight, "Snowy day");
Snow p1(0,0,WHITE,10);
while (!kbhit())
{
delay(100);
p1.move();
}
return 0;
}
You should use speed in move function. For example:
void move() {
undraw();
x=rand() % getmaxwidth();
// fall
y += speed;
draw();
}
I am trying to create a game of Tetris as a pet project in visual C++. I created a class to hold each piece and in that class I have protected variables. When I try to create functions to be able to change and set those values I run into these four errors:
expression must be a modifiable |value (on line 31)
expression must be a modifiable |value (on line 32)
explicit type is missing('int'assumed) [when i put in an int for that
function it expects an identifier] (on line 38)
return value type does not match the function type (on line 40)
Here is my code:
class Tetris
{
protected:
int x[4];
int y[4];
int ID;
int piece;
int rotation;
public:
Tetris(int &x, int &y, int ID, int piece, int rotation);
int getX();
void setX(int &x);
int getY();
void setY(int &y);
int getID();
void setID(int ID);
int getPiece();
void setPiece(int piece);
int getRotation();
void setRotation(int rotation);
};
Tetris::Tetris(int &x, int &y, int ID, int piece, int rotation)
{
this->x = x;
this->y = y;
this->ID = ID;
this->piece = piece;
this->rotation = rotation;
}
Tetris::int getX()
{
return x;
}
I was trying to follow the SFML Blueprint book. I managed to remove all the errors but one error remains in the code.
I have tried to find about the debug-assertion-failed.
I think this issue is arising due to the lists one of them is getting emptied.
My code for the world.cpp
#include "World.h"
#include "Entity.h"
World::World(int x, int y) : _x(x), _y(y) {}
World::~World() { clear(); }
void World::add(Entity* entity){
_entities_tmp.push_back(entity);
}
void World::clear()
{
for (Entity* entity : _entities)
delete entity;
_entities.clear();
for (Entity* entity : _entities_tmp)
delete entity;
_entities_tmp.clear();
_sounds.clear();
}
void World::add(Configuration::Sounds sound_id){
std::unique_ptr<sf::Sound> sound(new sf::Sound(Configuration::sounds.get(sound_id)));
sound->setAttenuation(0);
sound->play();
_sounds.emplace_back(std::move(sound));
}
bool World::isCollide(const Entity& other)
{
for (Entity* entity_ptr : _entities)
if (other.isCollide(*entity_ptr))
return true;
return false;
}
int World::size() {
return _entities.size() + _entities_tmp.size();
}
int World::getX() const{
return _x;
}
int World::getY() const{
return _y;
}
const std::list<Entity*> World::getEntities() const {
return _entities;
}
void World::update(sf::Time deltaTime)
{
if (_entities_tmp.size() > 0)
_entities.merge(_entities_tmp);
for (Entity* entity_ptr : _entities)
{
Entity& entity = *entity_ptr;
entity.update(deltaTime);
sf::Vector2f pos = entity.getPosition();
if (pos.x < 0)
{
pos.x = _x;
pos.y = _y - pos.y;
}
else if (pos.x > _x)
{
pos.x = 0;
pos.y = _y - pos.y;
}
if (pos.y < 0)
pos.y = _y;
else if (pos.y > _y)
pos.y = 0;
entity.setPosition(pos);
}
const auto end = _entities.end();
for (auto it_i = _entities.begin(); it_i != end; ++it_i)
{
Entity& entity_i = **it_i;
auto it_j = it_i;
it_j++;
for (; it_j != end; ++it_j)
{
Entity& entity_j = **it_j;
if (entity_i.isAlive() && entity_i.isCollide(entity_j))
entity_i.onDestroy();
if (entity_j.isAlive() && entity_j.isCollide(entity_i))
entity_j.onDestroy();
}
}
for (auto it = _entities.begin(); it != _entities.end();)
{
if (!(*it)->isAlive()){
delete *it;
it = _entities.erase(it);
}
else ++it;
}
_sounds.remove_if([](const std::unique_ptr<sf::Sound>& sound)->
bool {
return sound->getStatus() != sf::SoundSource::Status::Playing;
});
}
void World::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
for (Entity* entity : _entities)
target.draw(*entity, states);
}
Code for world.hpp
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <list>
#include <memory>
#include "Configuration.h"
class Entity;
class World : public sf :: Drawable
{
public:
World(const World&) = delete;
World& operator=(const World&) = delete;
World(int x, int y);
~World();
void add(Entity* entity);
void clear();
bool isCollide(const Entity& other);
int size();
void add(Configuration::Sounds sound_id);
const std::list<Entity*> getEntities() const;
int getX() const;
int getY() const;
void update(sf::Time deltaTime);
private:
std::list<Entity*> _entities;
std::list<Entity*> _entities_tmp;
std::list<std::unique_ptr<sf::Sound>> _sounds;
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
const int _x;
const int _y;
};
code for Entity.h
class World;
class Entity : public sf::Drawable
{
public:
//Constructors
Entity(const Entity&) = delete;
Entity& operator= (const Entity&) = delete;
Entity(Configuration::Textures tex_id, World& world);
virtual ~Entity();
//Helpers
virtual bool isAlive() const;
const sf::Vector2f& getPosition() const;
template<typename ... Args>
void setPosition(Args&& ... args);
virtual bool isCollide(const Entity& other) const = 0;
//Updates
virtual void update(sf::Time deltaTime) = 0;
virtual void onDestroy();
protected:
friend class Meteor;
friend class Player;
friend class Saucer;
friend class ShootPlayer;
friend class ShootSaucer;
sf::Sprite _sprite;
sf::Vector2f _impulse;
World& _world;
bool _alive;
private:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
};
if (_entities_tmp.size() > 0)
_entities.merge(_entities_tmp);
This does not work. merge works with two sorted ranges. And your vector is not sorted. This is why you get an assertion.
If not sorting them is on purpose and you just want to concatenate the two vectors, you can do:
_entities.reserve( _entities.size() + _entities_tmp.size() );
_entities.insert( _entities.end(), _entities_tmp.begin(), _entities_tmp.end() );
I have a problem that arised with another question I made. I am using a list of pointers of a custom class (class that I have implemented), and the program crashes when I call this method, however, if I do not use a pointer list, it works fine. This is the function where the program crashes:
void enemy_spawner()
{
Point2D enemy_pos = Point2D(rand() % (SCREEN_WIDTH - 20) + 20, -20);
Point2D enemy_vel = Point2D(0, rand() % 4 + 1);
Sprite* enemy = new Sprite(enemy_pos, enemy_vel, enemy_image, enemy_info);
//Kamikaze* enemy = new Kamikaze(enemy_pos, enemy_vel, 0, enemy_image, enemy_info);
if (enemy_group.size() < MAX_ENEMIES)
{
// Program crashes here
enemy_group.push_back(enemy);
}
}
The enemy_group is a global variable defined as follows:
std::list<Sprite*> enemy_group;
My Sprite class is as follows (I have read that I need to have properly defined copy constructors, etc)
class Sprite
{
private:
Point2D sp_pos;
Point2D sp_vel;
SDL_Surface* sp_img;
Point2D sp_center;
Point2D sp_size;
double sp_radius;
bool sp_animated;
int sp_frames;
int sp_cur_frame;
public:
Sprite() {}
Sprite(Point2D pos, Point2D vel, SDL_Surface *img, ImageInfo info, bool animated = false, int frames = 0);
virtual void draw(SDL_Surface* screen);
virtual void update();
void setInfo (ImageInfo info);
void setPos( Point2D pos ) { sp_pos = pos; }
void setVel( Point2D vel ) { sp_vel = vel; }
void setImg (SDL_Surface* img) { sp_img = img; }
void setNextFrame() { sp_cur_frame++; }
void setFrame( int frame ) { sp_cur_frame = frame; }
void setAnimated(bool animated) { sp_animated = animated; }
void changeVelX (int c) { sp_vel.setX(c);}
void changeVelY (int c) { sp_vel.setY(c);}
void changePosX (int c) { sp_pos.setX(c);}
void changePosY (int c) { sp_pos.setY(c);}
SDL_Surface* getImg() { return sp_img; }
Point2D getPos() { return sp_pos; }
Point2D getVel() { return sp_vel; }
Point2D getCenter() { return sp_center; }
Point2D getSize() { return sp_size; }
double getRadius() { return sp_radius; }
int getCurFrame() { return sp_cur_frame; }
int getFrames() { return sp_frames; }
bool collide(Sprite &another_sprite);
virtual ~Sprite() {}
Sprite& operator=(Sprite other) {
std::swap(sp_pos, other.sp_pos);
std::swap(sp_vel, other.sp_vel);
std::swap(sp_img, other.sp_img);
std::swap(sp_center, other.sp_center);
std::swap(sp_size, other.sp_size);
std::swap(sp_radius, other.sp_radius);
std::swap(sp_animated, other.sp_animated);
std::swap(sp_frames, other.sp_frames);
std::swap(sp_cur_frame, other.sp_cur_frame);
return *this;
}
Sprite(const Sprite &obj)
{
sp_pos = obj.sp_pos;
sp_vel = obj.sp_vel;
sp_img = new SDL_Surface;
*sp_img = *obj.sp_img;
sp_center = obj.sp_center;
sp_size = obj.sp_size;
sp_radius = obj.sp_radius;
sp_animated = obj.sp_animated;
sp_frames = obj.sp_frames;
sp_cur_frame = obj.sp_cur_frame;
}
};
If it matters, I am using gcc compiler (Actually my IDE is codeblocks). The question is, why does the program crash? How do I solve this issue?
Thanks in advance
I cannot modify the member values of a class object because of the above error:
When I call my initialize function to initialize my "garo" object, I receive the following run-time error,
"Unhandled exception at 0x01323976 in Heretic.exe: 0xC0000005: Access violation reading location 0x00000008."
NOTE: The class Garo is a child of Object.
THE CODE
Garo.h
#pragma once
#include "Object.h"
class Garo : public Object
{
private:
int animationRow;
public:
Garo();
void Destroy();
void Init(ALLEGRO_BITMAP *image = NULL);
void Update();
void Render();
void MoveLeft();
void MoveRight();
void Idle();
void SetAnimationRow(int row);
};
Garo.cpp
#include "Garo.h"
Garo::Garo()
{
Object::Init(20, 200, 3, 0, 0, 0, 16, 24);
}
void Garo::Init(ALLEGRO_BITMAP *image)
{
Object::Init(20, 200, 3, 0, 0, 0, 16, 24);
SetID(PLAYER);
SetAlive(true);
maxFrame = 3;
curFrame = 0;
frameWidth = 32;
frameHeight = 48;
animationColumns = 4;
animationDirection = 1;
animationRow = 0;
if(image != NULL)
Garo::image = image;
}
... the rest has been abbreviated
Object.h
#pragma once
#include <iostream>
#include <allegro5/allegro5.h>
#include <allegro5/allegro_primitives.h>
#include "Globals.h"
class Object
{
private:
int ID;
bool alive;
bool collidable;
protected:
float x;
float y;
float velX;
float velY;
int dirX;
int dirY;
int boundX;
int boundY;
int maxFrame;
int curFrame;
int frameCount;
int frameDelay;
int frameWidth;
int frameHeight;
int animationColumns;
int animationDirection;
ALLEGRO_BITMAP *image;
public:
Object();
void virtual Destroy();
void Init(float x, float y, float velX, float velY, int dirX, int dirY, int boundX, int boundY);
void virtual Update();
void virtual Render();
float GetX() {return x;}
float GetY() {return y;}
void SetX(float x) {Object::x = x;}
void SetY(float y) {Object::y = y;}
int GetBoundX() {return boundX;}
int GetBoundY() {return boundY;}
int GetID() {return ID;}
void SetID(int ID) {Object::ID = ID;}
bool GetAlive() {return alive;}
void SetAlive(bool alive) {Object::alive = alive;}
bool GetCollidable() {return collidable;}
void SetCollidable(bool collidable) {Object::collidable = collidable;}
bool CheckCollisions(Object *otherObject);
void virtual Collided(int objectID);
bool Collidable();
};
Object.cpp
#include "Object.h"
Object::Object()
{
x = 0;
y = 0;
velX = 0;
velY = 0;
dirX = 0;
dirY = 0;
boundX = 0;
boundY = 0;
maxFrame = 0;
curFrame = 0;
frameCount = 0;
frameDelay = 0;
frameWidth = 0;
frameHeight = 0;
animationColumns = 0;
animationDirection = 0;
image = NULL;
alive = true;
collidable = true;
}
void Object::Init(float x, float y, float velX, float velY, int dirX, int dirY, int boundX, int boundY)
{
std::cout << "HERE?" << std::endl;
Object::x = x;
Object::y = y;
Object::velX = velX;
Object::velY = velY;
Object::dirX = dirX;
Object::dirY = dirY;
Object::boundX = boundX;
Object::boundY = boundY;
}
The Calling Code
Garo *garo;
// ...
garo->Init(garo_img);
This is where I receive the run-time error. I'm using Allegro libraries, so feel free to ask about any weird types you may see. I am stilling learning C++, so please help me to understand in rudimentary terms.
You need to instantiate an object instance to operate on. For example:
garo = new Garo();
By missing this out you are trying to invoke methods on an uninitialized variable. You should probably consider using some form of smart pointer to ensure that the object is destroyed.