C语言 双缓冲控制台防闪屏技术
来源:互联网 发布:在虚拟机上安装mac os 编辑:程序博客网 时间:2024/06/05 23:42
对于这个东西相信大家非常陌生,因为现在除了学“C语言”和“数据结构”这些基础课程的大学生,基本没人会用到控制台了。哪怕是用到,也不会关心它闪不闪屏的问题。
但在一种特殊的情况下需要用到,那就是写“贪吃蛇”这个游戏的时候……
贪吃蛇游戏的设计原理,就是不断的重复”擦除->显示”控制台打印的内容,显示的内容由时间和用户的输入做出相应的变化。
控制台的擦除会用到如下语句:
system("cls");
也正是这一语句导致了闪屏,下面放出一套闪瞎眼的代码
#include "stdio.h"#include "stdlib.h"#define LENGTH 15void show(){ system("cls"); int i, j; for (i = 0; i < LENGTH; i++) { for (j = 0; j < LENGTH; j++) { printf("* "); } printf("\n"); }}void main(){ while (1) { show(); }}
具体原因可见如下的程序控制台显示流程图
即控制台从键盘或者程序命令中获得要输出的数据,然后输出到显示缓冲区进行输出。在这个流程之中,假设程序要打一万个 *,则第一个 * 的输出时间和第一万个 * 的输出时间是有差别的。而假设我们要程序去显示15*15的 * ,显示完后马上擦除,再来一次,则显示缓冲区不满15*15的 * 的状态会居多,因此就造成了闪烁
针对于贪吃蛇这个游戏,有一种比较取巧的解决方法,就是调用“SetConsoleCursorPosition”这个控制台API去动态设置光标,来打印和覆盖掉一些数据,以实现局部的刷新,也就是说原来可能需要重绘一万个字符现在可能只需要重绘1000个,这样可以减少闪烁的可能性。但该实现方法依然没能躲过上面的流程出现的问题,随着重绘的字符增多,闪烁的概率也在加大,因此也不算是好的解决方法。
那么有没有终极一点的解决方法呢?有,那就是我们在游戏绘图时用到吐的双缓冲技术,原理见下图
说简单也简单
1. 将要输出的数据写在缓冲区一(写的过程中显示的是缓冲区二的内容)
2.显示缓冲区一的内容
3.将要输出的数据写在缓冲区二(写的过程中显示的是缓冲区一的内容)
4.显示缓冲区二的内容 ,回到第1步
示例代码如下:
/** File : myRetroSnaker.cpp* Author : weixinhum* Date : 2017.5.16* Function : Snake game of overcoming the splash screen*/#include "stdio.h"#include "stdlib.h"#include <Windows.h>#define LENGTH 15HANDLE hOutput, hOutBuf;//控制台屏幕缓冲区句柄COORD coord = { 0,0 };//双缓冲处理显示DWORD bytes = 0;char data[LENGTH][LENGTH];void show(){ int i, j; for (i = 0; i < LENGTH; i++) { for (j = 0; j < LENGTH; j++) { data[i][j]='*'; } } for (i = 0; i < LENGTH; i++) { coord.Y = i; WriteConsoleOutputCharacterA(hOutBuf, data[i], LENGTH, coord, &bytes); } //设置新的缓冲区为活动显示缓冲 SetConsoleActiveScreenBuffer(hOutBuf); Sleep(500); for (i = 0; i < LENGTH; i++) { for (j = 0; j < LENGTH; j++) { data[i][j] = '-'; } } for (i = 0; i < LENGTH; i++) { coord.Y = i; WriteConsoleOutputCharacterA(hOutput, data[i], LENGTH, coord, &bytes); } //设置新的缓冲区为活动显示缓冲 SetConsoleActiveScreenBuffer(hOutput); Sleep(500);}void main(){ //创建新的控制台缓冲区 hOutBuf = CreateConsoleScreenBuffer( GENERIC_WRITE,//定义进程可以往缓冲区写数据 FILE_SHARE_WRITE,//定义缓冲区可共享写权限 NULL, CONSOLE_TEXTMODE_BUFFER, NULL ); hOutput = CreateConsoleScreenBuffer( GENERIC_WRITE,//定义进程可以往缓冲区写数据 FILE_SHARE_WRITE,//定义缓冲区可共享写权限 NULL, CONSOLE_TEXTMODE_BUFFER, NULL ); //隐藏两个缓冲区的光标 CONSOLE_CURSOR_INFO cci; cci.bVisible = 0; cci.dwSize = 1; SetConsoleCursorInfo(hOutput, &cci); SetConsoleCursorInfo(hOutBuf, &cci); while (1) { show(); }}
好啦,这就搞定啦,下篇文章就用这个来实现贪吃蛇吧!
参考文章:http://m.bubuko.com/infodetail-582228.html
阅读全文
1 0
- C语言 双缓冲控制台防闪屏技术
- C#: GDI+双缓冲技术的使用
- C# GDI+双缓冲技术
- c语言缓冲问题
- C语言控制台小游戏
- C语言控制台进度条
- C 语言控制台输入
- C语言-控制台俄罗斯方块
- c语言的输入缓冲
- C语言中的缓冲机制
- 双缓冲技术
- 双缓冲技术
- gdi+ 双缓冲技术
- C#双缓冲技术
- J2ME双缓冲技术
- Java双缓冲技术
- 双缓冲技术
- Android双缓冲技术
- ubuntu16.04 python ipc-bench 编译
- POI操作Excel常用方法总结
- solr6.5 Windows安装
- 自动驾驶领域巨头攒动 智能互联时代将近?
- springmvc+mybatis常见错误
- C语言 双缓冲控制台防闪屏技术
- JavaScript常用的固定方法
- 安卓网络编程socket基础
- spring 控制事务下手动回滚事务的方法
- 安卓学习笔记---android Opencv修改Camera 输出分辨率
- Linux 远程管理
- WebViewJavascriptBridge的使用和封装
- 对Promise中的resolve,reject,catch的理解
- 申请TexturePacker免费注册码(TP:XXXXXXXX)