【发布时间】:2015-01-05 04:56:14
【问题描述】:
我是 C++ 的菜鸟,我正在尝试制作一个简单的游戏。这是我的问题:
我创建了一个名为 sprite 的类:
class Sprite
{
private:
Point2D sp_pos;
Point2D sp_vel;
SDL_Surface* sp_img;
Point2D sp_center;
Point2D sp_size;
double sp_radius;
bool sp_animated;
int sp_frames;
int sp_cur_frame;
public:
Sprite() {}
Sprite(Point2D pos, Point2D vel, SDL_Surface *img, ImageInfo info, bool animated = false, int frames = 0);
virtual void draw(SDL_Surface* screen);
virtual void update();
void setInfo (ImageInfo info);
void setPos( Point2D pos ) { sp_pos = pos; }
void setVel( Point2D vel ) { sp_vel = vel; }
void setImg (SDL_Surface* img) { sp_img = img; }
void setNextFrame() { sp_cur_frame++; }
void setFrame( int frame ) { sp_cur_frame = frame; }
void setAnimated(bool animated) { sp_animated = animated; }
void changeVelX (int c) { sp_vel.setX(c);}
void changeVelY (int c) { sp_vel.setY(c);}
void changePosX (int c) { sp_pos.setX(c);}
void changePosY (int c) { sp_pos.setY(c);}
SDL_Surface* getImg() { return sp_img; }
Point2D getPos() { return sp_pos; }
Point2D getVel() { return sp_vel; }
Point2D getCenter() { return sp_center; }
Point2D getSize() { return sp_size; }
double getRadius() { return sp_radius; }
int getCurFrame() { return sp_cur_frame; }
int getFrames() { return sp_frames; }
bool collide(Sprite &another_sprite);
};
其中有一个名为“collide”的方法,该方法检测两个精灵之间的碰撞,工作原理如下:
bool Sprite::collide(Sprite &another_sprite)
{
double d = getPos().dist(another_sprite.getPos());
if ( d < ( getRadius() + another_sprite.getRadius() ) )
return true;
else
return false;
}
该方法效果很好。我的问题出现在以下方面,我已经实现了不同的类,它们是“Sprite”的子类,并且将代表我游戏中的敌人,因此,例如我会有对象:敌人 1 类:公共 Sprite,敌人 2 类:公共 Sprite 等。他们是不同的,因为他们有不同的行为。我实现了另外两个名为 group_collide 和 group_group_collide 的辅助函数,它们的工作原理如下:
bool group_collide(std::list<Sprite> &group, Sprite other_object)
{
bool collision = false;
for (std::list<Sprite>::iterator sprite = group.begin(), end = group.end(); sprite != end; ++sprite)
{
if (sprite->collide(other_object))
{
Sprite exp = Sprite(sprite->getPos(), Point2D(0, 0), exp_image, exp_info, true, 7);
exp_group.push_back(exp);
if( Mix_PlayChannel( -1, explosion, 0 ) == -1 )
{
//abort();
}
sprite = group.erase(sprite);
collision = true;
}
}
return collision;
}
int group_group_collide(std::list<Sprite> &group, std::list<Sprite> &other_group)
{
int scored = 0;
for (std::list<Sprite>::iterator it1 = group.begin(), end1 = group.end(); it1 != end1; ++it1)
{
if (group_collide(other_group, *it1))
{
it1 = group.erase(it1);
scored += 10;
}
}
return scored;
}
所以,事实上,group collide 会检测 sprite 和 sprite 列表之间的碰撞,而 group_group_collide 会检测 sprite 组(两个不同的列表)之间的碰撞。出现的问题是:至少有 4 种敌人,它们都是我的 Sprite 类的子类,但是当我创建精灵列表并添加精灵子类的元素时出现编译错误。我的解决方案是为所有类型的敌人编写一个 group_collide 和 group_group collide 方法,但这很不雅。有没有更好的方法来解决这个问题?
编辑:
感谢您的建议。我按照您的建议将列表定义为指针列表:
std::list<Sprite*> enemy_group;
例如,我以这种方式添加作为精灵子类的“Kamikaze”类的元素(该类中的方法更新不同):
enemy_group.push_back(new Kamikaze(enemy_pos, enemy_vel, 0, enemy_image, enemy_info));
但是,在遍历列表时:
for (list<Sprite*>::iterator it = enemy_group.begin(), end = enemy_group.end(); it != end; ++it) {
(*it)->draw(screen);
(*it)->update();
if ((*it)->getPos().getY() > SCREEN_HEIGHT + 30)
{
delete *it;
it = enemy_group.erase(it);
}
}
方法 update 是从 Sprite 类调用的,而不是 Kamikaze 类,因此我也有这种方法的对象切片问题,也许我所做的有问题?
【问题讨论】:
-
这听起来很像double dispatch 类型的问题。链接的维基百科页面上显示了一个非常相似的示例。
-
您不能将派生自
Sprite的类存储在std::list<Sprite>中。你可以试试,但你会得到这个:stackoverflow.com/questions/274626/what-is-object-slicing -
另外
collide应该是一个纯virtual函数。
标签: c++ list variables inheritance subclass