接下来是技能了,技能其实是一个主要业务逻辑组成部分,游戏的推动就是依靠技能的使用来实现的。技能的调用实质是调用卡牌的被攻击方法。
技能分单体,群体技能。所以我们需要建立一个虚基类,将必须实现的业务的方法设成虚函数,由子类去实现;
以下是具体代码,在这个类中,我们保存了全部的技能组,同样因为后期可能会对技能进行扩充,可能会有修改技能的方法,所以获取的技能亦然是副本。
副本的获取有两种。第一如我下面写的,使用覆盖clon方法来实现,优点是相当简单,只要它的子类实现这个方法即可,缺点是每个子类都要实现。
第二种,使用反射,当子类相当多的时候,可以使用反射获取构造函数来创建,优点是一次实现,子类就不需要管了。确点是构造函数要求参数相同。一种弥补措施是只使用一个构造函数。
注意:两个具体实现类的构造函数本应该使用protected(利于继续派生)或者private,这时使用反射生成对象方法应该修改(原本的只能获取public的)。
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import config.Config;
import config.SkillConfig;
public abstract class Skill extends GameUni {
/** 构造函数 **/
public Skill(int id, String name, int att) {
super(id, name, att);
}
/** 最大技能数 **/
private final static int MAX_SKILLS;
/**所有的技能**/
private final static Skill[] SKILL_ALL;
/**用于根据名字查找id,预留**/
private final static Map<String, Integer> SKILL_MAP;
static {
/**这一段同样可以先不看,可以先建立固定的数组,测试通过以后再反射使用**/
// 使用反射创建新实例
Map<String, ArrayList<String[]>> skillMap = Config.SKILLS.getSkillMap();
SKILL_ALL = new Skill[Config.SKILLS.getSkillCoutn()];
MAX_SKILLS = SKILL_ALL.length;
SKILL_MAP = new HashMap<String, Integer>();
Set<String> classes = skillMap.keySet();
int id = 0;
for (String className : classes) {
ArrayList<String[]> primers = skillMap.get(className);
try {
Class clazz = Class.forName(className);
Constructor<Skill> cons = clazz.getConstructor(int.class,
String.class, int.class);
for (String[] primer : primers) {
assert primer.length == SkillConfig.Primer_COUNT;
SKILL_ALL[id] = cons.newInstance(id++, primer[0],
Integer.parseInt(primer[1]));
SKILL_MAP.put(SKILL_ALL[id-1].getName(), SKILL_ALL[id-1].getId());
}
} catch (ClassNotFoundException e) {
System.err.println("找不到类:" + className);
continue;
} catch (NoSuchMethodException e) {
System.err.println("找不到此构造函数:" + e.getMessage());
continue;
} catch (Exception e) {
e.printStackTrace();
continue;
}
}
}
/**这是攻击某一张卡牌的方法,只提供给子类使用和复写**/
protected void attact(Card card) {
// TODO
card.attacked(getAtt());
System.out.println("card:" + getName() + "攻击了" + card.getName());
}
/**唯一获取实例的方法,通过各自的clone()来实现**/
public static Skill getSkill(int id) {
return (Skill) SKILL_ALL[id].clone();
}
/**通过名字查找Id的方法,这是提供给card根据配置文件实例化时调用的**/
public static int getSkillIdFromName(String name) {
return SKILL_MAP.get(name);
}
/**为了创建新实例而用的**/
@Override
abstract protected Object clone();
/**外部调用的方法**/
abstract public void attack(List<Card> cards);
}
以下是两种不同的技能的实现,单体和群体。以后的技能类都可以在这些类上进行继承,群体技能类也可以不继承基类,直接基础单体攻击的类
import java.util.List;
public class SingleSkill extends Skill{
/**构造**/
public SingleSkill(int id,String name, int act) {
super(id, name, act);
}
/**特定的实现,供外部调用**/
@Override
public void attack(List<Card> cards) {
//TODO 确定攻击目标
assert cards!=null;
for(Card card:cards) {
if(!card.isDaeth()) {
card.attacked(getAtt());
break;
}
}
}
/**供建立此对象的副本时使用**/
@Override
protected Object clone() {
return new SingleSkill(getId(), getName(), getAtt());
}
/**这是控制台界面时的显示用**/
@Override
public String toString() {
return "SingleSkill [=" + super.toString() + "]";
}
}
public class GroupSkill extends Skill{
public GroupSkill(int id, String name, int act) {
super(id, name, act);
}
@Override
public void attack(List<Card> cards) {
for(Card card:cards) {
if(!card.isDaeth()) {
card.attacked(this.getAtt());
}
}
}
@Override
public String toString() {
return "GroupSkill [" + super.toString() + "]";
}
@Override
protected Object clone() {
return new GroupSkill(getId(), getName(), getAtt());
}
}
以上,技能就写完了。