正确处理鼠标消息(解决鼠标操作不灵敏的问题)

本文讲解怎样处理鼠标消息。编程思路有很多种,本文只是提供一种思路,并非一定要照这么做。

通常写小游戏时,很多人会有一个主循环,类似这样:

while(true)
{
	获取用户控制();

	进行游戏运算();

	绘制游戏内容();

	Sleep(xx);
}

当添加鼠标操作时,会这样写(错误代码):

// 定义变量,保存鼠标消息
MouseMsg msg;

// 游戏的主循环
while(true)
{
	if (MouseHit())				// 当有鼠标消息的时候执行
	{
		msg = GetMouseMsg();	// 获取鼠标消息

		switch(msg.uMsg)		// 根据不同的鼠标消息,执行不同的代码
		{
			case xxxx: 进行游戏运算(); break;
			case xxxx: 进行游戏运算(); break;
		}
	}

	绘制游戏内容
...

实现桌面截图

本文讲解怎样截取整个桌面的图像。

对于控制台程序,执行后首先会创建一个黑色的控制台窗口,然后才会启动你的程序。因此这时候抓到的图,会包括一个黑色的控制台窗口,我想,这是大多数人不希望看到的。因此,实现抓图,要建立的项目需要是 Win32 Application,而不能是平时用的 Win32 Console Application。怎样创建一个 Win32 Application,请参考文章《在没有控制台的 Win32 Application 中使用 EasyX 绘图》。

[名词介绍]

DC:英文单词 Device Contexts(设备上下文) 的缩写。DC 中包含有用于该设备的一组绘图对象以及这些对象的属性(例如画笔、画刷等)。

[原理简介]

要获取桌面内容,先要获取桌面的 DC,然后再通过图像拷贝语句将桌面图像的内容拷贝到 IMAGE 的 DC 中。

[实现步骤]

因为实现起来简单,步骤已经以注释的形式写到了下面的示例代码中:

...

一步步拓展程序,实现文字在背景上的移动

本文适用读者:已经学完 C 语言基本知识,并对 EasyX 略有了解。

本文范例实现的功能:文字在背景上移动,并且不破坏背景。

本文范例编译平台:VC6 / VC2010 + EasyX 20140321(beta)。

本文并不直接写出最终代码,而是从最开始绘制背景,一步步拓展到我们需要的功能。希望这个过程能对初学者有所启发。

一、绘制背景

为了实现文字移动而不破坏背景的效果,我们先画个背景。做法很简单,就是画一连串的竖线,并且每次变换颜色,这样就能弄一个渐变色的背景,代码如下:

#include <graphics.h>
#include <conio.h>

// 主函数
void main()
{
	// 创建绘图窗口
	initgraph(640, 480);
	
	// 绘制背景
	for(int i = 0; i < 640; i++)
	{
		setlinecolor(i);
		li
...

怎样编写格式优美的代码

0. 序

很多初学者会被人一眼就看出来是初学者,为什么?原因很多。其中,代码格式是很重要的一项。不注重代码格式,不仅别人看起来不舒服,还会影响自己对代码的阅读。虽然错误的格式不会产生编译错误,但却会让你更容易犯错,并且更难排查错误。所以,学会编写格式优美的代码,是初学者必须要学的一课。

优秀的代码格式并不是唯一的,有很多种风格。本文仅讲解常见的 C/C++ 语言编码规则,而其它规则相信大家在学习工作中会慢慢接触到。

再有就是,为了便于阅读代码,EasyX 网站的代码都是比较注意格式的。所以,如果打算投稿到 EasyX,看看本文也很有必要。

以下讲解编写代码时在格式上一些常见的注意事项。

1. 正确缩进

所谓缩进,是指在某一行代码的左端留出一部分空白。采用缩进的目的为了清楚的定义一个块的开始和结束,这样会使程序更加清晰易读。虽然目前主流的开发平台都具备智能缩进的功能,但是很多时候修改代码还是需要自己注意缩进问题。

下面的范例代码是求解 100 以内的质数,该范例中有多种缩进情况的例子:

...

怎样产生随机方向(上下左右)?

比如坦克游戏,敌人坦克移动的四个方向通常不会用 1~4 这样四个数值表示,而是用 dx、dy 这样的 x、y 轴上的增量表示。对应关系如下:

dx =  0;  dy = -1; 表示向上
dx =  0;  dy =  1; 表示向下
dx = -1;  dy =  0; 表示向左
dx =  1;  dy =  0; 表示向右

如果用 1~4 表示 4 个方向,敌人坦克前进一步的代码要这样写:

...

同时执行两个或更多功能的方法

我留意到群里和贴吧有不少人都在问怎样同时执行两个过程,比如:

  1. 贪吃蛇游戏,怎样实现双人对抗?就是控制两条蛇移动。
  2. 俄罗斯方块游戏,要加一个时钟,怎样使时钟和游戏同时进行?
  3. 打砖块游戏,怎样实现一边让小球自由移动、一边实现玩家控制木板?

有些人会想到用多线程来解决。我这里首先要说:这个问题不要用多线程,多线程要解决是另一种问题,这里不再详述,本文只讲一下怎样实现前面说的问题。(当然不用多线程解决)

先说一个简单的程序要求:有一个变量 a,初值为 0,每秒钟增加 2,按任意键停止;还有一个变量 b,初值为 0,每秒钟增加 3。现在要求将这两个功能同时执行,该怎么做?

我相信很多人都能写出来这个简单的程序:

#include <stdio.h>
#include <conio.h>
#include <graphics.h>

void main()
{
	// 
...

禁用 EasyX 绘图窗口关闭按钮的方法(控制程序流程)

目前,点 EasyX 绘图窗口的“关闭”,会直接退出整个程序。有时候,程序需要执行完整的流程,因此,禁止关闭按钮就是一个很需要的方法。

可以通过 initgraph 函数的第三个参数禁用关闭按钮,确保程序按实际流程完整执行。

以下代码禁用关闭按钮(VC6 / VC2010 编译通过):

#include <graphics.h>
#include <conio.h>

void main()
{
	initgraph(640, 480, NOCLOSE);

	circle(320, 240, 100);
	
	_getch();
	closegraph();
}

修改 VC 生成的 EXE 文件的图标

默认 VC 生成的 EXE 文件的图标很大众,可以根据以下办法修改 exe 的图标。

以 Visual C++ 6.0 为例:

1. 创建项目,添加代码,并且保证项目可以正常编译。

2. 为项目增加资源文件:

  1. 点菜单:File -> New...,选择 Files 中的 Resource Script,并在右侧 File 中写入名称 myapp,点 OK 添加到项目中。VC 会默认打开 myapp.rc 文件,先关闭它,我们可以 FileView 找到新添加的 myapp.rc 文件。
  2. 双击 myapp.rc,会在 Workspace 区中打开 ResourceView 视图,这里就是资源列表,起初是空的。

3. 在资源文件中导入图标

  1. 为了整齐,我们在项目路径下建立 res 文件夹,并将图标放入该文件夹内,例如取名 app.ico。
  2. 切换到 ResourceView 视图,右击 myapp resources,选择 I
...

在游戏中使用 midi 音乐文件

关于什么是 midi 音乐文件,请参考百度百科:http://baike.baidu.com/view/7969.htm 。

这里简单说一说:

midi 是一种音乐文件,通常扩展名为 mid。不同于 mp3 的地方是:mp3 保存的是声音的波形数据,而 mid 保存的是乐器、音符、音调等。所以从文件体积上来说,mp3 的体积是 mid 体积的几十倍甚至上百倍。

鉴于 midi 的特点,早期很多游戏的都使用 midi 音乐。所以,本文讲怎样使用 midi 音乐。

【1. 素材获取】

网上搜索吧,网上有很多 mid 资源。但是不要尝试将 mp3 转换为 mid,由于原理不同,暂时无法实现 mp3 -> mid 的转换。

【2. 播放】

能播放 mp3 的方法,一般都可以用来播放 mid。所以,可以参考这些文章:

《在游戏中播放音乐》 http://www.easyx.cn/skills/View.aspx?id=44

《将 mp3 以

...

在没有控制台的 Win32 Application 中使用 EasyX 绘图

通常大家学习 VC 都会创建 Win32 Console Application,它的特点就是输入输出简单,调试简单方便。不过对界面要求高的程序有一个控制台窗口似乎并不美观。本文讲怎样在没有控制台的 Win32 Application 中使用 EasyX 绘图。

首先,创建新项目的时候,要选择 Win32 Application 项目。

然后,写主函数的时候,一定要注意,不是 main,而是 WinMain。完整的格式如下:

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	// 在这里写代码

	return 0;
}

这样就是一个没有控制台的、完整的 Win32 程序了。

需要注意的是,因为没有控制台,所以 conio.h 头文件中的函数都不能使用(conio 就是 Console

...