我的FogOfWar类中有以下函数,它计算其团队是否可以看到在参数上传递的位置:
package mwoke {
public class FogOfWar {
public var game:Game;
public var team:int;
private var cache:Vector.<CachePos> = new Vector.<CachePos>();
private var chars:Vector.<Character> = new Vector.<Character>();
public function FogOfWar($game:Game, $team:int) {
game = $game;
team = $team;
}
public function think():void {
cache.length = 0;
chars.length = 0;
var ent:Character;
for(var i:int = 0; i < game.entities.length;++i) {
if(game.entities[i] == null) continue;
if(!(game.entities[i] is Character)) continue;
ent = Character(game.entities[i]);
if(ent.team != team) continue;
if(ent.vision <= 0.0) continue;
chars.push(ent);
}
}
public function canSee(x:Number, y:Number):Boolean {
if(x < game.minX) return false;
if(y < game.minY) return false;
if(x >= game.maxX) return false;
if(y >= game.maxY) return false;
for each(var v:CachePos in cache) {
if(v.x == x && v.y == y) {
return v.result;
}
}
var res:Boolean = false;
for each(var ent:Character in chars) {
if(Game.distance(x, y, ent.x, ent.y) < ent.vision) {
res = true;
break;
}
}
var tmp:CachePos = new CachePos();
tmp.x = x;
tmp.y = y;
tmp.result = res;
cache.push(tmp);
return res;
}
}
}
internal class CachePos {
public var x:Number;
public var y:Number;
public var result:Boolean;
}
我的问题是,游戏中只有3个字符,每秒只能运行4000次,这并不算太多。
我可以实现缓存,因此它会缓存最常见的位置,但是,我还能做些什么来优化它?
答案 0 :(得分:2)
如果您的角色具有观察半径,您可以维护一个数据结构,该数据结构随着友好角色的移动而更新,这表明地图的哪些部分是可见的。
然后检查某些内容是否可见就像检查地图上该位置的数据结构值一样快。
编辑:
您也可以使用平方距离而不是绝对距离,这可以避免调用(有点贵)Math.sqrt
函数。基本上,进行Game.DistanceSquared < entity.VisionDistanceSquared
检查。
答案 1 :(得分:0)
如何将表示角色位置和观看半径的对象列表保存为精灵上的圆圈(不是显示列表的一部分),每当有人移动时,他们的圆圈由角色或中间类更新。这样你就不必每次都经历一个循环。
当你想看一个点是否在FOW中时,你可以对所有圆圈的精灵进行命中测试。额外的好处是你甚至可以使用数据来绘制FOW。
警告;虽然我认为使用内部函数应该更快(如命中测试)我没有测试它,所以它可能无法更好地工作。使用它的诀窍是不将它包含在显示列表中,一旦将fow精灵添加到显示列表中,您将看到性能下降。