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.
Related
When I try to compile the following code:
Alien::Action::Action(ActionType type, float x, float y) {
Action::type = type;
pos = Vec2(x, y);
}
Alien::Alien(float x, float y, int nMinions) {
srand(time(NULL));
sp = Sprite("img/alien.png");
box = Rect(x, y, sp.GetWidth(), sp.GetHeight());
box.x = x - box.h/2;
box.y = y - box.w/2;
hitpoints = 100;
speed.x = 0.5;
speed.y = 0.5;
minionArray = std::vector<Minion>();
for(int i = 0; i < nMinions; i++) {
int a = rand()%501;
float b = a/1000.0;
float c = b+1;
minionArray.emplace_back(Minion(get(), i*(360/nMinions), c));
}
taskQueue = std::queue<Action>();
}
The IDE (Eclipse) gives the following error message: "undefined reference to 'vtable for Alien'" (line 6 of the code). Since there's no virtual method inside Alien, I don't know the cause of the error. The following is the header file for Alien:
#ifndef ALIEN_H_
#define ALIEN_H_
#include "GameObject.h"
class Alien: public GameObject {
private:
class Action {
public:
enum ActionType {MOVE, SHOOT};
ActionType type;
Action(ActionType type, float x, float y);
Vec2 pos;
};
int hitpoints;
std::queue<Action> taskQueue;
std::vector<Minion> minionArray;
public:
Alien(float x, float y, int nMinions);
~Alien();
void Update(float dt);
void Render();
Alien* get();
bool IsDead();
};
#endif
The code for GameObject is :
#include "GameObject.h"
#include "InputManager.h"
#include "Camera.h"
#include "State.h"
GameObject::~GameObject() {
}
GameObject* GameObject::get() {
return this;
}
Minion::~Minion() {
}
Minion::Minion(GameObject* minionCenter, float arcOffset, float minionSize) {
sp = Sprite("img/minion.png");
center = minionCenter;
translation = arcOffset;
box = Rect(center->box.GetCenter().x+(cos(translation*M_PI/180)*200)-(sp.GetWidth()/2),
center->box.GetCenter().y+(sin(translation*M_PI/180)*200)-(sp.GetHeight()/2),
sp.GetWidth(), sp.GetHeight());
}
void Minion::Shoot(Vec2 pos) {
State::AddObject(new BulletWheel(box.GetCenter().x, box.GetCenter().y, center->box.GetCenter().GetDX(pos.x),
center->box.GetCenter().GetDY(pos.y), center->box.GetCenter().GetDS(pos), 0.3,
translation, center->box.GetCenter(), "img/minionbullet1.png"));
}
void Minion::Update(float dt) {
if(translation < 360)
translation += 0.03*dt;
else
translation += 0.03*dt-360;
/*rotation = translation-90;*/
if(rotation < 360)
rotation += 0.15*dt;
else
rotation += 0.15*dt-360;
box.x = center->box.GetCenter().x+(200*cos((translation)*M_PI/180))-(box.w/2);
box.y = center->box.GetCenter().y+(200*sin((translation)*M_PI/180))-(box.h/2);
}
void Minion::Render() {
sp.Render(box.x - Camera::GetInstance().pos.x, box.y - Camera::GetInstance().pos.y, rotation);
}
bool Minion::IsDead() {
return false;
}
Bullet::Bullet(float x, float y, float dx, float dy, float maxDistance, float speed, std::string sprite) {
sp = Sprite(sprite);
box = Rect(x-(sp.GetWidth()/2), y-(sp.GetHeight()/2), sp.GetWidth(), sp.GetHeight());
Bullet::speed = Vec2(speed*(dx/maxDistance), speed*(dy/maxDistance));
distanceLeft = maxDistance;
rotation = atan2(dy, dx)*(180/M_PI);
}
void Bullet::Update(float dt) {
if(distanceLeft > 0) {
box.x += speed.x*dt;
box.y += speed.y*dt;
distanceLeft -= pow(pow(speed.x*dt,2)+pow(speed.y*dt,2),0.5);
}
}
void Bullet::Render() {
sp.Render(box.x - Camera::GetInstance().pos.x, box.y - Camera::GetInstance().pos.y, rotation);
}
bool Bullet::IsDead() {
return (distanceLeft < 1) ? true : false;
}
Bullet* Bullet::get() {
return this;
}
BulletWheel::BulletWheel(float x, float y, float dx, float dy, float maxDistance, float speed, float arcOffset, Vec2 center, std::string sprite) {
sp = Sprite(sprite);
sp.SetScaleX(2);
sp.SetScaleY(2);
box = Rect(x-(sp.GetWidth()/2), y-(sp.GetHeight()/2), sp.GetWidth(), sp.GetHeight());
BulletWheel::speed = Vec2(speed*(dx/maxDistance), speed*(dy/maxDistance));
distanceLeft = maxDistance;
rotation = atan2(dy, dx)*(180/M_PI);
translation = arcOffset;
BulletWheel::center = center;
}
void BulletWheel::Update(float dt) {
if(translation < 360)
translation += 0.1*dt;
else
translation += 0.1*dt-360;
if(distanceLeft > 0.01) {
center.x += speed.x*dt;
center.y += speed.y*dt;
box.x = center.x+(200*cos((translation)*M_PI/180))-(box.w/2);
box.y = center.y+(200*sin((translation)*M_PI/180))-(box.h/2);
distanceLeft -= pow(pow(speed.x*dt,2)+pow(speed.y*dt,2),0.5);
}
}
void BulletWheel::Render() {
sp.Render(box.x - Camera::GetInstance().pos.x, box.y - Camera::GetInstance().pos.y, rotation);
}
bool BulletWheel::IsDead() {
return distanceLeft < 1;
}
BulletWheel* BulletWheel::get() {
return this;
}
and its header file is:
#ifndef GAMEOBJECT_H_
#define GAMEOBJECT_H_
#include "Sprite.h"
#include "Rect.h"
#include "Vec2.h"
#include <queue>
#include <vector>
#include <cmath>
#include <ctime>
class GameObject{
private:
public:
virtual ~GameObject();
virtual void Update(float dt) = 0;
virtual void Render() = 0;
virtual bool IsDead() = 0;
virtual GameObject* get();
int rotation = 0;
int translation = 0;
Sprite sp = Sprite();
Vec2 speed = Vec2();
Rect box = Rect();
};
class Minion : public GameObject {
private:
GameObject* center;
public:
Minion(GameObject* minionCenter, float arcOffset, float minionSize = 1);
~Minion();
void Shoot(Vec2 pos);
void Update(float dt);
void Render();
bool IsDead();
Minion* get();
};
class Bullet : public GameObject {
private:
float distanceLeft;
public:
Bullet(float x, float y, float dx, float dy, float maxDistance, float speed, std::string sprite);
void Update(float dt);
void Render();
bool IsDead();
Bullet* get();
};
class BulletWheel : public GameObject {
private:
float distanceLeft;
Vec2 center;
public:
BulletWheel(float x, float y, float dx, float dy, float maxDistance, float speed, float arcOffset, Vec2 center, std::string sprite);
void Update(float dt);
void Render();
bool IsDead();
BulletWheel* get();
};
#endif /* GAMEOBJECT_H_ */
There are the virtual functions of GameObject, declared inside Alien.cpp:
void Alien::Update(float dt) {
if(rotation > 0)
rotation -= 0.1*dt;
else
rotation -= 0.1*dt+360;
if(InputManager::GetInstance().MousePress(RIGHT_MOUSE_BUTTON)) {
taskQueue.push(Action(Action::MOVE,(InputManager::GetInstance().GetMouseX() + Camera::GetInstance().pos.x - (box.w/2)),
(InputManager::GetInstance().GetMouseY() + Camera::GetInstance().pos.y - (box.h/2))));
}
if(InputManager::GetInstance().MousePress(LEFT_MOUSE_BUTTON)) {
taskQueue.push(Action(Action::SHOOT,(InputManager::GetInstance().GetMouseX() + Camera::GetInstance().pos.x),
(InputManager::GetInstance().GetMouseY() + Camera::GetInstance().pos.y)));
}
if(taskQueue.size() > 0) {
Vec2 pos = taskQueue.front().pos;
if(taskQueue.front().type == Action::MOVE) {
float cos = (box.GetDX(pos.x)/box.GetDS(pos));
float sin = (box.GetDY(pos.y)/box.GetDS(pos));
if(cos != cos) {
cos = 0;
}
if(sin != sin) {
sin = 0;
}
if((box.x+speed.x*cos*dt > pos.x && pos.x > box.x) || (box.x+speed.x*cos*dt < pos.x && pos.x < box.x)) {
box.x = pos.x;
}
else {
box.x += speed.x*cos*dt;
}
if((box.y+speed.y*sin*dt > pos.y && pos.y > box.y) || (box.y+speed.y*sin*dt < pos.y && pos.y < box.y)) {
box.y = pos.y;
}
else {
box.y += speed.y*sin*dt;
}
if(box.x == pos.x && box.y == pos.y) {
taskQueue.pop();
}
}
else {
for(unsigned i = 0; i < minionArray.size(); i++) {
minionArray.at(i).Shoot(pos);
taskQueue.pop();
}
}
}
for(unsigned i = 0; i < minionArray.size(); i++) {
minionArray.at(i).Update(dt);
}
}
void Alien::Render() {
sp.Render(box.x - Camera::GetInstance().pos.x, box.y - Camera::GetInstance().pos.y, rotation);
if(minionArray.size() > 0) {
for(unsigned i = 0; i < Alien::minionArray.size(); i++) {
minionArray.at(i).Render();
}
}
}
bool Alien::IsDead() {
return (Alien::hitpoints <= 0);
}
EDIT: the destructor of Alien was missing.
All classes derived from GameObject must define all pure virtual functions in GameObject. In your case, this is:
virtual void Update(float dt) = 0;
virtual void Render() = 0;
virtual bool IsDead() = 0;
Here is a similar question with more information. Hope this helps!
I am attempting to create a graphical representation of finite automata using xcode, and as such I have created classes for states and transitions. In order to make moving objects easy, I have included a collection of pointers of transitions going in and out of the state. Compiling is fines, but when I try to append to the vector, it produces the following error. EXC_BAD_ACCESS(code=1, address=0x3f35)
Following the error takes me to the std library, and shows the error being in this line.
template <class _Tp, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
void
vector<_Tp, _Allocator>::push_back(const_reference __x)
{
if (this->__end_ != this->__end_cap())
{
__annotate_increase(1);
__alloc_traits::construct(this->__alloc(),
_VSTD::__to_raw_pointer(this->__end_), __x);
++this->__end_;
}
else
__push_back_slow_path(__x);
}
Here is a simplified version of my State class, my Transition class is declared before and is then defined afterwards.
class State
{
int id;
std::vector<Transition *> links_in;
std::vector<Transition *> links_out;
float x;
float y;
int r = radius; //x, y are centre coordinates of the circle representing the state, while r is the radius
bool is_active = false;
bool is_end = false;
bool is_shown = true;
bool is_moving;
public:
// Get Functions go here
// Set Functions go here
//Add functions
void add_in_trans(Transition * t){
links_in.push_back(t);
}
void add_out_trans(Transition * t){
links_out.push_back(t);
}
//Delete Functions
void remove_in_trans(){
links_in.pop_back();
}
void remove_out_trans(){
links_out.pop_back();
}
void draw_state();
State(int ix, int iy);
State(){}
}
If you have any suggestions for a better way of doing this, I am more then happy to hear them. I have spent all day trying to sort this out, to no avail.
Thanks in advance.
UPDATE:
I attempted to use integers and vectors as a temporary fix, but I came up with the same problem, so I assume that the problem isn't the pointers but the way I'm using vectors.
This is the code
#include <vector>
class Transition;
class State
{
int id;
std::vector<int> links_in;
std::vector<int> links_out;
float x;
float y;
int r = radius; //x, y are centre coordinates of the circle representing the state, while r is the radius
bool is_active = false;
bool is_end = false;
bool is_shown = true;
bool is_moving;
public:
// Get Functions
int get_x(){
return x;
}
int get_y(){
return y;
}
int get_id(){
return id;
}
bool is_it_active(){
return is_active;
}
bool is_it_moving(){
return is_moving;
}
bool is_in(int ix, int iy){ //Function to tell if pair of coordinates are in the circle, used to select.
std::cerr << ix-x << " " << iy-y << " " << r*r << std::endl;
if ((ix-x)*(ix-x) + (iy-y)*(iy-y) < r*r)
return true;
else
return false;
}
// Set Functions
void set_active(bool s){
is_active = s;
}
void set_moving(bool s){
is_moving = s;
}
void end_switch(){
is_end = !is_end;
}
void set_start(){
g_start_state = id;
}
void set_x(int ix){
x = ix;
}
void set_y(int iy){
y = iy;
}
//Add functions
void add_in_trans(int t){
links_in.push_back(t);
}
void add_out_trans(int t){
links_out.push_back(t);
}
//Delete Functions
void remove_in_trans(){
links_in.pop_back();
}
void remove_out_trans(){
links_out.pop_back();
}
void draw_state();
State(int ix, int iy);
State(){}
};
State::State(int ix, int iy){
id = g_state_num;
if (g_start_state == 0)
g_start_state = id;
x = ix;
y = iy;
}
void State::draw_state(){
if (is_shown){
if (is_moving)
glTranslatef(g_cursor_x, g_cursor_y, 0.0);
else
glTranslatef(x, y, 0.0);
fill_colour();
if (is_active)
active_fill_colour();
glBegin(GL_POLYGON);
for (size_t i=0; i<24; i++){
float n[2] = {static_cast<float>(r * cos(i*6)), static_cast<float>(r * sin(i*6))};
glVertex2fv(n);
}
glEnd();
line_colour();
glBegin(GL_LINES);
for (size_t i=0; i<24; i++){
float n[2] = {static_cast<float>(r * cos(i*6)), static_cast<float>(r * sin(i*6))};
glVertex2fv(n);
}
glEnd();
if(is_end){
glPushMatrix();
glScalef(0.9, 0.9, 0.9);
for (size_t i=0; i<24; i++){
float n[2] = {static_cast<float>(r * cos(i*6)), static_cast<float>(r * sin(i*6))};
glVertex2fv(n);
}
glPopMatrix();
}
text_colour();
std::string s = std::to_string(id);
for (int i=0; i<s.length(); i++){
glPushMatrix();
glTranslatef(-radius/2 + i*kerning, -radius/2, 0.0);
glScalef(0.3, 0.3, 1.0);
glutStrokeCharacter(GLUT_STROKE_ROMAN, s[i]);
glPopMatrix();
}
}
}
class Character{
int id;
char c;
public:
int get_id(){
return id;
}
char get_char(){
return c;
}
void set_char(char ic){
c = ic;
}
Character(char ic);
Character(){};
};
Character::Character(char ic){
id = g_character_num;
g_character_num++;
c = ic;
}
class Transition{
int ident;
State * from_state;
State * to_state;
float from[2];
float to[2];
Character c;
public:
void set_from(float x, float y){
from[0] = x;
from[1] = y;
}
void set_to(float x, float y){
to[0] = x;
to[1] = y;
}
void set_char(Character ic){
c = ic;
}
int get_id(){
return ident;
}
void draw_trans();
void set_trans(State * ifrom, State * ito, Character ic){
from_state = ifrom;
to_state = ito;
from[0] = ifrom->get_x();
from[1] = ifrom->get_y();
to[0] = ito->get_x();
to[1] = ito->get_y();
c = ic;
}
Transition(){};
Transition(State ifrom, State ito, Character ic){
from_state = &ifrom;
to_state = &ito;
from[0] = ifrom.get_x();
from[1] = ifrom.get_y();
to[0] = ito.get_x();
to[1] = ito.get_y();
c = ic;
}
};
void Transition::draw_trans(){
line_colour();
glBegin(GL_LINES);
glVertex2fv(from);
glVertex2fv(to);
glEnd();
float grad = (from[0] - to[0]) /(from[1] - to[1]); //(By finding the gradient of the slope, we can fin good place to show it's information, it's character.
if (grad < -1 || grad > 1){
glPushMatrix();
glTranslatef(from[0] - to[0] - 20, from[1] - to[1], 1.0);
}
else{
glPushMatrix();
glTranslatef(from[0] - to[0], from[1] - to[1] + 20, 1.0);
}
glutStrokeCharacter(GLUT_STROKE_ROMAN, (c.get_char()));
glPopMatrix();
}
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.
In my program I have created an Object class, that's not overly complicated (has a lot of types of constructors but that's beside the point). I have looked at the syntax for creating a pointer to a class, and I can't seem to find a problem with it, but it keeps producing this error code
Error: a value of type "Object (*)()" cannot be used to initialize an entity of type "Object
*"
System Info: Windows Embedded 8.1 x64
IDE: Microsoft Visual Studio 2013 Update 4
Object.h:
#ifndef OBJECT_H
#define OBJECT_H
#include "Point.h"
class Object {
private:
float mf_Mass;
float mf_Volume;
int mn_ID;
bool mb_Parent;
bool mb_Child;
Point position;
Object* mp_Child;
Object* mp_Parent;
public:
//ID generation
static int c_IDGenerator;
void generateID(){ mn_ID = c_IDGenerator++; return; }
//Constructor Prototypes
Object();
Object(Point point);
Object(Object* child);
Object(float mass);
Object(Point point, Object* child);
Object(Point point, float mass);
Object(Object* child, Object* parent);
Object(Object* child, float mass);
Object(float mass, float volume);
Object(Point point, Object* child, Object* parent);
Object(Point point, Object* child, float mass);
Object(Object* child, Object* parent, float mass);
Object(Object* child, float mass, float volume);
Object(Point point, Object* child, Object* parent, float mass);
Object(Point point, Object* child, float mass, float volume);
Object(Object* child, Object* parent, float mass, float volume);
Object(Point point, Object* child, Object* parent, float mass, float volume);
//Get and Set methods
float getMass(){ return mf_Mass; }
float getVolume(){ return mf_Volume; }
int getID(){ return mn_ID; }
Point getPosition(){ return position; }
Object& getChild(){ return &(mp_Child); }
Object& getParent(){ return &(mp_Parent); }
bool isParent(){ return mb_Parent; }
bool isChild(){ return mb_Child; }
void setMass(float mass){ mf_Mass = mass; return; }
void setVolume(float volume){ mf_Volume = volume; return; }
void setChild(Object* child){ mp_Child = child; return; }
void setParent(Object* parent){ mp_Parent = parent; return; }
//Object Interface
void move(int x, int y);
void move(Point point);
void destroyChild();
void resetChild();
void resetParent();
float calculateDensity();
}
#endif
Object.cpp:
#include "Object.h"
//Object Constructors with 0 known field(s)
Object::Object()
: position(0, 0)
{
mf_Mass = 1;
mf_Volume = 1;
mp_Child = 0;
mp_Parent = 0;
mb_Child = false;
mb_Parent = false;
generateID();
}
//Object Constructors with 1 known field(s)
Object::Object(Point point)
: position(point)
{
mf_Mass = 1;
mf_Volume = 1;
mp_Child = 0;
mp_Parent = 0;
mb_Child = false;
generateID();
}
Object::Object(Object* child)
: position(0, 0)
{
mf_Mass = 1;
mf_Volume = 1;
mp_Child = child;
mp_Parent = 0;
generateID();
}
Object::Object(float mass)
: position(0, 0)
{
mf_Mass = mass;
mf_Volume = 0;
mp_Child = 0;
mp_Parent = 0;
generateID();
}
//Object Constructors with 2 known field(s)
Object::Object(Point point, Object* child)
: position(point)
{
mf_Mass = 1;
mf_Volume = 1;
mp_Child = child;
mp_Parent = 0;
generateID();
}
Object::Object(Point point, float mass)
: position(point)
{
mf_Mass = mass;
mf_Volume = 1;
mp_Child = 0;
mp_Parent = 0;
generateID();
}
Object::Object(Object* child, Object* parent)
: position(0, 0)
{
mf_Mass = 1;
mf_Volume = 1;
mp_Child = child;
mp_Parent = parent;
generateID();
}
Object::Object(Object* child, float mass)
: position(0, 0)
{
mf_Mass = mass;
mf_Volume = 1;
mp_Child = child;
mp_Parent = 0;
generateID();
}
Object::Object(float mass, float volume)
: position(0, 0)
{
mf_Mass = mass;
mf_Volume = volume;
mp_Child = 0;
mp_Parent = 0;
generateID();
}
//Object Constructors with 3 known field(s)
Object::Object(Point point, Object* child, Object* parent)
: position(point)
{
mf_Mass = 1;
mf_Volume = 1;
mp_Child = child;
mp_Parent = parent;
generateID();
}
Object::Object(Point point, Object* child, float mass)
: position(point)
{
mf_Mass = mass;
mf_Volume = 1;
mp_Child = child;
mp_Parent = 0;
generateID();
}
Object::Object(Object* child, Object* parent, float mass)
: position(0, 0)
{
mf_Mass = mass;
mf_Volume = 1;
mp_Child = child;
mp_Parent = parent;
generateID();
}
Object::Object(Object* child, float mass, float volume)
: position(0, 0)
{
mf_Mass = mass;
mf_Volume = volume;
mp_Child = child;
mp_Parent = 0;
generateID();
}
//Object Constructors with 4 known field(s)
Object::Object(Point point, Object* child, Object* parent, float mass)
: position(point)
{
mf_Mass = mass;
mf_Volume = 1;
mp_Child = child;
mp_Parent = parent;
generateID();
}
Object::Object(Object* child, Object* parent, float mass, float volume)
: position(0, 0)
{
mf_Mass = mass;
mf_Volume = volume;
mp_Child = child;
mp_Parent = parent;
generateID();
}
//Object Constructors with 5 known field(s)
Object::Object(Point point, Object* child, Object* parent, float mass, float volume)
: position(point)
{
mf_Mass = mass;
mf_Volume = volume;
mp_Child = child;
mp_Parent = parent;
generateID();
}
//Object Interaction Methods
void Object::move(int x = 0, int y = 0)
{
position.move(x, y);
}
void Object::move(Point point)
{
position.move(point);
}
void Object::destroyChild()
{
if(mp_Child)
{
mp_Child->~Object();
resetChild();
}
else
{
resetChild();
}
}
void Object::resetChild()
{
mp_Child = 0;
mb_Parent = false;
}
void Object::resetParent()
{
mp_Parent = 0;
mb_Child = false;
}
float Object::calculateDensity()
{
return (mf_Mass / mf_Volume);
}
Point.h:
class Point {
public:
int _X;
int _Y;
Point()
{
_X = 0;
_Y = 0;
}
Point(int x)
{
_X = x;
_Y = 0;
}
Point(int x, int y)
{
_X = x;
_Y = y;
}
void reset()
{
_X = 0;
_Y = 0;
}
void moveX(int x)
{
_X = x;
}
void moveY(int y)
{
_Y = y;
}
void move(int x, int y)
{
_X = x;
_Y = y;
}
void move(Point point)
{
_X = point._X;
_Y = point._Y;
}
void offsetX(int osX)
{
_X += osX;
}
void offsetY(int osY)
{
_Y += osY;
}
void offset(int osX, int osY)
{
_X += osX;
_Y += osY;
}
}
Main.cpp:
#include "Object.h"
#include "Point.h"
#include <iostream>
using namespace std;
int main()
{
Point origin;
Point p1(1);
Point p2(1, 3);
Object obj1();
Object* child;
child = &obj1;
Object obj2(origin);
Object obj3(&obj2);
Object obj4(1.25);
Object obj5(p1, &obj1);
Object obj6(p1, 4.0f);
Object obj7(&obj1, 4.0f);
Object obj8(&obj2, &obj3);
Object obj9(2.0f, 4.0f);
Object obj10(p2, &obj1, &obj2);
Object obj11(p2, &obj1, 4.0f);
Object obj12(&obj1, &obj2, 3.0f);
Object obj13(&obj1, 2.5f, 2.6f);
Object obj14(origin, &obj10, &obj11, 10.0f);
Object obj15(&obj12, &obj13, 11.0f, 13.0f);
Object obj16(p1, &obj14, &obj15, 100.0f, 100.0f);
Object objs[] = { obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11, obj12, obj13, obj14, obj15, obj16 };
for (int i = 0; i < 16; i++)
{
cout << objs[i];
}
system("pause");
return 0;
}
PLEASE NOTE: I know I have not overloaded the operator<< function yet, that is to come. I want to get the other problem fixed before I attempt to move on with anything.
Also, I understand that the "system("pause");" line is not recommended and frowned upon, this is just a personal project so I don't care that it is OS specific at the moment, I'll change it if I decide to port to another platform.
I can't find anything wrong with my syntax or logic but, I'm pretty new to C++ classes so I'm open for any suggestions, thanks!!!
This:
Object obj1();
is a function declaration. It is a function named obj1 that takes zero arguments and returns an Object. This is known as the "most vexing parse." What you meant was:
Object obj1;
You can tell this from the error message, indicating that your right-hand-side is of type "pointer to function that takes zero arguments and returns an Object rather than the "pointer to Object" that you were expecting:
Error: a value of type "Object (*)()" cannot be used to initialize an entity of type "Object *"
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.