C++入门——实现见缝插针游戏

Posted cqu_shuai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++入门——实现见缝插针游戏相关的知识,希望对你有一定的参考价值。

参考

  1. 《C和C++游戏趣味编程》 童晶

见缝插针

“见缝插针”游戏:按下空格键后发射一根针到圆盘上,所有针逆时针方向转动;如果新发射的针碰到已有的针,游戏结束

绘制圆盘与针

绘制一个圆表示圆盘、一条线段表示一根针,圆心坐标及线段起点坐标均为(width/2, height/2)

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

int main()
{
	int width = 800;
	int height = 600;
	initgraph(width, height);
	setbkcolor(RGB(255, 255, 255));
	cleardevice();

	setlinestyle(PS_SOLID, 3);								   // 线宽为3
	setlinecolor(RGB(0, 0, 0));
	line(width / 2, height / 2, width / 2 + 160, height / 2);  // 绘制一根针

	setlinecolor(HSVtoRGB(0, 0.9, 0.8));                       // 设置圆盘线条颜色为红色
	circle(width / 2, height / 2, 60);

	_getch();
	closegraph();
	return 0;
}

针的旋转

针的起点坐标为画面中心(width/2, height/2),假设针的长度为lineLength,针的旋转角度为angle,则由三角函数可以求出针的末端坐标(xEnd, yEnd)。然后,让针的角度逐渐增加,就实现了针的旋转效果

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

int main()
{
	float PI = 3.1415926;
	int width = 800;
	int height = 600;
	initgraph(width, height);
	setbkcolor(RGB(255, 255, 255));

	float lineLength = 160;
	float xEnd, yEnd;
	float angle = 0;
	float rotateSpeed = PI / 360;

	setlinestyle(PS_SOLID, 3);								 // 线宽为3
	while (1)
	{
		cleardevice();
		angle += rotateSpeed;
		if (angle > 2 * PI)                                  // 防止角度数据无限增加
		{
			angle -= 2 * PI;
		}
		xEnd = lineLength * cos(-angle) + width / 2;         // 计算针的末端坐标
		yEnd = lineLength * sin(-angle) + height / 2;
		setlinecolor(RGB(0, 0, 0));
		line(width / 2, height / 2, xEnd, yEnd);             // 绘制一根针
		setlinecolor(HSVtoRGB(0, 0.9, 0.8));                 // 设置圆盘线条颜色为红色
		circle(width / 2, height / 2, 60);
		Sleep(10);
	}
	closegraph();
	return 0;
}

批量绘制多根针

用数组记录每根针的角度值。另外,当绘制的元素较多时,会出现明显的画面闪烁,这时可以使用批量绘图函数。BeginBatchDraw()用于开始批量绘图,执行后任何绘图操作都将暂时不输出到屏幕上,直到FlushBatchDraw()或EndBatchDraw()才将之前的绘图输出

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

int main()
{
	float PI = 3.1415926;
	int width = 800;
	int height = 600;
	initgraph(width, height);
	setbkcolor(RGB(255, 255, 255));
	setlinestyle(PS_SOLID, 3);								     // 线宽为3

	float lineLength = 160;
	float xEnd, yEnd;
	float rotateSpeed = PI / 360;
	int lineNum = 20;
	float Angles[20];
	int i;
	for (i = 0; i < lineNum; i++)
	{
		Angles[i] = i * 2 * PI / lineNum;
	}

	BeginBatchDraw();                                           
	while (1)
	{
		cleardevice();
		setlinecolor(RGB(0, 0, 0));
		for (i = 0; i < lineNum; i++)
		{
			Angles[i] += rotateSpeed;
			if (Angles[i] > 2 * PI)                              // 防止角度数据无限增加
			{
				Angles[i] -= 2 * PI;
			}
			xEnd = lineLength * cos(-Angles[i]) + width / 2;     // 计算针的末端坐标
			yEnd = lineLength * sin(-Angles[i]) + height / 2;
			line(width / 2, height / 2, xEnd, yEnd);             // 绘制一根针
			
		}

		setlinecolor(HSVtoRGB(0, 0.9, 0.8));                     // 设置圆盘线条颜色为红色
		circle(width / 2, height / 2, 60);
		FlushBatchDraw();
		Sleep(10);
	}
	closegraph();
	return 0;
}

针的发射与新增

首先在画面左边绘制一根针,表示待发射的位置;当用户按下空格键,针的个数加1,并且新增加的针初始角度为PI。用户不断按下空格键,即可持续生成新的针

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

int main()
{
	float PI = 3.1415926;
	int width = 800;
	int height = 600;
	initgraph(width, height);
	setbkcolor(RGB(255, 255, 255));
	setlinestyle(PS_SOLID, 3);								     // 线宽为3

	float lineLength = 160;
	float xEnd, yEnd;
	float rotateSpeed = PI / 360;
	int lineNum = 0;
	float Angles[1000];
	int i;

	BeginBatchDraw();                                           
	while (1)
	{
		cleardevice();
		setlinecolor(RGB(0, 0, 0));
		line(0, height / 2, lineLength, height / 2);             // 左边发射区域的一根针

		for (i = 0; i < lineNum; i++)
		{
			Angles[i] += rotateSpeed;
			if (Angles[i] > 2 * PI)                              // 防止角度数据无限增加
			{
				Angles[i] -= 2 * PI;
			}
			xEnd = lineLength * cos(-Angles[i]) + width / 2;     // 计算针的末端坐标
			yEnd = lineLength * sin(-Angles[i]) + height / 2;
			line(width / 2, height / 2, xEnd, yEnd);             // 绘制一根针
		}

		if (_kbhit())
		{
			char input = _getch();
			if (input == ' ')                                    // 如果为空格键
			{
				lineNum++;
				Angles[lineNum - 1] = PI;
				xEnd = lineLength * cos(-Angles[lineNum - 1]) + width / 2;
				yEnd = lineLength * sin(-Angles[lineNum - 1]) + height / 2;
				line(width / 2, height / 2, xEnd, yEnd);
			}
		}
		setlinecolor(HSVtoRGB(0, 0.9, 0.8));                     // 设置圆盘线条颜色为红色
		circle(width / 2, height / 2, 60);
		FlushBatchDraw();
		Sleep(10);
	}
	closegraph();
	return 0;
}

游戏失败判断

当两根针的旋转角度差的绝对值小于PI/60时,判断发生了碰撞

for (i = 0; i < lineNum - 1; i++)                // 拿新的针和之前所有针比较
{
	if (fabs(Angles[lineNum - 1] - Angles[i]) < PI / 60)
	{
		rotateSpeed = 0;                         // 如果碰撞,停止旋转
		break;
	}
}

得分与显示效果改进

当用户按空格键并且游戏没有失败,则得分增加1:

score += 1;

最后将score转换为字符串输出:

TCHAR s[20]; // 定义字符串数组
_stprintf(s, _T("%d"), score);
settextstyle(50, 0, _T("Times"));
settextcolor(RGB(50, 50, 50));
outtextxy(65, 200, s);

填充绘制圆盘,随着针数的增加,圆盘填充颜色越来鲜艳:

setfillcolor(HSVtoRGB(0, lineNum / 60.0, 0.8));
setlinecolor(HSVtoRGB(0, 0.9, 0.8));
fillcircle(width / 2, height / 2);

将正在旋转的针的颜色设为蓝色,最新发射的针的颜色设为红色:

setlinecolor(RGB(0, 0, 255));
if (i == lineNum - 1)
{
	setlinecolor(RGB(255, 0, 0));
}

完整代码

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

int main()
{
	float PI = 3.1415926;
	int width = 800;
	int height = 600;
	initgraph(width, height);
	setbkcolor(RGB(255, 255, 255));
	setlinestyle(PS_SOLID, 3);								     // 线宽为3

	float lineLength = 160;
	float xEnd, yEnd;
	float rotateSpeed = PI / 360;
	int lineNum = 0;
	float Angles[1000];
	int score = 0;
	int i;

	BeginBatchDraw();                                           
	while (1)
	{
		cleardevice();
		setlinecolor(RGB(0, 0, 0));
		line(0, height / 2, lineLength, height / 2);             // 左边发射区域的一根针

		for (i = 0; i < lineNum; i++)
		{
			Angles[i] += rotateSpeed;
			if (Angles[i] > 2 * PI)                              // 防止角度数据无限增加
			{
				Angles[i] -= 2 * PI;
			}
			xEnd = lineLength * cos(-Angles[i]) + width / 2;     // 计算针的末端坐标
			yEnd = lineLength * sin(-Angles[i]) + height / 2;
			setlinecolor(RGB(0, 0, 255));                        // 设定旋转针的颜色为蓝色
			if (i == lineNum - 1)
			{
				setlinecolor(RGB(255, 0, 0));                    // 新增的针为红色
			}
			line(width / 2, height / 2, xEnd, yEnd);             // 绘制一根针
		}

		if (_kbhit() && rotateSpeed != 0)
		{
			char input = _getch();
			if (input == ' ')                                    // 如果为空格键
			{
				lineNum++;
				Angles[lineNum - 1] = PI;
				xEnd = lineLength * cos(-Angles[lineNum - 1]) + width / 2;
				yEnd = lineLength * sin(-Angles[lineNum - 1]) + height / 2;
				line(width / 2, height / 2, xEnd, yEnd);
				for (i = 0; i < lineNum - 1; i++)                // 拿新的针和之前所有针比较
				{
					if (fabs(Angles[lineNum - 1] - Angles[i]) < PI / 60)
					{
						rotateSpeed = 0;                         // 如果碰撞,停止旋转
						break;
					}
				}
				score += 1;
			}
		}
		setfillcolor(HSVtoRGB(0, lineNum / 60.0, 0.8));          // 针越多,圆盘颜色越鲜艳
		setlinecolor(HSVtoRGB(0, 0.9, 0.8));                     // 圆盘线条颜色为红色
		fillcircle(width / 2, height / 2, 60);                   // 绘制中间的圆盘
		TCHAR s[20];                                             // 定义字符串数组
		swprintf_s(s, _T("%d"), score);
		settextstyle(50, 0, _T("Times"));                        // 设置文字大小、字体
		settextcolor(RGB(50, 50, 50));
		outtextxy(65, 200, s);

		FlushBatchDraw();
		Sleep(10);
	}
	closegraph();
	return 0;
}

以上是关于C++入门——实现见缝插针游戏的主要内容,如果未能解决你的问题,请参考以下文章

C语言实现见缝插圆游戏丨零基础代码思路+源码分享

iOS平台上aa(见缝插针)游戏的简易实现

完整源码分享C/C++游戏开发:见缝插针!

cocos creator见缝插针源码游戏结束的代码逻辑

Unity实战之见缝插针

Unity实战之见缝插针