我知道这些考虑的数百种变体已经发布在整个网络上。但是,我还没有找到任何可以解决我的确切问题的东西,所以我希望你能帮助我看到光明。
我目前正在使用 OpenGL 在 Java 中进行 2D 游戏开发。使用的语言和图形库与我的问题无关,因为它具有更一般的特征。
我正在尝试设计一个通用的游戏循环,它可以或多或少地用于任何具有中等重量图形(主要是位图纹理)和可能更重的游戏逻辑(AI、碰撞检测等)的游戏。
基本上,我希望维护一个可以更新(位置、速度和其他与游戏相关的更新)和渲染(更新位置的纹理/帧)的对象列表/数组/缓冲区,尽可能流畅和高效。
1)一个线程更新+渲染
我已经尝试并放弃了仅使用一个线程的顺序解决方案(好吧,计算用户输入时是两个)。
- 计算更改并更新缓冲区对象
- 将更新位置处的纹理渲染到后备缓冲区
- 将后台缓冲区交换到前台
显然,当交换缓冲区阻塞硬件时,浪费了大量的计算时间,这需要更有效的解决方案
2) 一个线程更新,一个渲染线程
通过将程序拆分为更新线程和渲染线程并同步访问共享缓冲区,我应该能够确保相当稳定的帧速率。可以通过多种方式实现对共享缓冲区的同步访问,但它们都有一个共同点。它们都禁止线程并发。虽然这可能是一个公平的权衡,但我想知道是什么使同步变得必要。
3) 同2,但不同步
我确实了解并发线程的粗心实现可能导致的许多问题。生产者/消费者、读者/作者和类似情况导致潜在的死锁。但是,我不明白如果满足以下条件(并且应该满足),为什么我需要确保共享数据的同步:
- 渲染线程只能从共享缓冲区中读取
- 更新线程可以读取和写入共享缓冲区(因此它是唯一的“写入器”)
- 游戏运行时共享缓冲区永远不会是空的或满的
- 线程永远不会休眠
- 渲染不必是 100% 准确的。如果某些共享对象尚未更新,导致它们比其他对象落后一个更新步骤(即大约 10-20 毫秒),则任何人都不应注意到。
-
那么......我在这里错过了什么明显的事情?为什么我需要此设置的同步?
- 线程是否可以在未正确同步时缓存导致问题的数据?
- 或者如果写入线程在不幸的时间被中断,数据会以某种方式出现乱码吗?
- 或者我提出的策略是否存在任何一般性问题,使其无用?
任何想法、评论或建议都非常受欢迎。或者,如果这个特定问题已经在其他地方得到解决,我将不胜感激。