最近我制作了一个Boss,并实现了花园场景的存档。

首先是Boss的制作,最麻烦的是找素材,因为在网上难以找到所有的原版PVZ的素材,所以开始我解包了原版PVZ的游戏资源,但是得到的是僵尸肢体的图片,所以想要完全再现原版需要我们手动拼装僵尸并制作动画,所以我解包了另一个游戏,制作了简单的几个动画。

上面两张是动画原图,下面是Boss在游戏中释放了技能。在Boss关卡中,只要Boss存活就会无限产生僵尸,这个很好实现,在无尽模式中已有僵尸管理器用来产生和销毁僵尸,那么只要定时调用方法增加场景中的僵尸即可。

private IEnumerator CreatZombie(){iscreateZombie = true;animator.Play("bossCall");yield return new WaitForSeconds(1.5f);switch (Random.Range(0, 3)){case 0:ZombieManager.Instance.UpdateZombieByBoss(7, ZombieType.Zombie);break;case 1:ZombieManager.Instance.UpdateZombieByBoss(5, ZombieType.ConeheadZombie);break;case 2:ZombieManager.Instance.UpdateZombieByBoss(2, ZombieType.BucketheadZombie);break;}yield return new WaitForSeconds(2f);animator.Play("BossStay");yield return new WaitForSeconds(15f);iscreateZombie = false;}

这里我使用了协程的方式,便于播放动画以及冷却召唤间隔,同时为了凸显与普通刷新不同,我做了简单的特效以表明这是由Boss召唤出来的僵尸。

在原版中僵王会召唤火球清除一路的植物,关于火球的实现我取巧将其视为僵尸以便它可以被樱桃炸弹和火爆辣椒消除。

原版的僵王作为一个Boss只有很简单的技能,但是因为庞大的身躯造成强烈的视觉效果而不觉得有什么违和,而我制作的Boss在失去了巨大的身躯后只能通过技能上的优势来凸显难度,所以我还做了两个技能。一个是场地会定时在随机位置产生爆炸对爆炸点周围8格产生高额伤害。当然这个爆炸点是随机的。

void ReleaseMissile(){StartCoroutine(DoReleaseMissile());}private IEnumerator DoReleaseMissile(){isReleaseMissile = true;yield return new WaitForSeconds(3.5f);animator.Play("bossReleaseSkill");yield return new WaitForSeconds(1.5f);//产生一个导弹GameObject prefab = GameManager.Instance.GameConf.Missile;Missile missile = PoolManager.Instance.GetObj(prefab).GetComponent<Missile>();missile.transform.SetParent(transform);missile.transform.position = GridManager.Instance.GetGrid().Position + new Vector2(0,1.9f);missile.StartBoom();yield return new WaitForSeconds(2f);animator.Play("BossStay");yield return new WaitForSeconds(80f);isReleaseMissile = false;}public void StartBoom(){StartCoroutine(CheckBoom());}/// <summary>/// 检测爆炸/// </summary>/// <returns></returns>IEnumerator CheckBoom(){while (true){yield return new WaitForSeconds(2.2f);Boom();}}private void Boom(){// 播放爆炸音效AudioManager.Instance.PlayEFAudio(GameManager.Instance.GameConf.Boom);// 找到可以被我攻击的敌人,并且附加伤害Vector2 pos = new Vector2(transform.position.x, transform.position.y-1.9f);List<Grid> grids = GridManager.Instance.GetGrids(pos, 2.25f);if (grids == null) return;for (int i = 0; i < grids.Count; i++){if (!grids[i].HavePlant){continue;}else{grids[i].CurrPlantBase.Hurt(500);}}// 放入缓冲池if (animator.GetCurrentAnimatorStateInfo(0).normalizedTime >= 1){Dead();}}

然后是一个大范围伤害技能,必定清除向日葵等功能性植物,豌豆等普通攻击植物会残余小部分生命值。考虑到难度问题我没有再设计新的技能。

//技能,全场攻击private IEnumerator DoReleaseFlame(){isReleaseFlame = true;yield return new WaitForSeconds(1.5f);animator.Play("bossReleaseSkill");yield return new WaitForSeconds(1.5f);//飞鸟GameObject prefab = GameManager.Instance.GameConf.Bird;for(int i = 0; i < 3; i++){Bird bird = PoolManager.Instance.GetObj(prefab).GetComponent<Bird>();bird.transform.SetParent(transform);bird.transform.position = new Vector2(3.8f, 2.8f*Random.Range(-1,2));bird.StartFly();yield return new WaitForSeconds(0.8f);}yield return new WaitForSeconds(2f);animator.Play("BossStay");yield return new WaitForSeconds(50f);isReleaseFlame = false;}
public void StartFly(){StartCoroutine(CheckFly());}/// <summary>/// 检测爆炸/// </summary>/// <returns></returns>IEnumerator CheckFly(){while (transform.position.x > -24){Fly();yield return new WaitForSeconds(0.04f);transform.Translate((new Vector2(-15f, 0) * (Time.deltaTime / 1)));}Dead();}private void Fly(){// 找到可以被我攻击的敌人,并且附加伤害Vector2 pos = new Vector2(transform.position.x, transform.position.y);List<Grid> grids = GridManager.Instance.GetGrids(pos, 3.25f);if (grids == null) return;for (int i = 0; i < grids.Count; i++){if (!grids[i].HavePlant){continue;}else{grids[i].CurrPlantBase.Hurt(8);}}}

然后是关于花园系统的完善,之前制作的时候只要点击种子就可以种植植物。但是在原版中情况是当僵尸死亡后会有几率掉落植物种子,然后在花园中的物品栏出现植物种子,种植后种子消失。那么为了实现不同场景间的数据交流,本地的数据存储与读取是必须的,我的实现方式是,当僵尸死亡时会掉落卡片,点击卡片会向本地文件写入一个种子的类型。

    /// <summary>/// 死亡,/// </summary>public void Dead(bool playOndead=true){if (playOndead){OnDead();}switch (Random.Range(0, 10)){case 0:case 1:case 2://掉落种子卡片store seed = PoolManager.Instance.GetObj(GameManager.Instance.GameConf.seedCard).GetComponent<store>();seed.transform.position = transform.position;seed.Init();break;}// 告诉僵尸管理器,我死了isSpecialDie = false;isSpeedUp = false;//不加速spriteRenderer.color = Color.white;  //把颜色恢复正常ZombieManager.Instance.RemoveZombie(this);StopAllCoroutines();currGrid = null;PoolManager.Instance.PushObj(Prefab, gameObject);}

当进入花园场景时会读取本地文件获取种子信息,如果有物品栏中就会出现种子,每次点击更新本地文件,当所有种子都被种下后,物品栏中的种子就会消失。

然后我通过读取本地文件的方式保存了花园的当前场景的种植信息,之前只是实现了种植,但是一旦切换了场景之后所有的场景就会重置,所以我在本地文件中保存了植物的种类以及种植的位置。最初我是想将自己写的Grid类序列化,因为整个场景是通过Grid的集合来管理的,每一个植物的信息都保存在Grid中,这样的话读取文件的时候就不需要再现种植操作了,但是在序列化的过车各种报了错,经过测试最终我只能序列化一些比较基本的数据类型,保存的数据如下:

[System.Serializable]
public class Save
{//我需要存储的数据public List<PlantType> type = new List<PlantType>();//种子代表的植物种类public int goldNum;//金币数量public List<PlantType> GardenGrids = new List<PlantType>();//目前已经中了哪些植物public List<float> PositionsX = new List<float>();//这些植物在什么位置public List<float> PositionsY = new List<float>();//这些植物在什么位置
}

最终在加载存档时,我通过植物类型与种植位置将其再次种植,实现了简单读档功能。大体操作如下,特殊场景特殊处理:

 //写入文件public void Save(){/*seed sed = GameObject.Instantiate<GameObject>(GameManager.Instance.GameConf.seed, new Vector3(-2.57f, 4.78f, 0), Quaternion.identity, transform).GetComponent<seed>();sed.CardType = type;*/// 如果文件存在,则显示保存成功if (File.Exists(path)){BinaryFormatter bf = new BinaryFormatter();// 打开一个文件流FileStream fileStream = File.Open(path, FileMode.Open);// 调用格式化程序的反序列化方法,将文件流转换为Save 对象Save save = (Save)bf.Deserialize(fileStream);for (int i = 0; i < save.type.Count; i++){Debug.Log(save.type[i]);}fileStream.Close();save.type.Add(type);//想将数据序列化需要将文件create而不是openfileStream = File.Create(path);bf.Serialize(fileStream, save);fileStream.Close();Debug.Log("保存成功");}else{Save s = new Save();s.type.Add(type);BinaryFormatter bf = new BinaryFormatter();// 创建一个文件流FileStream fileStream = File.Create(path);// 用二进制格式化程序的序列化方法 来 序列化Save对象//      参数:创建的文件流和需要序列化的对象bf.Serialize(fileStream, s);// 关闭流fileStream.Close();if (File.Exists(path)){Debug.Log("保存成功");}}}//读取文件public void Load(){if (File.Exists(path)){// 反序列化过程// 创建一个二进制格式化程序BinaryFormatter bf = new BinaryFormatter();// 打开一个文件流FileStream fileStream = File.Open(path, FileMode.Open);// 调用格式化程序的反序列化方法,将文件流转换为Save 对象Save save = (Save)bf.Deserialize(fileStream);// 关闭文件流fileStream.Close();for(int i = 0; i < save.type.Count; i++){Debug.Log(save.type[i]);}Debug.Log("加载成功");}else{Debug.Log("文件不存在");}}

项目实训个人报告(二)相关推荐

  1. 项目实训(十二)FPS游戏之角色移动的脚步声

    文章目录 前言 一.存放脚步声音 二.设置脚步声 1.角色发出声音的必备条件 2.如何检测角色是否有移动 3.如何实现角色踩踏位置的对应材质的声音 三.修复下蹲移动时没有脚步声音 前言 FPS游戏之角 ...

  2. 山东大学软件学院项目实训-创新实训-山大软院网络攻防靶场实验平台(二)-docker安装与学习

    目录 前言: 一.docker安装 1.centos7使用yum安装 二.命令行创建 docker 容器测试 前言: 项目实训立项通过后的几天均在学习 docker 的相关知识,上一篇文章也简单记述了 ...

  3. 项目实训工作记录(二)

    项目实训工作记录(二)赵乐乐 201800301115 词向量搜索分析与算法设计 项目实训工作记录(二)赵乐乐 201800301115 1.词向量搜索 2.搜索过程中的问题分析 3.基于效率的算法设 ...

  4. c语言小车寻迹实训报告,循迹小车项目实训报告.doc

    循迹小车项目实训报告 寻迹小车的设计与制作实训报告 课程名称: C51程序设计 EDA技术 专业班级: 应电0935班 指导老师: 方跃春 谭刚林 小组成员: 黄春桥 汤政 孙巍明 阳毅 实训项目要求 ...

  5. java质数和合数的程序_《java项目实训》课程设计计算器.doc

    <java项目实训>课程设计计算器.doc 课程设计报告课程名称JAVA项目实训课程设计设计名称基于JAVA计算器的设计与实现学生学号学生姓名学生学号学生姓名学生学号学生姓名学生学号学生姓 ...

  6. 大学计算机组装与维护实训的目的,计算机组装与维护实训实习报告

    计算机组装与维护实训实习报告 实验一 微机组装 一. 实训目标 通过学习本实训内容,掌握微机组装方面的知识,进一步加深对微机硬件系统的认识,具备微机硬件维护的基本功能. 二. 实训内容 分组练习微机硬 ...

  7. php实训方案,最新PHP实训实践报告资料

    <最新PHP实训实践报告资料>由会员分享,可在线阅读,更多相关<最新PHP实训实践报告资料(14页珍藏版)>请在人人文库网上搜索. 1.最新PHP实训实践报告资料最新PHP实训 ...

  8. 实训课教案二:计算机软件安装初步

    实训课教案二:计算机软件安装初步 实训内容:计算机操作系统安装之前的 CMOS设置和磁盘分区格式化 实训课时:2课时 实训地点:计算机组装与维护实验室 实训目的: 1.掌握CMOS的基本设置. 2.能 ...

  9. java编码规范文档 下载_软件项目实训及课程设计指导——制定待开发项目中各种文档的规范...

    软件项目实训及课程设计指导--制定待开发项目中各种形式文档的规范 1.制定对课程设计项目开发过程中的规范性要求 (1)从"形式"到"内容"两个方面控制和要求开发 ...

  10. web前端小项目个人实例_Web前端:小程序界面与逻辑项目实训

    大家好,我来了!本期为大家带来的Web前端学习知识是"Web前端:小程序界面与逻辑项目实训",喜欢Web前端的小伙伴,一起看看吧! 主要内容 数据绑定 渲染 界面层数据渲染 事件处 ...

最新文章

  1. Canonical面向Ubuntu 16.04 LTS发布首批内核安全修复补丁
  2. 第十六届全国大学生智能车竞赛百度智慧交通竞赛成绩
  3. mysql什么时候用in,什么时候用exists
  4. 图形渲染技术分享:《GTA V 》图形分析摘要
  5. 前端学习(2321):angular环境搭建1
  6. c语言case key pres,C#程序设计B-中国大学mooc-题库零氪
  7. 在deepin中安装docker
  8. Java是有法_Java基础语法
  9. 服务器组件架构,tomcat组件图解 一个web服务器的架构演化史
  10. C#.NET如何将cs文件编译成dll文件 exe文件 如何调用dll文件
  11. bzoj4144【AMPPZ2014】Petrol
  12. php可以用wamp哪个好,PHPWAMP好吗?phpwamp怎么用?PHPWAMP和其他集成环境有什么区别吗??...
  13. 世界名牌CD机解码芯片大全
  14. 网络:以太网类型(EthernetType)整理
  15. 千里马Android Framework-input系统专题blog目录集合
  16. Centos:设置代理
  17. 肠道微生物如何影响骨骼发育和代谢
  18. FTP服务器文件自动上传、下载(bat)
  19. 随身wifi与宽带的区别是什么?
  20. 如何找回误删除的微信好友?这五种方法简单有效

热门文章

  1. python中abbab什么意思_ABtest与Python代码-Go语言中文社区
  2. php中exec的用法,php exec用法详解
  3. 逻辑漏洞之任意密码重置
  4. axure原型怎么让文字自动换行_蓝湖 for Mac(自动切图sketch插件)
  5. Python类和包的介绍
  6. 京东方、立讯精密纷纷向苹果靠拢,再次撕下国产手机遮羞布
  7. Rational Rose 7.0安装教程
  8. 测试手机软件打开速度的app,一加6千分之一秒 百款APP打开速度对比
  9. 中国古代30大名将VS100名将排行(按时间顺序)
  10. ODL开发【SDN控制器-下】【C4-04】