话不多说,先上图
EasyX见缝插针
如何实现一个见缝插针游戏??
- 如何绘制圆盘与针
- 如何实现旋转
- 如何按下空格发射针
- 如何判定游戏输赢
1.绘制圆盘以及一根针
#include<graphics.h>
#include<conio.h>
#define WIDTH 800 //窗口的宽
#define HEIGHT 600 //窗口的高
int main()
{
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(); //关闭窗口
system("pause");
return 0;
}
2.实现针的旋转
实现旋转时,注意此时的二维坐标系的Y轴与我们平时使用的二维坐标系是相反的
实现顺时针旋转使用sin(角度)
实现逆时针旋转使用sin(-角度)
实现A到B为顺时针旋转
则Y轴坐标为圆心Y坐标+Rsin(角度)实现B到A为逆时针旋转
则Y轴坐标为圆心Y坐标+Rsin(-角度)X轴cos(-角度)或者cos(角度)正负均可
双缓冲绘图(批量绘图),解决循环绘图出现的闪屏现象
#include<graphics.h>
#include<conio.h>
#include<math.h>
#define WIDTH 800 //窗口的宽
#define HEIGHT 600 //窗口的高
#define PI 3.1415926
int main()
{
initgraph(WIDTH, HEIGHT);
float lineLength = 160; //针的长度
float xEnd = (WIDTH / 2) + lineLength; //针的末端x坐标
float yEnd = HEIGHT / 2; //针的末端y坐标
float angle = 0; //针的旋转角度
float rotateSpeed = PI / 360; //旋转的速度
setbkcolor(RGB(255, 255, 255)); //设置背景色为白色
cleardevice(); //清屏
while (1)
{
//加双缓冲绘图防止闪屏
BeginBatchDraw();
cleardevice();
angle += rotateSpeed; //增加角度
if (angle > PI * 2) //防止angle无限增加而导致越界
angle -= 2 * PI;
xEnd = lineLength * cos(-angle) + WIDTH / 2;
yEnd = lineLength * sin(angle) + HEIGHT / 2;
//画针
setlinestyle(PS_SOLID, 3); //实线 线宽为3
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);
EndBatchDraw();
}
_getch();
closegraph(); //关闭窗口
system("pause");
return 0;
}
3.实现多个针的绘制以及旋转
- 需要一个针的初始角度数组去保存每一根针的初始角度
- 需要变量保存针的个数
#include<graphics.h>
#include<conio.h>
#include<math.h>
#define WIDTH 800 //窗口的宽
#define HEIGHT 600 //窗口的高
#define PI 3.1415926
#define MAXSIZE 20 //针的最大个数
int main()
{
initgraph(WIDTH, HEIGHT);
float lineLength = 160; //针的长度
float xEnd = (WIDTH / 2) + lineLength; //针的终点X坐标
float yEnd = HEIGHT / 2; //针的终点Y坐标
float angle[MAXSIZE] = { 0 }; //针的旋转角度
float rotateSpeed = PI / 360; //旋转的速度
//设置每一根针的偏转角度
for (int i = 0; i < MAXSIZE; i++)
{
angle[i] = i * (2 * PI / MAXSIZE);
}
setbkcolor(RGB(255, 255, 255)); //设置背景色为白色
cleardevice(); //清屏
while (1)
{
//加双缓冲绘图防止闪屏
BeginBatchDraw();
cleardevice();
//绘制全部的针
for (int i = 0; i < MAXSIZE; i++)
{
angle[i] += rotateSpeed; //增加针的初始角度实现旋转效果
if (angle[i] > PI * 2)
angle[i] -= 2 * PI;
xEnd = lineLength * cos(-angle[i]) + WIDTH / 2;
yEnd = lineLength * sin(angle[i]) + HEIGHT / 2;
//画针
setlinestyle(PS_SOLID, 3); //实线 线宽为3
setlinecolor(RGB(0, 0, 0)); //设置线颜色为黑色
line(WIDTH / 2, HEIGHT / 2, xEnd, yEnd);
}
//绘制圆盘
setlinecolor(HSVtoRGB(0, 0.9, 0.8));
setfillcolor(HSVtoRGB(0, 0.9, 0.8));
fillcircle(WIDTH / 2, HEIGHT / 2, 60);
Sleep(10);
EndBatchDraw();
}
_getch();
closegraph(); //关闭窗口
system("pause");
return 0;
}
4.实现用户插入的那根针,以及用户按键操作
- 通过函数实现各个功能
- 需要使用全局变量以及static全局变量
#include<graphics.h>
#include<conio.h>
#include<math.h>
#define WIDTH 800 //窗口的宽
#define HEIGHT 600 //窗口的高
#define LINELENGTH 160 //针的长度
#define PI 3.1415926
static int lineNum = 0; //初始化针的个数为0根
float angle[180] = { 0 }; //每个针的旋转角度数组
float xEnd = 0; //针的终点X坐标
float yEnd = 0; //针的中断Y坐标
float rotateSpeed = PI / 360; //旋转的速度
//添加针以及初始化当前针的角度
void beamNeedle()
{
angle[lineNum++] = PI; //新针初始角度为PI
//初始化针的末端坐标
xEnd = LINELENGTH * cos(-angle[lineNum - 1]) + WIDTH / 2;
yEnd = LINELENGTH * sin(angle[lineNum - 1]) + HEIGHT / 2;
line(WIDTH / 2, HEIGHT / 2, xEnd, yEnd); //绘制针
}
//针的旋转
void needleRotate()
{
for (int i = 0; i < lineNum; i++)
{
angle[i] += rotateSpeed; //增加角度
if (angle[i] > PI * 2)
angle[i] -= 2 * PI;
xEnd = LINELENGTH * cos(-angle[i]) + WIDTH / 2;
yEnd = LINELENGTH * sin(angle[i]) + HEIGHT / 2;
line(WIDTH / 2, HEIGHT / 2, xEnd, yEnd);
}
}
//用户按键处理
void userKey()
{
if (_kbhit()) //检测是否存在按键
{
char userKey = _getch(); //保存用户输入的按键
if (userKey == ' ') //按键为空格就发射针
{
beamNeedle(); //调用添加针以及初始化当前针的角度
}
}
}
//绘制圆盘
void drawCircle()
{
setlinecolor(HSVtoRGB(0, 0.9, 0.8));
setfillcolor(HSVtoRGB(0, 0.9, 0.8));
fillcircle(WIDTH / 2, HEIGHT / 2, 60);
}
//绘制发射的针(左侧的那根针)
void stoneNeedle()
{
//绘制一根发射的针
setlinecolor(RGB(0, 0, 0));
setlinestyle(PS_SOLID, 3); //实线 线宽为3
line(0, HEIGHT / 2, LINELENGTH, HEIGHT / 2);
}
int main()
{
initgraph(WIDTH, HEIGHT);
setbkcolor(RGB(255, 255, 255)); //设置背景色为白色
cleardevice(); //清屏
while (1)
{
//加双缓冲绘图防止闪屏
BeginBatchDraw();
cleardevice();
stoneNeedle(); //绘制发射的针
needleRotate(); //绘制所有的针
userKey(); //获取用户输入
drawCircle(); //绘制圆盘
Sleep(10);
EndBatchDraw();
}
closegraph(); //关闭窗口
system("pause");
return 0;
}
5.实现游戏结束处理,以及分数的绘制
- 游戏结束的判断
- 只需要遍历圆盘上的针,当它们的角度差<PI/60时,做出重玩游戏还是退出的处理
- 头文件添加
因为使用了求绝对值的函数,因此需要加 math.h
#include<math.h>
void dieGame()
{
for (int i = 0; i < lineNum - 1; i++) //当前针与之前所有针比较
{
if (lineNum == 0)
{
printf("没有针啊!\n");
break;
}
if (fabs(angle[lineNum - 1] - angle[i]) < PI / 60)
{
int isok = MessageBox(GetHWnd(), "Low B you Die! 是否退出?",
"游戏结束", MB_YESNO | MB_ICONWARNING); //显示警告
if (MouseHit()) //监听鼠标消息
{
MOUSEMSG msg = GetMouseMsg();
if (isok == IDYES)
{
exit(666); //退出
}
else //重新玩
{
lineNum = 0; //将针的个数置为0
cleardevice();
}
}
}
}
}
- 分数的绘制
- 加处理安全检查的宏定义
- 由于需要使用sprintf()函数因此需要做上一步安全性检查的处理
#define _CRT_SECURE_NO_WARNINGS
- 添加一个全局变量用于保存分数
int score = 0; //分数
- 实现分数的变化
- 实现分数变化只需要在游戏判断输赢中做处理即可
void dieGame()
{
for (int i = 0; i < lineNum - 1; i++) //当前针与之前所有针比较
{
if (lineNum == 0)
{
printf("没有针啊!\n");
break;
}
if (fabs(angle[lineNum - 1] - angle[i]) < PI / 60)
{
int isok = MessageBox(GetHWnd(), "Low B you Die! 是否退出?", "游戏结束", MB_YESNO | MB_ICONWARNING); //显示警告
if (MouseHit()) //监听鼠标消息
{
MOUSEMSG msg = GetMouseMsg();
if (isok == IDYES)
{
exit(666); //退出
}
else
{
lineNum = 0; //将针的个数置为0
cleardevice();
}
}
}
}
score = lineNum * 10;
}
- 实现分数的绘制
//绘制分数
void printScore()
{
char buffer[20] = "";
sprintf(buffer, "分数: %d", score);
settextcolor(RGB(255, 0, 255));
settextstyle(50, 0, "宋体");
outtextxy(20, 20, buffer);
}
6.增加游戏的趣味性
- 随机针的颜色
只需要不断随机改变绘制针的颜色即可
头文件引入
#include<time.h>
//针的旋转
void needleRotate()
{
//*********************************************************
srand((unsigned int)time(NULL)); //随机数随时间变化
//*********************************************************
for (int i = 0; i < lineNum; i++)
{
angle[i] += rotateSpeed; //增加角度
if (angle[i] > PI * 2)
angle[i] -= 2 * PI;
xEnd = LINELENGTH * cos(-angle[i]) + WIDTH / 2;
yEnd = LINELENGTH * sin(angle[i]) + HEIGHT / 2;
//*********************************************************
setlinecolor(RGB(rand()%256, rand()%256, rand()%256)); //随机改变颜色
//*********************************************************
line(WIDTH / 2, HEIGHT / 2, xEnd, yEnd);
}
}
- 圆盘上有一定针的时候,加快旋转速度
//针的旋转
void needleRotate()
{
srand((unsigned int)time(NULL)); //随机数随时间变化
//*********************************************************
if (lineNum >= 10 && lineNum < 20) //随针变多,速度增加
{
rotateSpeed = 2 * PI / 360; //旋转速度变为原来的两倍
}
else if (lineNum >= 20)
{
rotateSpeed = 3 * PI / 360; //旋转速度变为原来的三倍
}
//*********************************************************
for (int i = 0; i < lineNum; i++)
{
angle[i] += rotateSpeed; //增加角度
if (angle[i] > PI * 2)
angle[i] -= 2 * PI;
xEnd = LINELENGTH * cos(-angle[i]) + WIDTH / 2;
yEnd = LINELENGTH * sin(angle[i]) + HEIGHT / 2;
setlinecolor(RGB(rand()%256, rand()%256, rand()%256));
line(WIDTH / 2, HEIGHT / 2, xEnd, yEnd);
}
}