C++ 游戏开发(二)见缝插针小游戏

本文详细介绍了使用C++开发见缝插针小游戏的主要步骤,包括绘制圆盘、实现旋转、多根针的绘制、针的发射、失败判定以及得分优化措施。通过三角函数和数组实现游戏核心功能,并讨论了如何处理图像闪烁和增加交互性。
摘要由CSDN通过智能技术生成

见缝插针

 见缝插针游戏的规则非常简单,给定一个旋转圆盘,每次按动按键,即可在圆盘上射入一根针,当两个针发生碰撞即挑战失败。胜利条件可以设置射出指定根数后胜利,也可以设置不限根数,以更多的根数作为挑战目标。

主要实现步骤

  1. 绘制圆盘
  2. 利用三角函数实现旋转
  3. 数组实现多根针
  4. 实现针的发射,失败判定
  5. 增加得分,关卡切换等设计

规制画布

 画布的设置涉及长宽,颜色设置。

	int canvas_width = 900;
	int canvas_height = 600;
	initgraph(canvas_width, canvas_height);//初始化绘图窗口,也就是设置画布的大小
	setbkcolor(RGB(0, 0, 0));//设置背景颜色为黑色
	cleardevice();//情况背景

圆盘绘制

	setlinestyle(PS_SOLID, 5);//设置线条样式
	setlinecolor(0xFFFFFF);//设置圆盘颜色为白色
	circle(canvas_width / 2, canvas_height / 2, 50);//设置圆盘的坐标和半径

绘制线条

	setlinestyle(PS_SOLID, 3);//设置线条样式
	setlinecolor(0xFFFFFF);//设置圆盘颜色为白色
	line(canvas_width / 2, canvas_height / 2, canvas_width / 2 + 50, canvas_height / 2);

实现旋转

 旋转的实现改变的变量是角度。设置一个变量,代表角度,另设一变量代表角度的改变量,设置延时函数调整旋转时间。

#include<graphics.h>//调用图形库
#include<conio.h>
#include<stdio.h>
#include<math.h>
int main()
{
	double canvas_width = 900;
	double canvas_height = 600;
	initgraph(canvas_width, canvas_height);//初始化绘图窗口,也就是设置画布的大小
	setbkcolor(RGB(0, 0, 0));//设置背景颜色为黑色
	cleardevice();//情况背景
	
	setlinestyle(PS_SOLID, 3);//设置线条样式
	setlinecolor(0xFFFFFF);//设置圆盘颜色为白色
	int radius = 50;
	circle(canvas_width / 2, canvas_height / 2, radius);//设置圆盘的坐标和半径

	double PI = 3.1415926;
	double lineLength = 100;
	double xBegin;
	double yBegin;
	double xEnd;
	double yEnd;
	setlinestyle(PS_SOLID, 3);//设置线条样式
	setlinecolor(0xFFFFFF);//设置圆盘颜色为白色
	
	double angle = 0;
	double rotate_speed = PI / 360;
	while (1)
	{
		cleardevice();
		angle += rotate_speed;
		if (angle > 200 * PI) angle -= 200 * PI;
		//计算坐标
		xBegin = radius * cos(-angle) + canvas_width / 2;
		yBegin = radius * sin(-angle) + canvas_height / 2;
		xEnd = lineLength * cos(-angle) + canvas_width / 2;
		yEnd = lineLength * sin(-angle) + canvas_height / 2;
		line(xBegin, yBegin, xEnd, yEnd);
		circle(canvas_width / 2, canvas_height / 2, radius);//设置圆盘的坐标和半径
		Sleep(10);
	}
	_getch();//设置一个读取字符函数,用于保持绘图窗口不关闭
	closegraph();//关闭绘图窗口
	return 0;
}

多根针的实现

 前文可知,对于针这一个对象,我们主要改变的是针对应的角度。对于n根针的绘制,就需要同时求n个角度。使用数组存储角度。

#include<graphics.h>//调用图形库
#include<conio.h>
#include<stdio.h>
#include<math.h>

const double PI = 3.1415926;

int main()
{
	double canvas_width = 900;
	double canvas_height = 600;
	initgraph(canvas_width, canvas_height);//初始化绘图窗口,也就是设置画布的大小
	setbkcolor(RGB(0, 0, 0));//设置背景颜色为黑色
	cleardevice();//情况背景
	
	setlinestyle(PS_SOLID, 3);//设置线条样式
	setlinecolor(0xFFFFFF);//设置圆盘颜色为白色
	int radius = 50;
	circle(canvas_width / 2, canvas_height / 2, radius);//设置圆盘的坐标和半径

	
	double lineLength = 100;
	double xBegin;
	double yBegin;
	double xEnd;
	double yEnd;
	setlinestyle(PS_SOLID, 3);//设置线条样式
	setlinecolor(0xFFFFFF);//设置圆盘颜色为白色
	
	int needle_num = 10;
	double needle_angles[20];
	for (int i = 0; i < needle_num; i++)
	{
		needle_angles[i] = i * 2 * PI / needle_num;
	}
	double rotate_speed = PI / 360;

	while (1)
	{
		cleardevice();
		for (int i = 0; i < needle_num; i++)
		{
			needle_angles[i] += rotate_speed;
			if (needle_angles[i] > 200 * PI) needle_angles[i] -= 200 * PI;
			//计算坐标
			xBegin = radius * cos(-needle_angles[i]) + canvas_width / 2;
			yBegin = radius * sin(-needle_angles[i]) + canvas_height / 2;
			xEnd = lineLength * cos(-needle_angles[i]) + canvas_width / 2;
			yEnd = lineLength * sin(-needle_angles[i]) + canvas_height / 2;
			line(xBegin, yBegin, xEnd, yEnd);
		}
		
		circle(canvas_width / 2, canvas_height / 2, radius);//设置圆盘的坐标和半径
		Sleep(5);
	}
	_getch();//设置一个读取字符函数,用于保持绘图窗口不关闭
	closegraph();//关闭绘图窗口
	return 0;
}

 此时已经实现了简单的动画效果
在这里插入图片描述
 如果以动画为开发目标,还可以在现有代码上添加一点细节。如一个旋转的太阳小哥
在这里插入图片描述

 如果按照上文给出代码,会发现图像绘制过程中有大量的闪烁,这种闪烁可以通过增加批量绘图函数解决额。

BeginBatchDraw();
FlushBatchDraw();

BeginBatchDraw();开始后任何绘图操作暂时搁置,直到FlushBatchDraw();将搁置的绘图操作全部完成。
上述两个函数分别放置在绘图循环开始时,和每一个绘图循环的最后,就可以实现批量绘制。

针的发射

 前面实现的所有操作,实际上都是静态的,程序使用者或者说是玩家,无法对我们已经绘制的旋转⚪和针实现任何操作,接下来要完成的就是“插针”的实现,也就是交互的设计。
 引入新的函数,用于交互
·检测按键

if (kbhit())//如果按键

·获得按键输入

char input = _getch();//获得用户按键

·判断是否为指定按键,以空格键为例

if (input == ' ')//如果为空格键

 将代码整合

#include<graphics.h>//调用图形库
#include<conio.h>
#include<stdio.h>
#include<math.h>

const double PI = 3.1415926;

int main()
{
	double canvas_width = 900;
	double canvas_height = 600;
	initgraph(canvas_width, canvas_height);//初始化绘图窗口,也就是设置画布的大小
	setbkcolor(RGB(0, 0, 0));//设置背景颜色为黑色
	cleardevice();//情况背景
	
	setlinestyle(PS_SOLID, 3);//设置线条样式
	setlinecolor(0xFFFFFF);//设置圆盘颜色为白色
	int radius = 50;
	circle(canvas_width / 2, canvas_height / 2, radius);//设置圆盘的坐标和半径

	
	double needle_length = 100;
	double xBegin;
	double yBegin;
	double xEnd;
	double yEnd;
	setlinestyle(PS_SOLID, 3);//设置线条样式
	setlinecolor(0xFFFFFF);//设置圆盘颜色为白色
	int needle_num = 0;
	double needle_angles[100];

	double rotate_speed = PI / 360;

	

	BeginBatchDraw();
	while (1)
	{
		cleardevice();
		line(0, canvas_height / 2, needle_length, canvas_height / 2);
		for (int i = 0; i < needle_num; i++)
		{
			needle_angles[i] += rotate_speed;
			if (needle_angles[i] > 200 * PI) needle_angles[i] -= 200 * PI;
			//计算坐标
			xBegin = radius * cos(-needle_angles[i]) + canvas_width / 2;
			yBegin = radius * sin(-needle_angles[i]) + canvas_height / 2;
			xEnd = needle_length * cos(-needle_angles[i]) + canvas_width / 2;
			yEnd = needle_length * sin(-needle_angles[i]) + canvas_height / 2;
			line(xBegin, yBegin, xEnd, yEnd);
		}

		if (_kbhit())//如果按键
		{
			char input = _getch();//获得用户按键
			if (input == ' ')//如果为空格键
			{
				//针的逻辑实现
				needle_num++;
				needle_angles[needle_num - 1] = PI;
				xBegin = radius * cos(-needle_angles[needle_num - 1]) + canvas_width / 2;
				yBegin = radius * sin(-needle_angles[needle_num - 1]) + canvas_height / 2;
				xEnd = needle_length * cos(-needle_angles[needle_num - 1]) + canvas_width / 2;
				yEnd = needle_length * sin(-needle_angles[needle_num - 1]) + canvas_height / 2;
				line(xBegin, yBegin, xEnd, yEnd);
			}
		}
		
		circle(canvas_width / 2, canvas_height / 2, radius);//设置圆盘的坐标和半径
		circle(canvas_width / 2-20, canvas_height / 2-20, radius/10);//设置圆盘的坐标和半径
		circle(canvas_width / 2+20, canvas_height / 2 - 20, radius / 10);//设置圆盘的坐标和半径
		circle(canvas_width / 2 , canvas_height / 2 + 20, radius / 4);//设置圆盘的坐标和半径
		FlushBatchDraw();
		Sleep(5);
	}
	_getch();//设置一个读取字符函数,用于保持绘图窗口不关闭
	closegraph();//关闭绘图窗口
	return 0;
}

失败判定

 通常用两个小针体积碰撞判定失败,在实现时,可以忽略针的形状,而采用角度判定失败。当两个针的角度差小于一定值时,认为发生了碰撞。

#include<graphics.h>//调用图形库
#include<conio.h>
#include<stdio.h>
#include<math.h>

const double PI = 3.1415926;

int main()
{
	double canvas_width = 900;
	double canvas_height = 600;
	initgraph(canvas_width, canvas_height);//初始化绘图窗口,也就是设置画布的大小
	setbkcolor(RGB(0, 0, 0));//设置背景颜色为黑色
	cleardevice();//情况背景
	
	setlinestyle(PS_SOLID, 3);//设置线条样式
	setlinecolor(0xFFFFFF);//设置圆盘颜色为白色
	int radius = 50;
	circle(canvas_width / 2, canvas_height / 2, radius);//设置圆盘的坐标和半径

	
	double needle_length = 100;
	double xBegin;
	double yBegin;
	double xEnd;
	double yEnd;
	setlinestyle(PS_SOLID, 3);//设置线条样式
	setlinecolor(0xFFFFFF);//设置圆盘颜色为白色
	int needle_num = 0;
	double needle_angles[100];

	double rotate_speed = PI / 360;

	

	BeginBatchDraw();
	while (1)
	{
		cleardevice();
		line(0, canvas_height / 2, needle_length, canvas_height / 2);
		for (int i = 0; i < needle_num; i++)
		{
			needle_angles[i] += rotate_speed;
			if (needle_angles[i] > 2 * PI) needle_angles[i] -= 2 * PI;
			//计算坐标
			xBegin = radius * cos(-needle_angles[i]) + canvas_width / 2;
			yBegin = radius * sin(-needle_angles[i]) + canvas_height / 2;
			xEnd = needle_length * cos(-needle_angles[i]) + canvas_width / 2;
			yEnd = needle_length * sin(-needle_angles[i]) + canvas_height / 2;
			line(xBegin, yBegin, xEnd, yEnd);
		}

		if (_kbhit() && rotate_speed != 0)//如果按键
		{
			char input = _getch();//获得用户按键
			if (input == ' ')//如果为空格键
			{
				//针的逻辑实现
				needle_num++;
				needle_angles[needle_num - 1] = PI;
				for (int i = 0; i <= needle_num-2; i++)
				{
					double fail_flag = needle_angles[needle_num - 1] - needle_angles[i];
					if (fabs(fail_flag) < PI / 60)//当角度小于设定值,失败
					{
						rotate_speed = 0;
						RECT r = { 0, 0, 600, 600 };
						LOGFONT f;
						gettextstyle(&f);						// 获取当前字体设置
						f.lfHeight = 78;						// 设置字体高度为 48
						f.lfQuality = ANTIALIASED_QUALITY;		// 设置输出效果为抗锯齿  
						settextstyle(&f);						// 设置字体样式
						drawtext(_T("you fail !!!!!"), &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//失败提示
						FlushBatchDraw();
						Sleep(10000);
					}
				}
				xBegin = radius * cos(-needle_angles[needle_num - 1]) + canvas_width / 2;
				yBegin = radius * sin(-needle_angles[needle_num - 1]) + canvas_height / 2;
				xEnd = needle_length * cos(-needle_angles[needle_num - 1]) + canvas_width / 2;
				yEnd = needle_length * sin(-needle_angles[needle_num - 1]) + canvas_height / 2;
				line(xBegin, yBegin, xEnd, yEnd);
			}
		}
		
		circle(canvas_width / 2, canvas_height / 2, radius);//设置圆盘的坐标和半径
		circle(canvas_width / 2-20, canvas_height / 2-20, radius/10);//设置圆盘的坐标和半径
		circle(canvas_width / 2+20, canvas_height / 2 - 20, radius / 10);//设置圆盘的坐标和半径
		circle(canvas_width / 2 , canvas_height / 2 + 20, radius / 4);//设置圆盘的坐标和半径
		FlushBatchDraw();
		Sleep(5);
	}
	_getch();//设置一个读取字符函数,用于保持绘图窗口不关闭
	closegraph();//关闭绘图窗口
	return 0;
}



 可以按照自己的喜好设置失败效果,我设置的如下
在这里插入图片描述

得分等优化措施

得分的展示
 得分可以简单按照发射数量来判定,即发射一根,得分增加一个。

#include<graphics.h>//调用图形库
#include<conio.h>
#include<stdio.h>
#include<math.h>
#include<iostream>
#include<string>
const double PI = 3.1415926;
using namespace std;
int main()
{
	double canvas_width = 900;
	double canvas_height = 600;
	initgraph(canvas_width, canvas_height);//初始化绘图窗口,也就是设置画布的大小
	setbkcolor(RGB(0, 0, 0));//设置背景颜色为黑色
	cleardevice();//情况背景
	
	setlinestyle(PS_SOLID, 3);//设置线条样式
	setlinecolor(0xFFFFFF);//设置圆盘颜色为白色
	int radius = 50;
	circle(canvas_width / 2, canvas_height / 2, radius);//设置圆盘的坐标和半径

	
	double needle_length = 100;
	double xBegin;
	double yBegin;
	double xEnd;
	double yEnd;
	setlinestyle(PS_SOLID, 3);//设置线条样式
	setlinecolor(0xFFFFFF);//设置圆盘颜色为白色
	int needle_num = 0;
	double needle_angles[100];

	double rotate_speed = PI / 360;

	int score = 0;
	TCHAR s[20];
	BeginBatchDraw();
	while (1)
	{
		cleardevice();
		line(0, canvas_height / 2, needle_length, canvas_height / 2);
		for (int i = 0; i < needle_num; i++)
		{
			needle_angles[i] += rotate_speed;
			if (needle_angles[i] > 2 * PI) needle_angles[i] -= 2 * PI;
			//计算坐标
			xBegin = radius * cos(-needle_angles[i]) + canvas_width / 2;
			yBegin = radius * sin(-needle_angles[i]) + canvas_height / 2;
			xEnd = needle_length * cos(-needle_angles[i]) + canvas_width / 2;
			yEnd = needle_length * sin(-needle_angles[i]) + canvas_height / 2;
			line(xBegin, yBegin, xEnd, yEnd);
		}

		if (_kbhit() && rotate_speed != 0)//如果按键
		{
			char input = _getch();//获得用户按键
			if (input == ' ')//如果为空格键
			{
				score++;
				//针的逻辑实现
				needle_num++;
				needle_angles[needle_num - 1] = PI;
				for (int i = 0; i <= needle_num-2; i++)
				{
					double fail_flag = needle_angles[needle_num - 1] - needle_angles[i];
					if (fabs(fail_flag) < PI / 60)
					{
						rotate_speed = 0;
						RECT r = { 0, 0, 600, 600 };
						LOGFONT f;
						gettextstyle(&f);						// 获取当前字体设置
						f.lfHeight = 78;						// 设置字体高度为 48
						f.lfQuality = ANTIALIASED_QUALITY;		// 设置输出效果为抗锯齿  
						settextstyle(&f);						// 设置字体样式
						drawtext(_T("you fail !!!!!"), &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
						FlushBatchDraw();
						Sleep(10000);
					}
					
				}
				xBegin = radius * cos(-needle_angles[needle_num - 1]) + canvas_width / 2;
				yBegin = radius * sin(-needle_angles[needle_num - 1]) + canvas_height / 2;
				xEnd = needle_length * cos(-needle_angles[needle_num - 1]) + canvas_width / 2;
				yEnd = needle_length * sin(-needle_angles[needle_num - 1]) + canvas_height / 2;
				line(xBegin, yBegin, xEnd, yEnd);
			}
		}
		_stprintf_s(s, _T("%d"), score);
		settextstyle(50, 0, _T("Times"));
		settextcolor(RGB(100, 100, 100));
		outtextxy(65, 200, s);
		circle(canvas_width / 2, canvas_height / 2, radius);//设置圆盘的坐标和半径
		circle(canvas_width / 2-20, canvas_height / 2-20, radius/10);//设置圆盘的坐标和半径
		circle(canvas_width / 2+20, canvas_height / 2 - 20, radius / 10);//设置圆盘的坐标和半径
		circle(canvas_width / 2 , canvas_height / 2 + 20, radius / 4);//设置圆盘的坐标和半径
		FlushBatchDraw();
		Sleep(5);
	}
	_getch();//设置一个读取字符函数,用于保持绘图窗口不关闭
	closegraph();//关闭绘图窗口
	return 0;
}

最终效果
在这里插入图片描述

在得分之外可以按照自己的喜好增加其他功能,如关卡,过场动画等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CCC_bi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值