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


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

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

    本篇主要记录金币、按钮、坦克工厂、小地图等小部件,让整个场景初步成为一个可玩的游戏。

    在本篇在制作过程中,修改了前两篇的很多东西,算是对Unity更加熟悉了。

    金币

    玩家击毁一个敌方坦克,会敌方坦克所在位置会出现1个金币。金币可以用来升级玩家坦克的速度、武器等,也可以用来恢复生命。

    金币有3个脚本。

    Show Up控制金币的出现是从透明到全不透明的。

     1 public class ShowUp : MonoBehaviour {
     2 
     3     public float showUpSpeed = 1;
     4     private SpriteRenderer spriteRenderer;
     5 
     6     void Awake()
     7     {
     8         this.spriteRenderer = this.GetComponent<SpriteRenderer>();
     9         var color = this.spriteRenderer.color;
    10         this.spriteRenderer.color = new Color(color.r, color.g, color.b, 0);
    11     }
    12     
    13     // Update is called once per frame
    14     void Update () {
    15         if (this.spriteRenderer == null) { return; }
    16 
    17         this.spriteRenderer.color = Color.Lerp(this.spriteRenderer.color, Color.white, this.showUpSpeed * Time.deltaTime);
    18 
    19         //Debug.Log(string.Format("A: {0}", this.spriteRenderer.color.a));
    20         if (Mathf.Abs(Color.white.a - this.spriteRenderer.color.a) <= 0.02f)
    21         {
    22             this.spriteRenderer.color = Color.white;
    23             this.spriteRenderer = null;
    24         }
    25     }
    ShowUp.cs

     

    Coin Info保存金币的价值。

    注意:脚本中要保留一个Start或一个Update函数,否则在Inspector面板就不会显示脚本组件前面的勾选框了。

    1 public class CoinInfo : MonoBehaviour {
    2 
    3     public int value;
    4     
    5     void Start()
    6     {
    7     }
    8 
    9 }

     

    Picked Coin让金币碰到玩家坦克时销毁自己。

     1 public class PickedCoin : MonoBehaviour {
     2 
     3     private bool picked;
     4 
     5     void Awake()
     6     {
     7         this.picked = false;
     8 }
     9 
    10     void Start () {
    11     
    12     }
    13 
    14     void OnTriggerEnter2D(Collider2D other)
    15     {
    16         if (other.tag != Tags.hero) { return; }
    17 
    18         if (!this.picked)
    19         {
    20             this.picked = true;
    21             MonoBehaviour.Destroy(this.gameObject);
    22         }
    23     }
    24 }

    游戏暂停和继续

    用一个按钮来控制游戏的暂停和继续。

    选择UI-Button即可添加一个按钮。

    在按钮的Button组件中,添加一个btnPause.cs脚本,添加一个On Click(),选择这个btnPause.cs脚本组件,选择对应的事件函数即可。(下图是错的,应该把btnPause.cs组件赋给On Click项。

    那么事件函数怎么写呢?

    游戏暂停的原理很简单,只需 Time.timeScale = 0; ,那么今后所有的 Time.deltaTime 都将是0。因此所有乘以 Time.deltaTime 的地方都不会再有进展。

     1     private float originalTimeScale;
     2     private UnityEngine.UI.Text buttonText;
     3 
     4     void Awake()
     5     {
     6         this.originalTimeScale = Time.timeScale;
     7         this.buttonText = this.GetComponentInChildren<UnityEngine.UI.Text>();
     8 }
     9 
    10     public void btnPause_Click()
    11     {
    12         if (Time.timeScale > 0)
    13         {
    14             Time.timeScale = 0;
    15             buttonText.text = "Continue";
    16         }
    17         else
    18         {
    19             Time.timeScale = this.originalTimeScale;
    20             buttonText.text = "Pause";
    21         }
    22     }
    btnPause

    在激烈的游戏过程中,把鼠标挪到屏幕某处点击按钮是很费劲的。所以,添加一个按下Space键就可以暂停或继续游戏的功能很有必要。只需给刚刚的btnPause.cs脚本添加如下代码。

    1     void Update () {
    2         if (Input.GetKeyDown(KeyCode.Space))
    3         {
    4             btnPause_Click();
    5         }
    6     }

    坦克工厂

    现在可以在界面上方三个点产生敌方坦克。后续我将此处改造为关卡控制器。此处暂时没什么可说的。

    小地图

    整个游戏地图有的大,一屏显示不完,所以给个能显示全地图的小地图是很好的。

    制作小地图的原理是再添加一个摄像机smallMap,确保其Depth大于主摄像机。这样小地图就会显示在主场景上层。调整smallMap的Viewport属性,使其只在界面的某个角落显示。这里我让小地图显示在场景左下角,其长宽均为场景的五分之一即0.2。

    注意,Viewport的X、Y、Width、Height属性都是0~1的,表示的是百分比

    注意,上图左上方红色围起来的白色框,其长宽比=下方Game视图的长宽比,后面我就是根据这个调整小地图的长宽的。

    完成后,在Game视图里是这样的,小地图并不是正方形。这不好。

    不过这个问题我用脚本解决了,实际上是调整了摄像机的Viewport的长宽属性,使之调整到相同的长度。

    脚本如下。思路是,当场景的width大于height时,要缩小小地图的width;当场景的width小于height时,要缩小小地图的height。

     1 public class AdjustViewPort : MonoBehaviour {
     2 
     3     Camera cameraComponent;
     4     private float screenWidth;
     5     private float screenHeight;
     6     private Rect originalCameraRect;
     7 
     8     void Awake()
     9     {
    10         this.cameraComponent = this.GetComponent<Camera>();
    11         this.originalCameraRect = this.cameraComponent.rect;
    12     }
    13 
    14     void Update () {
    15         var width = Screen.width;
    16         var height = Screen.height;
    17         if (width == this.screenWidth && height == this.screenHeight) { return; }
    18 
    19         this.screenWidth = width;
    20         this.screenHeight = height;
    21 
    22         if (width > height)
    23         {
    24             var rect = this.cameraComponent.rect;
    25             rect.width = this.originalCameraRect.width * ((float)height / (float)width);
    26             this.cameraComponent.rect = rect;
    27         }
    28         else
    29         {
    30             var rect = this.cameraComponent.rect;
    31             rect.height = this.originalCameraRect.height * ((float)width / (float)height);
    32             this.cameraComponent.rect = rect;
    33         }
    34     }
    35 }
    AdjustViewport.cs

     

    只显示小地图的话,可能会跟场景混淆,所以给小地图加个红色的边框,就区分得明显了。我搜了很多加边框的方法,发现都太繁琐,还要依赖各种包、库。还是直接画一个Texture简单。

    为方便起见,就在刚刚的AdjustViewPort脚本中同时绘制边框好了。

    所需的边框纹理就是一个内部透明四周为红色的PNG图片。

    (下面的脚本忽略了调整长宽相关的部分。)

     1 public class AdjustViewPort : MonoBehaviour {
     2 
     3     Camera cameraComponent;
     4     public Texture borderTexture;
     5 
     6     void Awake()
     7     {
     8         this.cameraComponent = this.GetComponent<Camera>();
     9     }
    10 
    11     void OnGUI()
    12     {
    13         var rect = this.cameraComponent.rect;
    14         float left = 0;
    15         float top = Screen.height - Screen.height * rect.height;
    16         float width = Screen.width * rect.width;
    17         float height = Screen.height * rect.height;
    18         
    19         GUI.DrawTexture(new Rect(left, top, width, height), this.borderTexture, ScaleMode.StretchToFill);
    20     }
    21 }

    总结

    本篇添加了一些虽小但用起来很方便的小部件。现在这个TankHero就算是可以玩了。下面我将设计实现关卡,让这个游戏具有多个关卡,并且可配置。

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

    请多多指教~

  • 相关阅读:
    R语言 dbWriteTable 写入数据库 为空和乱码问题
    data.table进阶
    简述ODS,和数据仓库做简单的比较
    深入ff and ffbase
    R语言操作mysql上亿数据量(ff包ffbase包和ETLUtils包)
    基于mondrain 的原理纠正特殊指标值
    基于mondrian聚合表的R计算olap开发
    dplyr快速入门
    R中的data.table 快速上手入门
    删除pentaho用户和用户文件夹
  • 原文地址:https://www.cnblogs.com/bitzhuwei/p/tank-hero-2d-3-coin-button-small-map-etc.html
Copyright © 2020-2023  润新知