1. 绘制自定义的图形

在4*4(当然也可以随便)的方格(看成二维数组)里把需要的地方随便赋值,画个南瓜饼(把除了四个角都赋值)什么的都行。

2.得分与显示

在game类加上一个数据成员表示这局游戏的分数,消行的时候增加分数(连续消行也可以加的更多)。

显示,绘制一个edit控件,然后对它右键选择创建变量,变量类型设为“值”,类型为int.

俄罗斯方块小游戏java 俄罗斯方块小游戏视频_控件

它本来的类型是“控件”,这样的话如果要显示就要用到内库的函数来写,比较麻烦,我们把他设置为值 这样就可以直接给他赋值,非常方便。例如:

m_edit = _game.mark;
UpdateData(FALSE);

然后就是下面那条语句了,这涉及到值交换的问题。
值的传递会用到上面你创建控件时自动生成的函数

void CMyboxDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_EDIT1, m_edit);
}

简单来说,把参数设置为FALSE代表把值传到控件变量,TRUE代表相反。所以我们这里把他设为FALSE;
点 重新开始 按钮时,别忘了把分数重置为0;

3.变速

首先我想到的办法是基于分数判断,如果分数大于一个值,那么在定时下落的函数里再下落一次,就是本来每个时钟周期本来下降一格,现在让他下降两格,如果再大于某个值的话,就下降三格。(分享的文件代码是这么写的)

if(CanMoveDown()){
		if(mark < 15){
			if (CanMoveDown()) 	//判断是否可以向下移动一格
				MoveDown();			//向下移动一格
		}
		else if (mark < 30) {
			if (CanMoveDown()) MoveDown();
			if (CanMoveDown()) MoveDown();
			
		}
		else {
			if(CanMoveDown()) MoveDown();
			if (CanMoveDown()) MoveDown();
			if (CanMoveDown()) MoveDown();		
			}
		return true;
		}

但是后来我想到了一个更好的办法,因为上面的难度提升时阶梯式的,很难控制参数使得玩家有一个比较好的游戏体验,于是设计一个难度连续提升的方式就显得尤为关键。
那么应该怎么做呢?
修改时钟周期!
因为我们在游戏开始按钮的函数里固定了他的时钟周期是500(ms),就是半秒钟响应一次。只要我们减小他的周期,那么执行速度变快,那么下落的速度也就变快了。
接下来的问题是我们应该在哪个函数里写这个代码、
首先我们应该想到分数的显示,因为我们要显示的是实时的分数,那么就很明显应该把代码写到时时刻刻都在执行的函数里,比如说绘图函数。(我是写在这里的,可能写在其他函数里更好)

if (_game._state == GO) {
		KillTimer(1);
		SetTimer(1, 500 - _game.mark * 50, NULL);
	}

一定要在游戏状态是“GO”即不是暂停也不是结束时执行(在游戏结束时我有一个显示游戏结束并显示分数的弹窗,此时绘图函数其实还在运行,所以你一直在 SetTimer,你把弹窗关了游戏又被检测为死亡,然后这个弹窗又会出现,你永远也关不了,只有去任务管理器关)。 50那个参数可以自己调一下,50还是太大了,分数到达10分左右就没法玩了,毫无游戏体验。
哦不,要是有10分时钟周期都没了500- 10 *50 =0,你根本不可能有10分,到8分估计都玩不了了hhh。

但是我发现这么做有一个bug,就是按变形健的时候方块就不会下落了,又试验了一下,其实不管按什么健定时下落的功能都没了,因为在接收键盘信号的函数里每次执行完相应操作后都会执行绘图函数,然后你又重新定义了一个时钟,到一个时钟周期前,他都不会执行定时下落的功能,就算是你按加速键,他也就相应手动下降函数下降了一个格子,所以他现在其实是减速健。不过到后面随着游戏时钟周期变短,他还是会下落的。

(所以这个东西还能用来测手速哈哈哈哈,只要先设置一个速度,然后让测试者按,如果能保持他不动,说明手速比这个快,然后一直加,就能测出你的手速了。)

解决方法:把代码放在 OnTimer 函数里就好了,我也不知道我当时为什么要把它放在绘图函数里,确实有点傻,。

4.闪频

因为每次绘图的时候都先会把背景擦除,然后在依次绘图,这样就会产生闪烁。
解决方法: 双缓冲 (去其他地方查)
#如果背景是纯色的话可以先用ps等软件查出这个颜色的RGB,然后每次直接暴力填充背景,然后慢慢绘制小方块,但都是在缓冲区完成。

memDC.FillSolidRect(rect, RGB(255, 192, 203));

每次现在缓冲区 即 memDC里把绘图一次性完成,然后再直接打到DC上,这样就避免了依次绘图产生的闪烁。

dc.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);

(这里写的很不详细);

5. 文件操作

因为要做一个显示历史做高分的操作,所以只能把最高分的数据存在文件中。

#头文件
ifstream ifs;
	ifs.open("a.txt", ios::in);
	if (!ifs.is_open())
	{
		ofstream OutFile("a.txt");
		OutFile << "0";
		OutFile.close();
		_game.maxmark = 0;
	}
	else {
		string buf;
		getline(ifs, buf);
		int x = 0, i = 0;
		while (buf[i] != '\0') {
			x = x * 10 + buf[i] - '0';
			i++;
		}
		_game.maxmark = x;
	}

如果没有相应的文件,就先创建一个 a.txt ;
否则就读取文件并把他赋值给 game类的成员变量。
到游戏结束时,做一次比较,如果超过了就要重新写一下文件。

if (_game.mark > _game.maxmark) {
			ofstream OutFile("a.txt");
			OutFile << _game.mark;
			OutFile.close();
			_game.maxmark = _game.mark;
		}

#重新生成一个同名文件,之前那个就没了。