我不是搞游戏开发的,最近突发奇想想用WPF 开发一个坦克大战的游戏。里面涉及到一个坦克在地图上移动时刷新界面的问题。比如某时刻,坦克在地图上的坐标为(x,y)。我按一下方向键,我会去改动坦克的坐标,变成了(x,y+1).如果我一直按住下方向键,那么坦克会一直网下移动。左右移动类似。假设按住方向键下的触发频率是1秒钟200次,那么理论上,我按住方向键下 ,一秒钟坦克会往下移动200个像素
我的问题是,我按住方向键的过程中,坦克移动是卡顿的。
可以非常明细的感觉出来。
我这里揣测一下卡顿的原因。
WPF的界面刷新帧数比较低,如果坐标变动一下(x,y)变成(x,y+1)就刷新一次,按上面的说法假设一秒触发200次,那么理论上每秒要刷新200次。这肯定是不可能的。我猜WPF刷新界面实际上比如1秒钟只有5次。那么就虽然坐标变了,但是界面却没渲染刷新。就会出现卡顿。 这个涉及到WPF的界面渲染逻辑,不过多讨论。
我们在玩小霸王的年代,坦克大战也没有感觉到卡(当然跟现在的游戏流畅度没法比)
我知道游戏开发一般都有专业的引擎比如unity3D等。那么有没有懂相关领域的大神,能给我解释下游戏开发中是如何解决这个问题的那?
是否单纯的提高每秒帧数,就能够解决这个问题那?
不知道我这样的思路是否有问题,如果问题本身就有问题,请多包涵
WinForm 和 WPF 之类的界面编程技术和游戏引擎在本质上就不同。WPF 之类的界面刷新是被动刷新,什么时候数据发生变更,会触发界面重绘事件更新界面,并且重绘只会发生在需要绘制的控件而不是整个界面。所以 WPF 在不动的时候根本不占用 CPU。游戏引擎是主动刷新,程序本身就是一个循环,每次循环刷新一次界面,如果不限制帧率,引擎会尽可能提高循环次数并刷新整个界面,所以游戏一开 CPU 就开始狂飙。
这是它们需求痛点和设计理念差异导致的,WPF 是编写工具软件或者数据管理软件开发的,这些软件界面复杂度低,界面变更频率低,拼命重绘静态画面毫无意义且浪费资源,由布局系统管理每个控件独立控制自己的重绘以支持局部刷新。
游戏界面变化频繁,且后台 3D 模型千变万化,不可能做引擎级局部刷新和布局管理,哪怕界面处于静止状态也只能重绘,况且现在游戏都有动态环境,你人不操作画面也在变。那么主动做定时刷新基本是合理的。
所以如果想要 WPF 做游戏,第一步就是设计定时器主动触发界面重绘,还要想办法绕过 Windows 消息队列的延迟。而且 WPF 如果在上次重绘后收到多个重绘事件,Windows 消息队列只会实际触发最后一次重绘。Windows 消息队列自带至少 5 ms 的延迟,毕竟涉及到内核与用户态的切换,开销极大。所以游戏引擎从来不用 Windows 消息队列,都是主动定时循环并直接与底层驱动交互信息以获取实时数据。
我不是做游戏的,下面的看看就好。
以前用过Winform做过一些小游戏练手,也算有点相关经验吧。说一下我的理解。
首先是卡顿,这个毫无疑问是因为WPF渲染效率太低,一秒绘图200次,肯定会卡的。如果要提高绘图性能,应该用WriteableBitmapEx来画图,这个应该是WPF下绘图最快的方法了。
然后还有一个问题,游戏应该定时渲染一帧数据,而不是按下按钮就触发绘图。你按下按钮,修改坦克的位置,等到需要渲染的时候,直接渲染最新的数据,然后就可以随意的调整帧率了。
楼上说得比较专业了。
土一点的说法就是,你别拿锤子当锯子去砍树。
如果用WPF开发游戏,比较适合的是2048,数独,俄罗斯方块这一类的。