欢迎光临散文网 会员登陆 & 注册

C语言手写-植物大战僵尸

2023-03-16 14:29 作者:C语言编程开发  | 我要投稿

项目效果(主页置顶视频)

说明:因为完整动图提交后提示违规,所以这里仅截图示意。如果需要演示视频,在评论中回复即可。

项目准备

  • 安装Visual Studio的任意版本(推荐VS2019社区版、VS2022社区版)

  • 安装easyx图形库(官网下载地址)

  • 领取项目素材(回复“植物大战僵尸”,即可领取)

    创建项目

    使用VS创建项目,使用空项目模板:

    导入素材:在项目目录下,创建res文件夹,把解压后的素材拷贝到res目录下。


    实现游戏初始场景

    代码如下(需要逐行代码视频讲解,可回复“代码讲解“)。

    添加启动菜单

    创建菜单界面,代码如下:

    在main函数中调用菜单,代码如下:


    生产阳光

    熟悉植物大战僵尸的同学都知道,种植植物才能消灭僵尸,但是种植植物,需要先具备一定数量的阳光值。初始的阳光值很小。有两种方式生成阳光:第一种,随机降落少量的阳光;第二种,通过种植向日葵,让向日葵自动生产阳光。我们先实现第一种方式。

    定义一个结构体,来表示阳光球。因为阳光是以旋转的方式运动的,所以定义一个图片帧数组,通过循环播放图片帧来实现旋转效果。

    在gameInit函数中,初始化阳光帧数组。


    创建阳光,代码如下。


    修改阳光的位置和帧序号,代码如下。

    在updateGame函数中调用以上两个函数 ,以创建阳光并更新阳光的状态。

    在updateWindow函数中,渲染阳光。


    收集阳光

    当“阳光球”出现的时候,用户点击阳光球,就可以“收集”这个阳光,当前总的阳光值就会增加25点。在原版的植物大战僵尸游戏中,阳光球被收集后,会慢慢移动到顶部的“工具栏”的左侧。这个阳光球的“移动过程”,我们后续再实现。

    定义一个全局变量,表示当前总的阳光值。

    int sunshine;

    在初始化gameInit中,设置一个初始值。

    sunshine = 150;

    创建收集阳光的函数,如下:

    在用户点击处理中,调用收集阳光的函数。

    显示当前总的阳光值

    在gameInit初始化中,设置字体。

    在updateWindow中绘制阳光值。


    创建僵尸

    创建僵尸的数据模型。这里一共创建了10个僵尸,这10个僵尸全部被消灭后,这个关卡就胜利了。

    僵尸数组,以及僵尸序列帧图片数组,在gameInit函数中进行初始化,如下。注意:把僵尸的素材图片保存到src/zm目录下。)


    创建僵尸,代码如下:

    更新僵尸的数据(僵尸的图片帧序号、僵尸的位置),代码如下:

    在updateGame函数中,创建僵尸并更新僵尸数据,如下:

    创建绘制僵尸的接口, 如下:


    在updateWindow函数中,绘制僵尸,如下:

    实现阳光球的飞跃

    现在的实现效果是,阳光被点击后,阳光球直接消失了!而原版的植物大战僵尸中,阳光被点击后,阳光会自动飞向左上角的位置,飞到终点后,阳光值才增加25点。我们的实现方式是,阳光球每次飞跃4个点,直到飞到终点,如下图:

    给阳光的结构体添加两个成员,表示飞跃过程中的偏移量:

    在阳光被创建时,把变异量设置为0, 如下:

    阳光被点击后,马上修改阳光球的xoff和yoff:


    在阳光飞跃过程中更新阳光的位置,如下:(注意是在飞跃过程中,不断计算偏移量,效果更好。)


    删除原来被点击后,立即更新阳光值的代码。


    修改渲染阳光的判断条件,如下:


    此时已经能够实现阳光的飞跃了,但是飞跃动作太慢了,后期我们再优化。

    发射豌豆

    僵尸靠近时,已经种植的植物豌豆就会自动发射“子弹”,我们先为子弹定义数据类型,如下:

    在gameInit函数中,初始化“豌豆子弹池”和子弹的图片,如下:

    在僵尸结构体中,添加成员row, 表示该僵尸所在的“行”,方便后续的判断。也可以不加,直接根据僵尸的y坐标来计算。


    在createZM函数中,创建僵尸的时候,设置row成员的值,如下:


    创建shoot函数,实现豌豆发射子弹,如下:


    更新子弹的位置,如下:


    在updateGame函数中,发射子弹并更新子弹的位置,如下:


    在updateWindow中绘制子弹,如下:


    子弹和僵尸的碰撞

    子弹碰到僵尸之后,子弹会“爆炸”,同时僵尸会“掉血”。我们先给僵尸添加血量成员。

    并在创建僵尸的时候,把血量初始化为100,如下:


    子弹在碰到僵尸之后才会爆炸,并显示爆炸图片:

    所以,我们在子弹的结构体中添加两个成员,分别表示当前是否已经爆炸,以及爆炸的帧图片序号,如下:


    在gameInit函数中对子弹帧图片数组,进行初始化,如下:


    在发射子弹shoot函数中,对子弹的blast和帧序号frameIndex进行初始化,如下:


    在更新子弹的updateBullets函数中,更新子弹爆炸的帧序号,如下:

    进行碰撞检测,检查子弹和僵尸是否发生碰撞,如下:


    在updateGame函数中,调用碰撞检测函数,如下:


    渲染子弹的爆炸效果,如下:


    僵尸死亡

    僵尸被豌豆子弹击中后,会“掉血”,血量掉光了,就直接KO了,同时变成一堆“黑沙”。

    给僵尸结构体添加dead成员,表示是否已经死亡,另外添加一个图片帧数组,用来表示变成成黑沙的过程。

    在gameInit中对这个图片帧数组进行初始化。

    在碰撞检测中对僵尸的血量做检测,如果血量降到0,就设置为死亡状态。如下:


    僵尸死亡后,在updateZM中,更新僵尸的状态(变成黑沙发)。如下:


    绘制僵尸的黑沙状态,如下:


    后续的内容详情看主页置顶视频

    C语言手写-植物大战僵尸的评论 (共 条)

    分享到微博请遵守国家法律