我是怎样完成了里世界,分身。
我之前已经完成了夜撩,大阳气炮,夜撩断魂,中华宝轮……后来证明,要实现里世界,分身是一件相当困难的事情,这几乎花了我两天的时间。
我前后想过很多办法,实现的结果不是很理想:
最开始,我想得很简单,就是记录一个时间差,比如只需要记住主角3秒钟前的坐标和攻击方位就行。
后来证明,这种想法太过幼稚。
不过是在实践中才得出这个结论,我这样做了,首先,我建了一个分身类,继承了我自己,省略了若干的方法,只留一个主干,其中包括绘制方法。接下来,我用几个常量记录3秒钟前的坐标和攻击方位,后来的结果是,分身几乎无法移动,即使移动也是瞬间移动。
所以,我想到了,用一个数组,因为我意识到,要顺滑的表现出分身的移动,分身其实就是重复我的移动,那实际上需要记录的是一系列数据,比如他是重复我3秒前的移动,那我不应该只记录3秒前我的状态,而必须记录我在3秒钟里几乎所有状态!
OK,现在开始做,我做了如下改进:我用一个二维数组,比如a[][],第一个下标代表3秒内的每一帧,第二个下标取值为0-2,记录3个数据,x坐标, y坐标,攻击方向。那从现在(假设已经是3秒后往前推,a[0][0]就带表3秒前第一帧的x坐标,a[100][2]代表大概1秒前的攻击方向。
我把这些数据传递给我的分身,我在分身里定义了相应的3个静态常量,之所以要静态的,是为了方便赋值,因为这些常量我只需要一份,因为同一个分身不可能有多个实例。这时,我想到的是我做一个分身就行了,所以,比如x,y坐标和攻击方向,我只需要一份(当然你也看到了,实际上我做出了多个分身的效果)。
但是,现在问题来了,主要问题有两个:
1、 攻击方向我是定义的一个枚举常量,数组中无法同时传递int 和枚举数据;
2、 最关键的,数组的大小是固定的,我该要定义多大的数组?我也许试过a[10000][3],很显然,我需要分身战斗200秒,每秒假设绘制50帧,那数组可能越界,而且这样会很耗内存,因为内存得不到释放。
所以我必须改变,要同时解决上面两个问题,我思考后,改进为:
我先定义了一个内部类(他们就是最后我完成的方式了,现在我可以粘贴一些代码了):
class Date {
int dx;
int dy;
Directionddir;
public Date(int dx, int dy, Direction ddir) {
this.dx = dx;
this.dy = dy;
this.ddir = ddir;
}
}
短短几行,却包含了足够信息。
完后,该是一个集合来盛放这些Date对象了,当然LIST和内部类简直是完美的搭配。代码如下:
List<Date> s;
我曾今考虑过这里用一个链表来装这个集合,因为这里不涉及到很多的随机读取,不过考虑到实际实现他后,list 的长度也只有不到20(通常情况下永远不会超过30,后面我会讲实现),所以我只是用了一个ArrayList轻松搞定。
在按下分身键后,一系列的计算开始了:(这就是说不按分身时是不需要去计算和保存list滴)
if (dir != Direction.stop) { //如果我在移动,才放入我的状态Date
if (fs1 > 0) { //fs1代表我随机出几个分身,最多4个,我不想要再多了
// if(ap)
a++; //a和b决定了分身跟我的位置。
Dated = new Date(x, y, dir); //每一次,只要我在移动,记录我的状态到一个Date里,很重要的,必须要移动才记录,否则结果会很尴尬,这是我试出来的,同时这个也保证list 的 size不会太大。
if (s == null) //因为按下分身后,是一个TimerTask 在记录分身时间,到时则要清理相关的a,b,s等所有信息,释放内存资源,并避免下一次激活分身冲突。
s = newArrayList<Date>();
if (Unit.Dfs) { //工具类,如果为真打印调试信息,毕竟项目有些大了。
System.out.println(b + " a= "+ a + " " + ",g24.size= "+ t.g24.size() + " " + ",s.size= "+ s.size());
}
s.add(d);
if (fs1 == 1) { //如果有一个分身,至少有一个。
if (a > b) {//a和b决定了分身跟我的位置。b是每一次timer.cancel时计算的随机值,以供下次激活分身使用。