我最近尝试进入游戏编程。我对 Java 很有经验,但对游戏编程没有经验。我读了 http://www.koonsolo.com/news/dewitters-gameloop/并使用以下代码实现了那里提出的游戏循环:
private static int UPDATES_PER_SECOND = 25;
private static int UPDATE_INTERVAL = 1000 / UPDATES_PER_SECOND * 1000000;
private static int MAX_FRAMESKIP = 5;
public void run() {
while (true) {
int skippedFrames = 0;
while (System.nanoTime() > this.nextUpdate && skippedFrames < MAX_FRAMESKIP) {
this.updateGame();
this.nextUpdate += UPDATE_INTERVAL;
skippedFrames++;
}
long currentNanoTime = System.nanoTime();
double interpolation = (currentNanoTime + UPDATE_INTERVAL - this.nextUpdate) / UPDATE_INTERVAL;
this.repaintGame(interpolation);
}
}
updateGame()负责计算位置,移动敌人,计算碰撞,......?由于插值没有传递给 updateGame() ,这是否意味着我们假设 updateGame()准确而稳定地调用 UPDATES_PER_SECOND每秒多少次?这是否意味着我们所有的计算都基于该假设?如果 - 无论出于何种原因 - 对 updateGame() 的调用延迟,这不会给我们带来很多麻烦吗?updateGame() 上的速度移动它。 - 如果该方法被延迟,那将意味着我们的计算完全关闭并且角色会滞后?If in the 10Th gametick the position is 500, and the speed is 100, then in the 11Th gametick the position will be 600. So where will you place your car when you render it? You could just take the position of the last gametick (in this case 500). But a better way is to predict where the car would be at exact 10.3, and this happens like this:
view_position = position + (speed * interpolation)
The car will then be rendered at position 530.
UPDATES_PER_SECOND ?所以更多的 UPS 意味着一辆更快的汽车?这不可能吧……?private static int UPDATES_PER_SECOND = 25;
private static int UPDATE_INTERVAL = 1000 / UPDATES_PER_SECOND * 1000000;
private static int MAX_FRAMESKIP = 5;
private long nextUpdate = System.nanoTime();
public void run() {
while (true) {
int skippedFrames = 0;
while (System.nanoTime() > this.nextUpdate && skippedFrames < MAX_FRAMESKIP) {
long delta = UPDATE_INTERVAL;
this.currentState = this.createGameState(delta);
this.newPredictedNextState = this.createGameState(delta + UPDATE_INTERVAL, true);
this.nextUpdate += UPDATE_INTERVAL;
skippedFrames++;
}
double interpolation = (System.nanoTime() + UPDATE_INTERVAL - this.nextUpdate) / (double) UPDATE_INTERVAL;
this.repaintGame(interpolation);
}
}
delta = UPDATE_INTERVAL ?是的。到目前为止,这是实验性的,但我认为它会起作用。问题是,一旦您实际从两个时间戳计算增量,就会引入浮点计算错误。这些很小,但考虑到你的更新被调用了数百万次,它们加起来了。由于第二个 while 循环确保我们 catch 错过的更新(例如,如果渲染需要很长时间),我们可以非常确定我们每秒获得 25 次更新。最坏的情况:我们错过了超过 MAX_FRAMESKIP更新 - 在这种情况下,更新会丢失并且游戏会滞后。不过,就像我说的,实验性的。我可能会再次将其更改为实际增量。 UPDATE_INTERVAL在将来。通过这种方式,渲染器可以使用插值值轻松地在两者之间进行插值。计算 future 的游戏状态实际上很容易 - 因为你的更新方法( createGameState() )无论如何都需要一个增量值,只需将增量增加 UPDATE_INTERVAL - 这样就可以预测 future 的状态。当然, future 状态假设用户输入等保持不变。如果没有,下一次游戏状态更新将处理更改。 MAX_FRAMESKIP在硬件真的很慢的情况下,它几乎是一种故障保护,以确保我们不时渲染一些东西。但如果这开始,我猜无论如何我们都会有极端的滞后。插值与以前相同 - 但现在渲染器可以简单地在两个游戏状态之间进行插值,除了插值数字外,它不必具有任何逻辑。那很好! public GameState createGameState(long delta, boolean ignoreNewInput) {
//Handle User Input and stuff if ignoreNewInput=false
GameState newState = this.currentState.copy();
Sprite charSprite = newState.getCharacterSprite();
charSprite.moveByX(charSprite.getMaxSpeed() * delta * charSprite.getMoveDirection().getX());
//getMoveDirection().getX() is 1.0 when the right arrow key is pressed, otherwise 0.0
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
Sprite currentCharSprite = currentGameState.getCharacterSprite();
Sprite nextCharSprite = predictedNextState.getCharacterSprite();
Position currentPos = currentCharSprite.getPosition();
Position nextPos = nextCharSprite.getPosition();
//Interpolate position
double x = currentPos.getX() + (nextPos.getX() - currentPos.getX()) * this.currentInterpolation;
double y = currentPos.getY() + (nextPos.getY() - currentPos.getY()) * this.currentInterpolation;
Position interpolatedCharPos = new Position(x, y);
g2d.drawImage(currentCharSprite.getImage(), (int) interpolatedCharPos.getX(), (int) interpolatedCharPos.getY(), null);
}
最佳答案
不要将您的游戏逻辑建立在更新间隔恒定的假设之上。包括一个精确测量两次更新之间耗时的游戏时钟。然后,您可以根据延迟进行所有计算,而不必担心实际更新率。
在这种情况下,汽车速度将以单位/秒为单位给出,增量将是自上次更新以来的总秒数:
car.position += car.velocity * delta;
关于java - "deWiTTERS Game Loop"是否假设不间断电源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15100348/
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查