我正和Scala一起玩游戏。
我的游戏中有几个用于保持敌人的游泳池。它们是不可变列表,因为它们被初始化为足够的大小(因为在游戏期间创建新的敌人实例非常昂贵)。
我的游戏通过询问enemy.isVisible
来了解敌人是否还活着。所以我的CollisionHandler就像:
让我感到沮丧的是,根据剖析器,步骤1占用了大部分时间。那一步的作用基本上是说:
def allActiveEnemies = List(enemyType1.getAllActive, enemyType2.getAllActive, ... ).flatten
flatten
看起来似乎并不昂贵,而是获得了getAllActive调用。它们在我的汇集特征中实现,如下所示:
trait Pooled[T <: Entity] {
var pool = List[T]()
val INITIAL_POOL_SIZE:Int
def initPool() {
for(i<-1 to INITIAL_POOL_SIZE)
{
addToPool(disable(createNew))
}
}
def getAllActive:List[T] = pool.filter(e => e.isVisible)
}
(我省略了大部分特性,因为我认为这与此无关。)
pool.filter是在CollisionHandler花费的总时间的45%,这看起来很奇怪。
有什么建议可以让事情变得更快吗?
也许使用ArrayLists而不是List?也许使用一些排序和可变集合?或者我只是做了一件可怕的错事?
谢谢!
答案 0 :(得分:4)
这些游泳池有多大?您知道每次创建列表时,都必须创建一个新对象来保存每个条目。您可以使用过滤器上的视图(即pool.view.filter(e => e.isVisible)
;然后返回Seq[T]
)来减少这一点。一般来说,我认为你的策略应该是不要每次都做额外的过滤工作。用Set
或其他东西跟踪你的活跃敌人;那么当你需要它们时你会拥有它们。