Juego en lenguaje C (flappy bird), con código fuente y materiales.

Prefacio

Este es el primer programa que escribí, escribiré un artículo para conmemorarlo y también lo daré como referencia para los estudiantes posteriores que recién comienzan a aprender computadoras.

Nota: Para completar este programa, necesita usar los datos <graphics.h> en la biblioteca easy-x. Se recomienda usar software como vc6 o vs2013 o superior que admita la instalación de la biblioteca easy-x. -
La instalación de la biblioteca x es bastante sencilla. Consulte
Instalación de Easy-X o
https://blog.csdn.net/qq_43605229/article/details/97611837

1. Introducción del sistema y efecto final.

Insertar descripción de la imagen aquí
El juego se llama FLIP, una adaptación de Flappy Bird. El juego implementa la función de presionar la barra espaciadora para saltar, cruzar obstáculos sin puntuar y tocar los límites de los obstáculos o los límites superior e inferior de la ventana del juego para finalizar el juego. Entre ellos, la interacción de imágenes, efectos de sonido, escritura/lectura de archivos, entrada de teclado y entrada de mouse mejora la experiencia del juego. Hay varios módulos para elegir en el menú principal del juego. Puedes iniciar/continuar/salir del juego y obtener ayuda e información relacionada con el juego. Puedes pausar y regresar al menú principal en cualquier momento durante el juego o elegir continuar el juego. Una vez finalizado el juego, también puedes optar por volver al menú principal o reiniciar o salir del juego.
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí

2. Descargue el diagrama del módulo de funciones y algunos materiales necesarios.

Diagrama del módulo de funciones
La siguiente imagen muestra las imágenes y los archivos de audio que utilicé al programar ( haga clic aquí para descargar los materiales con puntos ), haga clic aquí para descargar Baidu Cloud Disk y extraiga el código 2333 (admite la descarga de puntos si es posible). Si tienes que usar mis materiales, puedes usar tus imágenes y archivos de audio favoritos. Se recomienda guardar estos materiales en una carpeta para consultarlos fácilmente más adelante.
Insertar descripción de la imagen aquí

3. Código específico (hay una explicación específica en el código)

Lo estoy ejecutando en VC6.0 con la biblioteca easy-x instalada.

1. archivo de encabezado

// #include<bits/stdc++.h>
#include<stdio.h>
#include <conio.h>
#include <time.h>
#include <graphics.h>
#pragma comment(lib,"Winmm.lib")//导入音乐等多媒体

void main();//主函数
void startup();//初始化
void show();//画面显示
void updateWithInput();//与玩家输入有关的画面数据更新
void updateWithoutInput();//与玩家输入无关的画面数据更新
void gameOver();//结束处理

void startMenu();//开始菜单
oid pauseMenu();//暂停菜单
void overMenu();//结束菜单
void readHelpFile();//打开帮助页面
void readAboutFile();//打开关于页面
void readRecordFile();//读档
void writeRecordFile();//存档

#define High 600    //定义游戏界面的高度
#define Width 600   //定义游戏界面的宽度
#define Difficulty 10 //定义游戏难度(用Sleep函数控制快慢)

2. Definición de variable global

//定义全局变量
IMAGE
huaji1,huaji2,img_bk,tiao1,tiao2,pause,help,about,shang1,shang2,xia1,xia2,over1,over2,over3,over4;//各种图片
int huaji_x,huaji_y;//滑稽的坐标
int bar_x,shang_y,xia_y;//障碍的坐标
int score;//得分

//定义游戏状态:若为0初始化后显示主菜单,若为1直接进入游戏
int gameStatus=0;

3. Función de guardar y leer archivos

//读取游戏存档,实现“继续游戏”
void readRecordFile()
{
    FILE *fp;
    fp=fopen("F:\\游戏记录.txt","r");
    fscanf(fp,"%d %d %d %d %d %d",&huaji_x,&huaji_y,&bar_x,&shang_y,&xia_y,&score);//游戏核心数据读出
    fclose(fp);
}
//游戏数据写入存档,保存游戏记录
void writeRecordFile()
{
    FILE *fp;
    fp=fopen("F:\\游戏记录.txt","w+");
    fprintf(fp,"%d %d %d %d %d %d",huaji_x,huaji_y,bar_x,shang_y,xia_y,score);//游戏核心数据写入
    fclose(fp);
}

4. Función del menú Acerca de/Ayuda

//主菜单里的“帮助”界面
void readHelpFile()
{ 
    loadimage(&help,"F:\\帮助.jpg");//打开帮助界面背景图片
    putimage(0,0,&help);
    FlushBatchDraw();
    mciSendString("close bkmusic_1",NULL,0,NULL);//关闭主菜单背景音乐
    mciSendString("open F:\\帮助.mp3 alias help",NULL,0,NULL);//打开帮助界面背景音乐
    mciSendString("play help repeat",NULL,0,NULL);//播放

    FILE *fp;
    char s[32];
    fp=fopen("F:\\帮助.txt","r");//读取“帮助”文档
    int length=25;   //定义行间距
    while(!feof(fp)) // 经过试验发现每行32个字符很适合
    {

      fgets(s,32,fp);
 
      setbkmode(TRANSPARENT);//透明化文字背景
      settextcolor(WHITE);
      settextstyle(20,0,_T("楷体"));
      outtextxy(25,length, s);//将字符串输出到界面对应坐标位置上
      length+=25;
    }
     settextcolor(YELLOW);
     settextstyle(35,0,_T("华文新魏"));
     outtextxy(0,555,"温馨提示:点击屏幕任意位置回主菜单");//在底端输出温馨提示
     Sleep(1000);
     FlushBatchDraw();

     fclose(fp);
     MOUSEMSG m;//用鼠标控制退出帮助界面回到主菜单
     while(1)
     { 
          m=GetMouseMsg();
          if(m.uMsg==WM_LBUTTONDOWN)
         {
          mciSendString("close help",NULL,0,NULL);//左击任意位置回主菜单
          gameStatus=0;
          main();
         }
     }
}

//主菜单里的“关于”界面
void readAboutFile()
{
    loadimage(&about,"F:\\关于.jpg");//打开关于界面背景图片
    putimage(0,0,&about);
    FlushBatchDraw();

    mciSendString("close bkmusic_1",NULL,0,NULL);//关闭主菜单背景音乐
    mciSendString("open F:\\关于.mp3 alias about",NULL,0,NULL);//打开帮助界面背景音乐
    mciSendString("play about repeat",NULL,0,NULL);//播放

    FILE *fp;
    char s[80];
    fp=fopen("F:\\关于.txt","r");
    fgets(s,80,fp);

    setbkmode(TRANSPARENT);//背景透明
    settextcolor(BLACK);
    settextstyle(50,0,_T("华文彩云"));
    outtextxy(250,0,"关于");

    settextstyle(30,0,_T("华文行楷"));//输出关于界面的相关内容(内容较少就不用文本了直接写入)
    outtextxy(240,60,"关于的话");
    outtextxy(250,95,"emmmmmm");
    outtextxy(150,130,"这是个非常好玩的游戏");
    outtextxy(250,165,"嗯 没错");
    outtextxy(240,195,"就是这样");

    settextcolor(RED);
    settextstyle(35,0,_T("华文新魏"));
    outtextxy(0,555,"温馨提示:点击屏幕任意位置回主菜单");
    Sleep(1000);
    FlushBatchDraw();

    fclose(fp);
    MOUSEMSG m;//用鼠标控制退出帮助界面回到主菜单
    while(1)
    {
        m=GetMouseMsg();
        if(m.uMsg==WM_LBUTTONDOWN)
        { 
          mciSendString("close about",NULL,0,NULL);//左击任意位置回主菜单
          gameStatus=0;
          main();
        }
    }
}

5. Función de menú principal/menú de pausa/menú final

//主菜单界面
void startMenu()
{
    mciSendString("close bkmusic_2",NULL,0,NULL);//关闭背景音乐
    loadimage(&pause,"F:\\初始化界面.jpg");//打开初始化界面背景图片
    putimage(0,0,&pause);
    FlushBatchDraw();
    
    setbkmode(TRANSPARENT);//背景透明
    settextcolor(YELLOW);
    settextstyle(50,0,_T("华文行楷"));//在对应位置输出菜单选项内容
    outtextxy(175,150,"1 开始游戏");
    outtextxy(175,250,"2 继续游戏");   
    outtextxy(50,350,"3 什么游戏,我要学习!");
    
   settextcolor(WHITE);//这两个内容用不同字体
    settextstyle(40,0,_T("华文彩云"));
    outtextxy(50,500,"4 帮助");
    outtextxy(425,500,"5 关于");   

    char input;//判断是否有键盘输入
    if(kbhit())
    {
        input=getch();
        if(input=='1')
        gameStatus=1;//进入新游戏
        else if(input=='2')
        {
          readRecordFile();//读取存档,继续游戏
          gameStatus=1;
        }
        else if(input=='3')
        {
            gameStatus=1;//去学习,退出游戏
            exit(0);
        }
        else if(input=='4')
        {
            while(1)//让内容长久显示
            readHelpFile();//读取帮助界面内容
        }
        else if(input=='5')
        {
            while(1)//让内容长久显示
            readAboutFile();//读取关于界面内容
        }
    }
}
//暂停菜单界面
void pauseMenu()
{
   while(1)//让内容长久显示
   {
    loadimage(&pause,"F:\\暂停时的图片.jpg");//打开暂停菜单的背景图片
    putimage(0,0,&pause);
    FlushBatchDraw();

    char input;
    if(kbhit())//判断是否有鼠标输入
    {
        input=getch();
        if(input=='1')//开始新游戏
        {
            gameStatus=1;//不进入主菜单,直接开始新游戏
            main();
        }
        else if(input=='2')//继续游戏
        {  
            startup();//从头开始初始化后读取存档,继续游戏
            readRecordFile();//读取存档
            show();
            Sleep(1400);//预备开始阶段延时
            while(1)//游戏循环执行
          {
            show();//显示画面
            updateWithoutInput();//与玩家输入无关的游戏界面更新
            updateWithInput();//与玩家输入有光的游戏界面更新
          }
        }
        else if(input=='3')//回主菜单
        {
            gameStatus=0;
            startup();
            putimage(0,0,&img_bk);  //打开预备开始阶段背景画面
            FlushBatchDraw();
            show();
            Sleep(1400);//预备开始阶段延时
            break;
        }
        else if(input=='4')//退出游戏
        {
            gameStatus=1;
            exit(0);
        }
    }
   }
}

void overMenu()
{
    while(1) //让结束菜单长久显示
    {
        loadimage(&over4,"F:\\结束时的背景图片.jpg");
        putimage(0,0,&over4);
        setbkmode(TRANSPARENT);//透明化文字背景
        settextcolor(WHITE);
        settextstyle(50,0,_T("华文行楷"));
        outtextxy(Width-500,High-500,"1 不够爽!再来一局!");//输出菜单内容
        outtextxy(Width-500,High-400,"2 我想回主菜单了");   
        outtextxy(Width-500,High-300,"3 我要去学习了!!!"); 

        settextcolor(YELLOW);          
        settextstyle(50,0,_T("华文彩云"));
        outtextxy(Width-425,High-200,"得分: ");    //显示得分
        char s[10];
        sprintf(s,"%d",score);
        outtextxy(Width-275,High-200,s);   
        FlushBatchDraw();

        char input;  //判断是否有键盘输入
        if(kbhit())
        {
           input=getch();
           if(input=='1')//开始新游戏
          {
            gameStatus=1;
            main();
          }
          else if(input=='2')//回主菜单
          {
            gameStatus=0;//状态值为零,初始化后显示主菜单
            startup();

            putimage(0,0,&img_bk);  //打开背景画面
            FlushBatchDraw();
            show();
            Sleep(1400);
            break;
          }
           else if(input=='3')//去学习,退出游戏
           exit(0);
        }
      }
}

6. Función de inicialización

//初始化
void startup()  
{
   score=0;   //初始化分数为0
   initgraph(Width,High); //定义游戏界面大小

   loadimage(&img_bk,"F:\\背景图片.jpg");//打开一系列游戏界面的图片
    loadimage(&huaji1,"F:\\滑稽1.jpg");
    loadimage(&huaji2,"F:\\滑稽2.jpg");
    loadimage(&shang1,"F:\\上障碍1.jpg");
    loadimage(&shang2,"F:\\上障碍2.jpg");
    loadimage(&xia1,"F:\\下障碍1.jpg");
    loadimage(&xia2,"F:\\下障碍2.jpg");

    mciSendString("open F:\\背景音乐1.mp3 alias bkmusic_1",NULL,0,NULL);//打开背景音乐
    mciSendString("play bkmusic_1 repeat",NULL,0,NULL);//播放
    
    srand(time(NULL));  //利用系统时间产生伪随机种子,以为了得到随机位置的障碍

    huaji_x = 24;       //初始化滑稽坐标
    huaji_y = rand() % 150 + 250;
    bar_x = 450;        //初始化障碍的坐标
    shang_y = rand() % 400 - 550;
    while(xia_y - shang_y>730 || xia_y - shang_y<670) //上下障碍随机出现的坐标范围
    {
        shang_y = rand()%400 - 550;
        xia_y = rand()%300 + 150 ;
    }
    while(gameStatus==0)      //状态为0则进入主菜单
    {
        Sleep(200);
        startMenu();//主菜单界面
        FlushBatchDraw();
    }
    mciSendString("close bkmusic_1",NULL,0,NULL);//关闭主菜单背景音乐
    mciSendString("open F:\\背景音乐2.mp3 alias bkmusic_2",NULL,0,NULL);//打开游戏背景音乐
    mciSendString("play bkmusic_2 repeat",NULL,0,NULL);//播放
    mciSendString("close beginmusic",NULL,0,NULL);
    mciSendString("open F:\\开始.mp3 alias beginmusic ",NULL,0,NULL);//播放一次开始时的预备音效
    mciSendString("play beginmusic",NULL,0,NULL);
}


7. Otras funciones auxiliares

//显示画面 
void show()
{
    Sleep(Difficulty);  //整体速度控制即难度
    putimage(0,0,&img_bk);  //打开背景画面
    //采用精灵图与掩码图叠加偶读方法实现抠图,让部分区域透明
    putimage(huaji_x,huaji_y,&huaji1,NOTSRCERASE);  //透明化边界外的图片
    putimage(huaji_x,huaji_y,&huaji2,SRCINVERT);    
    putimage(bar_x,shang_y,&shang1,NOTSRCERASE);//上障碍
    putimage(bar_x,shang_y,&shang2,SRCINVERT);
    putimage(bar_x,xia_y,&xia1,NOTSRCERASE);//下障碍
    putimage(bar_x,xia_y,&xia2,SRCINVERT);
    
    setbkmode(TRANSPARENT);//文字背景透明

    settextcolor(RED);
    settextstyle(50,0,_T("华文行楷"));
    outtextxy(0,0,"得分:");
    settextcolor(RED);  
    settextstyle(50,0,_T("Algerain"));//显示分数
    char s[10];
    sprintf(s,"%d",score);
    outtextxy(125,0,s);
    FlushBatchDraw();
}

//与输入有关的更新
void updateWithInput()  
{
    char input;
    if (kbhit())//判断是否有键盘输入
    {
        input = getch();
        if (input==' ')
        {   
        loadimage(&tiao1,"F:\\我跳1.jpg");
        loadimage(&tiao2,"F:\\我跳2.jpg");
        putimage(huaji_x,huaji_y,&tiao1,NOTSRCERASE);//每跳一下滑稽的表情就变一次
        putimage(huaji_x,huaji_y,&tiao2,SRCINVERT); 
        huaji_y-=30;//点一下空格滑稽就会上跳的高度

        mciSendString("close jpmusic",NULL,0,NULL);
        mciSendString("open F:\\跳.mp3 alias jpmusic ",NULL,0,NULL);//按一下空格播放一次音效
        mciSendString("play jpmusic",NULL,0,NULL);
        }
        else if(input==27)//27为esc 键的ascll码
        {
        writeRecordFile();//存档
        mciSendString("close bkmusic_2",NULL,0,NULL);//关闭游戏时的背景音乐
        pauseMenu();//打开暂停界面
        }
    }
}

//与玩家输入无关的游戏界面更新
void updateWithoutInput()
{
    if (huaji_y<High)   //自动下落
        huaji_y++;
    if (bar_x>-140)        //障碍左移,140为整个障碍的宽度
        bar_x--;
    else                   //障碍重新从右边出现
    {
        bar_x = Width;
        shang_y = rand()%300 - 450;
        while(xia_y - shang_y>730 || xia_y - shang_y<670)
        {
            shang_y =rand()%300 - 450;
            xia_y = rand()%300 + 150 ;
        }
    }
    
    if (((bar_x<50 && bar_x>-100) && (huaji_y+40>xia_y || huaji_y<shang_y+585)) || (huaji_y>550 || huaji_y<0 ))//判断失败
    {
        mciSendString("close bkmusic_2",NULL,0,NULL);//关闭背景音乐
        mciSendString("close overmusic_1",NULL,0,NULL);
        mciSendString("open F:\\尖叫.mp3 alias overmusic_1 ",NULL,0,NULL);//播放触碰危险边缘的尖叫音效
        mciSendString("play overmusic_1",NULL,0,NULL);

      loadimage(&over1,"F:\\我输了1.jpg");//还是用两图叠加的方法实现 失败时表情边缘的透明
        loadimage(&over2,"F:\\我输了2.jpg");
        putimage(huaji_x,huaji_y,&over1,NOTSRCERASE);//输了后滑稽变为 失败时 的表情
        putimage(huaji_x,huaji_y,&over2,SRCINVERT);
        FlushBatchDraw();
        Sleep(2000);//表情出现后停留一段时间

        mciSendString("close overmusic_2",NULL,0,NULL);
        mciSendString("open F:\\失败.mp3 alias overmusic_2 ",NULL,0,NULL);//播放 失败后 的背景音乐
        mciSendString("play overmusic_2",NULL,0,NULL);
        loadimage(&over3,"F:\\不要打扰我学习.jpg");//打开 失败后 的背景图片
        putimage(0,0,&over3);
        FlushBatchDraw();
        Sleep(5000);//图片出现后停留一段时间
         overMenu();
    }
         if
(bar_x==-90) //跳过障碍后加一分
         {
           score++;
           mciSendString("close score",NULL,0,NULL);
           
           mciSendString("open F:\\加一.mp3 alias score",NULL,0,NULL);//打开加分时的音效
           mciSendString("play score",NULL,0,NULL);
        }
}
//游戏结束处理
void gameOver()
{
    EndBatchDraw();//结束绘图
    closegraph();//关闭图片
}

8. Función principal

void main()
{
    startup();              //数据初始化
    show();                 //显示画面(这一画面为准备阶段的画面)
    Sleep(1400);            //游戏准备阶段的延时
    while(1)//游戏循环执行
    {
        show();                           //再次显示画面(游戏开始玩时的界面)
        updateWithoutInput();//与玩家输入无关的游戏界面更新
        updateWithInput();//与玩家输入有光的游戏界面更新
    }
   gameOver();//游戏结束处理
}

4. Algunos principios de procesamiento de imágenes.

El procesamiento de imágenes consiste principalmente en recortar imágenes y realizar los pasos deseados, emmmm, tomemos lo siguiente como ejemplo.
Primero encontramos la imagen que necesitamos, como la siguiente: Quiero que esta imagen no tenga el borde blanco exterior cuando el programa se esté ejecutando, es decir, cortar la expresión en el medio.
Luego necesitamos usar un software de edición de fotografías para hacer la imagen de la izquierda (la hice con PS).
Aquí hay un tutorial de PS: abra Photoshop, abra [Imagen] → [Ajuste] → [Umbral] en la barra de menú de arriba, y luego ajuste el Umbral para obtener la imagen en blanco y negro deseada, como la imagen de abajo a la izquierda (la parte que queremos recortar es blanca y la parte que no queremos es negra)
Insertar descripción de la imagen aquí

loadimage(&tiao1,"F:\\我跳1.jpg"); //导入图片
loadimage(&tiao2,"F:\\我跳2.jpg");
putimage(huaji_x,huaji_y,&tiao1,NOTSRCERASE);  //这里输入一张黑白图
putimage(huaji_x,huaji_y,&tiao2,SRCINVERT);        // 这里输入原图

Después de procesar estas pocas líneas de código, la expresión que necesitamos se dibujará en el programa y no habrá bordes blancos alrededor de los bordes.

5. Código fuente completo

#include<stdio.h>
#include <conio.h>
#include <time.h>
#include <graphics.h>
#pragma comment(lib,"Winmm.lib")//导入音乐等多媒体

void main();//主函数
void startup();//初始化
void show();//画面显示
void updateWithInput();//与玩家输入有关的画面数据更新
void updateWithoutInput();//与玩家输入无关的画面数据更新
void gameOver();//结束处理

void startMenu();//开始菜单
void pauseMenu();//暂停菜单
void overMenu();//结束菜单
void readHelpFile();//打开帮助页面
void readAboutFile();//打开关于页面
void readRecordFile();//读档
void writeRecordFile();//存档

#define High 600    //定义游戏界面的高度
#define Width 600   //定义游戏界面的宽度
#define Difficulty 10 //定义游戏难度(用Sleep函数控制快慢)

//定义全局变量
IMAGE
huaji1,huaji2,img_bk,tiao1,tiao2,pause,help,about,shang1,shang2,xia1,xia2,over1,over2,over3,over4;//各种图片
int huaji_x,huaji_y;//滑稽的坐标
int bar_x,shang_y,xia_y;//障碍的坐标
int score;//得分

//定义游戏状态:若为0初始化后显示主菜单,若为1直接进入游戏
int gameStatus=0;

//读取游戏存档,实现“继续游戏”
void readRecordFile()
{
    FILE *fp;
    fp=fopen("F:\\游戏记录.txt","r");
    fscanf(fp,"%d %d %d %d %d %d",&huaji_x,&huaji_y,&bar_x,&shang_y,&xia_y,&score);//游戏核心数据读出
    fclose(fp);
}
//游戏数据写入存档,保存游戏记录
void writeRecordFile()
{
    FILE *fp;
    fp=fopen("F:\\游戏记录.txt","w+");
    fprintf(fp,"%d %d %d %d %d %d",huaji_x,huaji_y,bar_x,shang_y,xia_y,score);//游戏核心数据写入
    fclose(fp);
}


//主菜单里的“帮助”界面
void readHelpFile()
{ 
    loadimage(&help,"F:\\帮助.jpg");//打开帮助界面背景图片
    putimage(0,0,&help);
    FlushBatchDraw();
    mciSendString("close bkmusic_1",NULL,0,NULL);//关闭主菜单背景音乐
    mciSendString("open F:\\帮助.mp3 alias help",NULL,0,NULL);//打开帮助界面背景音乐
    mciSendString("play help repeat",NULL,0,NULL);//播放

    FILE *fp;
    char s[32];
    fp=fopen("F:\\帮助.txt","r");//读取“帮助”文档
    int length=25;   //定义行间距
    while(!feof(fp)) // 经过试验发现每行32个字符很适合
    {

      fgets(s,32,fp);
 
      setbkmode(TRANSPARENT);//透明化文字背景
      settextcolor(WHITE);
      settextstyle(20,0,_T("楷体"));
      outtextxy(25,length, s);//将字符串输出到界面对应坐标位置上
      length+=25;
    }
     settextcolor(YELLOW);
     settextstyle(35,0,_T("华文新魏"));
     outtextxy(0,555,"温馨提示:点击屏幕任意位置回主菜单");//在底端输出温馨提示
     Sleep(1000);
     FlushBatchDraw();

     fclose(fp);
     MOUSEMSG m;//用鼠标控制退出帮助界面回到主菜单
     while(1)
     { 
          m=GetMouseMsg();
          if(m.uMsg==WM_LBUTTONDOWN)
         {
          mciSendString("close help",NULL,0,NULL);//左击任意位置回主菜单
          gameStatus=0;
          main();
         }
     }
}

//主菜单里的“关于”界面
void readAboutFile()
{
    loadimage(&about,"F:\\关于.jpg");//打开关于界面背景图片
    putimage(0,0,&about);
    FlushBatchDraw();

    mciSendString("close bkmusic_1",NULL,0,NULL);//关闭主菜单背景音乐
    mciSendString("open F:\\关于.mp3 alias about",NULL,0,NULL);//打开帮助界面背景音乐
    mciSendString("play about repeat",NULL,0,NULL);//播放

    FILE *fp;
    char s[80];
    fp=fopen("F:\\关于.txt","r");
    fgets(s,80,fp);

    setbkmode(TRANSPARENT);//背景透明
    settextcolor(BLACK);
    settextstyle(50,0,_T("华文彩云"));
    outtextxy(250,0,"关于");

    settextstyle(30,0,_T("华文行楷"));//输出关于界面的相关内容(内容较少就不用文本了直接写入)
    outtextxy(240,60,"关于的话");
    outtextxy(250,95,"emmmmmm");
    outtextxy(150,130,"这是个非常好玩的游戏");
    outtextxy(250,165,"嗯 没错");
    outtextxy(240,195,"就是这样");

    settextcolor(RED);
    settextstyle(35,0,_T("华文新魏"));
    outtextxy(0,555,"温馨提示:点击屏幕任意位置回主菜单");
    Sleep(1000);
    FlushBatchDraw();

    fclose(fp);
    MOUSEMSG m;//用鼠标控制退出帮助界面回到主菜单
    while(1)
    {
        m=GetMouseMsg();
        if(m.uMsg==WM_LBUTTONDOWN)
        { 
          mciSendString("close about",NULL,0,NULL);//左击任意位置回主菜单
          gameStatus=0;
          main();
        }
    }
}

//主菜单界面
void startMenu()
{
    mciSendString("close bkmusic_2",NULL,0,NULL);//关闭背景音乐
    loadimage(&pause,"F:\\初始化界面.jpg");//打开初始化界面背景图片
    putimage(0,0,&pause);
    FlushBatchDraw();
    
    setbkmode(TRANSPARENT);//背景透明
    settextcolor(YELLOW);
    settextstyle(50,0,_T("华文行楷"));//在对应位置输出菜单选项内容
    outtextxy(175,150,"1 开始游戏");
    outtextxy(175,250,"2 继续游戏");   
    outtextxy(50,350,"3 什么游戏,我要学习!");
    
   settextcolor(WHITE);//这两个内容用不同字体
    settextstyle(40,0,_T("华文彩云"));
    outtextxy(50,500,"4 帮助");
    outtextxy(425,500,"5 关于");   

    char input;//判断是否有键盘输入
    if(kbhit())
    {
        input=getch();
        if(input=='1')
        gameStatus=1;//进入新游戏
        else if(input=='2')
        {
          readRecordFile();//读取存档,继续游戏
          gameStatus=1;
        }
        else if(input=='3')
        {
            gameStatus=1;//去学习,退出游戏
            exit(0);
        }
        else if(input=='4')
        {
            while(1)//让内容长久显示
            readHelpFile();//读取帮助界面内容
        }
        else if(input=='5')
        {
            while(1)//让内容长久显示
            readAboutFile();//读取关于界面内容
        }
    }
}

//暂停菜单界面
void pauseMenu()
{
   while(1)//让内容长久显示
   {
    loadimage(&pause,"F:\\暂停时的图片.jpg");//打开暂停菜单的背景图片
    putimage(0,0,&pause);
    FlushBatchDraw();

    char input;
    if(kbhit())//判断是否有鼠标输入
    {
        input=getch();
        if(input=='1')//开始新游戏
        {
            gameStatus=1;//不进入主菜单,直接开始新游戏
            main();
        }
        else if(input=='2')//继续游戏
        {  
            startup();//从头开始初始化后读取存档,继续游戏
            readRecordFile();//读取存档
            show();
            Sleep(1400);//预备开始阶段延时
            while(1)//游戏循环执行
          {
            show();//显示画面
            updateWithoutInput();//与玩家输入无关的游戏界面更新
            updateWithInput();//与玩家输入有光的游戏界面更新
          }
        }
        else if(input=='3')//回主菜单
        {
            gameStatus=0;
            startup();
            putimage(0,0,&img_bk);  //打开预备开始阶段背景画面
            FlushBatchDraw();
            show();
            Sleep(1400);//预备开始阶段延时
            break;
        }
        else if(input=='4')//退出游戏
        {
            gameStatus=1;
            exit(0);
        }
    }
   }
}

 

void overMenu()
{
    while(1) //让结束菜单长久显示
    {
        loadimage(&over4,"F:\\结束时的背景图片.jpg");
        putimage(0,0,&over4);
        setbkmode(TRANSPARENT);//透明化文字背景
        settextcolor(WHITE);
        settextstyle(50,0,_T("华文行楷"));
        outtextxy(Width-500,High-500,"1 不够爽!再来一局!");//输出菜单内容
        outtextxy(Width-500,High-400,"2 我想回主菜单了");   
        outtextxy(Width-500,High-300,"3 我要去学习了!!!"); 

        settextcolor(YELLOW);          
        settextstyle(50,0,_T("华文彩云"));
        outtextxy(Width-425,High-200,"得分: ");    //显示得分
        char s[10];
        sprintf(s,"%d",score);
        outtextxy(Width-275,High-200,s);   
        FlushBatchDraw();

        char input;  //判断是否有键盘输入
        if(kbhit())
        {
           input=getch();
           if(input=='1')//开始新游戏
          {
            gameStatus=1;
            main();
          }
          else if(input=='2')//回主菜单
          {
            gameStatus=0;//状态值为零,初始化后显示主菜单
            startup();

            putimage(0,0,&img_bk);  //打开背景画面
            FlushBatchDraw();
            show();
            Sleep(1400);
            break;
          }
           else if(input=='3')//去学习,退出游戏
           exit(0);
        }
      }
}

//初始化
void startup()  
{
   score=0;   //初始化分数为0
   initgraph(Width,High); //定义游戏界面大小

   loadimage(&img_bk,"F:\\背景图片.jpg");//打开一系列游戏界面的图片
    loadimage(&huaji1,"F:\\滑稽1.jpg");
    loadimage(&huaji2,"F:\\滑稽2.jpg");
    loadimage(&shang1,"F:\\上障碍1.jpg");
    loadimage(&shang2,"F:\\上障碍2.jpg");
    loadimage(&xia1,"F:\\下障碍1.jpg");
    loadimage(&xia2,"F:\\下障碍2.jpg");

    mciSendString("open F:\\背景音乐1.mp3 alias bkmusic_1",NULL,0,NULL);//打开背景音乐
    mciSendString("play bkmusic_1 repeat",NULL,0,NULL);//播放
    
    srand(time(NULL));  //利用系统时间产生伪随机种子,以为了得到随机位置的障碍

    huaji_x = 24;       //初始化滑稽坐标
    huaji_y = rand() % 150 + 250;
    bar_x = 450;        //初始化障碍的坐标
    shang_y = rand() % 400 - 550;
    while(xia_y - shang_y>730 || xia_y - shang_y<670) //上下障碍随机出现的坐标范围
    {
        shang_y = rand()%400 - 550;
        xia_y = rand()%300 + 150 ;
    }
    while(gameStatus==0)      //状态为0则进入主菜单
    {
        Sleep(200);
        startMenu();//主菜单界面
        FlushBatchDraw();
    }
    mciSendString("close bkmusic_1",NULL,0,NULL);//关闭主菜单背景音乐
    mciSendString("open F:\\背景音乐2.mp3 alias bkmusic_2",NULL,0,NULL);//打开游戏背景音乐
    mciSendString("play bkmusic_2 repeat",NULL,0,NULL);//播放
    mciSendString("close beginmusic",NULL,0,NULL);
    mciSendString("open F:\\开始.mp3 alias beginmusic ",NULL,0,NULL);//播放一次开始时的预备音效
    mciSendString("play beginmusic",NULL,0,NULL);
}

//显示画面 
void show()
{
    Sleep(Difficulty);  //整体速度控制即难度
    putimage(0,0,&img_bk);  //打开背景画面
    //采用精灵图与掩码图叠加偶读方法实现抠图,让部分区域透明
    putimage(huaji_x,huaji_y,&huaji1,NOTSRCERASE);  //透明化边界外的图片
    putimage(huaji_x,huaji_y,&huaji2,SRCINVERT);    
    putimage(bar_x,shang_y,&shang1,NOTSRCERASE);//上障碍
    putimage(bar_x,shang_y,&shang2,SRCINVERT);
    putimage(bar_x,xia_y,&xia1,NOTSRCERASE);//下障碍
    putimage(bar_x,xia_y,&xia2,SRCINVERT);
    
    setbkmode(TRANSPARENT);//文字背景透明

    settextcolor(RED);
    settextstyle(50,0,_T("华文行楷"));
    outtextxy(0,0,"得分:");
    settextcolor(RED);  
    settextstyle(50,0,_T("Algerain"));//显示分数
    char s[10];
    sprintf(s,"%d",score);
    outtextxy(125,0,s);
    FlushBatchDraw();
}

//与输入有关的更新
void updateWithInput()  
{
    char input;
    if (kbhit())//判断是否有键盘输入
    {
        input = getch();
        if (input==' ')
        {   
        loadimage(&tiao1,"F:\\我跳1.jpg");
        loadimage(&tiao2,"F:\\我跳2.jpg");
        putimage(huaji_x,huaji_y,&tiao1,NOTSRCERASE);//每跳一下滑稽的表情就变一次
        putimage(huaji_x,huaji_y,&tiao2,SRCINVERT); 
        huaji_y-=30;//点一下空格滑稽就会上跳的高度

        mciSendString("close jpmusic",NULL,0,NULL);
        mciSendString("open F:\\跳.mp3 alias jpmusic ",NULL,0,NULL);//按一下空格播放一次音效
        mciSendString("play jpmusic",NULL,0,NULL);
        }
        else if(input==27)//27为esc 键的ascll码
        {
        writeRecordFile();//存档
        mciSendString("close bkmusic_2",NULL,0,NULL);//关闭游戏时的背景音乐
        pauseMenu();//打开暂停界面
        }
    }
}

//与玩家输入无关的游戏界面更新
void updateWithoutInput()
{
    if (huaji_y<High)   //自动下落
        huaji_y++;
    if (bar_x>-140)        //障碍左移,140为整个障碍的宽度
        bar_x--;
    else                   //障碍重新从右边出现
    {
        bar_x = Width;
        shang_y = rand()%300 - 450;
        while(xia_y - shang_y>730 || xia_y - shang_y<670)
        {
            shang_y =rand()%300 - 450;
            xia_y = rand()%300 + 150 ;
        }
    }
    
    if (((bar_x<50 && bar_x>-100) && (huaji_y+40>xia_y || huaji_y<shang_y+585)) || (huaji_y>550 || huaji_y<0 ))//判断失败
    {
        mciSendString("close bkmusic_2",NULL,0,NULL);//关闭背景音乐
        mciSendString("close overmusic_1",NULL,0,NULL);
        mciSendString("open F:\\尖叫.mp3 alias overmusic_1 ",NULL,0,NULL);//播放触碰危险边缘的尖叫音效
        mciSendString("play overmusic_1",NULL,0,NULL);

      loadimage(&over1,"F:\\我输了1.jpg");//还是用两图叠加的方法实现 失败时表情边缘的透明
        loadimage(&over2,"F:\\我输了2.jpg");
        putimage(huaji_x,huaji_y,&over1,NOTSRCERASE);//输了后滑稽变为 失败时 的表情
        putimage(huaji_x,huaji_y,&over2,SRCINVERT);
        FlushBatchDraw();
        Sleep(2000);//表情出现后停留一段时间

        mciSendString("close overmusic_2",NULL,0,NULL);
        mciSendString("open F:\\失败.mp3 alias overmusic_2 ",NULL,0,NULL);//播放 失败后 的背景音乐
        mciSendString("play overmusic_2",NULL,0,NULL);
        loadimage(&over3,"F:\\不要打扰我学习.jpg");//打开 失败后 的背景图片
        putimage(0,0,&over3);
        FlushBatchDraw();
        Sleep(5000);//图片出现后停留一段时间
         overMenu();
    }
         if
(bar_x==-90) //跳过障碍后加一分
         {
           score++;
           mciSendString("close score",NULL,0,NULL);
           
           mciSendString("open F:\\加一.mp3 alias score",NULL,0,NULL);//打开加分时的音效
           mciSendString("play score",NULL,0,NULL);
        }
}
//游戏结束处理
void gameOver()
{
    EndBatchDraw();//结束绘图
    closegraph();//关闭图片
}

void main()
{
    startup();              //数据初始化
    show();                 //显示画面(这一画面为准备阶段的画面)
    Sleep(1400);            //游戏准备阶段的延时
    while(1)//游戏循环执行
    {
        show();                           //再次显示画面(游戏开始玩时的界面)
        updateWithoutInput();//与玩家输入无关的游戏界面更新
        updateWithInput();//与玩家输入有光的游戏界面更新
    }
   gameOver();//游戏结束处理
}

Supongo que te gusta

Origin blog.csdn.net/qq_43605229/article/details/88948520
Recomendado
Clasificación