今天我们来尝试用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/PcJiP

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

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/Nh8Tz) 注意:这里要注意边界情况,使飞机在触碰边缘后停止移动,防止飞机出界

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

c语言小游戏-飞机大战相关推荐

  1. C语言小游戏 飞机大战

    C语言写的一个小游戏,飞机大战 直接复制代码就可以运行了QAQ #include<stdio.h> #include<stdlib.h> #include<windows ...

  2. c 语言500行小游戏代码,500行代码使用python写个微信小游戏飞机大战游戏.pdf

    500行行代代码码使使用用python写写个个微微信信小小游游戏戏飞飞机机大大战战游游戏戏 这篇文章主要介绍了500行代码使用python写个微信小游戏飞机大战游戏,本文通过实例代码给大家介绍的非常详 ...

  3. 用JAVA制作小游戏——飞机大战(三)

    本篇博客是对飞机大战游戏项目完整代码的展示 详细代码讲解: 用JAVA制作小游戏--飞机大战(一) 用JAVA制作小游戏--飞机大战(二) 最下方附整个程序的文件下载链接 代码展示 主界面 impor ...

  4. 用JAVA制作小游戏——飞机大战(二)

    本篇博客是对飞机大战游戏使用代码的展示 重难点: 首先需要鼠标能够控制战机,使鼠标在窗口内时始终能够使战机的位置与鼠标相同,实现鼠标控制战斗机移动. 其次需要能够以一定的速度产生子弹和敌机,并且以一定 ...

  5. java小游戏-java小游戏-飞机大战

    java小游戏-java小游戏-飞机大战 1 窗口创建 2 背景图片添加 3 启动页面制作 4 启动页面点击事件 5 游戏物体父类的编写 6 背景的移动 7 双缓存的添加 8 背景图片的循环出现 9 ...

  6. 【游戏开发实战】使用Unity 2019制作仿微信小游戏飞机大战(七):主角飞机碰撞与爆炸

    文章目录 零.教程目录 一.前言 二.本篇目标 三.飞机机碰撞组件:BoxCollider2D.Rigidbody2D 四.添加Tag:Enemy 五.主角飞机碰撞处理:OnTriggerEnter2 ...

  7. 【Python】Python小游戏--飞机大战

    一.前言 今天已经初四,舒服的在家躺尸的春节也算过去了,又要开始辛勤的(苦逼的)学习和工作了.说点题外话,今年春节的病毒疫情真的弄的人心惶惶,我也在这为国家和武汉加油,也向一线工作人员致敬,希望早日结 ...

  8. c语言小程序飞机大战,飞机大战微信小游戏:经典像素飞机大战小程序,点开即玩...

    50000+游戏爱好者已加入我们! 每天推荐好玩游戏! 关注我们,沐沐带你发现好游戏! <经典像素飞机大战>游戏小程序好玩吗? <经典像素飞机大战>小游戏怎么玩? 怎么进入&l ...

  9. cocos2d-x小游戏——飞机大战

    上周,我做了一个基于 cocos2d-x 的飞机大战的游戏,因为我刚学cocos2d-x没多久,所以这个飞机大战很多都是看着别人的教程,再加上自己的一些想法,来做的. 下面我想说一说我的思路. 飞机大 ...

最新文章

  1. LSGO软件技术团队招新
  2. Silverlight3实现按路径运动[原创]
  3. 堆栈被无意中修改导致程序挂掉
  4. PaddlePaddle训练营——公开课——AI核心技术掌握——第1章迈入现代人工智能的大门——深度学习的基础算法——反向传播算法简介
  5. Intellij IDEA 使用学习
  6. SAP 电商云 Spartacus UI 的 feature module 设计原理
  7. java 判断域密码到期提醒,Exchange Server 2010下,检测用户密码到期通知提醒脚本...
  8. TensorFlow 是一个用于人工智能的开源神器
  9. SAP License:物料分类帐-上一期间结算错误处理办法
  10. 《树莓派Python编程入门与实战》——1.2 获取树莓派
  11. mysql修改最大连接数笔记
  12. Matlab实现的数学模型(2020新整理)
  13. 2018年版北大中文核心期刊目录(2017最新第八版)
  14. 【常用0x000000类型颜色代码表】
  15. 浅谈输入阻抗、输出阻抗和阻抗匹配
  16. PAT日志 1147 Heaps
  17. python计算特征根以及特征向量
  18. python自定义函数求方差_计算高斯函数的标准差
  19. 索骥馆-思维训练之最佳记忆方法-王洪礼的奇象记忆思维技术与方法 》扫描版[PDF]
  20. RAC(ReactiveCocoa)之 RAC宏定义

热门文章

  1. 面向对象设计五大原则
  2. 从零开始学习React:掌握前端开发的核心技能——更新中
  3. 【systemverilog项目】AHB-SRAMC(AHB总线)个人学习笔记
  4. AES GCM算法实现
  5. 【负荷预测】基于灰色理论负荷预测的应用研究(Matlab代码实现)
  6. VeeValidate 配置中文
  7. swagger2 介绍+注解说明
  8. CCNP实验:CHAP认证、MGRE技术
  9. 互联网江湖,从此再无 BAT
  10. 计算机基础中k代表克,计算机信息计量单位中的k代表是什么?