我有一个包含多种turret
类型的游戏,每种类型都可以简单地用枚号表示。
当存在turret
的子类别时会出现重复代码问题。
我目前的代码如下: -
switch(type_of_turret){
//category : SHOOTER
case SHOOTER_FIRE :
case SHOOTER_ICE :
{
float temperator=0;
switch(type_of_turret){ //duplicate switch case
case SHOOTER_FIRE : temperator=1000; break;
case SHOOTER_ICE : temperator=-1000; break;
}
temperator=sinWave(temperator,time); //(Edit) an example of calculation
shoot(rigidBody,temperator);
}break;
//category : PROPULSION
......
break;
}
type_of_turret
(10到20)的类型并不多,但重复对我来说已经很糟糕了。
如果我可以在交换机内声明变量(但不在内部情况下),那就太好了: -
switch(type_of_turret){
float temperator=0; //neat but wrong syntax
case SHOOTER_FIRE : temperator=1000; /*break?*/ //neat
case SHOOTER_ICE : temperator=-1000; /*break?*/ //neat
temperator=sinWave(temperator,time); //(Edit) just an example
shoot(rigidBody,temperator); //neat
break;
....
break;
}
如何使代码更整洁?
具体来说,我如何模仿" switch-case"中的声明变量?行为?
为每个类别创建类,例如来自Shooter
的{{1}}和Propulsion
然后使用枚举或更多派生类创建Turret
的子类别
缺点:引入了不必要的复杂性,性能可能会降低(虚拟功能)
编辑(另一个缺点):它打破"无方法宗教"我的实体组件系统的内容如下: -
你会发现代理组件的方法都应该存在于系统内部,而不是组件
http://t-machine.org/index.php/2007/12/22/entity-systems-are-the-future-of-mmog-development-part-3/
stackoverflow上有一些类似的问题,例如: Why can't variables be declared in a switch statement?,但没有人讨论替代方法是什么。
答案 0 :(得分:1)
您的问题实际上并没有为某些(但不是全部)交换机案例调用公共变量。相反,显而易见的解决方案是从每个shoot()
案例中简单SHOOTER
:
enum struct shooter { fire, ice };
inline int temperature(shooter);
switch(type_of_turret){
case SHOOTER_FIRE: shoot(rigidBody, temperature(shooter::fire));
break;
case SHOOTER_ICE: shoot(rigidBody, temperature(shooter::ice));
break;
......
}
答案 1 :(得分:1)
正如我在评论中所说,不要害怕具有虚函数的多态类。例如,我会在每个炮塔子类中定义一个虚拟shoot()
函数来处理温度,甚至虚拟MyTemp()
:
class BaseTurretT
{
virtual int MyTemp() = 0;
public:
virtual void shootAt(RigidBodyT &rb)
{
// default implementation, may be overriden
shoot(rb, MyTemp());
}
// ...
};
class HotTurretT: public BaseTurretT
{
int MyTemp() { return 1000; }
// ...
};
class ColdTurretT: public BaseTurretT
{
int MyTemp() { return -1000; }
// ...
};
// more turrets in the future.
通过这些定义,您的整个交换机将折叠为一行。假设我们有一个指向基础炮塔的指针向量。指向的对象是各种派生炮塔,但使用代码并不知道并且不关心:
RigidBodyT rb;
vector<BaseTurretT *> turrets;
// ...
for(BaseTurretT *turret: turrets)
{
turret->shootAt(rb); // no switch. No idea which turret type.
}
这种设计最好的一点是它的可维护性。如果你想在未来添加更多的炮塔(并观察游戏进化的方式,这似乎是一个安全的赌注),你不必重新访问你使用炮塔的地方。你只需要添加一个新的类,所有现有的代码都会自行处理。