自制Unity小游戏TankHero-2D(2)制作敌方坦克

我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的。仅为学习Unity之用。图片大部分是自己画的,少数是从网上搜来的。您可以到我的github页面(https://github.com/bitzhuwei/TankHero-2D)上得到工程源码。

本篇主要记录制作敌方坦克(Tank1)的一些重点。

原本制作敌方坦克是很简单的,只要把TankHero复制一份,改改贴图就差不多了。不过考虑到代码的简洁和可重用,本篇花了些心思在重构上。

关于自定义鼠标箭头

上一篇介绍了如何自定义鼠标箭头的事。这里补个漏。经过上一篇的研究,已经可以显示自定义的鼠标样式了,但是原有的鼠标箭头仍然存在,这怎么办?容易,只需制作一个1*1像素的全透明的png图片,赋给Default Cursor即可。实际上就是让默认鼠标样式透明掉。

敌方坦克模型

这个模型依旧是用PPT做的。SmartArt+“形状”解决问题。具体技巧可参考上一篇。

敌方坦克结构

如上图所示,使用Duplicate从TankHero复制一个,重命名为Tank1。Tank1就是我们要做的敌方坦克了。其炮塔、底座、炮弹起始点这些结构都是一样的。

重构坦克运动代码

玩家坦克和敌方坦克有很多共同点,比如坦克对象的结构。也有一些特征(移动、旋转、开炮等)既相似又不同。具体来说,玩家坦克是由鼠标键盘指挥的,敌方坦克则要由AI指挥。指挥者不同,但是指挥的效果都是移动旋转开炮,是可以用同样的代码处理的。所以我在这里抽象出一个专门保存指挥信息的Movement类,这样就隔开了指挥者与执行者。

PlayerMovement接收用户输入的信息,存到基类的字段。Tank1Movement用AI获取指挥信息,存到基类的字段。

这样一来,在其它地方(不同类型的坦克的炮塔、底座)就都可以用 Movement m = this.GetComponentXXX<PlayerMovement>(); 这样统一的方式获取平移、旋转、目标、目的地等信息了。

下面我们来详细介绍。

底座的旋转和轮子滚动

两种坦克的底座部分,只有轮子滚动部分是不同的。两者使用的脚本则都是TankBaseRotation和WheelMovement。

WheelMovement代码没有任何改变,只不过在Inspector里的Wheels数组元素不同而已。

在TankBaseRotation中则出现了这样的代码:

1     private Movement movementScript;
2
3     void Awake()
4     {
5         movementScript = this.GetComponentInParent<Movement> ();
6     }

有了 movementScript 就可以得到坦克的移动方向 movementScript.baseDirection ,就可以更新坦克底座的旋转角度了。

 1     void Update () {
 2         if (movementScript == null) { return; }
 3
 4         var angle = Mathf.Atan2 (movementScript.baseDirection.y, movementScript.baseDirection.x) * Mathf.Rad2Deg;
 5         if (Mathf.Abs(angle - this.targetAngle) > 0.01f)
 6         {
 7             this.targetAngle = angle;
 8             this.targetRotation = Quaternion.Euler (0, 0, angle);
 9         }
10
11         this.transform.rotation = Quaternion.Slerp (
12             this.transform.rotation,
13             Quaternion.Euler (0, 0, angle),
14             rotationSpeed * Time.deltaTime);
15     }

炮塔的旋转和武器管理

这样就无需为两种坦克写两套旋转底座的脚本了。以后添加了新型坦克也仍然只需这一个脚本。

TankHero和Tank1的炮塔旋转中心(Rotation Center)和武器(Weapons)不同,但他们使用了相同的脚本(TankHeadRotation和WeaponManager)。这两个脚本中也都有如下的代码。

1     private Movement movementScript;
2
3     void Awake()
4     {
5         this.movementScript = this.GetComponentInParent<Movement> ();
6     }

在movementScript中保存着目标的位置( fireTarget ),旋转炮塔也很容易。

 1     void Update () {
 2         if (this.movementScript == null) { return; }
 3
 4         var y = this.movementScript.fireTarget.y - this.transform.position.y;
 5         var x = this.movementScript.fireTarget.x - this.transform.position.x;
 6         if (Mathf.Abs(y) > Quaternion.kEpsilon || Mathf.Abs(x) > Quaternion.kEpsilon)
 7         {
 8             this.targetAngle = Mathf.Atan2(y, x) * Mathf.Rad2Deg;
 9             var angle = this.targetAngle - this.transform.rotation.eulerAngles.z;
10             this.transform.RotateAround (this.rotationCenter.position, new Vector3 (0, 0, 1), angle);
11         }
12     }

TankHero是玩家用鼠标开炮的,敌方坦克是自动开炮的。用 autoFire 标记坦克是否自动开炮即可。

 1     void Update () {
 2         passedInterval += Time.deltaTime * 10;
 3         if (passedInterval >= currentWeaponConfig.interval)
 4         {
 5             if (this.autoFire || Input.GetButton("Fire1"))
 6             {
 7                 passedInterval = 0;
 8                 var bullet = Instantiate(currentBullet, bulletStartPosition.position, this.transform.rotation) as Transform;
 9                 bullet.renderer.enabled = true;
10                 var bulletFly = bullet.GetComponent<BulletFly>();
11                 bulletFly.undying = false;
12                 bulletFly.velocity = currentWeaponConfig.velocity;
13                 bulletFly.shooter = this.gameObject;
14                 bulletFly.targetPosition = movementScript.fireTarget;
15             }
16         }
17     }

武器系统

有了新的坦克,我们需要给它设计新的武器。只需Duplicate一下NormalBulletWeapon,再在WeaponConfig组件里调整一下敌方坦克武器的参数(炮弹速度调慢一点,不然敌人就太厉害了)。将新武器EnemyNormalBulletWeapon赋给Tank1的炮塔即可。

炮弹仍然是原有的那个,只需换一个贴图即可。

多种炮弹

玩过(http://game.kid.qq.com/a/20140221/028931.htm)的会发现有多种炮弹。其速度、攻击形式都不一样。

就是说,在不同类型的炮弹碰撞到某物时,会发生不同的事。因此我对控制炮弹飞行的脚本进行了抽象,在具体的子类里编写 Trigger 碰撞事件,用以处理不同的炮弹。

注意:如果在子类(NormalBulletFly)你添加了 void Update(); 方法,那么Unity就不会调用父类(BulletFly)的Update方法了。这对 Awake 等都适用。就是说,Unity引擎只查找那些在继承层次上离MonoBehaviour最远的事件函数,找到之后就不再理会其它层上的同名函数了。

为什么是最远的?因为一个gameobject,其具有NormalBulletFly这个组件,意思是此gameobject拥有一个类型为NormalBulletFly的实例。很自然地,Unity会选中此类型的方法表中的Update方法。只有在NormalBulletFly中不存在时,才会轮到其父类的方法表。

当然目前为止只有1种炮弹,所以只有1个具体的NormalBulletFly脚本。这样,以后无论有多少种炮弹,只需一个Bullet的prefab即可。

总结

坦克的运动和炮弹的攻击,我都进行了重构。重构的目的是为了将重复的代码(平移、旋转、开炮、飞行)合并到一处,不同的代码(用户输入vs AI控制,不同的攻击方式)分别写如不同的脚本。重构的技术就是面向对象设计。

您可以到我的github页面(https://github.com/bitzhuwei/TankHero-2D)上得到工程源码。

请多多指教~

转载于:https://www.cnblogs.com/bitzhuwei/p/tank-hero-2d-1-make-enemy-tank.html

自制Unity小游戏TankHero-2D(2)制作敌方坦克相关推荐

  1. 自制Unity小游戏TankHero-2D(1)制作主角坦克

    自制Unity小游戏TankHero-2D(1)制作主角坦克 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的. ...

  2. 自制Unity小游戏TankHero-2D(3)开始玩起来

    自制Unity小游戏TankHero-2D(3)开始玩起来 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的.仅 ...

  3. python自制小游戏_教你用Python自制拼图小游戏,一起来制作吧

    摘要: 本文主要为大家详细介绍了python实现拼图小游戏,文中还有示例代码介绍,感兴趣的小伙伴们可以参考一下. 开发工具 Python版本:3.6.4 相关模块: pygame模块: 以及一些Pyt ...

  4. unity小游戏制作之见缝插针

    unity小游戏制作之见缝插针 先看效果图这个游戏是一个入门的小游戏,主要技术就是圆盘的旋转,针跟随圆盘旋转以及分数累加等 游戏先拖入一个圆,更改格式为2D然后建立脚本使其转动 public clas ...

  5. Unity小游戏-彩笔画师(安卓、PC)2D益智类游戏 项目展示+完整项目源码

    游戏录像 游戏玩法 谁画在屏幕上占的颜色最多,谁获胜. 功能 1.游戏有多个关卡,每个关卡的人机难度不一致. 2.可以存金币购买角色,不同角色的技能和属性不一样. 3.每个关卡的评分等数据存到本地. ...

  6. Unity小游戏-平衡大师(安卓、PC、web)2D益智类游戏 项目展示+完整项目源码

    游戏录像 游戏试玩 平衡带师_平衡带师html5游戏_4399h5游戏-h.4399.com 游戏玩法 这是一款类似堆积木的游戏,它非常考验玩家的智商和手速,难度系数很高的游戏,谁能征服它,谁就是平衡 ...

  7. 帽子接球小游戏(一)--制作UI面板

    帽子接球小游戏(一)--制作UI面板 注:本小游戏共两章,第一章讲界面的制作,第二章讲后台代码控制接球.最终效果见下章. (工程中所使用到的所有图片都是我自己PS画的,比较粗糙,不太美观,能看就行,哈 ...

  8. 2022unity超简单课设-模拟太阳系的Unity小游戏

    模拟太阳系的Unity小游戏(附下载链接) 下载链接 unity课程实践做的一个模拟太阳系的Unity小游戏,你可以使用飞船移动来查看太阳系中的各个星球. 飞船拥有两种驾驶模式,一种更加真实,是通过给 ...

  9. Unity 小游戏:3D射箭

    Unity 小游戏:3D射箭 前两周因为实训太忙,再加上自己对老师所讲的设计模式并不是很理解,所以就没有写博客.这次博客是记录3D射箭游戏的实现过程. Unity 小游戏3D射箭 准备资源 布置场景 ...

  10. Unity小游戏(一)——Unity JigsawPuzzle(拼图游戏)

    1.前言: 简单的Unity小游戏,切割图片,生成随机区块,拖拽交换位置. 此游戏代码只贴了一小部分,具体可见GitHub:源码 效果: 2.素材准备 简单做了下,所以没有用太多素材,只准备了两种字体 ...

最新文章

  1. 【廖雪峰python入门笔记】list_替换元素
  2. 遗传算法 Genetic Algorithm
  3. Linux环境变量的设置和查看方法
  4. Java开发命名规范总结
  5. 5种JavaScript中常用的排序方法
  6. SQL Server数据库损坏、检测以及简单的修复办法
  7. 半导体对物联网之水与鱼的关系
  8. Java技巧-解决JAVA_HOME变量无效问题
  9. Java黑皮书课后题第8章:*8.3(按考分对学生排序)重写程序清单8-2,按照正确答案个数的升序显示学生
  10. 《textanalytics》课程简单总结(1):两种word relations——Paradigmatic vs. Syntagmatic...
  11. python观察日志(part3)--绘制科赫雪花图
  12. ASP.NET Core Razor 页面使用教程
  13. android各个版本的名称和更新(转)
  14. fdisk 分区_【linux】循序渐进学运维-基础篇-分区命令fdisk
  15. 空间统计分析_【空间分析】地理探测器原理
  16. 哈工大大数据实验_【新闻动态】南京大学PASA大数据实验室在KDD Cup 2020 AutoGraph自动化图数据建模国际挑战赛中荣获第二名...
  17. 《小艾上班记》—— 读后总结
  18. Partition does not end on cylinder boundary
  19. 用友U8案例教程委外管理前台操作
  20. 基于STM32的微信视频电话机,让家里的老人也能轻松使用微信视频电话

热门文章

  1. java判断字符串长度_JAVA 判断字符长度
  2. Insyde uefi 隐藏设置_vivo手机怎么隐藏应用 vivo手机怎样把软件隐藏起来?
  3. sow 项目范围说明书的区别
  4. 120xa变频器调试参数_图文并茂 | 西门子G120变频器的面板调试操作
  5. JUCE-VST-001 JUCE的下载与安装
  6. 马尔可夫链模型的信贷风险分析与预测
  7. 计算机求百钱买百鸡问题采用,5.5 百钱买百鸡问题
  8. Ubuntu临时修改ip地址
  9. 无线网路中的虚拟AP技术
  10. 用友商贸宝问题解答一