Bootstrap

C++语言图形编程基本函数

说明

    C++语言图形编程最基本的几个函数,简略代码,仅介绍函数及参数,并举例说明。非常简单,适合新人查阅。

工具及环境

平台:Windows 10, VS2013(注:文件 -> 新建 -> 项目 -> Visual C++ -> 空项目)
主要头文件:graphics.h   (百度EasyX安装依赖的库文件)


基本图形绘制

生成图形窗口
HWND initgraph(int WIDTH, int HEIGHT)
	WIDTH:窗口宽度,单位:像素
	HEIGHT:窗口高度

例:创建一个宽度为600像素,高度为400像素的窗口
initgraph(600,400);

closegraph();	//关闭窗口

辅助函数:
刷新(清空)屏幕:cleardevice()

绘制点
void putpixel(int X, int Y, COLORREF COLOR)
	X:X 轴坐标
	Y:Y 轴坐标
	COLOR:点颜色,支持宏、16进制颜色代码
	注:窗口左上角坐标为(0,0),横轴为 X 轴,纵轴为 Y 轴

例:在(300,200)位置生成一个蓝色点
putpixel(300, 200, 0xFF0000);

绘制线
void line(int X1, int Y1, int X2, int Y2)
	X1:第一点 X 轴坐标
	Y1:第一点 Y 轴坐标
	X2:第二点 X 轴坐标
	Y2:第二点 Y 轴坐标
	注:绘制前使用 setlinecolor(COLORREF COLOR) 设置线颜色
	    setlinestyle(int LINE_STYLE, int THICKNESS)
	    	STYLE:线风格,常用如
	    		0 实线
	    		1 点线
	    		2 中心线
	    		3 断续线
	    	THICKNESS:线宽

例:绘制一个窗口左上角至窗口右下角的红色实线
setlinestyle(0, 2)
setlinecolor(0x0000FF);
line(0, 0, 600, 400);

绘制矩形
空心矩形:void rectangle(int X1, int Y1, int X2, int Y2)
	注:用法如 line 函数,不再赘述
实心有边框矩形:void fillrectangle(int X1, int Y1, int X2, int Y2)
实心无边框矩形:void solidrectangle(int X1, int Y1, int X2, int Y2)

注:实心矩形颜色使用 setfillcolor(COLORREF COLOR) 设置颜色
   有边框矩形(包含空心矩形)使用 setlinecolor(COLORREF COLOR) 设置颜色

例:创建一个以(100,100)为挤出点,宽度为200,高度为150的实心有边框矩形,填充颜色白色,边框红色
setlinecolor(0x0000FF);
setfillcolor(0xFFFFFF);
fillrectangle(100, 100, 100+200, 100+150);

绘制圆
空心圆:void circle(int X, int Y, int R)
	X:圆心 X 轴坐标
	Y:圆心 Y 轴坐标
	R:半径
实心有边框圆:void fillcircle(int X, int Y, int R)
实心无边框圆:void solidcircle(int X, int Y, int R)

注:设置填充和边框颜色在矩形部分已有讲解

例:在窗口中心绘制一个半径为150的绿色实心圆
setfillcolor(0x00FF00);
solidcircle(300,200, 150);

文字输出
outtextxy(int X, int Y, char* STR)
	X:文字输出位置 X 轴坐标
	Y:文字输出位置 Y 轴坐标
	STR:输出内容,支持明文字符串

设置字符风格:void settextstyle(int HEIGHT, int WIDTH, char* FONT)
	HEIGHT:字符高
	WIDTH:字符宽,为 0 则为自适应宽度,通常指定高度,宽度自适应
	FONT:字体
设置字符颜色:void settextcolor(COLORREF COLOR)
设置字符背景色:void setbkcolor(COLORREF COLOR)
设置字符背景模式:void setbkmode(int MODE)
	MODE:经测试值为 2 时背景为默认或者设置的字符背景色,其他值为透明

例:在(100,100)位置输出字符串,背景透明,字符颜色红色,楷体,高度30
setbkmode(1);
settextcolor(0x0000FF);
settextstyle(30,0,"楷体");
outtextxy(100, 100, "你好世界!");

注:图形化界面输出格式化数据的方法(如数字转字符串)
char str[32];
int score = 100;
sprintf(str, "分数:%d", score);	//格式化数据转字符串
outtextxy(0, 0, str);	//最终输出 分数:100


贴图操作

声明 IMAGE 类型变量
IMAGE IMG;
载入图片
void loadimage(IMAGE* IMG, LPCTSTR FILE, int WIDTH, int HEIGHT, bool RESIZE)
	IMG:IMAGE类型变量
	FILE:图片文件路径,char*类型,如果有多层目录结构,间隔符号用 / 或者 \\
	     文件当前路径为 .cpp 文件所在路径
	WIDTH:载入图片的宽度
	HEIGHT:载入图片的高度
	RESIZE:缺省值为 false
	注:指明了载入图片宽度和高度,图片将以缩放形式适应设定值
输出图片
void putimage(int X, int Y, const IMAGE* IMG)
	X:输出至屏幕位置 X 轴坐标
	Y:输出至屏幕位置 Y 轴坐标
	IMG:图片变量地址,如 &img

void putimage(int X, int Y, int WIDTH, int HEIGHT, const IMAGE* IMG, int IMG_X, int IMG_Y)
	X:输出至窗口起始位置 X 轴坐标
	Y:输出至窗口起始位置 Y 轴坐标
	WIDTH:指定绘制宽度
	HEIGHT:指定绘制高度
	IMG:图片变量地址,如 &img
	IMG_X:图片起始打印位置的 X 轴坐标。此时图片大小为载入后的大小
	IMG_Y:图片起始打印位置的 Y 轴坐标。
	函数解释:从图片的 (IMG_X,IMG_Y) 位置开始截取 WIDTH 宽、HEIGHT 高的图形
	        输出至窗口 (X, Y) 位置

例:图片载入后拉伸与窗口(600x400)同大小,现在在窗口上半部分输出图片的下半部分
IMAGE img;
loadimage(&img, "main.jpg", 600, 400);
putimage(0, 0, 600, 400/2, &img, 0400/2);


其他补充

媒体控制
mciSendString(LPCTSTR lpszCommand, LPTSTR lpszReturnString, UINT cchReturn, HANDLE hwndCallback);
    lpszCommand:mci命令字符串
    lpszReturnString:反馈信息缓冲区
    cchReturn:缓冲区长度
    hwndCallback:回调窗口句柄
    
注:请添加如下行避免mciSendString()无法解析
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")

mci常用命令:
1、open:打开设备
    open DEVICE_NAME type DEVICE_TYPE alias DEVICE_ALIAS
        DEVICE_NAME:设备名,通常是文件名
        type DEVICE_TYPE:指明设备类型,常省略
        alias DEVICE_ALIAS:设备别名,(理解为指代设备的变量名)可在其他mci命令中使用
2、play:设备播放
    play DEVICE_ALIAS from POS1 to POS2 wait|repeat
        DEVICE_ALIAS:播放的设备别名
        from POS1 to POS2:从POS1磁道播放至POS2磁道,省from表从头播放,省to表播放至尾部
        wait|repeat:播放模式,wait播放一次后命令返回,repeat循环播放
3、暂停,恢复,停止,关闭
    pause DEVICE_ALIAS
    resume DEVICE_ALIAS
    stop DEVICE_ALIAS:停止播放非关闭
    close DEVICE_ALIAS:关闭设备

例:播放 程序路径下 music/1.mp3 文件
mciSendString("open music\\1.mp3 alias m1", 0, 0, 0);	//打开设备
mciSendString("play m1 wait", 0, 0, 0);	//单次播放
mciSendString("close m1", 0, 0, 0);	//关闭设备
多线程
1、多线程回调函数
DWORD WINAPI fun1(LPVOID lpParame)
{
    //...
    //fun1()需要执行的动作
    //...
    return 0;
}

2、创建线程并执行回调函数
CreateThread(NULL, 0, fun1, NULL, NULL, NULL);
批处理绘制

     在图形编程过程中,频繁的刷新(cleardevice()函数)会产生屏幕闪烁情况,使用批处理绘制可将特定的绘图操作事先进行缓冲,然后批量输出至屏幕。

BeginBatchDraw();	//此后绘图将不会输出至屏幕
// ...
// 大量绘图函数
// ...
EndBatchDraw();	//程序执行到此处后,将器件缓冲的信息批量输出至屏幕
时间控制

     控制特定步骤的执行时间间隔,而不影响其他步骤。不同于Sleep()函数,Sleep()是将整个程序暂停特定时间。

DWORD t1, t2;
t1 = t2 = GetTickCount();	//GetTickCount():获取开机至当前时间长度,单位ms
while(1)
{
    t2 = GetTickCount();
    if(t2 - t1 > 50)	//fun1()至少每隔 50ms 执行一次,fun2()正常执行
    {
        fun1();
        t1 = t2;
    }
    fun2();
}
鼠标键盘事件
1、键盘事件
char ch;
if(_kbhit())	// 存在键盘点击事件,_kbhit()返回非0值,conio.h
    ch = _getch();	// 键盘输入字符赋值给ch


2、鼠标事件
方法一:
MOUSEMSG m;	//鼠标事件结构体
if(MouseHit())	// 如果存在鼠标消息则返回 true,conio.h
    m = GetMouseMsg();
    
MOUSEMSG原型
struct MOUSEMSG{
	UINT uMsg;      // 当前鼠标消息
	/*其中鼠标消息包含:
		WM_MOUSEMOVE     鼠标移动消息
		WM_MOUSEWHEEL    鼠标滚轮拨动消息
		WM_LBUTTONDOWN   左键按下消息
		WM_LBUTTONUP     左键弹起消息
		WM_LBUTTONDBLCLK 左键双击消息
		WM_MBUTTONDOWN   中键按下消息
		WM_MBUTTONUP     中键弹起消息
		WM_MBUTTONDBLCLK 中键双击消息
		WM_RBUTTONDOWN   右键按下消息
		WM_RBUTTONUP     右键弹起消息
		WM_RBUTTONDBLCLK 右键双击消息
	*/
	bool mkCtrl;    // Ctrl 键是否按下
	bool mkShift;   // Shift 键是否按下
	bool mkLButton; // 鼠标左键是否按下
	bool mkMButton; // 鼠标中键是否按下
	bool mkRButton; // 鼠标右键是否按下
	int x;          // 当前鼠标 x 坐标	int
	y;          // 当前鼠标 y 坐标
	int wheel;      // 鼠标滚轮滚动值
};

方法二:
GetMouseMsg()仅能够在鼠标有动作的情况下获取鼠标信息,若鼠标无动作,则返回空值,m结构体中则不存在x,y值。
如果想要实时获取鼠标位置信息时,需要引入MouseHit()进行判断,存在消息才对m赋值。
以下方法也可以实时获取鼠标位置,但该法获取的位置可以超出绘图窗口,需要时要都进行判断以限制坐标值。
POINT p;
HWND hwnd;

hwnd = GetWind();	// 获取绘图窗口句柄
GetCursorPos(&p);   // 获取鼠标指针位置(屏幕坐标)
ScreenToClient(hwnd, &p); // 将鼠标指针位置转换为绘图窗口坐标
此后可以使用 p.x 与 p.y 表示鼠标在绘图窗口的坐标

图形绘制工作区
intigraph(100,100);
IMAGE bkImg(200, 200);	//声明一个IMAGE变量,并初始化尺寸200x200
SetWorkingImage(&bkImg);	//设置工作区
/*
大量绘图操作
此时绘制的图形存在于bkImg上,而非100x100的图形窗口
*/
SetWorkingImage();	//恢复工作区为100x100窗口

游戏中窗口显示部分区域,视野随某个点移动解决方案:
1、事先绘制更大的图形(为所需地图大小),相关内容一并绘制在该图形上
2、以目标角色为中心,即窗口区域为视野
根据角色坐标、窗口大小,计算出窗口 (0, 0) 点在图形上的真实位置
     假设角色坐标 (x, y),窗口宽 WIN_W、高 WIN_H,
     那么窗口 (0,0) 位置真坐标为:(x - WIN_W/2, y - WIN_H/2)
3、putimage( )函数输出对应区域至窗口
     putimage(0, 0, WIN_W, WIN_H, &bkImg, x - WIN_W/2, y - WIN_H/2);

在这里插入图片描述

;