C ++通过基类数组派生类的事件处理程序

时间:2013-09-26 00:11:00

标签: c++ class event-handling derived-class overloading

我一直试图制作一个游戏引擎已经有一段时间了,而且大部分时间它已经相当不错,考虑到它是我制作的第一个。但是当我开始使用包含在基类指针向量数组中的派生类创建事件发送/接收系统时,我在使接收器获取类类型并使用正确的函数时遇到了一些麻烦;这就是我所拥有的:

这是我的基类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);
}

这是我的派生类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

没有body.cpp

这是我的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);
}

这是我的实体派生类,玩家:

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);}

我有另一个类Enemy,但它几乎与播放器完全一样(没有键盘控制)。

现在这是我的问题(不是错误),对于我希望任何主体执行事件的每个对象,我需要在这个基类中创建所有这些的虚函数,这样如果任何对象调用body-&gt; obj_event(this),它将选择具有最多派生参数的正确函数。

例如,如果玩家调用object-&gt;交互(此)的敌人,敌人将首先使用它的基类对象的虚拟函数交互(Body *),然后检查派生类是否具有相同的功能(敌人的功能),然后敌人通过它的基类 Body 调用玩家身体的body-&gt; obj_event(this)。然后玩家身体将首先使用它的基类 Body 的虚函数obj_event(Enemy *),如果它们具有相同的函数(实体所做的那样),它将检查派生类,然后实体执行obj_event(Enemy *)。至少我就是这样理解的。

我想要的是任何派生类通过它的基本函数调用任何其他派生类的交互,然后让它为派生类调用它的obj_event函数,而不必拥有任何Base类知道它们的派生类。

正如我所提到的,这是我第一次制作引擎,而且我可能正在使用完全忙乱且容易出错的方法。我认为模板可以在这种情况下提供帮助,但不知道如何实现它们。

0 个答案:

没有答案