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.
Related
I am working on recreating pong, and while moving drawPaddle function from the main Game class to the Paddle class I ran into an issue where the function cannot read the member variables (even though they are in the same class). The class is in a header file and the function definitions are in a cpp file. The variables in question are height, width, xPos, and yPos.
Paddle class
#include "Graphics.h"
class Paddle
{
public:
void setX(int z)
{
xPos = z;
}
int getX()
{
return xPos;
}
void setY(int z)
{
yPos = z;
}
int getY()
{
return yPos;
}
int getWidth() {
return width;
}
void setHeight(int z)
{
height = z;
}
int getHeight()
{
return height;
}
void setPlayer(bool z)
{
player = z;
}
bool getPlayer()
{
return player;
}
private:
//functions
void drawPaddle(Graphics& gfx);
void updatePaddle(Graphics& gfx);
//variables
int xPos;
int yPos = Graphics::ScreenHeight / 2 - Paddle::height / 2;
bool player;
static constexpr int width = 20;
int height = 100;
};
drawPaddle function
#include "Paddle.h"
#include "Graphics.h"
void drawPaddle(Graphics gfx)
{
for (int i = 0; i < width; i++)
{
for (int j = 0; j < Paddle::height; j++)
{
gfx.PutPixel(p.getX() + i, p.getY() + j, Colors::White);
}
}
}
As you can see I've tried accessing it with the raw variable (tells me the variable is undefined), through the class (tells me the variable is inaccessible), and using the getter for it (failed because it must be in reference to a specific instance). Anyone have any idea what I am doing wrong? Thanks.
In the definition, you didn't indicate that drawPaddle was a member of Paddle, so it was treating that definition as a definition of a free function, not a member function. Free functions wouldn't have access to the private members.
It should start with
void Paddle::drawPaddle(Graphics gfx)
I tried to write a simple game and I accidently got errors
"No matching function for call to Monster::Monster()"
and
"No matching function for call to Player::Player()".
Both were for the Game class constructor. Class Game is not related to classes Monster or Player in any way. Here are the codes.
main.cpp
#include <game.h>
#include <iostream>
using namespace std;
int main() {
Game game = Game( );
while(!game.hasFinished( )) {
game.round( );
}
}
game.h
#ifndef GAME
#define GAME
#include <entity.h>
class Game {
private:
bool finished = false;
char area[15][15];
char defaultSign = '*';
int size = 15;
Monster monsters[4];
Player player;
int score = 0;
void cls();
void fill();
void display();
void playerMove();
public:
Game();
void round();
int getScore();
bool hasFinished();
};
#endif
game.cpp
#include <game.h>
#include <iostream>
#include <conio.h>
Game::Game() {
player = Player(7, 7);
monsters[0] = Monster(0, 0);
monsters[1] = Monster(size - 1, size - 1);
monsters[2] = Monster(size - 1, 0);
monsters[3] = Monster(0, size - 1);
}
bool Game::hasFinished() {
return !finished;
}
int Game::getScore() {
return score;
}
void Game::cls() {
for(int i = 0; i < 50; i++) {
std::cout << "\n";
}
}
void Game::fill() {
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++) {
area[i][j] = defaultSign;
}
}
for(int i = 0; i < 4; i++) {
area[monsters[i].getX( )][monsters[i].getY( )] = monsters[i].getSign( );
}
area[player.getX( )][player.getY( )] = player.getSign( );
}
void Game::display() {
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++) {
std::cout << area[i][j];
}
std::cout << "\n";
}
}
void Game::round() {
cls( );
fill( );
display( );
playerMove( );
for(int i = 0; i < 4; i++) {
monsters[i].moveTowards(player);
}
score++;
}
void Game::playerMove() {
bool moved = false;
while(!moved) {
char c = getch( );
if(c == 'w' || c == 'W') {
player.move(player.getX( ), player.getY( ) + 1);
moved = true;
}
if(c == 'a' || c == 'A') {
player.move(player.getX( ) - 1, player.getY( ));
moved = true;
}
if(c == 's' || c == 'S') {
player.move(player.getX( ), player.getY( ) - 1);
moved = true;
}
if(c == 'd' || c == 'D') {
player.move(player.getX( ) + 1, player.getY( ));
moved = true;
}
}
}
entity.h
#ifndef ENTITY
#define ENTITY
class Entity {
protected:
int x, y;
char sign;
public:
Entity(int xPos, int yPos);
int getX();
int getY();
void move(int xPos, int yPos);
char getSign();
};
class Player : public Entity {
private:
char sign = 'P';
public:
Player(int xPos, int yPos);
};
class Monster : public Entity {
private:
char sign = 'M';
public:
Monster(int xPos, int yPos);
void moveTowards(Entity p);
};
#endif
entity.cpp
#include <entity.h>
Entity::Entity(int xPos, int yPos) {
x = xPos;
y = yPos;
sign = '*';
}
void Entity::move(int xPos, int yPos) {
x = xPos;
y = yPos;
}
int Entity::getX() {
return x;
}
int Entity::getY() {
return y;
}
char Entity::getSign() {
return sign;
}
Player::Player(int xPos, int yPos)
: Entity(xPos, yPos) {
}
Monster::Monster(int xPos, int yPos)
: Entity(xPos, yPos) {
}
void Monster::moveTowards(Entity p) {
int moveArea[2] = {x, y};
if(x > p.getX( )) moveArea[0]--;
if(x < p.getX( )) moveArea[0]++;
if(y > p.getY( )) moveArea[1]--;
if(y < p.getY( )) moveArea[1]++;
move(moveArea[0], moveArea[1]);
}
Please, help!
The problem is
Monster monsters[4]; // ---> Means initiliaze 4 Monsters with a ctor which takes no arguments(eg default Ctor)
Player player; ---> //The initiliaze 1 Player with a ctor which take no arguments
Since you defined Monster(int xPos, int yPos); default Ctors are deleted. You have to define them yourself. Entity has the same problem. I compiled your code , if you do like below it will work.
Add "Entity() = default;" , initiliaze x and y like below,
class Entity {
protected:
int x = 0; --> Critical
int y = 0; --> Critical
char sign;
public:
Entity() = default; --> Critical
Entity(int xPos, int yPos);
int getX();
int getY();
void move(int xPos, int yPos);
char getSign();
};
Do the same for player and monster
class Monster : public Entity {
private:
char sign = 'M';
public:
Monster(int xPos, int yPos);
Monster() = default; --> Critical
void moveTowards(Entity p);
};
class Player : public Entity {
private:
char sign = 'P';
public:
Player() = default; --> Critical
Player(int xPos, int yPos);
};
You should add a default constructor to your Monster class because it's implicitly called when the Monster array is initialized. If you don't want to do that for some reason, you could change the Monster array contain raw or smart pointers to Monster objects.
I'm trying to construct a two-dimensional boolean array with a class I've created called Grid. The Grid object is a private member class of another class called GameOfLife. Whenever I create a GameOfLife object with the parameters belove, the Grid object first gets created with the default constructor, then it gets created again with the constructor with parameters, and then for some reason Grid's deconstructor runs and deletes everything ? I'm really out of ideas :p I'm running MinGW GCC on Eclipse Luna.
Main.cpp
const int HEIGHT = 25;
const int WIDTH = 25;
#include <iostream>
#include "GameOfLife.h"
int main(int argc, const char * argv[]) {
GameOfLife game = GameOfLife(HEIGHT, WIDTH, false);
game.play();
return 0;
}
Grid.h
#ifndef __Game_Of_Life__Grid__
#define __Game_Of_Life__Grid__
#include <stdio.h>
class Grid {
public:
Grid(int y, int x, bool state);
Grid();
void allocate(int x, int y, bool state);
void deallocate();
void set(int x, int y, bool state);
bool get(int x, int y);
void setAll(bool state);
void switchBoards();
~Grid();
private:
bool ** oldGeneration;
bool ** newGeneration;
int height;
int width;
};
#endif /* defined(__Game_Of_Life__Grid__) */
Grid.cpp
#include "Grid.h"
Grid::Grid(int y, int x, bool state) {
allocate(x, y, state);
}
void Grid::allocate(int x, int y, bool state) {
height = y;
width = x;
oldGeneration = new bool*[height];
newGeneration = new bool*[height];
for (int i = 0; i < height; i++) {
oldGeneration[i] = new bool[width];
newGeneration[i] = new bool[width];
}
}
Grid::~Grid() {
deallocate();
}
void Grid::switchBoards() {
bool ** temp = oldGeneration;
oldGeneration = newGeneration;
newGeneration = temp;
delete temp;
}
bool Grid::get(int x, int y) {
return oldGeneration[y][x];
}
void Grid::set(int x, int y, bool state) {
newGeneration[y][x] = state;
}
void Grid::deallocate() {
if (oldGeneration != NULL || newGeneration != NULL) {
for (int i = 0; i < height; i++) {
delete [] oldGeneration[i];
delete [] newGeneration[i];
}
delete [] oldGeneration;
delete [] newGeneration;
}
return;
}
Grid::Grid() {
oldGeneration = NULL;
newGeneration = NULL;
width = 0;
height = 0;
}
void Grid::setAll(bool state) {
for (int i = 0; i < height; i++) {
for (int n = 0; n < width; n++) {
newGeneration[i][n] = state;
}
}
}
GameOfLife.h
#ifndef __Game_Of_Life__GameOfLife__
#define __Game_Of_Life__GameOfLife__
#include <stdio.h>
#include "Grid.h"
#include <iostream>
class GameOfLife {
private:
Grid board;
public:
GameOfLife(int y, int x, bool state);
GameOfLife();
~GameOfLife();
void play();
void welcome();
void makeBoard();
void updateBoard();
int findAliveNeighbours(int x, int y);
};
#endif /* defined(__Conway__GameOfLife__) */
GameOfLife.cpp
#include "GameOfLife.h"
const int WIDTH = 100;
const int HEIGHT= 75;
GameOfLife::GameOfLife(int y, int x, bool state) {
board = Grid(y, x, state);
}
GameOfLife::GameOfLife() {
board = Grid();
}
GameOfLife::~GameOfLife() {
board.deallocate();
}
void GameOfLife::play() {
welcome();
makeBoard();
for (int i = 0; i < HEIGHT; i++) {
for (int n = 0; n < WIDTH; n++) {
std::cout << board.get(n,i) << " ";
}
std::cout << std::endl;
}
updateBoard();
std::cout << std::endl;
for (int i = 0; i < HEIGHT; i++) {
for (int n = 0; n < WIDTH; n++) {
std::cout << board.get(n,i) << " ";
}
std::cout << std::endl;
}
}
void GameOfLife::makeBoard() {
int x1,x2,x3,x4, y1,y2,y3,y4;
x1 = 10; y1 = 10;
x2 = 10; y2 = 11;
x3 = 10; y3 = 12;
x4 = 11; y4 = 13;
int x5 = 0; int y5 = 0;
board.set(x1, y1, true);
board.set(x2, y2, true);
board.set(x3, y3, true);
board.set(x4, y4, true);
board.set(x5, y5, true);
}
void GameOfLife::welcome() {
std::cout << "Welcome to Conway's Game Of Life"
<< std::endl;
}
GameOfLife::GameOfLife(int y, int x, bool state) {
// board is a member variable that gets initialized
// with the default constructor.
// Then it gets replaced by assignment with a different
// Grid object. The temporary object gets deleted at
// the end of the line.
board = Grid(y, x, state);
}
Change the implementation to:
GameOfLife::GameOfLife(int y, int x, bool state) : board(y, x, state) {}
Similarly, change the default constructor to:
GameOfLife::GameOfLife() {}
The more important problem that needs to be fixed is that you are breaking The Rule of Three.
You need to add proper implementations of the copy constructor and the copy assignment opertor in Grid.
The other, and better, option is to change the internal data of Grid to
std::vector<std::vector<bool>> oldGeneration;
std::vector<std::vector<bool>> newGeneration;
Then, the compiler generated copy constructor and copy assignment operator will be good enough.
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;
}
}
LeftCollision in CheckCollision() goes true, when ever Object1 collides with Object2(square which is scrolling from right to left of screen) left side. But in the GameObject::Update()
Leftcollision never updates to True, though it changes to true in the CheckCollision section!!
What i want is, whenever the LeftCollision is true, Update should stop, until it becomes false again!!
Below is the code for Header file and CPP file!!
The problem is with LeftCollision updation!! Why is the value not reflected in the Update if condition!!
#pragma once
#include <iostream>
#include <allegro5/allegro5.h>
#include <allegro5/allegro_primitives.h>
#include "Globals.h"
class GameObject
{
private :
int ID;
bool alive;
bool collidable;
protected :
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 :
float x;
float y;
bool LeftCollision;
bool pause;
GameObject();
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) {GameObject ::x = x;}
void SetY(float y) {GameObject ::y = y;}
int GetBoundX() {return boundX;}
int GetBoundY() {return boundY;}
int GetID() {return ID;}
void SetID(int ID) {GameObject::ID = ID;}
bool GetAlive() {return alive;}
void SetAlive(bool alive) {GameObject :: alive = alive;}
bool GetCollidable() {return collidable;}
void SetCollidable(bool collidable) {GameObject :: collidable = collidable;}
bool CheckCollisions(GameObject *otherObject);
void virtual Collided(int objectID);
bool Collidable();
};
#include "GameObject.h"
GameObject :: GameObject()
{
x = 0;
y = 0;
velX = 0;
velY = 0;
dirX = 0;
dirY = 0;
boundX = 0;
boundY = 0;
LeftCollision = false;
maxFrame = 0;
curFrame = 0;
frameCount = 0;
frameDelay = 0;
frameWidth = 0;
frameHeight = 0;
animationColumns = 0;
animationDirection = 0;
image = NULL;
alive = true;
collidable = true;
}
void GameObject :: Destroy()
{
}
void GameObject :: Init(float x, float y, float velX, float velY, int dirX, int dirY, int boundX, int boundY)
{
GameObject :: x = x;
GameObject :: y = y;
GameObject :: velX = velX;
GameObject :: velY = velY;
GameObject :: dirX = dirX;
GameObject :: dirY = dirY;
GameObject :: boundX = boundX;
GameObject :: boundY = boundY;
}
void GameObject :: Update()
{
if(LeftCollision == false)
{
x += velX * dirX;
y += velY * dirY;
}
}
void GameObject :: Render()
{
}
bool GameObject :: CheckCollisions(GameObject *otherObject)
{
float oX = otherObject->GetX();
float oY = otherObject->GetY();
int obX = otherObject->GetBoundX();
int obY = otherObject->GetBoundY();
if( x + boundX > oX - obX &&
x - boundX < oX + obX &&
y + boundY > oY - obY &&
y - boundY < oY + obY && otherObject->GetID() == TRIANGLE)
{
return true;
}
else if(((oX < x + boundX + 14)&&(oX+ 40 >x - boundX))&&!((oY < y + boundY)&&(oY+40 > y - boundY))
&& otherObject->GetID() == SQUARE)
{
y = oY - boundX - 10;
//x = oX + 40;
return true;
}
else if((oX < x + boundX + 14) && (oX > x - boundX) && otherObject->GetID() == SQUARE)
{
LeftCollision = true;
return false;
}
else
{
return false;
LeftCollision = false;
}
}
void GameObject :: Collided(int objectID)
{
}
bool GameObject :: Collidable()
{
return alive && collidable;
}
Is this part of your problem - returning without setting the value
else
{
return false;
LeftCollision = false;
}
The only thing that jumps to mind is that you've got more than one object going around and you're not always using the one you expect. Try putting something like:
printf("here(%s:%d) this=%p\n", __FILE__, __LINE__, this);
at the start of each method to make sure that the this point is what you think it is. The problem may lie in the calling code that you haven't shown.