I have been trying to make a game engine for some time, and for the most part it has been turning out quite well, considering it's the first one i've made. But when I started to make an event send/recieve system with derived classes contained in a base class pointer vector array, I had some trouble making the reciever get the class type and use the proper function; here's what I have:
This is my base class Object:
object.h:
#include "all.h" //Contains '#include "SDL/SDL.h"' and constant variables.
#include <vector>
#include "mask.h" //An unimportant class used for collision checking
class Body;
class Room;
class Object//Objects that belong here are those without step events.
{
public:
vector<vector<Room> > *world_map;//Should hold the address of the world map.
Room *room;//The room holding this object.
unsigned int x;
unsigned int y;
unsigned int pos;//Position of the object in the room's list.
int depth;//The deeper it is, the later it will be drawn.
virtual void draw(SDL_Surface *buffer,int viewx, int viewy){}
virtual void interact(Body *body);//Sends a pointer of this object to the
//the obj_event function of the body calling it.
Object(unsigned int xx=0, unsigned int yy=0,int d=0):x(xx),y(yy),depth(d){}
};
#endif // INSTANCE_H_INCLUDED
object.cpp:
#include "object.h"
#include "body.h"
void Object::interact(Body *body)
{
body->obj_event(this);
}
This is my derived class Body:
body.h:
#ifndef BODY_H_INCLUDED
#define BODY_H_INCLUDED
#include "all.h"
#include "object.h"
class Entity;
class Enemy;
class Player;
class Body : public Object//Objects that belong here are those with step events.
{
public:
int priority;//Decides which body will perform their step event first.
virtual void step()=0;
Body(int xx=0, int yy=0, int d=0, int p=0):Object(xx,yy,d),priority(p){}
//These scripts are for handling objects and bodies it has called through
//interact()
virtual void obj_event(Object *object){}
virtual void obj_event(Entity *entity){}
virtual void obj_event(Enemy *enemy){}
virtual void obj_event(Player *player){}
};
#endif // BODY_H_INCLUDED
there is no body.cpp
This is my derived class of Body, Entity:
entity.h:
#ifndef ENTITY_H_INCLUDED
#define ENTITY_H_INCLUDED
#include "all.h"
#include "body.h"
#include "items.h"
#include <vector>
#include "mask.h"
class Entity : public Body
{
public:
vector<Item> inv;
unsigned int width;
unsigned int height;
Mask mask;
Entity(int xx,int yy,int w,int h,int d=0,int p=0);
void step();
void collide_action(Entity *entity);
virtual void obj_event(Player *player);
virtual void obj_event(Enemy *enemy);
};
#endif // ENTITY_H_INCLUDED
entity.cpp:
#include "entity.h"
#include "room.h"
#include "player.h"
#include "enemy.h"
Entity::Entity(int xx,int yy,int w,int h,int d,int p):Body(xx,yy,d,p),width(w),height(h),mask(xx,yy,w,h,m_rectangle)
{}
void Entity::step()
{
for(int iii=0;iii<room->inv.size();iii++)//Iterates through objects
{
room->inv[iii]->interact(this);
mask.update(x,y,width,height);
}
for(int iii=0;iii<room->index.size();iii++)//Iterates through bodies
{
room->index[iii]->interact(this);
mask.update(x,y,width,height);
}
}
void Entity::collide_action(Entity *entity)
{
if(entity!=this)
{
if (mask_collide(mask,entity->mask))
{
short xchange;
short ychange;
if (entity->x<x)
{
xchange=width-(x-entity->x);
}
else
{
xchange=(entity->x-x)-width;
}
if (entity->y<y)
{
ychange=height-(y-entity->y);
}
else
{
ychange=(entity->y-y)-height;
}
if(abs(xchange)<abs(ychange))
x+=xchange;
else
y+=ychange;
}
}
}
void Entity::obj_event(Player *player)
{
collide_action(player);
}
void Entity::obj_event(Enemy *enemy)
{
collide_action(enemy);
}
This is my derived class of Entity, Player:
player.h:
#ifndef PLAYER_H_INCLUDED
#define PLAYER_H_INCLUDED
#include "all.h"
#include "body.h"
#include "items.h"
#include <vector>
#include "mask.h"
#include "entity.h"
enum keylist
{
kl_left=0,
kl_up=1,
kl_right=2,
kl_down=3,
};
class Player : public Entity
{
public:
SDLKey keys[4]; //List of action's corresponding keys.
Player(int xx,int yy,int w,int h,int d=0,int p=0);
void step();
void draw(SDL_Surface *buffer,int viewx,int viewy);
void interact(Body *body);
};
#endif // PLAYER_H_INCLUDED
player.cpp:
#include "player.h"
#include "room.h"
Player::Player(int xx,int yy,int ww,int hh,int dd,int pp):Entity(xx,yy,ww,hh,dd,pp)
{
//Default keys, can be changed.
keys[kl_left]=SDLK_LEFT;
keys[kl_up]=SDLK_UP;
keys[kl_right]=SDLK_RIGHT;
keys[kl_down]=SDLK_DOWN;
}
void Player::step()
{
Uint8 *key=SDL_GetKeyState(NULL);
if (key[keys[kl_left]])
x-=1;
if (key[keys[kl_right]])
x+=1;
if (key[keys[kl_up]])
y-=1;
if (key[keys[kl_down]])
y+=1;
mask.update(x,y,width,height);
Entity::step();
}
void Player::draw(SDL_Surface *buffer,int viewx,int viewy)
{
FillRect(buffer,x-viewx,y-viewy,width,height,0xFF0000);
}
void Player::interact(Body *body){body->obj_event(this);}
I have another class Enemy, but it's pretty much exactly like player (without the keyboard controls).
Now here's my problem (not error), for every object I want any body to perform an event for, I need to make virtual functions of ALL of them in this base class, that way if any object calls body->obj_event(this), it will pick the proper function with the most derived argument.
For example, if Player called object->interact(this) of an enemy, the enemy would first use it's base class Object's virtual function interact(Body*), which would then check the derived classes if they have an identical function (which enemy does), and then enemy calls body->obj_event(this) of the player body through it's base class, Body. The player body would then first use it's base class Body's virtual function obj_event(Enemy*), which would then check the derived classes if they have an identical function (which Entity does), and then Entity executes obj_event(Enemy*). At least that's how I understand it.
What I'd like to have is a way for any derived class to call interact of any other derived class through it's base function, and would then have it call it's obj_event function for the derived class, without having to have any of the Base classes know about their derived classes.
As I mentioned, this is my first time making an engine, and I'm probably using methods that are completely hectic and error-prone. I was thinking that templates might be able to help out in this situation, but don't know how to implement them.
I have been trying to make a game engine for some time, and for the most part it has been turning out quite well, considering it's the first one i've made. But when I started to make an event send/recieve system with derived classes contained in a base class pointer vector array, I had some trouble making the reciever get the class type and use the proper function; here's what I have:
This is my base class Object:
object.h:
#include "all.h" //Contains '#include "SDL/SDL.h"' and constant variables.
#include <vector>
#include "mask.h" //An unimportant class used for collision checking
class Body;
class Room;
class Object//Objects that belong here are those without step events.
{
public:
vector<vector<Room> > *world_map;//Should hold the address of the world map.
Room *room;//The room holding this object.
unsigned int x;
unsigned int y;
unsigned int pos;//Position of the object in the room's list.
int depth;//The deeper it is, the later it will be drawn.
virtual void draw(SDL_Surface *buffer,int viewx, int viewy){}
virtual void interact(Body *body);//Sends a pointer of this object to the
//the obj_event function of the body calling it.
Object(unsigned int xx=0, unsigned int yy=0,int d=0):x(xx),y(yy),depth(d){}
};
#endif // INSTANCE_H_INCLUDED
object.cpp:
#include "object.h"
#include "body.h"
void Object::interact(Body *body)
{
body->obj_event(this);
}
This is my derived class Body:
body.h:
#ifndef BODY_H_INCLUDED
#define BODY_H_INCLUDED
#include "all.h"
#include "object.h"
class Entity;
class Enemy;
class Player;
class Body : public Object//Objects that belong here are those with step events.
{
public:
int priority;//Decides which body will perform their step event first.
virtual void step()=0;
Body(int xx=0, int yy=0, int d=0, int p=0):Object(xx,yy,d),priority(p){}
//These scripts are for handling objects and bodies it has called through
//interact()
virtual void obj_event(Object *object){}
virtual void obj_event(Entity *entity){}
virtual void obj_event(Enemy *enemy){}
virtual void obj_event(Player *player){}
};
#endif // BODY_H_INCLUDED
there is no body.cpp
This is my derived class of Body, Entity:
entity.h:
#ifndef ENTITY_H_INCLUDED
#define ENTITY_H_INCLUDED
#include "all.h"
#include "body.h"
#include "items.h"
#include <vector>
#include "mask.h"
class Entity : public Body
{
public:
vector<Item> inv;
unsigned int width;
unsigned int height;
Mask mask;
Entity(int xx,int yy,int w,int h,int d=0,int p=0);
void step();
void collide_action(Entity *entity);
virtual void obj_event(Player *player);
virtual void obj_event(Enemy *enemy);
};
#endif // ENTITY_H_INCLUDED
entity.cpp:
#include "entity.h"
#include "room.h"
#include "player.h"
#include "enemy.h"
Entity::Entity(int xx,int yy,int w,int h,int d,int p):Body(xx,yy,d,p),width(w),height(h),mask(xx,yy,w,h,m_rectangle)
{}
void Entity::step()
{
for(int iii=0;iii<room->inv.size();iii++)//Iterates through objects
{
room->inv[iii]->interact(this);
mask.update(x,y,width,height);
}
for(int iii=0;iii<room->index.size();iii++)//Iterates through bodies
{
room->index[iii]->interact(this);
mask.update(x,y,width,height);
}
}
void Entity::collide_action(Entity *entity)
{
if(entity!=this)
{
if (mask_collide(mask,entity->mask))
{
short xchange;
short ychange;
if (entity->x<x)
{
xchange=width-(x-entity->x);
}
else
{
xchange=(entity->x-x)-width;
}
if (entity->y<y)
{
ychange=height-(y-entity->y);
}
else
{
ychange=(entity->y-y)-height;
}
if(abs(xchange)<abs(ychange))
x+=xchange;
else
y+=ychange;
}
}
}
void Entity::obj_event(Player *player)
{
collide_action(player);
}
void Entity::obj_event(Enemy *enemy)
{
collide_action(enemy);
}
This is my derived class of Entity, Player:
player.h:
#ifndef PLAYER_H_INCLUDED
#define PLAYER_H_INCLUDED
#include "all.h"
#include "body.h"
#include "items.h"
#include <vector>
#include "mask.h"
#include "entity.h"
enum keylist
{
kl_left=0,
kl_up=1,
kl_right=2,
kl_down=3,
};
class Player : public Entity
{
public:
SDLKey keys[4]; //List of action's corresponding keys.
Player(int xx,int yy,int w,int h,int d=0,int p=0);
void step();
void draw(SDL_Surface *buffer,int viewx,int viewy);
void interact(Body *body);
};
#endif // PLAYER_H_INCLUDED
player.cpp:
#include "player.h"
#include "room.h"
Player::Player(int xx,int yy,int ww,int hh,int dd,int pp):Entity(xx,yy,ww,hh,dd,pp)
{
//Default keys, can be changed.
keys[kl_left]=SDLK_LEFT;
keys[kl_up]=SDLK_UP;
keys[kl_right]=SDLK_RIGHT;
keys[kl_down]=SDLK_DOWN;
}
void Player::step()
{
Uint8 *key=SDL_GetKeyState(NULL);
if (key[keys[kl_left]])
x-=1;
if (key[keys[kl_right]])
x+=1;
if (key[keys[kl_up]])
y-=1;
if (key[keys[kl_down]])
y+=1;
mask.update(x,y,width,height);
Entity::step();
}
void Player::draw(SDL_Surface *buffer,int viewx,int viewy)
{
FillRect(buffer,x-viewx,y-viewy,width,height,0xFF0000);
}
void Player::interact(Body *body){body->obj_event(this);}
I have another class Enemy, but it's pretty much exactly like player (without the keyboard controls).
Now here's my problem (not error), for every object I want any body to perform an event for, I need to make virtual functions of ALL of them in this base class, that way if any object calls body->obj_event(this), it will pick the proper function with the most derived argument.
For example, if Player called object->interact(this) of an enemy, the enemy would first use it's base class Object's virtual function interact(Body*), which would then check the derived classes if they have an identical function (which enemy does), and then enemy calls body->obj_event(this) of the player body through it's base class, Body. The player body would then first use it's base class Body's virtual function obj_event(Enemy*), which would then check the derived classes if they have an identical function (which Entity does), and then Entity executes obj_event(Enemy*). At least that's how I understand it.
What I'd like to have is a way for any derived class to call interact of any other derived class through it's base function, and would then have it call it's obj_event function for the derived class, without having to have any of the Base classes know about their derived classes.
As I mentioned, this is my first time making an engine, and I'm probably using methods that are completely hectic and error-prone. I was thinking that templates might be able to help out in this situation, but don't know how to implement them.
0 commentaires:
Enregistrer un commentaire