飞机大战小游戏(c语言)

请事先下好图片素材和easyX函数库

若加载图片报错,有可能是字符集不对,改为多字符集即可。

#include<stdio.h>    //标准输入输出函数库
#include<conio.h>    //接收键盘输入输出
#include<time.h>    //时间戳
#include<random>    //随机数
#include<graphics.h>    //图形库,可以帮助我们新手,快速入门图形编程 EasyX


enum My    //enum是一种数据类型(枚举类型),用于定义一组有限的整型值集合,列举出所有可能的值,且变量取值不能超过定义的范围
{
    WIDTH = 480,    //背景大小为 480 x 700 像素
    HEIGHT = 700,
    Player_WIDTH = 102,    //飞机大小
    Player_HEIGHT = 126,

    Bullet_NUM = 10,    //子弹的数量
    //子弹的尺寸
    Bullet_WIDTH=5,
    Bullet_HEIGHT=11,

    Enemy_NUM = 10,        //敌机的数量
    //敌机的尺寸
    Enemy0_WIDTH =57,
    Enemy0_HEIGHT=43,
    Enemy1_WIDTH =69,
    Enemy1_HEIGHT=99,
    Enemy2_WIDTH =169,
    Enemy2_HEIGHT=258
};
struct Plane    //飞机模块    struct是一种结构体类型
{
    float x;
    float y;
    bool live;    //是否存活
    int HP;
    int type;    //敌机类型
    float speed;    //敌机速度
}player,bullet[Bullet_NUM],enemy[Enemy_NUM];


//把图片加载进程序
    //背景图片
IMAGE background;    //image是一种数据类型,用于表示图像数据
    //玩家图片
IMAGE image_player[2];
    //玩家子弹图片
IMAGE image_bullet;
    //敌机图片
IMAGE image_enemy[2][3];
    //敌机毁灭图片
IMAGE image_enemy_destroy[3][2][6];
//加载素材函数
void LoadIMAGE()
{
    //加载背景图片
    loadimage(&background, "./Material/images/background.png");
        //可能报错:error c2665:"loadimage":2 个重载中没有一个可以转换所有参数类型
        //参数有误,因为字符集不对,Unicode   多字节字符集
    //加载玩家
    loadimage(&image_player[0], "./Material/images/me1_bw.png");
    loadimage(&image_player[1], "./Material/images/me1_w.png");
    //加载敌机
    loadimage(&image_enemy[0][0], "./Material/images/enemy1_bw.png");
    loadimage(&image_enemy[1][0], "./Material/images/enemy1_w.png");
    loadimage(&image_enemy[0][1], "./Material/images/enemy2_bw.png");
    loadimage(&image_enemy[1][1], "./Material/images/enemy2_w.png");
    loadimage(&image_enemy[0][2], "./Material/images/enemy3_n1_bw.png");
    loadimage(&image_enemy[1][2], "./Material/images/enemy3_n1_w.png");
    //加载敌机毁灭动画
    loadimage(&image_enemy_destroy[0][0][0], "./Material/images/enemy1_down1_bw.png");
    loadimage(&image_enemy_destroy[0][1][0], "./Material/images/enemy1_down1_w.png");
    loadimage(&image_enemy_destroy[0][0][1], "./Material/images/enemy1_down2_bw.png");
    loadimage(&image_enemy_destroy[0][1][1], "./Material/images/enemy1_down2_w.png");
    loadimage(&image_enemy_destroy[0][0][2], "./Material/images/enemy1_down3_bw.png");
    loadimage(&image_enemy_destroy[0][1][2], "./Material/images/enemy1_down3_w.png");
    loadimage(&image_enemy_destroy[0][0][3], "./Material/images/enemy1_down4_bw.png");
    loadimage(&image_enemy_destroy[0][1][3], "./Material/images/enemy1_down4_w.png");

    loadimage(&image_enemy_destroy[1][0][0], "./Material/images/enemy2_down1_bw.png");
    loadimage(&image_enemy_destroy[1][1][0], "./Material/images/enemy2_down1_w.png");
    loadimage(&image_enemy_destroy[1][0][1], "./Material/images/enemy2_down2_bw.png");
    loadimage(&image_enemy_destroy[1][1][1], "./Material/images/enemy2_down2_w.png");
    loadimage(&image_enemy_destroy[1][0][2], "./Material/images/enemy2_down3_bw.png");
    loadimage(&image_enemy_destroy[1][1][2], "./Material/images/enemy2_down3_w.png");
    loadimage(&image_enemy_destroy[1][0][3], "./Material/images/enemy2_down4_bw.png");
    loadimage(&image_enemy_destroy[1][1][3], "./Material/images/enemy2_down4_w.png");

    loadimage(&image_enemy_destroy[2][0][0], "./Material/images/enemy3_down1_bw.png");
    loadimage(&image_enemy_destroy[2][1][0], "./Material/images/enemy3_down1_w.png");
    loadimage(&image_enemy_destroy[2][0][1], "./Material/images/enemy3_down2_bw.png");
    loadimage(&image_enemy_destroy[2][1][1], "./Material/images/enemy3_down2_w.png");
    loadimage(&image_enemy_destroy[2][0][2], "./Material/images/enemy3_down3_bw.png");
    loadimage(&image_enemy_destroy[2][1][2], "./Material/images/enemy3_down3_w.png");
    loadimage(&image_enemy_destroy[2][0][3], "./Material/images/enemy3_down4_bw.png");
    loadimage(&image_enemy_destroy[2][1][3], "./Material/images/enemy3_down4_w.png");
    loadimage(&image_enemy_destroy[2][0][4], "./Material/images/enemy3_down5_bw.png");
    loadimage(&image_enemy_destroy[2][1][4], "./Material/images/enemy3_down5_w.png");
    loadimage(&image_enemy_destroy[2][0][5], "./Material/images/enemy3_down6_bw.png");
    loadimage(&image_enemy_destroy[2][1][5], "./Material/images/enemy3_down6_w.png");
    //加载子弹
    loadimage(&image_bullet, "./Material/images/bullet1.png");
}
//敌机毁灭动画函数
void EnemyDestroy(int i)
{
    
    if (enemy[i].type == 1)
    {
        putimage(enemy[i].x, enemy[i].y, &image_enemy_destroy[enemy[i].type][0][2], NOTSRCERASE);
        putimage(enemy[i].x, enemy[i].y, &image_enemy_destroy[enemy[i].type][1][2], SRCERASE);

    }
    else if (enemy[i].type == 2)
    {
        putimage(enemy[i].x, enemy[i].y, &image_enemy_destroy[enemy[i].type][0][4], NOTSRCERASE);
        putimage(enemy[i].x, enemy[i].y, &image_enemy_destroy[enemy[i].type][1][4], SRCERASE);
    }
    else if (enemy[i].type == 0)
    {
        putimage(enemy[i].x, enemy[i].y, &image_enemy_destroy[enemy[i].type][0][2], NOTSRCERASE);
        putimage(enemy[i].x, enemy[i].y, &image_enemy_destroy[enemy[i].type][1][2], SRCERASE);
    }
}
//游戏初始化函数
void GameInit()
{
    LoadIMAGE();    //调用加载函数


    player.x = WIDTH / 2;
    player.y = HEIGHT - 120;
    player.live = true;
    player.HP = 1;
    //玩家子弹初始化
    for (int i = 0; i < Bullet_NUM; i++)
    {
        bullet[i].live = false;
    }
    //敌机初始化
    for (int i = 0; i < Enemy_NUM; i++)
    {
        enemy[i].live = false;
    }
}
//产生子弹函数
void CreateBullet()
{
    for (int i = 0; i < Bullet_NUM; i++)
    {
        if (!bullet[i].live)
        {
            bullet[i].x = (player.x + Player_WIDTH/2);
            bullet[i].y = (player.y - Bullet_HEIGHT);
            bullet[i].live = true;
            break;
        }
    }
}
//产生敌机函数
void CreateEnemy()
{
    int Random_value;
    for (int i = 0; i < Enemy_NUM; i++)
    {
        if (!enemy[i].live)
        {

            Random_value = rand();
            if (Random_value % 10 == 9)
            {
                enemy[i].type = 2;
                enemy[i].HP = 10;
            }
            else if (Random_value % 10 < 6)
            {
                enemy[i].type = 0;
                enemy[i].HP = 1;
            }
            else
            {
                enemy[i].type = 1;
                enemy[i].HP = 3;
            }
            srand(clock());
            enemy[i].x = rand() % 4 * 100 + rand() % 10 * 10 + rand() % 10;
            enemy[i].y = - 126;
            enemy[i].live = true;
            break;
        }
    }
}
//消灭敌机函数
void AttackEnemy()
{
    for (int i = 0; i < Bullet_NUM; i++)
    {
        if (bullet[i].live)
        {
            for (int j = 0; j < Enemy_NUM; j++)
            {
                if (enemy[j].live)
                {
                    if (enemy[j].type == 0)
                    {
                        if ((bullet[i].x >= enemy[j].x) && ((bullet[i].x + Bullet_WIDTH) <= (enemy[j].x + Enemy0_WIDTH)) && ((bullet[i].y + Bullet_HEIGHT) <= (enemy[j].y + Enemy0_HEIGHT)) && (bullet[i].y >= enemy[j].y))
                        {
                            bullet[i].live = false;
                            enemy[j].HP--;
                        }
                    }
                    if (enemy[j].type == 1)
                    {
                        if ((bullet[i].x >= enemy[j].x) && ((bullet[i].x + Bullet_WIDTH) <= (enemy[j].x + Enemy1_WIDTH)) && ((bullet[i].y + Bullet_HEIGHT) <= (enemy[j].y + Enemy1_HEIGHT)) && (bullet[i].y >= enemy[j].y))
                        {
                            bullet[i].live = false;
                            enemy[j].HP--;
                        }
                    }
                    if (enemy[j].type == 2)
                    {
                        if ((bullet[i].x >= enemy[j].x) && ((bullet[i].x + Bullet_WIDTH) <= (enemy[j].x + Enemy2_WIDTH)) && ((bullet[i].y + Bullet_HEIGHT) <= (enemy[j].y + Enemy2_HEIGHT)) && (bullet[i].y >= enemy[j].y))
                        {
                            bullet[i].live = false;
                            enemy[j].HP--;
                        }
                    }
                }
            }
        }
    }
}
//游戏的窗口绘制函数
void GameDraw()
{
    //把背景图片贴到窗口
    putimage(0, 0, &background);
    //飞机图片贴到窗口
    putimage(player.x, player.y, &image_player[0], NOTSRCERASE);
    putimage(player.x, player.y, &image_player[1], SRCERASE);
    //子弹图片
    for (int i = 0; i < Bullet_NUM; i++)
    {
        if (bullet[i].live)
        {
            putimage(bullet[i].x, bullet[i].y, &image_bullet);
        }
    }
    //敌机图片
    for (int i = 0; i < Enemy_NUM; i++)
    {
        if (enemy[i].HP <= 0)
        {
            EnemyDestroy(i);
            enemy[i].live = false;
        }
        if (enemy[i].live)
        {
            putimage(enemy[i].x, enemy[i].y, &image_enemy[0][enemy[i].type], NOTSRCERASE);
            putimage(enemy[i].x, enemy[i].y, &image_enemy[1][enemy[i].type], SRCERASE);
        }
    }
}
//子弹移动,存活判断函数
void BulletMove(float speed)
{
    for (int i = 0; i < Bullet_NUM; i++)
    {
        if (bullet[i].live)
        {
            bullet[i].y -= speed;    //子弹移动速度
            if (bullet[i].y < 0)    //子弹存活条件判断
            {
                bullet[i].live = false;
            }
        }
    }
}
//敌机的移动,存活判断函数
void WnemyMove()
{
    for (int i = 0; i < Enemy_NUM; i++)
    {
        if (enemy[i].live)
        {
            //敌机的移动速度
            if (enemy[i].type == 0)
            {
                enemy[i].y += 0.1;
            }
            else if (enemy[i].type == 1)
            {
                enemy[i].y += 0.02;
            }
            else
            {
                enemy[i].y += 0.005;
            }
            //敌机的存活条件判断
            if (enemy[i].y > 700)
            {
                enemy[i].live = false;
            }
        }
    }
}
//玩家的存活判断函数
void PlayerLive()
{
    for (int i = 0; i < Enemy_NUM; i++)
    {
        if (enemy[i].type == 0)
        {
            if (player.x > (enemy[i].x - Player_WIDTH * 0.7) && player.x < (enemy[i].x + Enemy0_WIDTH * 0.7) && player.y >(enemy[i].y - Player_HEIGHT * 0.8) && player.y < (enemy[i].y + Enemy0_HEIGHT * 0.8))
            {
                player.HP--;
            }
        }
        if (enemy[i].type == 1)
        {
            if (player.x > (enemy[i].x - Player_WIDTH * 0.7) && player.x < (enemy[i].x + Enemy1_WIDTH * 0.7) && player.y >(enemy[i].y - Player_HEIGHT * 0.8) && player.y < (enemy[i].y + Enemy1_HEIGHT * 0.8))
            {
                player.HP--;
            }
        }
        if (enemy[i].type == 2)
        {
            if (player.x > (enemy[i].x - Player_WIDTH * 0.7) && player.x < (enemy[i].x + Enemy2_WIDTH * 0.7) && player.y >(enemy[i].y - Player_HEIGHT * 0.8) && player.y < (enemy[i].y + Enemy2_HEIGHT * 0.8))
            {
                player.HP--;
            }
        }
    }
    if (player.HP <= 0)
    {
        player.live = false;
        printf("游戏结束");
        exit(0);
    }
}
//角色移动函数
void PlayerMove(float speed)
{
    //使用windows函数获取键盘输入 GetAsyncKeyState 非阻塞函数,较为流畅
    if ((GetAsyncKeyState(VK_UP) || GetAsyncKeyState('W')) && player.y > 0)        player.y -= speed;
    if ((GetAsyncKeyState(VK_LEFT) || GetAsyncKeyState('A')) && player.x > 0)      player.x -= speed;
    if ((GetAsyncKeyState(VK_DOWN) || GetAsyncKeyState('S')) && (player.y + Player_HEIGHT) < HEIGHT)      player.y += speed;
    if ((GetAsyncKeyState(VK_RIGHT) || GetAsyncKeyState('D')) && (player.x + Player_WIDTH) < WIDTH)        player.x += speed;
}


//主函数
int main()
{
    clock_t start, end;
    //创建一个窗口,控制台窗口是自动创建,而图形窗口需要我们自己手动创建
    initgraph(WIDTH,HEIGHT,SHOWCONSOLE);    //创建绘图窗口
    GameInit();        //调用初始化函数

    //开始游戏
    outtextxy(170, 350, _T("按任意键开始游戏"));
    _getch();

    
    //双缓冲绘图(防止图片闪烁)
    BeginBatchDraw();    //这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到屏幕上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。
    while (1)
    {
        start = clock();    //与end搭配,做了一个计时器,来控制子弹发射时间差
        while (1)
        {
            end = clock();
            if (end - start > 400)
            {
                CreateBullet();    //产生子弹函数
                CreateEnemy();    //产生敌机函数
                break;
            }
            AttackEnemy();    //调用消灭敌机函数
            GameDraw();        //调用绘制函数

            FlushBatchDraw();    //这个函数用于执行未完成的绘制任务。

            BulletMove(0.15);    //调用子弹移动函数
            WnemyMove();    //调用敌机移动函数
            PlayerMove(0.1);    //调用角色移动函数

            PlayerLive();    //调用角色存活判断函数
        }
    }

    EndBatchDraw();        //这个函数用于结束批量绘制,并执行未完成的绘制任务。
    return 0;
}

#该代码还有很大修改和优化空间。

Supongo que te gusta

Origin blog.csdn.net/qq_74349936/article/details/132245574
Recomendado
Clasificación