内容来自RyiSnow视频讲解
这一节讲的是**Entity ArrayList(Render Order Revised)**实体数组列表(渲染顺序修改)。
前言
由于NPC和player的实体碰撞区域比他们本身的大小要小,所以会造成一个bug,当前的绘制顺序是,NPC先绘制,player后绘制,导致player从npc上面向下碰到npc的时候,2者的绘制出现了重叠现象。
下图红色部分为player或npc的实体碰撞检测区域。比他们的实际尺寸大小要小。
重叠问题如下图所示:
实现
创建一个ArrayList,把npc, objects, player都放进去,按每个Entity的worldY坐标从小到大排序,前面的小,越往后面worldY越大。这样向上图老人npc就会排在player后面,按这个顺序绘制,老人就不会被他上面的player遮挡了,更合理。
这里为了方便实现,将SuperObject类删除,替换为了Entity类,必要的属性做了保留。
看作者的代码,修复了一次这个bug了,但是如果有多个npc还是会出这个问题。根据作者代码实际验证了一下,1个npc,没有问题,如果多个就不行了。不过看下面代码这个逻辑也不该再出现这个问题啊,感觉很蹊跷,略有些迷茫。另外,估计作者有修改代码,视频讲解没出,以至于有些地方改了,视频上没反应出来。
作者上传了一个修改渲染顺序的视频,但是这个解决方案不完善,没有彻底解决绘制不合理的bug,作者删除了前一个视频又重新修改代码彻底解决了这个问题,制作了新的视频。
// npc
for (int i = 0; i < npc.length; i++) {
if (npc[i] != null) {
int npcY = npc[i].worldY;
if (playerY < npcY) {
player.draw(g2);
npc[i].draw(g2);
} else {
npc[i].draw(g2);
player.draw(g2);
}
}
}
重新修改,按worldY坐标排序
// sort
Collections.sort(entityList, new Comparator<Entity>() {
@Override
public int compare(Entity e1, Entity e2) {
int result = Integer.compare(e1.worldY, e2.worldY);
return result;
}
});
//draw entities
for (int i = 0; i < entityList.size(); i++) {
entityList.get(i).draw(g2);
}
// empty entity list
entityList.clear();
这里出现了一个jdk很方便的比较方法。
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
接下来即可遍历entityList进行绘制,绘制结束后,清空entityList,不然它会重复添加元素,持续膨胀。
为了测试新的渲染效果,增加了很多测试代码,测试完可以删除掉。
测试
增加了几扇门和几个老人NPC,门缩小了一些solidArea碰撞检测区域。
代码
参考第6篇文章最后,可以使用git clone或直接下载获得完整项目