私はしばらくの間、ゲーム エンジンを作ろうとしてきましたが、それが初めて作ったものであることを考えると、ほとんどの部分で非常にうまくいっています。しかし、基本クラスのポインター ベクトル配列に含まれる派生クラスを使用してイベントの送受信システムを作成し始めたとき、レシーバーがクラス型を取得して適切な関数を使用するのに問題がありました。ここに私が持っているものがあります:
これは私の基本クラスのオブジェクトです:
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
オブジェクト.cpp:
#include "object.h"
#include "body.h"
void Object::interact(Body *body)
{
body->obj_event(this);
}
これは私の派生クラスの本体です:
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はありません
これは、ボディ、エンティティの派生クラスです。
エンティティ.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
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);}
私は別のクラスの敵を持っていますが、それはプレーヤーとほとんど同じです(キーボードコントロールなし)。
これが私の問題です(エラーではありません)。ボディにイベントを実行させたいすべてのオブジェクトについて、この基本クラスでそれらすべての仮想関数を作成する必要があります。 、最も派生した引数を持つ適切な関数を選択します。
たとえば、Player が敵の object->interact(this) を呼び出した場合、敵は最初にその基本クラスObjectの仮想関数 interact(Body*) を使用し、派生クラスが同じ関数 (どの敵が行うか)、次に敵は、基本クラスのBodyを介して、プレイヤーの体の body->obj_event(this) を呼び出します。次に、プレーヤーの本体は、最初にその基本クラスのBodyの仮想関数 obj_event(Enemy*) を使用します。次に、派生クラスが同一の関数を持っているかどうかをチェックし (Entity が実行します)、Entity が obj_event(Enemy*) を実行します。少なくとも私はそう理解しています。
私が望んでいるのは、派生クラスがその基本関数を介して他の派生クラスの対話を呼び出す方法であり、その後、基本クラスを持たなくても、派生クラスの obj_event 関数を呼び出すことができます。派生クラスについて知っています。
前述したように、エンジンを作成するのはこれが初めてであり、おそらく完全に多忙でエラーが発生しやすい方法を使用しています。この状況でテンプレートが役立つかもしれないと考えていましたが、それらを実装する方法がわかりません。