0

一段时间以来,我一直在尝试制作游戏引擎,考虑到这是我制作的第一个引擎,大部分时间都做得很好。但是当我开始使用包含在基类指针向量数组中的派生类来制作事件发送/接收系统时,我在让接收器获取类类型并使用正确的函数时遇到了一些麻烦;这就是我所拥有的:

这是我的基类对象:

对象.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

对象.cpp:

#include "object.h"
#include "body.h"

void Object::interact(Body *body)
{
    body->obj_event(this);
}

这是我的派生类正文:

身体.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 类:

实体.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

实体.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

播放器.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->obj_event(this) ,它将选择具有最多派生参数的正确函数。

例如,如果 Player 调用了敌人的 object->interact(this),则敌人将首先使用它的基类Object的虚函数 interact(Body*),然后检查派生类是否具有相同的函数 (哪个敌人做的),然后敌人通过它的基类Body调用玩家身体的 body->obj_event(this) 。玩家主体将首先使用它的基类Body的虚函数 obj_event(Enemy*),然后检查派生类是否具有相同的功能(Entity 有),然后 Entity 执行 obj_event(Enemy*)。至少我是这么理解的。

我想要的是任何派生类通过它的基函数调用任何其他派生类的交互的方法,然后让它为派生类调用它的 obj_event 函数,而不必具有任何基类了解他们的派生类。

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

4

0 回答 0