美文网首页
网易C++--书籍练习案例03--利用文件读写游戏存档

网易C++--书籍练习案例03--利用文件读写游戏存档

作者: heiqimingren | 来源:发表于2020-11-09 22:51 被阅读0次

第一版本:多画面显示

//#include <tchar.h>        //在程序中使用 #include <tchar.h> 添加对 TCHAR 的支持。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>    //清屏命令在这里。
#include <windows.h> //延时10毫秒-sleep,gotoxy函数
#include <iostream>
#include <conio.h>       //getch()----不用按回车,就可以输入字符。    
#include <graphics.h>      //EasyX库,所使用的!
#include <math.h>         //三角函数
#include <algorithm>      //max(),min(),和abs(),sort函数排序方法,https://blog.csdn.net/BIGKALA/article/details/81624691,这是方法适用的地址
#include <time.h>


using namespace std;


//引用 windows multimedia api
#pragma comment(lib,"Winmm.lib " )

#define High 870
#define Width 591         //游戏画面尺寸

IMAGE img_bk;       //背景图片
float position_x, position_y;          //飞机的位置
float bullet_x, bullet_y;              //子弹的位置
float enemy_x, enemy_y;                //敌机的位置
IMAGE img_planeNormal1, img_planeNormal2;      //正常飞机图片
IMAGE img_planeExplode1, img_planeExplode2;        //爆炸飞机图片
IMAGE img_bullet1, img_bullet2;                     //子弹图片
IMAGE img_enemyPlane1, img_enemyPlane2;     //敌机图片
int isExpolde = 0;                       //飞机是否爆炸
int score = 0;                            //得分
int gameStatus = 0;                  //游戏状态,0为初始菜单界面,1为正常游戏,2为结束游戏状态,3位游戏暂停

void startMenu();                        //初始菜单界面
void pauseMenu();                       //游戏暂停后的菜单界面,一般按下esc键后启动该界面
void startup();                         //数据的初始化
void show();                            //显示画面
void updateWithoutInput();              //与用户输入无关的更新
void updateWithInpute();                //与用户输入有关的更新
void gameover();                       //游戏结束,进入后续处理

void startMenu()      //初始菜单界面
{
    putimage(0, 0, &img_bk);          //显示背景
    setbkmode(TRANSPARENT);
    settextcolor(BLACK);
    settextstyle(50, 0, _T("黑体"));
    outtextxy(Width*0.3, High*0.3, _T("1,进入游戏 "));
    outtextxy(Width*0.3, High*0.4, _T("2,退出 "));
    FlushBatchDraw();
    Sleep(2);

    char input;
    if (kbhit())       //判断用户是否有输入?
    {
        input = getch();     //根据用户的不同输入来移动,不必输入回车
        if (input == '1')
        {
            gameStatus = 1;
        }
        else if (input == '2')
        {
            gameStatus = 2;
            exit(0);
        }
    }
}

void pauseMenu()
{
    putimage(0, 0, &img_bk);
    setbkmode(TRANSPARENT);
    settextcolor(BLACK);
    settextstyle(50, 0, _T("黑体"));
    outtextxy(Width*0.3, High*0.3, _T("1,继续游戏 "));
    outtextxy(Width*0.3, High*0.4, _T("2,退出 "));
    FlushBatchDraw();
    Sleep(2);

    char input;
    if (kbhit())       //判断用户是否有输入?
    {
        input = getch();     //根据用户的不同输入来移动,不必输入回车
        if (input == '1')
        {
            gameStatus = 1;
        }
        else if (input == '2')
        {
            gameStatus = 2;
            exit(0);
        }
    }

}

void startup()
{
    mciSendString(_T("open .\\game_music.mp3 alias bkmusic"), NULL, 0, NULL);   //打开背景音乐
    mciSendString(_T("play bkmusic repeat"), NULL, 0, NULL);                   //循环播放

    initgraph(Width, High);
    //获取窗口句柄
    HWND hwnd = GetHWnd();
    //设置窗口标题文字
    SetWindowText(hwnd, _T("飞机大战V1.0 "));

    loadimage(&img_bk, _T(".\\background.jpg"));
    /*loadimage(&img_planeNormal1, _T(".\\planeNormal1.jpg"));
    loadimage(&img_planeNormal2, _T(".\\planeNormal2.jpg"));
    loadimage(&img_bullet1, _T(".\\bullet1.jpg"));
    loadimage(&img_bullet2, _T(".\\bullet2.jpg"));
    loadimage(&img_enemyPlane1, _T(".\\enemyPlane1.jpg"));
    loadimage(&img_enemyPlane2, _T(".\\enemyPlane2.jpg"));
    loadimage(&img_planeExplode1, _T(".\\planeExplode1.jpg"));
    loadimage(&img_planeExplode2, _T(".\\planeExplode2.jpg"));
    */
    position_x = Width*0.5;
    position_y = High*0.7;
    bullet_x = position_x;
    bullet_y = -85;
    enemy_x = Width*0.5;
    enemy_y = 10;

    BeginBatchDraw();

    while (gameStatus == 1)
    {
        startMenu();           //初始菜单界面
    }

}

void show()
{
    while (gameStatus == 3)
    {
        pauseMenu();        //游戏暂停后的菜单界面,一般按ESC键后启动该界面
    }
    putimage(0, 0, &img_bk);  //显示背景
    if (isExpolde == 0)
    {
        putimage(position_x - 50, position_y - 60, &img_planeNormal1, NOTSRCERASE);         //显示正常飞机
        putimage(position_x - 50, position_y - 60, &img_planeNormal2, SRCINVERT);

        putimage(bullet_x - 7, bullet_y, &img_bullet1, NOTSRCERASE);      //显示子弹
        putimage(bullet_x - 7, bullet_y, &img_bullet2, SRCINVERT);

        putimage(enemy_x, enemy_y, &img_enemyPlane1, NOTSRCERASE);     //显示敌机
        putimage(enemy_x, enemy_y, &img_enemyPlane2, SRCINVERT);
    }
    else
    {
        putimage(position_x - 50, position_y - 60, &img_planeExplode1, NOTSRCERASE);   //显示爆炸飞机
        putimage(position_x - 50, position_y - 60, &img_planeExplode2, SRCINVERT);

    }

    settextcolor(RED);
    settextstyle(20, 0, _T("黑体"));
    outtextxy(Width*0.48, High*0.95, _T("得分: "));
    //TCHAR s[5];      //这里竟然出现了一个bug,字符串宽度问题   把char 改成TCHAR即可  https://www.cnblogs.com/zhougeng/p/11827675.html
    TCHAR s[5];
    scanf("%d", &s);
    outtextxy(Width*0.55, High*0.95, s);

    FlushBatchDraw();
    Sleep(2);
}

void updateWithoutInput()
{
    if (isExpolde == 0)
    {
        if (bullet_y>-25 )
        {
            bullet_y = bullet_y - 2;
        }
        if (enemy_y<High-25 )
        {
            enemy_y = enemy_y + 0.5;
        }
        else
        {
            enemy_y = 10;
        }

        if (abs(bullet_x-enemy_x )+abs(bullet_y-enemy_y )<80   )
        {
            enemy_x = rand() % Width;
            enemy_y = -40;
            bullet_y = -85;

            mciSendString(_T("stop fgmusic"), NULL, 0, NULL);       //先把前面一次的音乐停止
            mciSendString(_T("close fgmusic"), NULL, 0, NULL);     //先把前面一次的音乐关闭
            mciSendString(_T("open .\\gotEnemy.mp3 alias gemusic"), NULL, 0, NULL);        //打开跳动音乐
            mciSendString(_T("play gemusic"), NULL, 0, NULL);          //仅仅播放一次
            score++;
        }

        if (score>0 && score%5==0 &&score%2!=0 )
        {
            mciSendString(_T("stop 5music"), NULL, 0, NULL);       //先把前面一次的音乐停止
            mciSendString(_T("close 5music"), NULL, 0, NULL);     //先把前面一次的音乐关闭
            mciSendString(_T("open .\\5.mp3 alias 5music"), NULL, 0, NULL);        //打开跳动音乐
            mciSendString(_T("play 5music"), NULL, 0, NULL);          //仅仅播放一次
        }

        if (score%10==0)
        {
            mciSendString(_T("stop 10music"), NULL, 0, NULL);       //先把前面一次的音乐停止
            mciSendString(_T("close 10music"), NULL, 0, NULL);     //先把前面一次的音乐关闭
            mciSendString(_T("open .\\10.mp3 alias 10music"), NULL, 0, NULL);        //打开跳动音乐
            mciSendString(_T("play 10music"), NULL, 0, NULL);          //仅仅播放一次
        }
    }

    if (abs(position_x-enemy_x )+abs(position_y-enemy_y )<150  )      //敌机击中我机
    {
        isExpolde = 1;
        mciSendString(_T("stop exmusic"), NULL, 0, NULL);       //先把前面一次的音乐停止
        mciSendString(_T("close exmusic"), NULL, 0, NULL);     //先把前面一次的音乐关闭
        mciSendString(_T("open .\\explode.mp3 alias 10music"), NULL, 0, NULL);        //打开跳动音乐
        mciSendString(_T("play exmusic"), NULL, 0, NULL);          //仅仅播放一次

    }


    

}
void updateWithInpute()
{
    MOUSEMSG m;
    while (MouseHit())
    {
        m = GetMouseMsg();                    //定义鼠标消息
        if (m.uMsg==WM_MOUSEMOVE )            //这个函数用于检测当前是否有鼠标消息
        {
            //飞机的位置等于鼠标所在的位置
            position_x = m.x;
            position_y = m.y;
        }
        else if (m.uMsg==WM_LBUTTONDOWN )
        {
            //按下鼠标左键发射子弹
            bullet_x = position_x;
            bullet_y = position_y - 85;

            mciSendString(_T("stop fgmusic"), NULL, 0, NULL);       //先把前面一次的音乐停止
            mciSendString(_T("close fgmusic"), NULL, 0, NULL);     //先把前面一次的音乐关闭
            mciSendString(_T("open .\\f_gun.mp3 alias fgmusic"), NULL, 0, NULL);        //打开跳动音乐
            mciSendString(_T("play fgmusic"), NULL, 0, NULL);          //仅仅播放一次
        }
    }
    char input;
    if (kbhit())
    {
        input = getch();
        if (input == 27)
        {
            gameStatus = 3;
        }
    }

}

void gameover()
{
    EndBatchDraw();
    getch();
    closegraph();
}
int main()
{
    startup();             //数据的初始化
    while (1)               //游戏循环执行
    {
        show();             //显示画面
        updateWithoutInput();
        updateWithInpute();
    }
    gameover();            //游戏结束,进行后续处理
    return 0;
}

我去调试,结果提示我这个错误


image.png

1>源.obj : error LNK2019: 无法解析的外部符号 "void __cdecl updateWithInpute(void)" (?updateWithInpute@@YAXXZ),该符号在函数 _main 中被引用
1>G:\360data\重要数据\我的文档\Visual Studio 2013\Projects\C++文件01\Debug\C++文件01.exe : fatal error LNK1120: 1 个无法解析的外部命令

解决办法很简单,有一个updatewithinput函数,我忘记写了。完善之后就搞定了

但是我遇到了新的问题!
加载图片,失败,加载不进去。

image.png
=========
找了很多方法,都不行!
https://tieba.baidu.com/p/5138402911
https://tieba.baidu.com/p/5053729526

最后还是解决了,原来是代码游戏状态 gamestatus的问题

//#include <tchar.h>        //在程序中使用 #include <tchar.h> 添加对 TCHAR 的支持。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>    //清屏命令在这里。
#include <windows.h> //延时10毫秒-sleep,gotoxy函数
#include <iostream>
#include <conio.h>       //getch()----不用按回车,就可以输入字符。    
#include <graphics.h>      //EasyX库,所使用的!
#include <math.h>         //三角函数
#include <algorithm>      //max(),min(),和abs(),sort函数排序方法,https://blog.csdn.net/BIGKALA/article/details/81624691,这是方法适用的地址
#include <time.h>


using namespace std;


//引用 windows multimedia api
#pragma comment(lib,"Winmm.lib " )

#define High 870
#define Width 591         //游戏画面尺寸

IMAGE img_bk;       //背景图片
float position_x, position_y;          //飞机的位置
float bullet_x, bullet_y;              //子弹的位置
float enemy_x, enemy_y;                //敌机的位置
IMAGE img_planeNormal1, img_planeNormal2;      //正常飞机图片
IMAGE img_planeExplode1, img_planeExplode2;        //爆炸飞机图片
IMAGE img_bullet1, img_bullet2;                     //子弹图片
IMAGE img_enemyPlane1, img_enemyPlane2;     //敌机图片
int isExpolde = 0;                       //飞机是否爆炸
int score = 0;                            //得分
int gameStatus = 0;                  //游戏状态,0为初始菜单界面,1为正常游戏,2为结束游戏状态,3位游戏暂停

void startMenu();                        //初始菜单界面
void pauseMenu();                       //游戏暂停后的菜单界面,一般按下esc键后启动该界面
void startup();                         //数据的初始化
void show();                            //显示画面
void updateWithoutInput();              //与用户输入无关的更新
void updateWithInpute();                //与用户输入有关的更新
void gameover();                       //游戏结束,进入后续处理

void startMenu()      //初始菜单界面
{
    putimage(0, 0, &img_bk);          //显示背景
    setbkmode(TRANSPARENT);
    settextcolor(BLACK);
    settextstyle(50, 0, _T("黑体"));
    outtextxy(Width*0.3, High*0.3, _T("1,进入游戏 "));
    outtextxy(Width*0.3, High*0.4, _T("2,退出 "));
    FlushBatchDraw();
    Sleep(2);

    char input;
    if (kbhit())       //判断用户是否有输入?
    {
        input = getch();     //根据用户的不同输入来移动,不必输入回车
        if (input == '1')
        {
            gameStatus = 1;
        }
        else if (input == '2')
        {
            gameStatus = 2;
            exit(0);
        }
    }
}

void pauseMenu()
{
    putimage(0, 0, &img_bk);
    setbkmode(TRANSPARENT);
    settextcolor(BLACK);
    settextstyle(50, 0, _T("黑体"));
    outtextxy(Width*0.3, High*0.3, _T("1,继续游戏 "));
    outtextxy(Width*0.3, High*0.4, _T("2,退出 "));
    FlushBatchDraw();
    Sleep(2);

    char input;
    if (kbhit())       //判断用户是否有输入?
    {
        input = getch();     //根据用户的不同输入来移动,不必输入回车
        if (input == '1')
        {
            gameStatus = 1;
        }
        else if (input == '2')
        {
            gameStatus = 2;
            exit(0);
        }
    }

}

void startup()
{
    mciSendString(_T("open .\\game_music.mp3 alias bkmusic"), NULL, 0, NULL);   //打开背景音乐
    mciSendString(_T("play bkmusic repeat"), NULL, 0, NULL);                   //循环播放

    initgraph(Width, High);
    //获取窗口句柄
    HWND hwnd = GetHWnd();
    //设置窗口标题文字

    SetWindowText(hwnd, _T("飞机大战V1.0 "));
    
    //loadimage,就是将这些图片载入到内存中。
    loadimage(&img_bk, _T(".\\background.jpg"));
    loadimage(&img_planeNormal1, _T(".\\planeNormal1.jpg"));
    loadimage(&img_planeNormal2, _T(".\\planeNormal2.jpg"));
    loadimage(&img_bullet1, _T(".\\bullet1.jpg"));
    loadimage(&img_bullet2, _T(".\\bullet2.jpg"));
    loadimage(&img_enemyPlane1, _T(".\\enemyPlane1.jpg"));
    loadimage(&img_enemyPlane2, _T(".\\enemyPlane2.jpg"));
    loadimage(&img_planeExplode1, _T(".\\planeExplode1.jpg"));
    loadimage(&img_planeExplode2, _T(".\\planeExplode2.jpg"));
    
    position_x = Width*0.5;
    position_y = High*0.7;
    bullet_x = position_x;
    bullet_y = -85;
    enemy_x = Width*0.5;
    enemy_y = 10;

    BeginBatchDraw();

    while (gameStatus == 0)       //游戏状态为0,初始菜单界面
    {
        startMenu();           //初始菜单界面
    }
    cout << "跳出了初始化。。。。。" << endl;
}

void show()
{
    
    while (gameStatus == 3)
    {
        pauseMenu();        //游戏暂停后的菜单界面,一般按ESC键后启动该界面
    }
    putimage(0, 0, &img_bk);  //显示背景
    if (isExpolde == 0)     //0代表没有爆炸
    {
        putimage(position_x - 50, position_y - 60, &img_planeNormal1, NOTSRCERASE);         //显示正常飞机
        putimage(position_x - 50, position_y - 60, &img_planeNormal2, SRCINVERT);

        putimage(bullet_x - 7, bullet_y, &img_bullet1, NOTSRCERASE);      //显示子弹
        putimage(bullet_x - 7, bullet_y, &img_bullet2, SRCINVERT);

        putimage(enemy_x, enemy_y, &img_enemyPlane1, NOTSRCERASE);     //显示敌机
        putimage(enemy_x, enemy_y, &img_enemyPlane2, SRCINVERT);
    }
    else
    {
        putimage(position_x - 50, position_y - 60, &img_planeExplode1, NOTSRCERASE);   //显示爆炸飞机
        putimage(position_x - 50, position_y - 60, &img_planeExplode2, SRCINVERT);

    }

    settextcolor(RED);
    settextstyle(20, 0, _T("黑体"));
    outtextxy(Width*0.48, High*0.95, _T("得分: "));
    //TCHAR s[5];      //这里竟然出现了一个bug,字符串宽度问题   把char 改成TCHAR即可  https://www.cnblogs.com/zhougeng/p/11827675.html
    TCHAR s[5];
    scanf("%d", &s);
    outtextxy(Width*0.55, High*0.95, s);

    FlushBatchDraw();
    Sleep(2);
}

void updateWithoutInput()
{
    if (isExpolde == 0)
    {
        if (bullet_y>-25 )
        {
            bullet_y = bullet_y - 2;
        }
        if (enemy_y<High-25 )
        {
            enemy_y = enemy_y + 0.5;
        }
        else
        {
            enemy_y = 10;
        }

        if (abs(bullet_x-enemy_x )+abs(bullet_y-enemy_y )<80   )
        {
            enemy_x = rand() % Width;
            enemy_y = -40;
            bullet_y = -85;

            mciSendString(_T("stop fgmusic"), NULL, 0, NULL);       //先把前面一次的音乐停止
            mciSendString(_T("close fgmusic"), NULL, 0, NULL);     //先把前面一次的音乐关闭
            mciSendString(_T("open .\\gotEnemy.mp3 alias gemusic"), NULL, 0, NULL);        //打开跳动音乐
            mciSendString(_T("play gemusic"), NULL, 0, NULL);          //仅仅播放一次
            score++;
        }

        if (score>0 && score%5==0 &&score%2!=0 )
        {
            mciSendString(_T("stop 5music"), NULL, 0, NULL);       //先把前面一次的音乐停止
            mciSendString(_T("close 5music"), NULL, 0, NULL);     //先把前面一次的音乐关闭
            mciSendString(_T("open .\\5.mp3 alias 5music"), NULL, 0, NULL);        //打开跳动音乐
            mciSendString(_T("play 5music"), NULL, 0, NULL);          //仅仅播放一次
        }

        if (score%10==0)
        {
            mciSendString(_T("stop 10music"), NULL, 0, NULL);       //先把前面一次的音乐停止
            mciSendString(_T("close 10music"), NULL, 0, NULL);     //先把前面一次的音乐关闭
            mciSendString(_T("open .\\10.mp3 alias 10music"), NULL, 0, NULL);        //打开跳动音乐
            mciSendString(_T("play 10music"), NULL, 0, NULL);          //仅仅播放一次
        }
    }

    if (abs(position_x-enemy_x )+abs(position_y-enemy_y )<150  )      //敌机击中我机
    {
        isExpolde = 1;
        mciSendString(_T("stop exmusic"), NULL, 0, NULL);       //先把前面一次的音乐停止
        mciSendString(_T("close exmusic"), NULL, 0, NULL);     //先把前面一次的音乐关闭
        mciSendString(_T("open .\\explode.mp3 alias 10music"), NULL, 0, NULL);        //打开跳动音乐
        mciSendString(_T("play exmusic"), NULL, 0, NULL);          //仅仅播放一次

    }


    

}
void updateWithInpute()
{
    MOUSEMSG m;
    while (MouseHit())
    {
        m = GetMouseMsg();                    //定义鼠标消息
        if (m.uMsg==WM_MOUSEMOVE )            //这个函数用于检测当前是否有鼠标消息
        {
            //飞机的位置等于鼠标所在的位置
            position_x = m.x;
            position_y = m.y;
        }
        else if (m.uMsg==WM_LBUTTONDOWN )
        {
            //按下鼠标左键发射子弹
            bullet_x = position_x;
            bullet_y = position_y - 85;

            mciSendString(_T("stop fgmusic"), NULL, 0, NULL);       //先把前面一次的音乐停止
            mciSendString(_T("close fgmusic"), NULL, 0, NULL);     //先把前面一次的音乐关闭
            mciSendString(_T("open .\\f_gun.mp3 alias fgmusic"), NULL, 0, NULL);        //打开跳动音乐
            mciSendString(_T("play fgmusic"), NULL, 0, NULL);          //仅仅播放一次
        }
    }
    char input;
    if (kbhit())
    {
        input = getch();
        if (input == 27)
        {
            gameStatus = 3;
        }
    }

}

void gameover()
{
    EndBatchDraw();
    getch();
    closegraph();
}
int main()
{
    startup();             //数据的初始化
    while (true)
    {
        show();             //显示画面,背景图片之类的,都在这里显示。。
        updateWithoutInput();
        updateWithInpute();
    }            //游戏循环执行
    
    gameover();            //游戏结束,进行后续处理
    return 0;
}

但是遇到了新的问题,按键数字1或者2,都不好使


image.png

也解决了。
下面是我测试成功之后,可以正常运行的版本

//#include <tchar.h>        //在程序中使用 #include <tchar.h> 添加对 TCHAR 的支持。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>    //清屏命令在这里。
#include <windows.h> //延时10毫秒-sleep,gotoxy函数
#include <iostream>
#include <conio.h>       //getch()----不用按回车,就可以输入字符。    
#include <graphics.h>      //EasyX库,所使用的!
#include <math.h>         //三角函数
#include <algorithm>      //max(),min(),和abs(),sort函数排序方法,https://blog.csdn.net/BIGKALA/article/details/81624691,这是方法适用的地址
#include <time.h>


using namespace std;


//引用 windows multimedia api
#pragma comment(lib,"Winmm.lib " )

#define High 870
#define Width 591         //游戏画面尺寸

IMAGE img_bk;       //背景图片
float position_x, position_y;          //飞机的位置
float bullet_x, bullet_y;              //子弹的位置
float enemy_x, enemy_y;                //敌机的位置
IMAGE img_planeNormal1, img_planeNormal2;      //正常飞机图片
IMAGE img_planeExplode1, img_planeExplode2;        //爆炸飞机图片
IMAGE img_bullet1, img_bullet2;                     //子弹图片
IMAGE img_enemyPlane1, img_enemyPlane2;     //敌机图片
int isExpolde = 0;                       //飞机是否爆炸
int score = 0;                            //得分
int gameStatus = 0;                  //游戏状态,0为初始菜单界面,1为正常游戏,2为结束游戏状态,3位游戏暂停

void startMenu();                        //初始菜单界面
void pauseMenu();                       //游戏暂停后的菜单界面,一般按下esc键后启动该界面
void startup();                         //数据的初始化
void show();                            //显示画面
void updateWithoutInput();              //与用户输入无关的更新
void updateWithInpute();                //与用户输入有关的更新
void gameover();                       //游戏结束,进入后续处理

void startMenu()      //初始菜单界面
{
    putimage(0, 0, &img_bk);          //显示背景
    setbkmode(TRANSPARENT);
    settextcolor(BLACK);
    settextstyle(50, 0, _T("黑体"));
    outtextxy(Width*0.3, High*0.3, _T("1,进入游戏 "));
    outtextxy(Width*0.3, High*0.4, _T("2,退出 "));
    FlushBatchDraw();
    Sleep(2);

    char input;
    if (kbhit())       //判断用户是否有输入?
    {
        input = getch();     //根据用户的不同输入来移动,不必输入回车
        if (input == '1')
        {
            gameStatus = 1;
        }
        else if (input == '2')
        {
            gameStatus = 2;
            exit(0);
        }
    }
    else
    {
        cout << "没有案件消息" << endl;
    }
    cout << "startmenu结束了" << endl;
}

void pauseMenu()
{
    putimage(0, 0, &img_bk);
    setbkmode(TRANSPARENT);
    settextcolor(BLACK);
    settextstyle(50, 0, _T("黑体"));
    outtextxy(Width*0.3, High*0.3, _T("1,继续游戏 "));
    outtextxy(Width*0.3, High*0.4, _T("2,退出 "));
    FlushBatchDraw();
    Sleep(2);

    char input;
    if (kbhit())       //判断用户是否有输入?
    {
        input = getch();     //根据用户的不同输入来移动,不必输入回车
    
        if (input == '1')
        {
            gameStatus = 1;
        }
        else if (input == '2')
        {
            gameStatus = 2;
            exit(0);
        }
    }

}

void startup()
{
    mciSendString(_T("open .\\game_music.mp3 alias bkmusic"), NULL, 0, NULL);   //打开背景音乐
    mciSendString(_T("play bkmusic repeat"), NULL, 0, NULL);                   //循环播放

    initgraph(Width, High);
    //获取窗口句柄
    HWND hwnd = GetHWnd();
    //设置窗口标题文字

    SetWindowText(hwnd, _T("飞机大战V1.0 "));
    
    //loadimage,就是将这些图片载入到内存中。
    loadimage(&img_bk, _T(".\\background.jpg"));
    loadimage(&img_planeNormal1, _T(".\\planeNormal_1.jpg"));
    loadimage(&img_planeNormal2, _T(".\\planeNormal_2.jpg"));
    loadimage(&img_bullet1, _T(".\\bullet1.jpg"));
    loadimage(&img_bullet2, _T(".\\bullet2.jpg"));
    loadimage(&img_enemyPlane1, _T(".\\enemyPlane1.jpg"));
    loadimage(&img_enemyPlane2, _T(".\\enemyPlane2.jpg"));
    loadimage(&img_planeExplode1, _T(".\\planeExplode_1.jpg"));
    loadimage(&img_planeExplode2, _T(".\\planeExplode_2.jpg"));
    
    position_x = Width*0.5;
    position_y = High*0.7;
    bullet_x = position_x;
    bullet_y = -85;
    enemy_x = Width*0.5;
    enemy_y = 10;

    BeginBatchDraw();

    while (gameStatus == 0)       //游戏状态为0,初始菜单界面
    {
        startMenu();           //初始菜单界面,等待用户按键1-进入游戏,还是按键2---退出程序
    }
    cout << "跳出了初始化。。。。。" << endl;
}

void show()
{
    
    while (gameStatus == 3)        //按下ESC的时候,游戏状态为3
    {
        pauseMenu();        //游戏暂停后的菜单界面,一般按ESC键后启动该界面
    }
    putimage(0, 0, &img_bk);  //显示背景
    if (isExpolde == 0)     //0代表没有爆炸.然后就显示了正常飞机,子弹,敌机的图片都显示出来
    {
        putimage(position_x - 50, position_y - 60, &img_planeNormal1, NOTSRCERASE);         //显示正常飞机
        putimage(position_x - 50, position_y - 60, &img_planeNormal2, SRCINVERT);

        putimage(bullet_x - 7, bullet_y, &img_bullet1, NOTSRCERASE);      //显示子弹
        putimage(bullet_x - 7, bullet_y, &img_bullet2, SRCINVERT);

        putimage(enemy_x, enemy_y, &img_enemyPlane1, NOTSRCERASE);     //显示敌机
        putimage(enemy_x, enemy_y, &img_enemyPlane2, SRCINVERT);
    }
    else
    {
        putimage(position_x - 50, position_y - 60, &img_planeExplode1, NOTSRCERASE);   //显示爆炸飞机
        putimage(position_x - 50, position_y - 60, &img_planeExplode2, SRCINVERT);

    }

    settextcolor(RED);
    settextstyle(20, 0, _T("黑体"));
    outtextxy(Width*0.48, High*0.95, _T("得分: "));
    //TCHAR s[5];      //这里竟然出现了一个bug,字符串宽度问题   把char 改成TCHAR即可  https://www.cnblogs.com/zhougeng/p/11827675.html
    //char s[5];
    ////scanf("%d", &s);
    //sprintf_s(s, "%d", score);
    outtextxy(Width*0.6, High*0.95, score);     //这个得分显示,有一些问题,显示的不够完整,以后再说。

    FlushBatchDraw();
    Sleep(2);
}

void updateWithoutInput()
{
    if (isExpolde == 0)     //0--没有爆炸的时候,
    {
        if (bullet_y>-25 )           //当子弹速度大于  -25的时候
        {
            bullet_y = bullet_y - 2;       //子弹持续往上走
        }
        if (enemy_y<High-25 )        //当飞机没有落到最底下的时候,
        {
            enemy_y = enemy_y + 0.5;      //飞机Y坐标缓慢的往下飞!
        }
        else
        {
            enemy_y = 10;           //否则,当飞机落到最底下的时候,从上面重新往下落
        }

        if (abs(bullet_x-enemy_x )+abs(bullet_y-enemy_y )<80   )     //当子弹距离敌机足够近,也就是击中敌机的时候
        {
            enemy_x = rand() % Width;        //敌机x坐标,重新生成
            enemy_y = -40;                  //敌机Y坐标,从上往下走
            bullet_y = -85;                 //子弹也在最上面,屏幕外面

            mciSendString(_T("stop fgmusic"), NULL, 0, NULL);       //先把前面一次的音乐停止
            mciSendString(_T("close fgmusic"), NULL, 0, NULL);     //先把前面一次的音乐关闭
            mciSendString(_T("open .\\gotEnemy.mp3 alias gemusic"), NULL, 0, NULL);        //打开跳动音乐
            mciSendString(_T("play gemusic"), NULL, 0, NULL);          //仅仅播放一次
            score++;                                          //得分加1
        }

        if (score>0 && score%5==0 &&score%2!=0 )       //当得分是1,3,7,9等数字的时候,播放很嚣张的音乐,谁能阻止我?
        {
            //谁能阻止我
            mciSendString(_T("stop 5music"), NULL, 0, NULL);       //先把前面一次的音乐停止
            mciSendString(_T("close 5music"), NULL, 0, NULL);     //先把前面一次的音乐关闭
            mciSendString(_T("open .\\5.mp3 alias 5music"), NULL, 0, NULL);        //打开跳动音乐
            mciSendString(_T("play 5music"), NULL, 0, NULL);          //仅仅播放一次
        }

        if (score%10==0)    //每得10分,就播放,还要继续吗?如此嚣张的言论
        {
            mciSendString(_T("stop 10music"), NULL, 0, NULL);       //先把前面一次的音乐停止
            mciSendString(_T("close 10music"), NULL, 0, NULL);     //先把前面一次的音乐关闭
            mciSendString(_T("open .\\10.mp3 alias 10music"), NULL, 0, NULL);        //打开跳动音乐
            mciSendString(_T("play 10music"), NULL, 0, NULL);          //仅仅播放一次
        }
    }

    if (abs(position_x-enemy_x )+abs(position_y-enemy_y )<150  )      //敌机击中我机
    {
        isExpolde = 1;
        mciSendString(_T("stop exmusic"), NULL, 0, NULL);       //先把前面一次的音乐停止
        mciSendString(_T("close exmusic"), NULL, 0, NULL);     //先把前面一次的音乐关闭
        mciSendString(_T("open .\\explode.mp3 alias 10music"), NULL, 0, NULL);        //打开跳动音乐
        mciSendString(_T("play exmusic"), NULL, 0, NULL);          //仅仅播放一次
    }


}
void updateWithInpute()
{
    MOUSEMSG m;                 //实例化一个对象  //定义鼠标消息
    while (MouseHit())          //这个函数用于检测当前是否有鼠标消息
    {
        m = GetMouseMsg();                   
        if (m.uMsg==WM_MOUSEMOVE )      //当鼠标移动的时候,飞机坐标就等同于鼠标坐标      
        {
            //飞机的位置等于鼠标所在的位置
            position_x = m.x;
            position_y = m.y;
        }
        else if (m.uMsg==WM_LBUTTONDOWN ) //按下鼠标左键发射子弹
        {
            
            bullet_x = position_x;
            bullet_y = position_y - 85;

            mciSendString(_T("stop fgmusic"), NULL, 0, NULL);       //先把前面一次的音乐停止
            mciSendString(_T("close fgmusic"), NULL, 0, NULL);     //先把前面一次的音乐关闭
            mciSendString(_T("open .\\f_gun.mp3 alias fgmusic"), NULL, 0, NULL);        //打开跳动音乐
            mciSendString(_T("play fgmusic"), NULL, 0, NULL);          //仅仅播放一次
        }
    }
    char input;
    if (kbhit())
    {
        input = getch();
        if (input == 27)
        {
            gameStatus = 3;
        }
    }

}

void gameover()
{
    EndBatchDraw();
    getch();
    closegraph();
}
int main()
{
    startup();             //数据的初始化,游戏状态为0时,会一直在初始化界面。当用户按键1时候,会进入到下个页面
    while (true)
    {
        show();             //显示画面,背景图片之类的,都在这里显示。。
        updateWithoutInput();
        updateWithInpute();
    }            //游戏循环执行
    
    gameover();            //游戏结束,进行后续处理
    return 0;
}

========================
接下来的版本,要加上游戏的读档和存档

//新的延时函数
void delay(DWORD ms)     //新的延时函数
{
    static DWORD oldtime = GetTickCount();
    while (GetTickCount()-oldtime<ms )
    {
        Sleep(1);
    }
    oldtime = GetTickCount();
}  //用delay(5)代替sleep(5)进行调用,

============

//#include <tchar.h>        //在程序中使用 #include <tchar.h> 添加对 TCHAR 的支持。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>    //清屏命令在这里。
#include <windows.h> //延时10毫秒-sleep,gotoxy函数
#include <iostream>
#include <conio.h>       //getch()----不用按回车,就可以输入字符。    
#include <graphics.h>      //EasyX库,所使用的!
#include <math.h>         //三角函数
#include <algorithm>      //max(),min(),和abs(),sort函数排序方法,https://blog.csdn.net/BIGKALA/article/details/81624691,这是方法适用的地址
#include <time.h>


using namespace std;


//引用 windows multimedia api
#pragma comment(lib,"Winmm.lib " )

#define High 870
#define Width 591         //游戏画面尺寸

IMAGE img_bk;       //背景图片
float position_x, position_y;          //飞机的位置
float bullet_x, bullet_y;              //子弹的位置
float enemy_x, enemy_y;                //敌机的位置
IMAGE img_planeNormal1, img_planeNormal2;      //正常飞机图片
IMAGE img_planeExplode1, img_planeExplode2;        //爆炸飞机图片
IMAGE img_bullet1, img_bullet2;                     //子弹图片
IMAGE img_enemyPlane1, img_enemyPlane2;     //敌机图片
int isExpolde = 0;                       //飞机是否爆炸
int score = 0;                            //得分
int gameStatus = 0;                  //游戏状态,0为初始菜单界面,1为正常游戏,2为结束游戏状态,3位游戏暂停

void startMenu();                        //初始菜单界面
void pauseMenu();                       //游戏暂停后的菜单界面,一般按下esc键后启动该界面
void startup();                         //数据的初始化
void show();                            //显示画面
void updateWithoutInput();              //与用户输入无关的更新
void updateWithInpute();                //与用户输入有关的更新
void gameover();                       //游戏结束,进入后续处理
void readRecordFile();                  //读取游戏存档
void writeRecordFile();                 //存储游戏存档

void delay(DWORD ms)     //新的延时函数
{
    static DWORD oldtime = GetTickCount();
    while (GetTickCount()-oldtime<ms )
    {
        Sleep(1);
    }
    oldtime = GetTickCount();
}  //用delay(5)代替sleep(5)进行调用,

void startMenu()      //初始菜单界面
{
    putimage(0, 0, &img_bk);          //显示背景
    setbkmode(TRANSPARENT);
    settextcolor(BLACK);
    settextstyle(50, 0, _T("黑体"));
    outtextxy(Width*0.3, High*0.2, _T("1,进入游戏 "));
    outtextxy(Width*0.3, High*0.3, _T("2,读取游戏存档 "));
    outtextxy(Width*0.3, High*0.4, _T("3,退出 "));

    settextcolor(BLUE);
    settextstyle(30, 0, _T("黑体"));
    outtextxy(Width*0.25, High*0.6, _T("鼠标移动控制飞机移动 "));
    outtextxy(Width*0.25, High*0.65, _T("鼠标左键发射子弹 "));
    outtextxy(Width*0.25, High*0.7, _T("ESC键暂停游戏 "));
    outtextxy(Width*0.25, High*0.75, _T("撞击后按任意键重新开始 "));

    FlushBatchDraw();
    Sleep(2);

    char input;
    if (kbhit())       //判断用户是否有输入?
    {
        input = getch();     //根据用户的不同输入来移动,不必输入回车
        if (input == '1')
        {
            gameStatus = 1;
        }
        else if (input == '2')
        {
            
            gameStatus = 1;
        }
        else if (input == '3')
        {
            gameStatus = 2;
            exit(0);
        }
    }

}

void pauseMenu()
{
    putimage(0, 0, &img_bk);
    setbkmode(TRANSPARENT);
    settextcolor(BLACK);
    settextstyle(50, 0, _T("黑体"));
    outtextxy(Width*0.3, High*0.2, _T("1,继续游戏 "));
    outtextxy(Width*0.3, High*0.3, _T("2,保存档案 "));
    outtextxy(Width*0.3, High*0.4, _T("3,退出 "));

    settextcolor(BLUE);
    settextstyle(30, 0, _T("黑体"));
    outtextxy(Width*0.25, High*0.6, _T("鼠标移动控制飞机移动 "));
    outtextxy(Width*0.25, High*0.65, _T("鼠标左键发射子弹 "));
    outtextxy(Width*0.25, High*0.7, _T("ESC键暂停游戏 "));
    outtextxy(Width*0.25, High*0.75, _T("撞击后按任意键重新开始 "));

    FlushBatchDraw();
    Sleep(2);


    char input;
    if (kbhit())       //判断用户是否有输入?
    {
        input = getch();     //根据用户的不同输入来移动,不必输入回车
        if (input == '1')
        {
            gameStatus = 1;
        }
        else if (input == '2')
        {
            writeRecordFile();
            gameStatus = 1;
        }
        else if (input == '3')
        {
            gameStatus = 2;
            exit(0);
        }
    }

}
void readRecordFile()
{
    FILE *fp;
    fp = fopen(".\\gameRecord.dat ", "r");
    fscanf(fp, "%f %f %f %f %f %f %d %d ", &position_x, &position_y, &bullet_x, &bullet_y, &enemy_x, &enemy_y, &isExpolde, &score);
    fclose(fp);
}
void writeRecordFile()
{
    FILE *fp;
    fp = fopen(".\\gameRecord.dat ", "w");
    fprintf(fp, "%f %f %f %f %f %f %d %d ", position_x, position_y, bullet_x, bullet_y, enemy_x, enemy_y, isExpolde, score);
    fclose(fp);
}



void startup()
{
    mciSendString(_T("open .\\game_music.mp3 alias bkmusic"), NULL, 0, NULL);   //打开背景音乐
    mciSendString(_T("play bkmusic repeat"), NULL, 0, NULL);                   //循环播放

    initgraph(Width, High);
    //获取窗口句柄
    HWND hwnd = GetHWnd();
    //设置窗口标题文字

    SetWindowText(hwnd, _T("飞机大战V1.0 "));
    
    //loadimage,就是将这些图片载入到内存中。
    loadimage(&img_bk, _T(".\\background.jpg"));
    loadimage(&img_planeNormal1, _T(".\\planeNormal_1.jpg"));
    loadimage(&img_planeNormal2, _T(".\\planeNormal_2.jpg"));
    loadimage(&img_bullet1, _T(".\\bullet1.jpg"));
    loadimage(&img_bullet2, _T(".\\bullet2.jpg"));
    loadimage(&img_enemyPlane1, _T(".\\enemyPlane1.jpg"));
    loadimage(&img_enemyPlane2, _T(".\\enemyPlane2.jpg"));
    loadimage(&img_planeExplode1, _T(".\\planeExplode_1.jpg"));
    loadimage(&img_planeExplode2, _T(".\\planeExplode_2.jpg"));
    
    position_x = Width*0.5;
    position_y = High*0.7;
    bullet_x = position_x;
    bullet_y = -85;
    enemy_x = Width*0.5;
    enemy_y = 10;

    BeginBatchDraw();

    while (gameStatus == 0)       //游戏状态为0,初始菜单界面
    {
        startMenu();           //初始菜单界面,等待用户按键1-进入游戏,还是按键2---退出程序
    }
    
}

void show()
{
    
    while (gameStatus == 3)        //按下ESC的时候,游戏状态为3
    {
        pauseMenu();        //游戏暂停后的菜单界面,一般按ESC键后启动该界面
    }
    putimage(0, 0, &img_bk);  //显示背景
    if (isExpolde == 0)     //0代表没有爆炸.然后就显示了正常飞机,子弹,敌机的图片都显示出来
    {
        putimage(position_x - 50, position_y - 60, &img_planeNormal1, NOTSRCERASE);         //显示正常飞机
        putimage(position_x - 50, position_y - 60, &img_planeNormal2, SRCINVERT);

        putimage(bullet_x - 7, bullet_y, &img_bullet1, NOTSRCERASE);      //显示子弹
        putimage(bullet_x - 7, bullet_y, &img_bullet2, SRCINVERT);

        putimage(enemy_x, enemy_y, &img_enemyPlane1, NOTSRCERASE);     //显示敌机
        putimage(enemy_x, enemy_y, &img_enemyPlane2, SRCINVERT);
    }
    else
    {
        putimage(position_x - 50, position_y - 60, &img_planeExplode1, NOTSRCERASE);   //显示爆炸飞机
        putimage(position_x - 50, position_y - 60, &img_planeExplode2, SRCINVERT);

    }

    settextcolor(RED);
    settextstyle(20, 0, _T("黑体"));
    outtextxy(Width*0.48, High*0.95, _T("得分: "));
    //TCHAR s[5];      //这里竟然出现了一个bug,字符串宽度问题   把char 改成TCHAR即可  https://www.cnblogs.com/zhougeng/p/11827675.html
    //char s[5];
    ////scanf("%d", &s);
    //sprintf_s(s, "%d", score);
    outtextxy(Width*0.6, High*0.95, score);     //这个得分显示,有一些问题,显示的不够完整,以后再说。

    FlushBatchDraw();
    Sleep(2);
}

void updateWithoutInput()
{
    if (isExpolde == 0)     //0--没有爆炸的时候,
    {
        if (bullet_y>-25 )           //当子弹速度大于  -25的时候
        {
            bullet_y = bullet_y - 2;       //子弹持续往上走
        }
        if (enemy_y<High-25 )        //当飞机没有落到最底下的时候,
        {
            enemy_y = enemy_y + 0.5;      //飞机Y坐标缓慢的往下飞!
        }
        else
        {
            enemy_y = 10;           //否则,当飞机落到最底下的时候,从上面重新往下落
        }

        if (abs(bullet_x-enemy_x )+abs(bullet_y-enemy_y )<80   )     //当子弹距离敌机足够近,也就是击中敌机的时候
        {
            enemy_x = rand() % Width;        //敌机x坐标,重新生成
            enemy_y = -40;                  //敌机Y坐标,从上往下走
            bullet_y = -85;                 //子弹也在最上面,屏幕外面

            mciSendString(_T("stop fgmusic"), NULL, 0, NULL);       //先把前面一次的音乐停止
            mciSendString(_T("close fgmusic"), NULL, 0, NULL);     //先把前面一次的音乐关闭
            mciSendString(_T("open .\\gotEnemy.mp3 alias gemusic"), NULL, 0, NULL);        //打开跳动音乐
            mciSendString(_T("play gemusic"), NULL, 0, NULL);          //仅仅播放一次
            score++;                                          //得分加1
        }

        if (score>0 && score%5==0 &&score%2!=0 )       //当得分是1,3,7,9等数字的时候,播放很嚣张的音乐,谁能阻止我?
        {
            //谁能阻止我
            mciSendString(_T("stop 5music"), NULL, 0, NULL);       //先把前面一次的音乐停止
            mciSendString(_T("close 5music"), NULL, 0, NULL);     //先把前面一次的音乐关闭
            mciSendString(_T("open .\\5.mp3 alias 5music"), NULL, 0, NULL);        //打开跳动音乐
            mciSendString(_T("play 5music"), NULL, 0, NULL);          //仅仅播放一次
        }

        if (score%10==0)    //每得10分,就播放,还要继续吗?如此嚣张的言论
        {
            mciSendString(_T("stop 10music"), NULL, 0, NULL);       //先把前面一次的音乐停止
            mciSendString(_T("close 10music"), NULL, 0, NULL);     //先把前面一次的音乐关闭
            mciSendString(_T("open .\\10.mp3 alias 10music"), NULL, 0, NULL);        //打开跳动音乐
            mciSendString(_T("play 10music"), NULL, 0, NULL);          //仅仅播放一次
        }
    }

    if (abs(position_x-enemy_x )+abs(position_y-enemy_y )<150  )      //敌机击中我机
    {
        isExpolde = 1;
        mciSendString(_T("stop exmusic"), NULL, 0, NULL);       //先把前面一次的音乐停止
        mciSendString(_T("close exmusic"), NULL, 0, NULL);     //先把前面一次的音乐关闭
        mciSendString(_T("open .\\explode.mp3 alias 10music"), NULL, 0, NULL);        //打开跳动音乐
        mciSendString(_T("play exmusic"), NULL, 0, NULL);          //仅仅播放一次
    }


}
void updateWithInpute()
{
    MOUSEMSG m;                 //实例化一个对象  //定义鼠标消息
    while (MouseHit())          //这个函数用于检测当前是否有鼠标消息
    {
        m = GetMouseMsg();                   
        if (m.uMsg==WM_MOUSEMOVE )      //当鼠标移动的时候,飞机坐标就等同于鼠标坐标      
        {
            //飞机的位置等于鼠标所在的位置
            position_x = m.x;
            position_y = m.y;
        }
        else if (m.uMsg==WM_LBUTTONDOWN ) //按下鼠标左键发射子弹
        {
            
            bullet_x = position_x;
            bullet_y = position_y - 85;

            mciSendString(_T("stop fgmusic"), NULL, 0, NULL);       //先把前面一次的音乐停止
            mciSendString(_T("close fgmusic"), NULL, 0, NULL);     //先把前面一次的音乐关闭
            mciSendString(_T("open .\\f_gun.mp3 alias fgmusic"), NULL, 0, NULL);        //打开跳动音乐
            mciSendString(_T("play fgmusic"), NULL, 0, NULL);          //仅仅播放一次
        }
    }
    char input;
    if (kbhit())
    {
        input = getch();
        if (input == 27)
        {
            gameStatus = 3;
        }
    }

}

void gameover()
{
    EndBatchDraw();
    getch();
    closegraph();
}
int main()
{
    startup();             //数据的初始化,游戏状态为0时,会一直在初始化界面。当用户按键1时候,会进入到下个页面
    while (true)
    {
        show();             //显示画面,背景图片之类的,都在这里显示。。
        updateWithoutInput();
        updateWithInpute();
    }            //游戏循环执行
    
    gameover();            //游戏结束,进行后续处理
    return 0;
}

相关文章

网友评论

      本文标题:网易C++--书籍练习案例03--利用文件读写游戏存档

      本文链接:https://www.haomeiwen.com/subject/hozrbktx.html