c语言小游戏-飞机大战

article/2025/9/23 1:59:18

(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹)

今天我们来尝试用easyx图形库实现c语言小游戏-飞机大战(源代码和图片已经在结尾给出

先引用头文件

#include<stdio.h>
#include<time.h>//用于后期制作定时器
#include<graphics.h>//便于引入easyx窗口及其函数
#include<conio.h>//用于按键控制

 接着就是一系列数据的准备工作,先创建一个窗口,为了后续方便,我们用枚举法定义窗口的变量

enum My{WIDTH=591,HEIGHT=864}

int main()

{

    initgraph(WIDTH,HEIGHT);

}

然后对飞机进行定义

struct Plance//定义飞机
{
    int x;
    int y;
    int live;//是否存活
}player; 

接着就是对飞机的相关数据初始化

void gameInit()//初始化数据
{
    player.x = WIDTH / 2;
    player.y = HEIGHT - 120;
    player.live = 1;

}

别忘了将飞机的图片加载进去,在我之前的博客中有讲到如何插入图片http://t.csdn.cn/h4POw

这里我们用两张图片对飞机进行绘制,这样的话才能更好得实现动态图画,减少图片背景的影响

IMAGE bk;//背景图片
IMAGE img_role[2];//飞机图片

void loadImage()//加载图片
{
    loadimage(&bk, "./background.jpg");
    loadimage(&img_role[0], "./planeNormal_1.jpg");
    loadimage(&img_role[1], "./planeNormal_2.jpg");

}

void gameDraw()//输出图片
{
    putimage(0, 0, &bk);
    putimage(player.x, player.y, &img_role[0],NOTSRCERASE);//NOTSRCERASE贴掩码图
    putimage(player.x, player.y, &img_role[1],SRCINVERT);//SRCINVERT贴背景图

}

飞机的相关数据创建好后,就是如何移动飞机,我这里用两种移动方法,在我之前的博客中讲到如何使用键盘移动(http://t.csdn.cn/RNF6C) 注意:这里要注意边界情况,使飞机在触碰边缘后停止移动,防止飞机出界

void playerMove(int speed)//移动玩家
{
    if (_kbhit())//判断是否有按键,有按键才处理,无按键就不处理
    {
        char input = _getch(); //控制台可以直接读取我按的键
        switch (input)
        {
        case 'w':
            player.y -= speed;
            if (player.y <= 0)   //边界处理,下面也是这样
                player.y = 0;
            break;
        case 's':
            player.y += speed;
            if (player.y >= HEIGHT - 120)
                player.y = HEIGHT - 120;
            break;
        case 'a':
            player.x -= speed;
            if (player.x <= -40)
                player.x = -40;
            break;
        case 'd':
            player.x += speed;
            if (player.x >= WIDTH - (117 / 2))
                player.x = WIDTH - (117 / 2);
            break;
        }
        //与上一种按键方式相比,这一种更加丝滑流畅
        if (GetAsyncKeyState(VK_UP))//上键
        {
            player.y -= speed;
            if (player.y <= 0)
                player.y = 0;
        }
        if (GetAsyncKeyState(VK_DOWN))//下键
        {
            player.y += speed;
            if (player.y >= HEIGHT - 120)
                player.y = HEIGHT - 120;
        }
        if (GetAsyncKeyState(VK_LEFT))//左键
        {
            player.x -= speed;
            if (player.x <= -40)
                player.x = -40;
        }
        if (GetAsyncKeyState(VK_RIGHT))//右键
        {
            player.x += speed;
            if (player.x >= WIDTH - (117 / 2))
                player.x = WIDTH - (117 / 2);
        }
    }
}

在飞机变量创建好以后,接下来就是对子弹的变量进行定义以及输出 ,这里为了方便(偷懒),我直接用之前飞机的定义来定义子弹

struct Plance//定义飞机
{
    int x;
    int y;
    int live;//是否存活
}player,bull[BULLET_NUM]

然后就是子弹的初始化,这里我枚举了子弹的数量

enum My{WIDTH=591,HEIGHT=864,BULLET_NUM=15}

void gameInit()//初始化数据
{
    player.x = WIDTH / 2;
    player.y = HEIGHT - 120;
    player.live = 1;
    for (int i = 0; i < BULLET_NUM; i++)//初始化子弹
    {
        bull[i].x;
        bull[i].y;
        bull[i].live = 0;
    } 

}

子弹的图片输出与飞机一样

IMAGE img_bull[2];

loadimage(&img_bull[0], "./bullet1.jpg");

loadimage(&img_bull[1], "./bullet2.jpg");

for (int i = 0; i < BULLET_NUM; i++)
    {
        if (bull[i].live == 1)
        {
            putimage(bull[i].x, bull[i].y, &img_bull[0], NOTSRCERASE);
            putimage(bull[i].x, bull[i].y, &img_bull[1] , SRCINVERT);
        }
    } 

然后就是对子弹的控制

if (GetAsyncKeyState(VK_SPACE))//空格发射子弹
        {
            createBullet();
        } 

 接下来就是输出敌机的相关数据,这里我们用两种飞机,一个大飞机和一个小飞机,他们的血量,大小各有差异

enum My{WIDTH=591,HEIGHT=864,BULLET_NUM=15,ENEMY_NUM=10,BIG,SMALL};

struct Plance//定义飞机
{
    int x;
    int y;
    int live;//是否存活
    int width;
    int height;
    int hp;
    int type;//敌机类型
}player,bull[BULLET_NUM],enemy[ENEMY_NUM];

 这里我们对不同类型的飞机的血量,出现概率都要有所调整

void enemyHp(int i)
{
    if (rand() % 10 == 2 )//十分之一的概率出现大飞机
    {
        enemy[i].type = BIG;
        enemy[i].hp = 3;
        enemy[i].width = 104;
        enemy[i].height = 148;
    }
    else
    {
        enemy[i].type = SMALL;
        enemy[i].hp = 1;
        enemy[i].width = 52;
        enemy[i].height = 39;
    }
}

for (int i = 0; i < ENEMY_NUM; i++)//初始化敌机
    {
        enemy[i].live = 0;
        enemyHp(i);
    }

因为上面用到了rand()函数,为了避免重复,我们在主函数中创建随机函数种子

srand((unsigned int)time(0));//生成随机数种子 

初始化敌机后,接着就是敌机的绘制与移动,绘制与上面相同,这里我就具体讲述移动

void createEnemy()
{
    for (int i = 0; i < ENEMY_NUM; i++)
    {
        if (enemy[i].live == 0)
        {
            enemy[i].live = 1;
            enemy[i].x = rand() % (WIDTH - 60);
            enemy[i].y = 0;
            enemyHp(i);//重置血量,防止一波打完以后飞机不在产生
            break;
        }
    }
}
void enemyMove(int speed)
{
    for (int i = 0; i < ENEMY_NUM; i++)
    {
        if (enemy[i].live == 1)
        {
            enemy[i].y += speed;
            if (enemy[i].y > HEIGHT)
            {
                enemy[i].live = 0;
            }
        }
    }
}  

因为飞机会同时下落,所以这里我们创建一个定时器,使飞机下落时有延续 

定时器,顾名思义,肯定会用到时间的,所以,获取时间我们就要用到time库,所以要引用头文件<time.h>

要做出定时器,首先就需要设定静态变量t1和t2,因为只有在设置静态变量的时候,t1和t2的值才不会在循环中每执行一次就变成原来初始化的值,我们要将其固定住,在下一次循环中执行的初始值为上一次执行后的结果值,所以,就自然地会考虑到使用静态变量这种方法。

接下来,就是在循环中设置一个条件,比如你想两次改变之间的间隔为500毫秒的时候,就可以在条件语句中写入t2 - t1 > 500,这样,就可以很好地表示出来。然后在条件语句中的语句块中先写你想要让程序执行的代码或自定义函数等,并将t2赋值给t1。如果在不满足条件语句的时候,或者执行完条件语句块之后,再将当前时间赋值给t2,所以,这里就需要用到clock函数来获取当前时间。这样,就可以把最基本的定时器很简单的就做出来了,具体的代码如下:

		static DWORD t1, t2,t3,t4;//定时器if (t2 - t1 > 500){createEnemy();t1 = t2;}t2 = clock();if (t4 - t3 > 5){enemyMove(1);t3 = t4;}t4 = clock();

最后就是如何击落敌机了

void playPlance()//击落敌机
{
    for (int i = 0; i < ENEMY_NUM; i++)
    {
        if (enemy[i].live == 0)
        {
            continue;
        }
        for (int k = 0; k < BULLET_NUM; k++)
        {
            if (bull[k].live == 0)
            {
                continue;
            }
            if (bull[k].x > enemy[i].x && bull[k].x<enemy[i].x + enemy[i].width
                && bull[k].y>enemy[i].y && bull[k].y < enemy[i].y + enemy[i].height)
            {
                bull[k].live = 0;
                enemy[i].hp--;
            }
        }
        if (enemy[i].hp <= 0)
        {
            enemy[i].live = 0;

        }
    }
}

总体代码就是这样,如果大家发现bug或者有更好的方法 ,欢迎大家一起来讨论呀,一起加油

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<time.h>//用于后期制作定时器
#include<graphics.h>//便于引入easyx窗口及其函数
#include<conio.h>//用于按键控制
IMAGE bk;
IMAGE img_role[2];
IMAGE img_bull[2];
IMAGE my_enemy[2];
IMAGE enemyPlane[2];
enum My{WIDTH=591,HEIGHT=864,BULLET_NUM=15,ENEMY_NUM=10,BIG,SMALL};
struct Plance//定义飞机
{int x;int y;int live;//是否存活int width;int height;int hp;int type;//敌机类型
}player,bull[BULLET_NUM],enemy[ENEMY_NUM];
void loadImage()//加载图片
{loadimage(&bk, "./background.jpg");loadimage(&img_role[0], "./planeNormal_1.jpg");loadimage(&img_role[1], "./planeNormal_2.jpg");loadimage(&img_bull[0], "./bullet1.jpg");loadimage(&img_bull[1], "./bullet2.jpg");loadimage(&my_enemy[0], "./enemy_1.jpg");loadimage(&my_enemy[1], "./enmey_2.jpg");loadimage(&enemyPlane[0], "./enemyPlane1.jpg");loadimage(&enemyPlane[1], "./enemyPlane2.jpg");
}
void enemyHp(int i)
{if (rand() % 10 == 2 )//十分之一的概率出现大飞机{enemy[i].type = BIG;enemy[i].hp = 3;enemy[i].width = 104;enemy[i].height = 148;}else{enemy[i].type = SMALL;enemy[i].hp = 1;enemy[i].width = 52;enemy[i].height = 39;}
}
void gameInit()//初始化数据
{player.x = WIDTH / 2;player.y = HEIGHT - 120;player.live = 1;for (int i = 0; i < BULLET_NUM; i++)//初始化子弹{bull[i].x;bull[i].y;bull[i].live = 0;}for (int i = 0; i < ENEMY_NUM; i++)//初始化敌机{enemy[i].live = 0;enemyHp(i);}
}
void createBullet()
{for (int i = 0; i < BULLET_NUM; i++){if (bull[i].live == 0){bull[i].x = player.x+60 ;bull[i].y = player.y ;bull[i].live = 1;break;}}
}
void BulletMove()
{for (int i = 0; i < BULLET_NUM; i++){if (bull[i].live == 1){bull[i].y -= 1;if (bull[i].y < 0){bull[i].live = 0;}}}
}
void gameDraw()//输出图片
{BeginBatchDraw();//开始绘图putimage(0, 0, &bk);putimage(player.x, player.y, &img_role[0],NOTSRCERASE);putimage(player.x, player.y, &img_role[1],SRCINVERT);//绘制子弹for (int i = 0; i < BULLET_NUM; i++){if (bull[i].live == 1){putimage(bull[i].x, bull[i].y, &img_bull[0], NOTSRCERASE);putimage(bull[i].x, bull[i].y, &img_bull[1] , SRCINVERT);}}//绘制敌机for (int i = 0; i < ENEMY_NUM; i++){if (enemy[i].live == 1){if (enemy[i].type == BIG){putimage(enemy[i].x, enemy[i].y, &enemyPlane[0], NOTSRCERASE);putimage(enemy[i].x, enemy[i].y, &enemyPlane[1], SRCINVERT);}else{putimage(enemy[i].x, enemy[i].y, &my_enemy[0], SRCINVERT);putimage(enemy[i].x, enemy[i].y, &my_enemy[1], NOTSRCERASE);}}}EndBatchDraw();// 结束绘图
}
void createEnemy()
{for (int i = 0; i < ENEMY_NUM; i++){if (enemy[i].live == 0){enemy[i].live = 1;enemy[i].x = rand() % (WIDTH - 60);enemy[i].y = 0;enemyHp(i);//重置血量,防止一波打完以后飞机不在产生break;}}
}
void enemyMove(int speed)
{for (int i = 0; i < ENEMY_NUM; i++){if (enemy[i].live == 1){enemy[i].y += speed;if (enemy[i].y > HEIGHT){enemy[i].live = 0;}}}
}
void playerMove(int speed)//移动玩家
{if (_kbhit())//判断是否有按键,有按键才处理,无按键就不处理{char input = _getch(); //控制台可以直接读取我按的键switch (input){case 'w':player.y -= speed;if (player.y <= 0)   //边界处理player.y = 0;break;case 's':player.y += speed;if (player.y >= HEIGHT - 120)player.y = HEIGHT - 120;break;case 'a':player.x -= speed;if (player.x <= -40)player.x = -40;break;case 'd':player.x += speed;if (player.x >= WIDTH - (117 / 2))player.x = WIDTH - (117 / 2);break;}//与上一种按键方式相比,这一种更加丝滑流畅if (GetAsyncKeyState(VK_UP))//上键{player.y -= speed;if (player.y <= 0)player.y = 0;}if (GetAsyncKeyState(VK_DOWN))//下键{player.y += speed;if (player.y >= HEIGHT - 120)player.y = HEIGHT - 120;}if (GetAsyncKeyState(VK_LEFT))//左键{player.x -= speed;if (player.x <= -40)player.x = -40;}if (GetAsyncKeyState(VK_RIGHT))//右键{player.x += speed;if (player.x >= WIDTH - (117 / 2))player.x = WIDTH - (117 / 2);}if (GetAsyncKeyState(VK_SPACE))//空格发射子弹{createBullet();}}
}
int Timer(int ms)
{static DWORD t1, t2;//定时器if (t2 - t1 > ms){t1 = t2;return 1;}t2 = clock();
}
void playPlance()//击落敌机
{for (int i = 0; i < ENEMY_NUM; i++){if (enemy[i].live == 0){continue;}for (int k = 0; k < BULLET_NUM; k++){if (bull[k].live == 0){continue;}if (bull[k].x > enemy[i].x && bull[k].x<enemy[i].x + enemy[i].width&& bull[k].y>enemy[i].y && bull[k].y < enemy[i].y + enemy[i].height){bull[k].live = 0;enemy[i].hp--;}}if (enemy[i].hp <= 0){enemy[i].live = 0;}}
}
int main()
{srand((unsigned int)time(0));//生成随机数种子//创建一个窗口initgraph(WIDTH,HEIGHT);loadImage();gameInit();//双缓冲绘图BeginBatchDraw();while (1){gameDraw();FlushBatchDraw();//刷新一下,防止黑屏playerMove(30);BulletMove();static DWORD t1, t2,t3,t4;//定时器if (t2 - t1 > 500){createEnemy();t1 = t2;}t2 = clock();if (t4 - t3 > 5){enemyMove(1);t3 = t4;}t4 = clock();playPlance();}EndBatchDraw();return 0;
}

 


http://chatgpt.dhexx.cn/article/0iVSbMPN.shtml

相关文章

c语言小游戏百度云资源,c语言小游戏合集

这是c语言小游戏合集下载&#xff0c;这是我用c语言写的程序&#xff0c;我在大三上学期的劳动成果展示。我的其他资源都是免费的&#xff0c;是对于c语言初学者的帮助比较大的&#xff0c;其中有数据结构&#xff0c;window编程。我也在学c语言&#xff0c;每当我写完一个程序…

C语言俄罗斯方块

C语言俄罗斯方块 先看效果 代码如下 /************************************** 俄罗斯方块* 1. 游戏开始界面&#xff0c;显示界面* 2. 方块的产生,及判断方块产生的位置是否有方块&#xff0c;有就退出游戏* 3. 方块的移动&#xff0c;旋转&#xff0c;左右移动&#xff0c;…

C语言小游戏快速入门--弹跳小球

目录 一、前言二、弹跳小球的实现2.1、界面设置2.2、弹跳逻辑1、 game.h2、 game.c3、 test.c 三、总结 一、前言 相信很多小伙伴在学习完C语言语法之后就想要做几个小游戏&#xff0c;来练练手。弹跳小球就很适合C语言初学者&#xff0c;甚至你不需要学习到数组的知识就可以上…

【C语言】简单小游戏项目:《别踩白块儿》

序 突然喜欢惊鸿一瞥这个词&#xff0c;一见钟情太肤浅日久生情太苍白&#xff0c;别人眉来眼去&#xff0c;我只偷偷看你一眼。 嗨&#xff01;这里是狐狸~ 新的一周又开始了&#xff0c;时间过得还真快&#xff0c;不知道给大家分享点啥了&#xff0c;想发偏算法之类怕大家…

【C语言小游戏】走迷宫

偶然翻到了自己大一时候写的一些代码&#xff0c;代码冗余&#xff0c;但还是想保存下来&#xff0c;以作纪念。 文章目录 1.运行效果2.运行环境3.完整代码 1.运行效果 2.运行环境 源码(Dev5.4.0版本下可直接(.cpp文件)运行 gcc 4.7.2) 注意&#xff1a;由于部分代码为C11标准&…

C语言小游戏------贪吃蛇----小白专用

C语言贪吃蛇小游戏 视频正在随缘策划中。。。。 废话在后面直接上程序 该程序在VS2019上可完美运行。 #include<stdio.h> #include<stdlib.h> #include<Windows.h> #include<time.h> #include<conio.h> constexpr auto maphigh 28, mapwid…

bootstrap时间控件--时间选择器

对应上面的三个时间选择器&#xff0c;写法如下&#xff1a; 首先引入css和js&#xff1a; <link href"https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel"stylesheet"> <link href"https://cdn.bootcss.com/bootstrap-…

日期时间控件

标题 开发软件使用到日期时间控件的地方很多&#xff0c;但是很多时候Html5自带的时间控件无法满足开发的需要&#xff0c;所以使用这种时间控件完全没有问题 引用 很多时候我们开发引用别人的控件时候&#xff0c;发现老是出现错误&#xff0c;是因为我们引用出现错误&#x…

时间控件(Time Control)

之前在网上看时间控件&#xff0c;看到这个http://hi.baidu.com/fxh19860822/blog/item/dd17d923343556ae4623e8e9.html&#xff0c;感觉颜色蛮好的&#xff0c;后来觉得要是时针、分针、秒针也可以供用户交互就更好了&#xff0c;不管怎样&#xff0c;有了idea就试试吧。 老规…

时间日期选择控件

这篇blog带来一个感觉不错的时间日期选择控件&#xff0c;当然&#xff0c;该控件也可以自定义选项内容。但这里主要说下时间选择的功能&#xff01; github地址 跟着大神的脚步&#xff0c;总有一天会成为神&#xff01; 效果&#xff1a; 关键点&#xff1a; 该控件可以…

jqueryUI日期控件和时间控件

日期控件用法&#xff1a; <!DOCTYPE html> <head><meta charset"utf-8"><title>日期</title><link rel"stylesheet" href"css/jquery-ui.css"><script src"js/jquery-3.3.1.min.js"><…

Timer时间控件

第一步、创建一个Windows窗体&#xff0c; 第二步、创建样式&#xff0c;在工具箱中找到TextBox和Labell、Button、timer。 第三步、改变属性的Name和 Text&#xff08;就是改写名称&#xff09; 第四步、排版按钮 1&#xff1a;使用的控制器是Label&#xff1b;name改为lbl…

web前端时间控件使用

官方参考地址&#xff1a;http://www.layui.com/laydate/ 1.首先把下载的layDate文件夹放入项目目录下 2.在需要使用的页面引入/layDate/laydate.js 3.创建input并使用js初始化input&#xff0c;获取选择时间值时只需获取input的value即可 官方实例&#xff1a; 生成效果&a…

时间日期控件的使用

在Android中&#xff0c;时间日期控件相对来说还是比较丰富的。其中&#xff0c;DatePicker用来实现日期输入设置&#xff0c;TimePicker用来实现时间输入设置。DatePickerDialog用来显示日期对话框&#xff0c;TimePickerDialog用来显示时间对话框。AnalogClock用来显示一个指…

Android中日期和时间控件的使用

本文主要讲述Android中的日期控件和时间控件的使用&#xff0c;以一个Demo的例子来展示日期和时间控件的使用&#xff0c;先看下如下效果图&#xff1a; 从效果图中可以看到该Demo是通过单击【选择日期】按钮和【选择时间】按钮弹出日期或者时间的对话框&#xff0c;然后设置日…

前端时间控件

1.My97 Datepicker js引入&input标签编写 <script type"text/javascript" src"<%request.getContextPath() %>/js/My97DatePicker/WdatePicker.js"></script> <input style"width: 80%" id"showStartDate&quo…

Android开发之日期时间控件选择

Android开发之日期时间控件选择 文章目录 前言一、创建弹出Layout1.1 新建Layout&#xff0c;修改样式为LinearLayout1.2 Layout中添加日期和时间控件 二、新建DateTimeDialog2.1 创建静态方法2.1.1 创建SetDateDialog&#xff0c;用于选择日期2.1.2 SetDateDialog中绑定textVi…

Web前端-时间日期控件

需求&#xff1a;同时可以选择 时间 和 日期 通过设置type属性为datetime&#xff0c;即可在同一个选择器里同时进行日期和时间的选择 <template><div class"block"><span class"demonstration">默认</span><el-date-pickerv…

android时间控件

原文地址&#xff1a;http://www.360doc.com/content/14/0617/16/18203124_387517665.shtml 前言 这一篇博客分别讲解Android平台下&#xff0c;关于日期和时间的几个相关控件。包括DatePicker&#xff08;日期选择控件&#xff09;、TimePicker&#xff08;时间选择控件&…

时间控件(选择时间范围的插件)

后台开发&#xff0c;一般都是有筛选条件的查询&#xff0c;那么问题就来了&#xff0c;根据日期范围搜索的情况下&#xff0c;插件要怎么选&#xff1f;&#xff1f;&#xff1f;&#xff1f; 这个是最开始&#xff0c;我采用的是两个时间插件&#xff0c;其他也没啥&#xff…