我试图弄清楚如何在Windows游戏中手动管理整个游戏循环,而不使用常规游戏Microsoft.Xna.Framework.Game类.
这样做的原因是使用常规的Game类会导致我的游戏中出现一些口吃.不多,但由于游戏的特殊性,它仍然是非常明显的.
在尝试了一堆不同的设置(vsync,fixedtimestep,各种帧率等)后,我决定尝试编写自己的Game类来完全控制时间.我不确定会解决它,但至少这样我完全可以控制.
基本上我需要:
谁知道怎么做?事实上这听起来很容易,但找不到任何关于如何做的文档.
不确定我做错了什么,但我有以下代码(仅用于测试,时间将以不同方式处理),并且循环将运行一段时间然后停止.一旦我将鼠标指针移过窗口,循环将再次运行一段时间.
private void Application_Idle(object pSender, EventArgs pEventArgs)
{
Thread.Sleep(500);
//Message message;
//while (!PeekMessage(out message, IntPtr.Zero, 0, 0, 0))
{
gametime.update();
Update(gametime);
Draw(gametime);
GraphicsDevice.Present();
}
}
Run Code Online (Sandbox Code Playgroud)
如果启用"while PeekMessage",循环将连续运行,但忽略睡眠并在鼠标移动窗口时停止.不确定这里发生了什么......
我认为最好我只想在主渲染循环中做这样简单的事情:
while (alive)
{
Thread.Sleep(100);
gametime.update();
Update(gametime);
Draw(gametime);
GraphicsDevice.Present();
}
Run Code Online (Sandbox Code Playgroud)
但在这种情况下,窗口仍然是空白的,因为看起来窗口实际上没有使用新内容重绘.我尝试了一个form.Refresh(),但仍然没有...任何想法?
我的设置是一个多人游戏,带有用于异步传输数据的套接字.
现在,由于游戏的本质,我有一个游戏循环,应该每隔500毫秒进行一次玩家更新(例如位置,外观......).
var self = this;
this.gameLoop = setInterval(function()
{
for (var i = 0; i < playerSize; i++)
{
self.players.get(i).update();
};
}, 500);
Run Code Online (Sandbox Code Playgroud)
我目前正在使用setInterval,但当我做了大约200个连接的基准时,setInterval漂移到1000毫秒而不是500毫秒,这使得整个游戏看起来很滞后.不幸的是,对于少量玩家而言,它还不够准确.(请注意,更新调用最多只需要大约100毫秒)
所以在研究之后,似乎没有其他选择产生只处理定时机制的过程?还是有其他选择吗?
任何人都已经做过这个,或者可以提供一些基本的想法/解决方案来解决这个问题?
完整代码:
Game.prototype.start = function()
{
var average = 0;
var cycles = 10;
var prev = Date.now();
this.thread = setInterval(function()
{
console.log("interval time="+(Date.now() - prev));
prev = Date.now();
var s = Date.now();
// EXECUTE UPDATES
for (var i = 0; i < playerSize; i++)
{
self.players.get(i).update();
};
average += …Run Code Online (Sandbox Code Playgroud) 我正在尝试用Java制作一个简单的2D游戏.
到目前为止,我有一个JFrame带有菜单栏的类,以及一个扩展JPanel并覆盖它的paint方法的类.现在,我需要进行游戏循环,在那里我将更新图像的位置等等.但是,我坚持如何最好地实现这一目标.我应该使用多线程,因为当然,如果你在主线程上放置一个无限循环,UI(以及我的菜单栏)会冻结吗?
到目前为止,这是我的代码:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class GameCanvas extends JPanel {
public void paint(Graphics g) {
while (true) {
g.setColor(Color.DARK_GRAY);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
@SuppressWarnings("serial")
public class Main extends JFrame {
GameCanvas canvas = new GameCanvas();
final int FRAME_HEIGHT = 400;
final int FRAME_WIDTH = 400;
public static void main(String args[]) { …Run Code Online (Sandbox Code Playgroud) 我一直在阅读Koen Witters 关于不同游戏循环解决方案的详细文章,但是我在使用GLUT实现最后一个时遇到了一些问题,这是推荐的.
在阅读了几篇关于如何实现恒定游戏速度的文章,教程和代码之后,我认为我目前已实现的内容(我将在下面发布代码)是Koen Witters所谓的Game Speed依赖于可变FPS,第二篇关于他的文章.
首先,通过我的搜索经验,有几个人可能有帮助,但不知道什么是GLUT,我将尝试解释(随意纠正我)相关的功能我的这个OpenGL工具包的问题.如果您知道GLUT是什么以及如何使用它,请跳过此部分.
GLUT工具包:
glutDisplayFunc(renderScene)采用指向一个renderScene()回调函数,这将是负责呈现的一切.该renderScene()函数仅在回调注册后调用一次.glutTimerFunc(TIMER_MILLISECONDS, processAnimationTimer, 0)需要的毫秒数调用回调之前通过processAnimationTimer().最后一个参数只是一个传递给计时器回调的值.该processAnimationTimer()不会叫每个TIMER_MILLISECONDS但只有一次.glutPostRedisplay()函数请求GLUT渲染一个新帧,因此每当我们改变场景中的某些内容时我们都需要调用它.glutIdleFunc(renderScene)可用于注册一个回调renderScene()(这并没有使glutDisplayFunc()无关),但应避免使用此功能,因为没有被接收到事件时的空闲回调不断要求,增加了CPU的负载.glutGet(GLUT_ELAPSED_TIME)函数返回自glutInit调用(或第一次调用glutGet(GLUT_ELAPSED_TIME))以来的毫秒数.那是GLUT的计时器.我知道高分辨率计时器还有更好的选择,但是现在让我们继续使用这个计时器.我认为这是关于GLUT如何渲染帧的足够信息,所以那些不了解它的人也可以投入这个问题来试图帮助它们如果它们像它一样堕落.
目前的实施:
现在,我不确定我是否正确实施了Koen提出的第二种解决方案,游戏速度依赖于可变FPS.相关代码如下:
#define TICKS_PER_SECOND 30
#define MOVEMENT_SPEED 2.0f
const int TIMER_MILLISECONDS = 1000 / TICKS_PER_SECOND;
int previousTime;
int currentTime;
int elapsedTime;
void renderScene(void) {
(...)
// Setup the camera …Run Code Online (Sandbox Code Playgroud) 在与一些游戏开发者交谈时,他们建议基于OpenGL ES的高性能游戏引擎不会处理主线程上的所有内容.这允许游戏引擎在具有多个CPU核心的设备上执行得更好.
他们说我可以从渲染中解除更新.所以,如果我理解这是正确的,游戏引擎运行循环可以像这样工作:
设置调用render方法的CADisplayLink .
render 方法在后台渲染当前世界模型.
render方法然后update在主线程上调用方法.
因此,当它在后台渲染时,它可以同时为下一次迭代更新世界模型.
对我而言,这一切都让人感到非常不稳定.有人可以解释或链接到这种并发渲染+模型更新是如何在现实中完成的吗?令我难以理解的是,这不会导致问题,因为如果模型更新需要比渲染或其他方式更长的时间.谁等待什么,何时等待.
我试图理解的是,从理论上讲,从高层次的角度来看,这也是如何实现的.
concurrency game-engine game-loop grand-central-dispatch ios
我正在实现一个具有恒定FPS的游戏循环.我想25-30 FPS应该足够了.您自己的经验中的任何想法?我甚至应该限制FPS吗?
我正在做一个简单的游戏,这是我的第一个游戏项目.
我找到的大多数样本都有一个渲染循环,其中所有的游戏逻辑也是如此,我只是不喜欢这样.假设我有一个X = 0的球,一个X = 10的墙和一个慢机器,第一个循环将球置于X = 7,而在第二个循环中,它将球置于X = 14.它会让游戏崩溃!
这个"渲染循环"是制作游戏的正确方法吗?我应该编写代码来检查每一帧中的这类事情吗?例如,新帧X = 14,最后一帧有X = 7,所以我应该检查是否有从X = 7到X = 14的任何东西?
我当时认为我应该为游戏逻辑和渲染循环设置一个独立的线程,我应该只是"拍摄当前游戏逻辑的快照"并显示,不是吗?
你们这些经验丰富的游戏开发者如何解决这个问题呢?
谢谢!
我已经实现了如下游戏引擎循环:
public static Boolean Start ( )
{
if (hasBoard)
{
// start engine on worker thread
asyncTask = new AsyncResult ( stopEngine, asyncTask );
isRunning = ThreadPool.QueueUserWorkItem ( startEngine, asyncTask );
if (isRunning)
{
Console.WriteLine ( "[{0}] Engine started",
DateTime.Now.ToString ( "hh:mm:ss" ) );
}
else
{
Console.WriteLine ( "[{0}] Engine failed to start",
DateTime.Now.ToString ( "hh:mm:ss" ) );
}
}
return isRunning;
}
public static void Stop ( )
{
Console.WriteLine ( "[{0}] Engine stopping",
DateTime.Now.ToString ( "hh:mm:ss" …Run Code Online (Sandbox Code Playgroud) 我正在试图找出用于管理两个交互对象之间"竞争"的最佳设计模式.例如,如果我想要Fox一个Rabbit通过简单环境追逐类的类.我想让他们"竞争"并找出哪一个获胜.最终它将成为学生可以用来试验继承和其他OO编程技能的教学工具.
这个用例是否有既定的设计模式?
这是我能想到的最好的:一个表示托管其他对象的环境的类.我保持它非常简单,并假设动物只是直线运行而狐狸抓住兔子,如果他足够接近咬兔子.这是一些代码,展示了我所描述的内容.我使用PHP是因为我可以快速编写它,但我不想专注于语言的细节.我的问题是关于设计模式/架构.
class Forrest() {
public $fox;
public $rabbit;
public $width = 100; //meters?
public $length = 100;
__construct() {
$this->fox = new Fox();
$this->rabbit = new Rabbit();
$this->theChase();
}
public function theChase() {
while (!$this->rabbit->isBitten) {
$this->rabbit->react($fox);
$this->fox->react($rabbit);
}
log('The fox got the rabbit!');
}
}
abstract class Animal() {
public $speed;
public $hasTeeth = false;
public $position;
public $direction;
public $isBitten = false;
public function run($distance) {
// update coordinates based on direction …Run Code Online (Sandbox Code Playgroud) events design-patterns software-design game-engine game-loop
所以我编写了以下函数来说明我的意思:
use std::{thread, time};
const TARGET_FPS: u64 = 60;
fn main() {
let mut frames = 0;
let target_ft = time::Duration::from_micros(1000000 / TARGET_FPS);
println!("target frame time: {:?}",target_ft);
let mut time_slept = time::Duration::from_micros(0);
let start = time::Instant::now();
loop {
let frame_time = time::Instant::now();
frames+=1;
if frames == 60 {
break
}
if let Some(i) = (target_ft).checked_sub(frame_time.elapsed()) {
time_slept+=i;
thread::sleep(i)
}
}
println!("time elapsed: {:?}",start.elapsed());
println!("time slept: {:?}",time_slept);
}
Run Code Online (Sandbox Code Playgroud)
该函数的想法是以 60 fps 的速度执行 60 个周期,然后根据经过的时间和循环期间睡眠所花费的总时间退出。理想情况下,由于我以 60 fps 执行 60 个周期,并且中间没有发生任何实际计算,因此执行时间应该大约为一秒,并且基本上整个秒都在睡觉。但当我运行它时它返回:
target frame …Run Code Online (Sandbox Code Playgroud) game-loop ×10
game-engine ×3
frame-rate ×2
.net ×1
android ×1
asynchronous ×1
c ×1
c# ×1
concurrency ×1
events ×1
glut ×1
ios ×1
java ×1
javascript ×1
node.js ×1
opengl ×1
rendering ×1
rust ×1
swing ×1
thread-sleep ×1
timer ×1
xna ×1