我正在用java和slick2d制作冒险游戏,因为我的学校的面向对象的软件工程项目,不幸的是。
我正在应用MVC架构,我正在通过从ItemFactory类中的Tiled地图文件中读取来创建Items。它们似乎适合这种游戏。
游戏中有多个项目影响游戏,特别是角色。 (在这种情况下,角色与玩家相同)
有一个角色模型,它有一个内部类库存,它基本上由一个项目的ArrayList组成。
字符控制器有一个名为takeItem的函数,它接受一个容器参数(即shelf),它还有一个项目的ArrayList,然后删除内部的内容并放入库存。
它有一个名为useItem的函数,接受一个int索引并使用相应索引中的项。
在那之前,一切都很好。
现在主要问题是,这些项目有特定用途。例如,健康药水可以增加角色的健康,隐形药水可以使角色看不见等。
为了维持一个好的设计,如何以及在哪里可以解释和附加这些项目的功能?
到目前为止,我认为这样的事情: 1-我没有向项目类添加任何功能。它只有名称,描述和Enumerated ItemType和int power 2-我正在角色控制器的useItem()方法中做所有工作,即
if (itemBeingUsed.getType() == Common.ItemType.POTION)
`characterModel.increaseHealth(itemBeingUsed.getPower())`
正如你所看到的,这看起来很奇怪,因为角色控制器就像一个项目解释器。
3-另一种方法可能是创建一个带有角色控制器的ItemInterpreter类。虽然这看起来更优雅,但它会让我在角色控制器中做一堆不必要的函数,比如“increaseCharacterHealth”函数,它会调用字符模型的increaseHelth()函数等等。
另一个可能的问题是我使用角色控制器的功能来使用物品,但物品也可能影响游戏,即减慢时间,但角色控制器低于游戏的类层次结构,不能访问游戏/游戏控制器功能。至少现在看起来比较慢,所以看起来我可以在CharacterController类中使用Items但我想知道你的意见,如果它是一个好的设计或什么可能更好。
清除问题的一些代码:(注意:它们不完整) 注意:我将诸如ItemType,Direction等的枚举类型放在Common类中,这对所有类都是通用的。
在CharacterController中使用item函数:
public void useItem(int index){
Item item = ((Character)obj).inventory.takeItem(index);
if (item != null) {
if (item.getType() == Common.ItemType.POTION) {
((Character)obj).increaseHealth(item.getPower()); // I have extended a Person class, now I have to typecast to character everytime, which is also nonsense
}
else
System.out.println("and other items..");
}
else
System.out.println("Cannot use");
}
我没有提供所有代码,但如果我不清楚解释那么我可以。
答案 0 :(得分:4)
这是接口,继承和多态发挥作用的经典案例。每当你使用switch
或if
序列时,你应该考虑多态性。
在这种情况下,为可用项定义接口或抽象类。
public interface Useable {
public void useItem(Person personUsing);
}
现在每个项目只是实现可用,您可以检查一个项目是否可用,如果它显示使用它的选项并在使用时调用该方法。
答案 1 :(得分:1)
作为一个SOA(面向服务的体系结构)开发人员,我不会在我的项目中添加逻辑,因为在这种情况下我的代码很难分解和合理化。此外,如果您想要可扩展的代码,请记住composition is far better than inheritance。
public interface ItemEffectInterface {
public String getName();
public void affectCharacter(ItemInterface item, CharacterInterface character, parameters);
public void affectInventory(ItemInterface item, InventoryInterface inventory, parameters);
public void affectGame(ItemInterface item, GameInterface game, parameters);
}
我会定义一些处理逻辑的项效果:
AbstractItemEffect
我使用所有对象的接口在我的类之间创建低耦合(这提供了更具可伸缩性,可维护性和可测试性的代码)。
如果要定义默认行为,可以定义抽象类[
{
"item": "health potion",
"effect": "heal",
"parameters": {
"hp": 100
}
},
{
"item": "mana potion",
"effect": "regen",
"parameters": {
"mp": 150
}
},
{
"item": "mana potion",
"effect": "drunk",
"parameters": {
"duration": 1000
}
},
...
[
"什么都不做"在所有方法的扩展项目效果中,只需为每个效果定义活动方法。
然后,如果您想要一个动态可配置游戏,您可以在文件/数据库中定义项目和效果的交互。这是一个JSON示例:
public class ItemUser {
private Map itemEffects = new HashMap();
// Call it at service initialization after interpreting the configuration
// (configuration is optional, you can call it directly of course).
public void addItemEffect(ItemInterface item, ItemEffectInterface itemEffect, parameters) {
Map effect = new HashMap();
effect.push("effect", itemEffect);
effect.pust("parameters", parameters);
this.itemEffects.put(item.getName(), effect);
}
// Call it when you want to use an item.
public void useItem(ItemInterface item, Character character, GameInterface game, InventoryInterface inventory) {
Map itemEffects = this.itemEffect[item.getName()];
// Process all the effects attached to your item
// on game, character, inventory, ...
}
}
然后使用服务类将效果映射到使用时的项目:
2.
使用此架构,您可以将效果附加到许多项目,将项目附加到多种效果。这可以防止您进行代码重复。
同时,每个项目和项目效果将处理其自身的复杂性,并且不会使整个系统更复杂。对于模式'开关盒而言,情况并非如此。就像你在fun(
object.getA() != null ? object.getA() :
object.getB() != null ? object.getB() :
object.getC() != null ? object.getC() :
object.getD() != null ? object.getD() :
object.getE() != null ? object.getE() : "error"
)
中描述的一样。想想你的课程,如果你有100个效果和200个项目......
抱歉我的JAVA代码不好/不完整!