简体   繁体   English

有关游戏循环迭代数据结构的问题

[英]Questions about a game-loop iteration data structure

So, I'm writing a 2D Java game engine based on LWJGL. 因此,我正在编写一个基于LWJGL的2D Java游戏引擎。 (It'll be open source, but when it's a bit more polished. :P) I'm pretty far along, but as I'm trying to go through another polish I've decided I need some outside opinion on a data structure I'm using. (它将是开源的,但是当它更加完善时。:P)我已经走得很远了,但是当我尝试进行另一种润色时,我决定我需要一个关于数据结构的外部意见我正在使用。


The structure is called an UpdateList<(generic)> . 该结构称为UpdateList <(generic)> Basically, I want a fully dynamic list of objects to represent all objects in a game, yet be able to iterate through it with the speed of an array, as conceivably hundreds+ of objects could be referenced. 基本上,我想要一个完整的动态对象列表来表示游戏中的所有对象,但又能够以数组的速度遍历整个对象,因为可以想到可以引用数百个以上的对象。

To do this, the class has 3 data members: an ArrayList<(generic)> , an array of the same type, and a boolean marking whether or not the list has changed (titled changed ). 为此,该类具有3个数据成员: ArrayList <(generic)> ,相同类型的数组和一个布尔值,用于标记列表是否已更改(标题更改 )。

The class works fairly straightforwardly - objects are added and removed from the ArrayList as you would imagine, and doing so sets changed to true . 该类的工作原理非常简单-如您所想,可以从ArrayList中添加和删除对象,并且将设置更改true

Then, there are two methods that involve accessing the array - updateList(T[]) and getUpdateList() . 然后,有两种方法涉及访问数组-updateList(T [])getUpdateList()

updateList passes the array to ArrayList for it's toArray(generic[]) method; updateList将数组的toArray(generic [])方法传递给ArrayList; the array is set to this new value (iff changed is true - if the list hasn't changed, nothing happens). 将该数组设置为此新值(如果change更改为true-如果列表未更改,则什么也没有发生)。

getUpdateList returns the array. getUpdateList返回数组。


So, for use, updateList is called whenever the developer wants to update the array, and getUpdateList is used for the iteration. 因此,使用时,只要开发人员想要更新数组,都会调用updateList,并且将getUpdateList用于迭代。 Not only is this a little bit faster than just using an ArrayList, but it also avoids ConcurrentModificationErrors, and the UpdateList can be edited during an iteration through itself. 这不仅比仅使用ArrayList快一点,而且还避免了ConcurrentModificationErrors,并且UpdateList可以在迭代过程中通过自身进行编辑。

So, two questions: 因此,有两个问题:

1:) Is this a good way of achieving the type of data structure I need? 1 :)这是实现所需数据结构类型的好方法吗? In terms of use/API, it's extremely simple, but I'm concerned about ArrayList's toArray method. 在使用/ API方面,这非常简单,但是我担心ArrayList的toArray方法。 How long does this take at higher numbers of entries? 条目数量多时需要多长时间? If it's unwieldy, is there a better dynamic class I can use? 如果不方便,是否可以使用更好的动态类?

2:) Secondly, I don't like having to call updateLists(T[0]). 2 :)其次,我不喜欢必须调用updateLists(T [0])。 Is there a good way to manage the copy of the ArrayList into an array without needing this? 有没有一种好方法可以将ArrayList的副本管理到数组中而不需要这样做?

1:) Is this a good way of achieving the type of data structure I need? 1 :)这是实现所需数据结构类型的好方法吗?

In short, no, I think you can do better than passing arrays around. 简而言之,不,我认为您可以做得比传递数组更好。 In reading your original post, it seemed that almost everything that you wanted to do would involve an O(N) operation (linear in terms of the number of objects). 在阅读您的原始文章时,您几乎想做的所有事情似乎都涉及到O(N)操作(就对象数而言是线性的)。 That would get very slow quickly. 那很快就会变得很慢。

In terms of use/API, it's extremely simple, but I'm concerned about ArrayList's toArray method. 在使用/ API方面,这非常简单,但是我担心ArrayList的toArray方法。 How long does this take at higher numbers of entries? 条目数量多时需要多长时间? If it's unwieldy, is there a better dynamic class I can use? 如果不方便,是否可以使用更好的动态类?

Yes. 是。 Consider having a set of objects that represent things in your virtual world. 考虑拥有一组代表您的虚拟世界中事物的对象。 Instead of making an array of objects that change for each frame update, you can instead think of multiple threads of computation: 您可以考虑多个计算线程,而不必制作一个随帧更新而变化的对象数组:

  1. One thread watches for changes and writes individual object references to a ChangedSet data structure (with a write-lock around the writing). 一个线程ChangedSet更改,并将单个对象引用写入ChangedSet数据结构(在写入过程中带有写锁)。 This replaces your changed boolean with a set of changed objects. 这将用一组更改的对象替换您changed布尔值。 Note, also, that Sets have the uniqueness property, so you don't have to worrying about adding the same object mutiple times. 另外请注意, Sets具有uniqueness属性,因此您不必担心多次添加同一对象。

  2. Another thread waits for a signal to update screen, read-locks the ChangedSet , copies the contents out as an ArrayList (or UpdateList , if that's what you're calling it) and then empties the ChangedSet (releasing the read-lock). 另一个线程等待信号更新屏幕,读取锁定ChangedSet ,将内容复制为ArrayList (或UpdateList ,如果您正在调用它的话),然后清空ChangedSet (释放读取锁定)。

Now your UpdateList can be used independently, without worrying about passing arrays back and forth. 现在,您的UpdateList可以独立使用,而不必担心来回传递数组。

EDIT : responding to the question in the comment 编辑 :回应评论中的问题

It's almost always easy to take data structures from a multithreaded architecture and bring them to a single threaded one. 从多线程体系结构中获取数据结构并将其带到单线程结构中几乎总是很容易的。 In this case, adapt the above to have a loop watching for changes that adds to the Set . 在这种情况下,请对以上内容进行调整,使其循环监视添加到Set更改。 Follow that with a loop that takes the changed set and puts it in the ArrayList . 紧随其后的是一个循环,该循环将更改后的集合放入ArrayList

HOWEVER , you should remember the Java is always multithreaded, whether you realize it or not. 但是 ,无论您是否意识到,Java始终都是多线程的。 The Swing thread (AKA AWT Event Queue) is separate from your computation. Swing线程(又名AWT事件队列)与您的计算是分开的。 SwingUtilities.invokeLater() is an excellent solution for adding deferred rendering code to an otherwise single-threaded solution. SwingUtilities.invokeLater()是将延迟渲染代码添加到原本单线程解决方案中的绝佳解决方案。

Just remember, it's critical to create that disconnect between the rendering code and the data management. 请记住,在渲染代码和数据管理之间建立断开连接至关重要。 You can do that with either separate structures or proper concurrency but if you ignore the problem, you'll either have deadlock or ConcurrentModificationExceptions . 您可以使用单独的结构或适当的并发性来做到这一点,但是如果您忽略该问题,则将出现死锁或ConcurrentModificationExceptions

END EDIT : 结束编辑

An ArrayList is really an array under the hood, so there is no need to use the extra array. ArrayList实际上是一个底层的数组,因此不需要使用额外的数组。 As for concurrency, you can make your operations thread safe. 至于并发性,您可以使您的操作线程安全。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM