gpt4 book ai didi

java - 具有快速删除/迭代/插入的集合,可回收 Android/Java 程序中的对象?

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:18:11 24 4
gpt4 key购买 nike

我正在为Android编写游戏。例如,游戏可能涉及子弹、敌人、 gem 等,它们需要:

  • 在游戏过程中在游戏世界中创建和销毁,例如子弹是火,然后在撞到墙上时消失。
  • 按顺序访问了很多,例如全部按顺序更新,然后全部按顺序绘制。

  • 根据我迄今为止在 Android 中的工作所了解的情况,为了保持我的帧速率,我需要考虑以下几点:
  • 当你不需要时不要分配对象,因为垃圾收集器会启动并破坏你的帧率。
  • 喜欢例如局部变量访问访问对象字段和调用函数。

  • 对于上面提到的 PC 游戏中的游戏对象,我通常会使用 Vector 或 LinkedList 之类的东西。但是,这些不会回收对象,并且使用 Iterator 将创建一个新对象,并且在迭代时涉及多个函数调用。

    什么是适合使用的集合?

    我目前发现效果很好的是创建例如100 个子弹的标准数组,其中所有 100 个子弹都是预先创建的。然后,当所有 Activity 的子弹都出现在数组的开头时,我会计算有多少子弹是 Activity 的。每当我迭代一系列子弹并且需要销毁一个子弹时,我只需将当前子弹索引与最后一个 Activity 子弹索引交换,然后减少 Activity 子弹编号。这会更改项目符号顺序,但这很好。

    这很好用:

    优点:回收对象,很少/没有函数调用
    缺点:当不作为集合类实现时容易出错(尤其是删除)

    任何人都可以提出更好的选择吗?我见过很多用于管理对象池的类,但我不确定哪些适合我。

    谢谢。

    最佳答案

    我在 80 年代后期为游戏编程,最近在为移动设备编写 Java。我可以告诉你,如果你使用 LinkedList 或 Vector 来存储与子弹等琐碎事物相对应的 Java 对象,你将会降低帧率。手机游戏的编程效率并非如此。通过考虑“每一点都很重要”来编写高效的手机游戏。这是优化为王的领域之一。

    过度简化,但想象一下你有一个游戏,当前有四个子弹“活着”(它并不是真正的“在屏幕上”,你的“活跃世界”可以而且通常应该比你的屏幕大一点,它使很多处理更容易)。

    (20,30,3) (10, 50, 2) (30, 40, -3) (50, 50, 5)

    所以项目符号一位于坐标空间中的像素 (20,30) 处,并以 3 的速度(无论 3 的速度意味着什么,这只是一个示例)向右移动(过于简化,只是为了解释),项目符号二在 (10,50) 以 2 的速度向右移动,子弹 3 在 (30,40),以 3 的速度向左移动(减号表示向左),最后一个子弹在 (50, 50,5) 以 5 的速度向右行驶。

    在当前的手机游戏中,这在内存中是如何表示的?

    像这样,在 int[] 中:

    int[] = { 4, 20, 30, 3, 10, 50, 2, 30, 40, -3, 50, 50, 5, ..., ..., ... };

    前 4 个告诉我们这个“数据结构由 4 个元素组成。你知道每个元素都由 3 个值组成(在我们过于简化的示例中)。

    现在想象一下子弹 2 撞到墙上然后消失了,会发生什么?

    这个:

    int[] = { 3, 20, 30, 3, 50, 50, 5, 30, 40, -3, 50, 50, 5, ..., ..., ... };

    我们将第一个 int 的减量简化为 3,表示到目前为止我们的游戏世界中只剩下 3 个子弹,我们只是将 (50, 50, 5) 移动到位置 '2',替换 (10,50,2 ) 通过 (50, 50, 5)。那是因为我们的项目符号的顺序并不重要(它们都具有相同的效果)并且“将所有 int[] 元素向左移动”将非常低效。

    请注意,我们甚至没有费心去“清除”“第 4 个子弹”:旧的 (50,50,5) 最后仍然存在,但我们知道我们只剩下 3 个元素,所以我们不在乎.

    在内存中它看起来像这样:

    int[] = { 3, 20, 30, 3, 50, 50, 5, 30, 40, -3, 50, 50, 5, ..., ..., ... };

    你只关心这个:

    int[] = { 3, 20, 30, 3, 50, 50, 5, 30, 40, -3, ..., ..., ..., ..., ..., ... } ;

    在大多数当前的手机游戏中是这样完成的:在主循环中为“子弹处理”创建零对象。您可以使用基元数组自己管理这些简单的数据结构。

    并且 int[] 在您的关卡游戏开始时被初始化为您的游戏/关卡中可能发生的最大子弹数。

    你的“可重复使用的子弹池”就在那里。

    如果您开始考虑将 Java 对象用于像子弹一样微不足道的东西,并使用您将在每一帧修改的 LinkedList 或 Vector,您将永远无法获得可接受的性能:您将生成无数不必要的每秒对象 50 次,并且过于频繁地触发 GC。

    现在我当然不是说 OO 编程在手机游戏中没有它的位置:我只是说如果你从对象的角度来思考像子弹这样微不足道的事情,你将永远无法获得可接受的性能。

    我的“子弹移除”技术在这里涉及一个减量(子弹的数量)和 3 个 int 副本。你不能打败那个;)

    它适用于很多事情:子弹,粒子效果,敌人,元素,奖金,诸如此类:)

    在游戏循环中可能经常被删除/重新创建的琐碎事物可能不应该使用对象建模,当然也不应该放在 Vector 或 LinkedList 中。

    关于java - 具有快速删除/迭代/插入的集合,可回收 Android/Java 程序中的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2152607/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com