【问题标题】:Java: Optimizing algorithm in gameJava:优化游戏中的算法
【发布时间】:2014-10-01 19:25:29
【问题描述】:

我正在使用 scene2d 创建一个游戏 (Java)。

我编写了用于碰撞检测的函数,但我认为这是一个糟糕的函数。看起来很糟糕。

如何优化它?制作得更快更漂亮。

private void deleteEnemies()
{
    for(int i = 0; i < getActors().size - 1; i++)
    {
        if(getActors().get(i) != null && getActors().get(i) instanceof Enemy)
        {
            ////////////////
            for (int j = 0; j < getActors().size - 1; j++)
            {
                if(getActors().get(j) != null && getActors().get(j) instanceof Ball)
                {
                    if (actorsIntersecting(getActors().get(i), getActors().get(j)))
                    {
                        getActors().get(i).remove();
                        getActors().get(j).remove();
                    }
                }
            }
            //////////////
        }
    }
}

【问题讨论】:

  • 你为什么认为它不好?
  • 快速说明 - 确保这一行是正确的:j &lt; getActors().size - 1 - 看来您可能会错过最后一个列表项。

标签: java android algorithm libgdx scene2d


【解决方案1】:
  1. getActors().get(i)放入一个变量中,不要在外部if中调用两次
  2. 内部 if 中的 getActors().get(j) 相同
  3. 在最内部的 if 条件和正文中使用这些变量
  4. 将大小保存在变量中,因为现在在检查 for 条件时,每次迭代都会调用 .size 函数
  5. 对于循环条件(因为您正在删除项目),您不应该使用在循环期间可以动态更改的大小,这会使我们回到 #4。 除此之外,它的编码风格视角非常好,我怀疑你是否能比我告诉你的更高效(除了使用线程)

【讨论】:

    【解决方案2】:

    由于您会经常这样做,请考虑将 Enemies 和 Balls 存储在它们自己的结构中(List 或 Set 或任何可行的方法)。这可以防止您循环访问不需要的演员,并避免 instanceof 检查。

    【讨论】:

      【解决方案3】:
      1. 嗯,我的第一个想法是只检查“最近”的敌人,而不是所有敌人。以某种方式尝试减小该列表的大小。

      2. 第二个 - 请一一检查你的和条件 - 现在你总是检查 2 个条件。如果稍后再尝试放“更重”,例如:

      来自:

        if(getActors().get(i) != null && getActors().get(i) instanceof Enemy)
      

      到:

      if(getActors().get(i) != null) {
          if(getActors().get(i) instanceof Enemy)  {
             .....
          }
      } 
      

      3. 调用一次 getActors().get(i) - 保存到变量。 4. 我在想为什么有必要检查一个演员是否为空,也许只是从列表中删除空值或将未初始化的演员保留在另一个列表中。也可以尝试使用 Balls and Enemies,请不要将每个演员都放在一个列表中。

      【讨论】:

      • 点赞检查接近度,以便将算法的顺序从 O(N^2)ish 减少到某种 O(NlogN) 顺序。线程会有所帮助,但改变策略是 IMO 的必经之路
      • 条件从左到右进行评估。在所有&amp;&amp; 的条件下,第一个 false 将停止条件检查。拆分 if 只会得到更多的行。
      【解决方案4】:

      我会稍微重写一下模型,这样他们就可以测试交叉点本身,然后像这样进行删除(可能还可以改进)

      private void deleteEnemies () {
          List<Actor> actors = getActors();
          List<Actor> toRemove = new ArrayList<Actor>();
          int actorsSize = actors.size();
          Actor first = null, second = null;
          for(int i = 0; i < actorsSize; ++i) {
              first = actors.get(i);
              for(int j = 0; j < actorsSize; ++j) {
                  if(i == j) continue;
                  second = actors.get(j);
                  if(first.intersects(second)) {
                      toRemove.add(first);
                      toRemove.add(second);
      
                  }
              }
          }
          actors.removeAll(toRemove);
      } 
      

      【讨论】:

        【解决方案5】:

        不要使用size(),定义一个变量 尽量不要投。尽量不要uae instanceof。 也许,通过 zsort 或类似的方式对列表进行排序,以便有时您可以更快地开始和或停止循环??

        【讨论】:

          【解决方案6】:

          补充其他参与者的(非常好的)建议:将敌人和射弹缓存在不同的结构中,这样您根本不必检查它们是什么。

          尽可能多地使用时间与空间的权衡:正如 Tomek 所暗示的那样,在这种情况下,标准方法是通过修剪无法执行的敌人和射弹来减少检查次数(=迭代)可能在当前帧内发生碰撞(它们距离很远)。

          不管怎样,一个忠告:继续游戏,尽可能多地完成,以便它能够正确运行(如果运行缓慢),然后然后进行优化。 p>

          那是因为

          1. 以这种方式先发制人地优化你永远不会完成它
          2. 您不知道最终游戏的真实情况,也许:也许在完成 90% 之后,您会看到一些容易优化的机会。

          【讨论】:

            【解决方案7】:

            正如其他人所说,真正提高速度的是两个集合,一个带球,另一个带敌人。至于让它看起来更好,你可以这样:

            for (Actor enemy : getActors()) {
                if (enemy != null && enemy instanceof Enemy) {
                    for (Actor ball : getActors()) {
                        if (ball != null && ball instanceof Ball && actorsIntersecting(enemy, ball)) {
                            ball.remove();
                            enemy.remove();
                        }
                    }
                }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-09-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-01-28
              • 1970-01-01
              • 2021-10-29
              • 2011-12-02
              相关资源
              最近更新 更多