能力值:
( LV2,RANK:10 )
|
-
-
2 楼
收藏拉
用gdi写的吧,gdi不支持页面翻转和双缓冲,所以每次刷新都会直接改变内存区域,从而在屏幕上引起闪烁。
当年dos下游戏通常都会出现这种情况,后来人们用双缓冲模式和页面翻转解决了这个问题,也就是预先在不可见的区域将图形拷贝上去,再将显示指针指向这个区域,比如常用的模式X。
至于解决问题,用direct是最好的,可是比较复杂;在gdi下可以判断一下那些区域需要更新,哪些不需要,并只更新部分rect区域。
对于这个程序,各个方块的位置不重叠,比较好办,方块下落的时候将上一个位置的方块擦除即可。在下对c++还比较在行,对于win32汇编是新手,就不献丑了,不好意思(拜托,不要乱扔果皮)
|
能力值:
( LV4,RANK:50 )
|
-
-
3 楼
建议使用DirectDraw,使用起来一点不复杂.
找个源码对照者学学.
|
能力值:
( LV4,RANK:50 )
|
-
-
4 楼
上次那个有点问题,变形后可能超出边界报错,空格可以加速下落。。
不过显示还是有问题啊。。。。。
我想问题是出在用InvalidateRect发送WM_PAINT消息时,我用的是:
invoke InvalidateRect,hWnd,NULL,TRUE 这种方法
也就是先擦除背景,再重新画图,这样每次收到WM_PAINT消息的时候屏幕就被全部画为白色后再重新画图,看起来就是一闪一闪的。
我把 InvalidateRect函数改了一下:
invoke InvalidateRect,hWnd,NULL,NULL,也就是不擦除背景。
再设置只有被移动的方块才重画,停在下方的方块不再重画,对移动的方块我是把方块上一个位置先擦除,再画下一个位置。
但结果还是很难看,不移动的方块不需要重画就不会闪,可是移动的方块看起来还是闪得相当厉害,真是没办法了。
我想问下二楼的就是“后来人们用双缓冲模式和页面翻转解决了这个问题,也就是预先在不可见的区域将图形拷贝上去,再将显示指针指向这个区域,比如常用的模式X。”显示指针是什么东西?怎么把图形拷贝到不可见的区域
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
由于现在的图形硬件实在是复杂,我大概说一下早期的dos vga模式,水平有限,大家不要拿砖拍我。
VGA是IBM兼容机的标准配置(我说的是n年以前),是一块非常简单的芯片。官方资料称他可支持640*480 16色,一般用out指令向端口发送数据控制。内部工作是以4个64kb的“位面”工作的,挺复杂的。幸好我可以利用硬件来做这些转换工作而把显示缓存看成是线性的。在分辨率较低时,显存(当时不是这么叫得)大于屏幕区域,这样就可以随意设置初始位置寄存器(crtc),具体端口是3D5H,是只写的,只读的端口是3B5H,这个16位的地址就是我说的那个“指针”,只要改变它的值,就可以确定显存中哪一块区域要显示。
-〉显示开始地址
|主显示区
-〉翻页指向的地址
|附显示区
―剩下的空间
基本就是这样,当然vga其他寄存器还有很多,设置很复杂,不小心就会造成可怕的后果。要设置好这些大约需要四五十行代码(汇编),在nt下更始麻烦,呵呵。现在的显卡好复杂,各位大哥有了解的给讲讲吧?
|
能力值:
(RANK:300 )
|
-
-
6 楼
用 GDI 做一些速度不快的游戏,是可以的
首先准备一个图像 buffer
每一次更新画面时,把图像 buffer 清空 (例如画上背景图) ,然后把你需要画的东西都全画上去
最后来一个 BitBlt 把整个 buffer 内容复制到你的窗口去
上面提及的 directx (direct draw)方法,是正式编写游戏时的基本技巧,我们在 display card 的内存里,建立一块 “back buffer”,每一次画面更新时都把内容画到 back buffer 去,完成绘图后,便执行一个 directx 的 “flip” 指令,意思是命令 display card 把显示影像的 pointer 指向 back buffer,同时把现在的前景内存当成 back buffer (前景和 back buffer 两者角色交换了) ,这样,当 monitor 下一次向 display card 查询画面影像时,便会很自然地显示了你刚才画好的图像
一次游戏的画面更新速度极快,例如一秒 60 次,那么游戏的绘图程序只需要每次把内容画到 back buffer 再进行一个 flip ,便可以很有效地显示新画面
|
能力值:
( LV12,RANK:650 )
|
-
-
7 楼
这个的确很恼人,记得我以前写一个下棋的游戏,不需要重画很多东西的,结果也是闪的厉害。解决思路就是先在内存中画好,具体实现忘记是怎么做的了,应该就是riijj提到的那种。
|
能力值:
( LV2,RANK:10 )
|
-
-
8 楼
用VC会容易一些
|
能力值:
( LV4,RANK:50 )
|
-
-
9 楼
问题已经解决了,就是用双缓存的办法。。。。
|
能力值:
( LV2,RANK:10 )
|
-
-
10 楼
InvalidateRect这个函数其实也可以解决问题
只不过要注意刷新区域就可以解决
我做过一个推箱子的游戏,刷新的是整个窗口区域
也是一闪闪的
后来把刷新区域改成只是刷新图片改变的区域
问题就解决了
不过要考虑计算刷新区域
|
|
|