我正在做一个简单的游戏,这是我的第一个游戏项目。
我发现的大多数示例都有一个Render Loop,所有的游戏逻辑也都是这样做的,我就是不喜欢这样。假设我有一个带有X=0的球,在X=10中有一堵墙,在一个速度很慢的机器中,第一个循环将球放在X=7中,在第二个循环中,它将球放在X=14中,这会导致游戏崩溃!
这种“渲染循环”是制作游戏的正确方式吗?我应该在每一帧中编写代码来检查这样的事情吗?例如,新的帧X=14,最后一帧有X=7,所以我应该检查是否有从X=7到X=14的任何东西??
我在想,我应该为游戏逻辑创建一个单独的线程,在渲染循环中,我应该只“拍摄”当前游戏逻辑的快照并显示出来,不是吗?
你们这些有经验的游戏开发人员是如何解决这个问题的?
谢谢!
发布于 2010-05-07 06:32:57
正如另一个答案所说,你看到的问题被称为“隧道”,这是“子弹穿透纸张”的问题,子弹移动得很快,纸张很薄,你怎么知道发生了碰撞?
如果你的世界边界很简单,这很容易。例如,在俄罗斯方块中,方块只允许左右移动,直到它们击中侧面,很容易测试最底部的坐标是否击中了“地面”。这些测试很简单,因为您可以一次做一个轴,并且与侧面的碰撞意味着与与凹坑底部的碰撞不同的东西。如果你有一个长方形的房间,只要“停止”移动的物体,如果它的移动已经把它放在房间之外,通过夹住它的坐标。也就是说,如果房间宽度是从-3到+3,而你的对象的X是5,只要把它改成3,你就完成了。
如果你想处理更复杂的世界,那就有点棘手了。你会想要阅读有关“扫描”几何碰撞的内容。基本上,如果你有一个圆,你需要用胶囊做碰撞测试,这个形状是通过从起点到终点“扫”圆而形成的。它就像一个长方形,两端各有一个半圆形。数学计算出奇地简单(IMHO),但它可能是棘手的正确,并真正理解发生了什么。不过,这是值得的!
编辑:在线程问题上的-不需要复杂的事情。一个线程就可以了。跳过更新帧也会变得混乱,这是相当先进的,因为你实际上需要弄清楚“未来”,然后对所有感兴趣的值进行插值。我自己并不把它叫做“渲染”循环,因为渲染循环只是这个过程的一部分。
def GameLoop():
while True:
ReadInputs()
FigureOutWhatStuffDoes()
DrawItAll()编辑2:这似乎是一个有趣的讨论:http://www.gamedev.net/community/forums/topic.asp?topic_id=482397
发布于 2010-05-07 06:18:48
如果您为此创建了一个单独的线程,那么您还会创建许多您可能不想处理的复杂性。使用一个线程和一个循环很容易处理。
基本上,你想要做的是有一个同时执行逻辑和渲染的循环,但不一定要在每次迭代中执行。请参阅此伪代码:
while(true) {
oldTime = currentTime;
currentTime = systemTime();
timeStep = currentTime - oldTime;
// Only do logic x times / second
if( currentTime > lastLogicTime + logicRefreshTime ){
doGameLogic( currentTime - lastLogicTime );
lastLogicTime = currentTime;
}
// Extrapolate all movements using timeStep
renderGraphics( timeStep );
wait( screenRefreshTime );
}
void doGameLogic( timeStep ) {
// Update all objects
for each( gameObject obj )
obj.move( timeStep );
}让所有实心可移动对象继承SolidObject类。当您调用SolidObject.move(timeStep)时,该方法会检查对象在给定timeStep内可以移动多远。如果在这一点之前有一堵墙,那么物体应该停止,反弹和改变方向,消亡或任何你喜欢的东西。
编辑:
如果两个对象移动,您可能需要检查 If 和,它们在发生冲突的地方。很多游戏都不能很好地做到这一点,但以下是你是如何做到的:
首先,为每个移动的对象计算oldTime和currentTime之间的移动线。然后比较两条线,看两条线是否相交。注意,您需要考虑对象的大小。交点是对象碰撞的地方。使用此方法可以准确检测移动对象的碰撞。
发布于 2012-10-11 11:04:26
可以有一个单独的更新线程和一个drawing-thread,,但这并不容易!通常,您需要做大量的互斥检查,以防止对相同变量的多线程访问,因此这并不是真正可行的(另外,您不希望处理半更新的状态)。对于正确的实现,您确实需要具有上一次呈现状态的某种形式的快照。如果你不介意其中的困难,你可以在这里找到一个很好的实现:
http://blog.slapware.eu/game-engine/programming/multithreaded-renderloop-part1/
http://blog.slapware.eu/game-engine/programming/multithreaded-renderloop-part2/
不要让唱反调的人打消你的念头。这是可能的,它是可行和有效的。唯一的缺点是它很难实现,因此可能不值得你花时间(除非你有一个非常占用CPU的游戏)。
https://stackoverflow.com/questions/2784171
复制相似问题