EasyX见缝插针

简介: 这篇博客介绍了如何使用C++和EasyX图形库来实现一个见缝插针的小游戏,包括绘制圆盘和针、实现旋转、发射针、判断游戏输赢以及绘制分数等功能。

话不多说,先上图

EasyX见缝插针

如何实现一个见缝插针游戏??

  1. 如何绘制圆盘与针
  2. 如何实现旋转
  3. 如何按下空格发射针
  4. 如何判定游戏输赢

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);
    }
}

在这里插入图片描述

相关文章
|
2月前
|
编译器 C++
easyx的有些函数报错?
easyx的有些函数报错?
26 0
|
1天前
EasyX之跳跳球
本文介绍了如何使用EasyX库开发一个跳跳球游戏,包括绘制小球和矩形、实现小球的起跳与下落、处理矩形的移动、解决小球二次起跳问题、判断游戏结束条件以及打印分数。
8 0
EasyX之跳跳球
|
1天前
|
C++
EasyX之太空人表盘(2021-6-16)
这篇文章介绍了如何使用C++和EasyX库制作一个太空人表盘程序,包括绘制圆盘、文字、动画、动态时间显示以及音乐播放等功能,并提供了详细的代码实现。
11 0
EasyX之太空人表盘(2021-6-16)
|
5月前
|
存储 编解码 Windows
EasyX图形库学习(三、用easyX控制图形界面中的小球、图片-加载、输出)
EasyX图形库学习(三、用easyX控制图形界面中的小球、图片-加载、输出)
|
5月前
|
关系型数据库 MySQL C++
|
11月前
EasyX图形库实现贪吃蛇游戏
EasyX图形库实现贪吃蛇游戏
127 0
|
11月前
|
C语言 C++ Windows
利用EasyX图形库实现趣味化编程note1
利用EasyX图形库实现趣味化编程note1
58 0
|
12月前
|
机器学习/深度学习 C语言 C++
【c语言】五子棋(EasyX图形库+背景音乐)
【c语言】五子棋(EasyX图形库+背景音乐)
168 0
|
C语言 C++
为什么要学习easyx图形库,他是做什么的?值得吗?
首先,easyx仅支持C语言和C++,这对于学习C语言的新生来说很友好,在熟悉C语言的同时还可以提高写代码的能力,在熟悉C语言以后,就可以尝试写一写小游戏了,比如说扫雷,三子棋,魔塔,贪吃蛇,飞机大战等等,但是当我们写出来运行的时候可以发现,游戏的逻辑写的没有问题,也的确可以玩,但是界面和人物怪兽什么的都很丑,全是符号不好看,同时控制台一闪一闪的,对玩家来说体验感极差,这也就是我们为什么要学习easyx图形库。
227 1