创建游戏重放时的计时问题(赛车鬼)

时间:2015-06-10 05:15:05

标签: ios objective-c cocos2d-iphone box2d game-physics

我在cocos2d中创建了一个使用box2d进行物理的iOS游戏。我想为这个游戏设置一个重播功能(你可以在那里比赛你以前尝试过的鬼魂)我知道box2d是确定性的(好吧它是相同的硬件......所以在你的同一部手机上运行它会有效)所以这应该是可行的。目前,在测试过程中,我用

记录了用户输入的时间
NSLog(@"%f", [[NSDate date] timeIntervalSince1970] - gameTime);

游戏开始时gameTime

然后我就这样做了回游戏

[self performSelector:@selector(simulateFingerDown:) withObject:nil afterDelay:0.753302];
[self performSelector:@selector(simulateFingerUp:) withObject:nil afterDelay:1.382405];
[self performSelector:@selector(simulateFingerDown:) withObject:nil afterDelay:2.066786];
[self performSelector:@selector(simulateFingerUp:) withObject:nil afterDelay:2.800533];
[self performSelector:@selector(simulateFingerDown:) withObject:nil afterDelay:3.950479];
[self performSelector:@selector(simulateFingerUp:) withObject:nil afterDelay:4.933555];
[self performSelector:@selector(simulateFingerDown:) withObject:nil afterDelay:6.607358];
[self performSelector:@selector(simulateFingerUp:) withObject:nil afterDelay:8.067316];
[self performSelector:@selector(simulateFingerDown:) withObject:nil afterDelay:8.700970];
[self performSelector:@selector(simulateFingerUp:) withObject:nil afterDelay:8.934012];

simulateFingerUp/Down调用与ccTouchBegan/Ended调用相同的内容。我游戏中唯一的功能就是触摸屏幕,所以我只是在特定的延迟时间内进行硬编码,以便何时触摸(或测试"幽灵"功能)此过程按预期工作。并且游戏是"模拟/重播"然而,应用程序的每次运行都会得到不同的结果。大概是调度选择器依赖于系统资源或类似的东西,因此它会导致运行之间的不同时间(这可能导致我的游戏中的巨大差异)

我应该使用什么来代替模拟重播?我可以记录用户输入的时间,并且只有在计算减法[[NSDate date] timeIntervalSince1970] - gameTime时它才可能关闭但是看起来用performSelector回放它是不可靠的。有人有建议吗?

另外我认为这可能有用吗? box2d的step函数始终为:_world->Step(0, 8, 3);

我不完全确定为什么会出现这些价值......我从在线教程中获取了一些没有解释这些特定值的box2d代码

2 个答案:

答案 0 :(得分:1)

有趣但错误的设备!我会说(只是猜测)使用时基将非常困难。虽然播放录音的设备相同,但在录制期间和播放期间,运行循环中存在一定量的随机性。为了说服自己,只需登录任何'更新'方法的dt参数,你会看到(假设你正在以60 fps的速度播放)一些频繁的'跳帧'......

0.016 0.016 .033< - 呃......这里发生了什么?可能设备中的某些其他任务消耗了足够的资源来阻止此运行循环足够长时间以完全错过调度帧!

现在,在录制和播放过程中随机性会有所不同。例如,您可能会在手机上收到通知,或者AdSheet可能正在忙着做两件事之间至关重要的(比如准备在后台投放应用的下一个广告)......等等。所以,你永远无法完全重复时间基础。

我想。只是一个猜测:)

答案 1 :(得分:1)

一种解决方案是在固定的时间步长运行模拟。假设您选择每次更新16毫秒。但是你仍然希望按照实际时间的推移来缩小比例。

现在假设一帧花了20ms。这意味着你将进行一次16ms的更新,并为下一帧留下4ms。然后说下一帧需要15ms。这意味着你需要做一次16ms的更新,然后剩下3ms用于下一帧,依此类推。然后假设您有一个需要40ms的长帧 - 您需要为该帧执行两次16ms更新。或者一帧可能需要10毫秒,并且没有足够的剩余时间来制作16毫秒 - 在这种情况下,你将不会执行物理更新。

现在你有了一个(希望)确定性*,可重复播放的更新循环。

到目前为止,这个实现的问题是动作不会显得非常平滑;你会得到一点打嗝,因为固定的16毫秒更新与你的实际时间并不相符。

在渲染函数中,使用“余数”时间(例如4ms)并按时间向前插入事物。因此,使用汽车的当前速度和角速度,将其渲染到您估计未来4ms的位置。这应该足够准确“看起来”正确。希望你能从物理引擎中获得汽车速度和角速度。

*我有希望地说,因为浮点是一件棘手的事情,即使你认为它应该是确定性的,也可能不是。我不确定iOS FP数学是否具有确定性,或者它是否依赖于编译器设置或什么。