C++练手小游戏4——见缝插针

这篇博客介绍了一个使用C++编程实现的飞镖游戏,游戏规则是向旋转的目标圆盘发射飞镖,两支飞镖重合则游戏结束。代码中涉及了vector容器的使用,以及EasyX图形库进行图形绘制。程序通过键盘输入控制发射飞镖,并判断飞镖是否碰撞。此外,还包含了得分计算和显示。博客内容涵盖了STL、图形编程、游戏逻辑和用户交互等多个方面。
摘要由CSDN通过智能技术生成

概述

这是用右侧的一个发射器,向旋转的目标圆盘上发射“飞镖”,然后如何两个飞镖重合就停止,否则就累加积分。

实现效果和涉及的知识

在这里插入图片描述

  1. 用到了vector,详细可见《STL源码剖析》
  2. using namespace std要慎用:在头文件最好不用,但在cpp文件中可以使用(但有比这更好的方法,之后说),但是有个条件,必须用在所有#include之后(如果在cpp文件中使用using namespace std; 而且,若放在#include之前,那相当于用在头文件中了,你不知道头文件展开后,这个using覆盖多大的范围。所以,必须用在所有#include之后。)

文件结构

在这里插入图片描述

具体代码

FQF_DartTarger.cpp

// FQF_DartTarger.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

#include <iostream>
#include <graphics.h>   // EasyX函数库
#include <conio.h>  // console input/output的简写,非cpp STL,定义了通过控制台进行输入输出的函数,如getch()
#include <cmath> // sin(),cos()

#include "data.h"   // 全局变量
#include "ifcoll.h"
#include "dart.h"
#include "score.h"
#include "FuncPlotDart.h"
#include "FuncShowScore.h"

//using namespace std; // 头文件慎用using,可能会出现冲突

int main()
{
	dart Dart;
	score Score;
	ifcoll IfColl;
	
	Dart.set_dartrotspd(pi / 360 * 2);
	Score.initscore();
	IfColl.setifcollrange(pi / 36);

	initgraph(grawid, grahei);
	setbkcolor(RGB(1, 1, 1)); // 背景为白色
	setlinestyle(PS_SOLID, 2); // 线宽为2,这样针看起来更明显

	BeginBatchDraw(); // 开始批量绘制

	while (1)
	{
		while (1)
		{
			cleardevice();

			// 绘制圆
			fillcircle(circlex, circley, r);
			setfillcolor(HSVtoRGB(1, dartang.size() /20.0, 1)); // 绘制中间的圆盘,针越多,其颜色越鲜艳
			setlinecolor(HSVtoRGB(0, 1, 1)); // 设置圆盘线条颜色为红色
			
			// 绘制发射器
			line(grawid * 2 / 3, grahei / 2, grawid * 2 / 3 + dartlength, grahei / 2);
			
			// 判断键盘输入
			if (_kbhit()) // 注意这个函数,非常特殊:键盘敲击:true or 键盘不敲击:null(不是false)
			// 如果不加_kbhit(),console在每个while循环都会被_getch()卡住:等待使用者键盘输入。
			{
				char kbin = _getch(); // Get a character from the console,在conio.h中
				if (kbin == ' ')
				{
					Dart.insert_dart(); // 更新飞镖数组

					// 判断碰撞
					if (IfColl.iflinecoll())
					{
						Dart.update_dartang(); // 更新dartang的数据
						FuncPlotDart(); // 绘制dart
						FuncShowScore(); // 显示分数
						FlushBatchDraw(); // 批量绘制

						break;
					}
				}
			}

			Dart.update_dartang(); // 更新dartang的数据
			FuncPlotDart(); // 绘制dart
			showscore = Score.calscore(); // 更新分数
			FuncShowScore(); // 显示分数

			FlushBatchDraw(); // 批量绘制

			Sleep(10);
		}

		while (1) // 按‘r’重新开始游戏
		{
			if (_kbhit()) // 注意这个函数,非常特殊:键盘敲击:true or 键盘不敲击:null(不是false)     
			{
				char kbinRS = _getch();
				if (kbinRS == 'r') // 按‘r’重新开始游戏
				{
					dartang.clear();
					Score.initscore();
					break;
				}
			}
		}
	}

	_getch();
	closegraph();

	return 0;
}

data.h

#pragma once

#include <vector>

extern float grawid, grahei;
extern std::vector<float> dartang;
extern float dartlength;
extern float r, circlex, circley;

extern float pi;

extern float dartHX, dartHY, dartEX, dartEY;

extern int showscore;

data.cpp

#include "data.h"

float grawid = 600, grahei = 400;
std::vector<float> dartang;
float dartlength = 100;
float r = 50, circlex = grawid * 1 / 3, circley = grahei / 2;

float pi = 3.141592653;

float dartHX = 0, dartHY = 0, dartEX = 0, dartEY = 0;

int showscore = 0;

ifcoll.h

#pragma once

#include "data.h"
#include <cmath> // abs()

class ifcoll
{
private:
	bool boolifcoll;
	float angrange;

public:
	ifcoll();
	~ifcoll();
	void setifcollrange(float);
	bool iflinecoll();
};

ifcoll.cpp

#include "ifcoll.h"

ifcoll::ifcoll()
{
	boolifcoll = false;
	angrange = 5;
}

ifcoll::~ifcoll()
{
}

void ifcoll::setifcollrange(float range)
{
	angrange = range;
}

bool ifcoll::iflinecoll()
{
	boolifcoll = false;

	if (dartang.size()>1)
	{
		for (int i = 0; i < dartang.size() - 1; i++)
		{
			if (abs(dartang[i]) < angrange|| abs(dartang[i]) > 2* pi- angrange)
			{
				boolifcoll = true;
			}
		}
	}

	return boolifcoll;
}

dart.h

#pragma once

#include "data.h"

class dart
{
private:
	float RotSpd;

public:
	dart();
	~dart();
	void set_dartrotspd(float);
	void insert_dart();
	void update_dartang();
};

dart.cpp

#include "dart.h"

dart::dart()
{
	RotSpd = 0;
}

dart::~dart()
{
}

void dart::set_dartrotspd(float rotspd)
{
	RotSpd = rotspd;
}

void dart::insert_dart()
{
	dartang.push_back(0);
}

void dart::update_dartang()
{
	for (int i = 0; i < dartang.size(); i++)
	{
		dartang[i] = dartang[i] + RotSpd;
		if (dartang[i] > 2*pi)
		{
			dartang[i] = 0;
		}
	}
}

score.h

#pragma once

#include "data.h"

class score
{
private:
	int userscore;

public:
	score();
	~score();
	void initscore();
	int calscore();
};

score.cpp

#include "score.h"

score::score()
{
	userscore = 0;
}

score::~score()
{
}

void score::initscore()
{
	userscore = 0;
}

int score::calscore()
{
	userscore = dartang.size();

	return userscore;
}

FuncPlotDart.h

#pragma once

extern void FuncPlotDart();

FuncPlotDart.cpp

// 绘制飞镖
#include <graphics.h>
#include "data.h"
#include "dart.h"

void FuncPlotDart()
{
	
	for (int i = 0; i < dartang.size(); i++)
	{
		dartHX = cos(dartang[i]) * r + circlex;
		dartHY = sin(dartang[i]) * r + circley;
		dartEX = cos(dartang[i]) * dartlength + circlex;
		dartEY = sin(dartang[i]) * dartlength + circley;

		line(dartHX, dartHY, dartEX, dartEY);
	}
}

FuncShowScore.h

#pragma once

extern void FuncShowScore();

FuncShowScore.cpp

// 计算并显示得分
#include <graphics.h>
#include "data.h"
#include "dart.h"

void FuncShowScore()
{
	TCHAR s[20]; // 这里划重点:_UNICODE宏。定义字符串数组
	swprintf_s(s, _T("%d"), showscore); // 将score转换为字符串
	settextstyle(40, 0, _T("宋体")); // EasyX:The function is used to styling the current font
	outtextxy(50, 30, s); // EasyX:The function is used to output the string at the specified location.
}

BODY { BACKGROUND-COLOR: white; FONT-FAMILY: "Verdana", sans-serif; FONT-SIZE: 100%; MARGIN-LEFT: 0px; MARGIN-TOP: 0px } P { FONT-FAMILY: "Verdana", sans-serif; FONT-SIZE: 70%; LINE-HEIGHT: 12pt; MARGIN-BOTTOM: 0px; MARGIN-LEFT: 10px; MARGIN-TOP: 10px } .note { BACKGROUND-COLOR: #ffffff; COLOR: #336699; FONT-FAMILY: "Verdana", sans-serif; FONT-SIZE: 100%; MARGIN-BOTTOM: 0px; MARGIN-LEFT: 0px; MARGIN-TOP: 0px; PADDING-RIGHT: 10px } .infotable { BACKGROUND-COLOR: #f0f0e0; BORDER-BOTTOM: #ffffff 0px solid; BORDER-COLLAPSE: collapse; BORDER-LEFT: #ffffff 0px solid; BORDER-RIGHT: #ffffff 0px solid; BORDER-TOP: #ffffff 0px solid; FONT-SIZE: 70%; MARGIN-LEFT: 10px } .issuetable { BACKGROUND-COLOR: #ffffe8; BORDER-COLLAPSE: collapse; COLOR: #000000; FONT-SIZE: 100%; MARGIN-BOTTOM: 10px; MARGIN-LEFT: 13px; MARGIN-TOP: 0px } .issuetitle { BACKGROUND-COLOR: #ffffff; BORDER-BOTTOM: #dcdcdc 1px solid; BORDER-TOP: #dcdcdc 1px; COLOR: #003366; FONT-WEIGHT: normal } .header { BACKGROUND-COLOR: #cecf9c; BORDER-BOTTOM: #ffffff 1px solid; BORDER-LEFT: #ffffff 1px solid; BORDER-RIGHT: #ffffff 1px solid; BORDER-TOP: #ffffff 1px solid; COLOR: #000000; FONT-WEIGHT: bold } .issuehdr { BACKGROUND-COLOR: #E0EBF5; BORDER-BOTTOM: #dcdcdc 1px solid; BORDER-TOP: #dcdcdc 1px solid; COLOR: #000000; FONT-WEIGHT: normal } .issuenone { BACKGROUND-COLOR: #ffffff; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; BORDER-RIGHT: 0px; BORDER-TOP: 0px; COLOR: #000000; FONT-WEIGHT: normal } .content { BACKGROUND-COLOR: #e7e7ce; BORDER-BOTTOM: #ffffff 1px solid; BORDER-LEFT: #ffffff 1px solid; BORDER-RIGHT: #ffffff 1px solid; BORDER-TOP: #ffffff 1px solid; PADDING-LEFT: 3px } .issuecontent { BACKGROUND-COLOR: #ffffff; BORDER-BOTTOM: #dcdcdc 1px solid; BORDER-TOP: #dcdcdc 1px solid; PADDING-LEFT: 3px } A:link { COLOR: #cc6633; TEXT-DECORATION: underline } A:visited { COLOR: #cc6633; } A:active { COLOR: #cc6633; } A:hover { COLOR: #cc3300; TEXT-DECORATION: underline } H1 { BACKGROUND-COLOR: #003366; BORDER-BOTTOM: #336699 6px solid; COLOR: #ffffff; FONT-SIZE: 130%; FONT-WEIGHT: normal; MARGIN: 0em 0em 0em -20px; PADDING-BOTTOM: 8px; PADDING-LEFT: 30px; PADDING-TOP: 16px } H2 { COLOR: #000000; FONT-SIZE: 80%; FONT-WEIGHT: bold; MARGIN-BOTTOM: 3px; MARGIN-LEFT: 10px; MARGIN-TOP: 20px; PADDING-LEFT: 0px } H3 { COLOR: #000000; FONT-SIZE: 80%; FONT-WEIGHT: bold; MARGIN-BOTTOM: -5px; MARGIN-LEFT: 10px; MARGIN-TOP: 20px } H4 { COLOR: #000000; FONT-SIZE: 70%; FONT-WEIGHT: bold; MARGIN-BOTTOM: 0px; MARGIN-TOP: 15px; PADDING-BOTTOM: 0px } UL { COLOR: #000000; FONT-SIZE: 70%; LIST-STYLE: square; MARGIN-BOTTOM: 0pt; MARGIN-TOP: 0pt } OL { COLOR: #000000; FONT-SIZE: 70%; LIST-STYLE: square; MARGIN-BOTTOM: 0pt; MARGIN-TOP: 0pt } LI { LIST-STYLE: square; MARGIN-LEFT: 0px } .expandable { CURSOR: hand } .expanded { color: black } .collapsed { DISPLAY: none } .foot { BACKGROUND-COLOR: #ffffff; BORDER-BOTTOM: #cecf9c 1px solid; BORDER-TOP: #cecf9c 2px solid } .settings { MARGIN-LEFT: 25PX; } .help { TEXT-ALIGN: right; margin-right: 10px; }
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值