Unity3D_(游戏)2D坦克大战 像素版

 

  2D坦克大战    像素版

 

游戏规则: 

  玩家通过上、下、左、右移动坦克,空格键发射子弹

  敌人AI出身时朝向己方大本营(未防止游戏快速结束,心脏上方三个单位障碍物设为刚体)   

  当玩家被击杀次数>=3  或  心脏被子弹击穿  重新加载游戏场景

  控制游戏每4秒发射一颗子弹(可自己做修改)  

 

  游戏项目已托管到Github上  传送门 

 

  (文章最下边有游戏脚本)

 

场景搭建

 

  设置Main Camera摄像头参数

 

 

游戏中制作预制体与动画

 

  创建一个Cube作为参照,Cube长宽高都为1m

  创建一个Player1_0作为玩家

     将Player1_0制作成预制体

 

  制作游戏砖块、钢铁、草丛、基地预制体

 

  创建游戏物体出生动画Animation

  快速创建动画:点击第一张图片->按住Shift->点击最后一张图片

  保存好后场景出现Born_0动画,修改scale大小为3 3 3

 

 

  制作坦克出生无敌、坦克爆炸、河流特效

  动画大小与预制体适配

 

 

控制玩家的移动

 

  添加Player.cs脚本,绑定到Player玩家坦克上

 

  默认移动速度

    public float moveSpeed = 3;

 

  监听玩家水平轴输入

    float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
                transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);

 

  监听玩家垂直轴输入

  float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);

 

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour {public float moveSpeed = 3;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);}
}
Player.cs

 

 

控制图片的移动和切换

 

  制作坦克渲染

  添加精灵数组的引用

    private SpriteRenderer sr;public Sprite[] tankSprite;

 

(上 右 下 左)

 

  玩家按上下左右控制坦克方向的移动

//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h>0){sr.sprite = tankSprite[1];}//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour {public float moveSpeed = 3;private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h>0){sr.sprite = tankSprite[1];}//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}}
}
Player.cs

 

 

碰撞器的添加

 

  碰撞检测

    两个物体都有碰撞器

    一个物体上挂载刚体组件

 

  给玩家Player添加2D刚体和2D碰撞器

  刚体的Gravity Scale设置为0,取消重力因素的影响

 

   给Barriar、Wall、River、Heart添加Box Collider 2D碰撞器

 

 

  发现坦克方向坐标轴会改变,在Rigidbody 2D中Constraints下的Freeze Rotation Z 进行绑定,当它碰撞到物体时坐标不发生偏移

 

  

 

  解决抖动问题

 

  使用private void FixedUpdate()

    FixedUpdate () 和 Update ()     同:当MonoBehaviour启用时,其在每一帧被调用。都是用来更新的异:Update()每一帧的时间不固定,即第一帧与第二帧的时间t1和第三帧与第四帧的时间t2不一定相同。FixedUpdate()每帧与每帧之间相差的时间是固定的.Update受当前渲染的物体影响,这与当前场景中正在被渲染的物体有关(比如人物的面数,个数等),有时快有时慢,帧率会变化,Update被调用的时间间隔就会发生变化。但是FixedUpdate则不受帧率的变化影响,它是以固定的时间间隔来被调用。所以一些物理属性的更新操作应该放在FxiedUpdate中操作,比如Force,Collider,Rigidbody等。外设的操作也是,比如说键盘或者鼠标的输入输出Input,因为这样GameObject的物理表现的更平滑,更接近现实。FixedUpdate的时间间隔可以在项目设置中更改,Edit->Project Setting->time 找到Fixed timestep。就可以修改了
FixedUpdate () 和 Update ()

 

//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);

 

  FixedUpdate()方法留空就行

    private void FixedUpdate(){}

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour {public float moveSpeed = 3;private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h>0){sr.sprite = tankSprite[1];}//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}}//
    private void FixedUpdate(){}
}
Player.cs

 

  解决玩家按方向键左右的同时按上下

  在监听玩家垂直轴输入后对v方向按键进行判断,如果为0则在Update()中直接返回

 float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}if(v!=0){return;}//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h>0){sr.sprite = tankSprite[1];}

 

  整理一下Player.cs脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour {//属性值public float moveSpeed = 3;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {}private void FixedUpdate(){Move();}//坦克的移动方法private void Move(){//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}if (v != 0){return;}//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h > 0){sr.sprite = tankSprite[1];}}
}
Player.cs

 

 

2D渲染层级

 

  设置游戏物体的层级

      

 

      

 

 

 

坦克的攻击

 

  坦克的攻击方法

private void Attack(){if(Input.GetKeyDown(KeyCode.Space)){Instantiate(bullectPrefab,transform.position,transform.rotation);}}

 

    private void FixedUpdate(){Move();Attack();}

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour {//属性值public float moveSpeed = 3;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {}private void FixedUpdate(){Move();Attack();}//坦克的攻击方法private void Attack(){if(Input.GetKeyDown(KeyCode.Space)){Instantiate(bullectPrefab,transform.position,transform.rotation);}}//坦克的移动方法private void Move(){//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}if (v != 0){return;}//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h > 0){sr.sprite = tankSprite[1];}}
}
player.cs

 

  子弹的朝向和移动

  通过按键V和H来判断子弹旋转的角度

 

  定义子弹旋转的角度

 private Vector3 bullectEulerAugles;

 

  子弹参数的角度:当前坦克的角度+子弹应该旋转的角度

Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));

 

---恢复内容结束---

 

 

未完~

 

完成时会有完整项目展示

 

 

场景搭建

 

  设置Main Camera摄像头参数

 

 

游戏中制作预制体与动画

 

  创建一个Cube作为参照,Cube长宽高都为1m

  创建一个Player1_0作为玩家

     将Player1_0制作成预制体

 

  制作游戏砖块、钢铁、草丛、基地预制体

 

  创建游戏物体出生动画Animation

  快速创建动画:点击第一张图片->按住Shift->点击最后一张图片

  保存好后场景出现Born_0动画,修改scale大小为3 3 3

 

 

  制作坦克出生无敌、坦克爆炸、河流特效

  动画大小与预制体适配

 

 

控制玩家的移动

 

  添加Player.cs脚本,绑定到Player玩家坦克上

 

  默认移动速度

    public float moveSpeed = 3;

 

  监听玩家水平轴输入

    float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
                transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);

 

  监听玩家垂直轴输入

  float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);

 

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour {public float moveSpeed = 3;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);}
}
Player.cs

 

 

控制图片的移动和切换

 

  制作坦克渲染

  添加精灵数组的引用

    private SpriteRenderer sr;public Sprite[] tankSprite;

 

(上 右 下 左)

 

  玩家按上下左右控制坦克方向的移动

//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h>0){sr.sprite = tankSprite[1];}//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour {public float moveSpeed = 3;private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h>0){sr.sprite = tankSprite[1];}//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}}
}
Player.cs

 

 

碰撞器的添加

 

  碰撞检测

    两个物体都有碰撞器

    一个物体上挂载刚体组件

 

  给玩家Player添加2D刚体和2D碰撞器

  刚体的Gravity Scale设置为0,取消重力因素的影响

 

   给Barriar、Wall、River、Heart添加Box Collider 2D碰撞器

 

 

  发现坦克方向坐标轴会改变,在Rigidbody 2D中Constraints下的Freeze Rotation Z 进行绑定,当它碰撞到物体时坐标不发生偏移

 

  

 

  解决抖动问题

 

  使用private void FixedUpdate()

    FixedUpdate () 和 Update ()     同:当MonoBehaviour启用时,其在每一帧被调用。都是用来更新的异:Update()每一帧的时间不固定,即第一帧与第二帧的时间t1和第三帧与第四帧的时间t2不一定相同。FixedUpdate()每帧与每帧之间相差的时间是固定的.Update受当前渲染的物体影响,这与当前场景中正在被渲染的物体有关(比如人物的面数,个数等),有时快有时慢,帧率会变化,Update被调用的时间间隔就会发生变化。但是FixedUpdate则不受帧率的变化影响,它是以固定的时间间隔来被调用。所以一些物理属性的更新操作应该放在FxiedUpdate中操作,比如Force,Collider,Rigidbody等。外设的操作也是,比如说键盘或者鼠标的输入输出Input,因为这样GameObject的物理表现的更平滑,更接近现实。FixedUpdate的时间间隔可以在项目设置中更改,Edit->Project Setting->time 找到Fixed timestep。就可以修改了
FixedUpdate () 和 Update ()

 

//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);

 

  FixedUpdate()方法留空就行

    private void FixedUpdate(){}

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour {public float moveSpeed = 3;private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h>0){sr.sprite = tankSprite[1];}//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}}//
    private void FixedUpdate(){}
}
Player.cs

 

  解决玩家按方向键左右的同时按上下

  在监听玩家垂直轴输入后对v方向按键进行判断,如果为0则在Update()中直接返回

 float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}if(v!=0){return;}//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h>0){sr.sprite = tankSprite[1];}

 

  整理一下Player.cs脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour {//属性值public float moveSpeed = 3;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {}private void FixedUpdate(){Move();}//坦克的移动方法private void Move(){//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}if (v != 0){return;}//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h > 0){sr.sprite = tankSprite[1];}}
}
Player.cs

 

 

2D渲染层级

 

  设置游戏物体的层级

      

 

      

 

 

 

坦克的攻击

 

  坦克的攻击方法

private void Attack(){if(Input.GetKeyDown(KeyCode.Space)){Instantiate(bullectPrefab,transform.position,transform.rotation);}}

 

    private void FixedUpdate(){Move();Attack();}

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour {//属性值public float moveSpeed = 3;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {}private void FixedUpdate(){Move();Attack();}//坦克的攻击方法private void Attack(){if(Input.GetKeyDown(KeyCode.Space)){Instantiate(bullectPrefab,transform.position,transform.rotation);}}//坦克的移动方法private void Move(){//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];}else if (v > 0){sr.sprite = tankSprite[0];}if (v != 0){return;}//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];}else if (h > 0){sr.sprite = tankSprite[1];}}
}
player.cs

 

  子弹的朝向和移动

  通过按键V和H来判断子弹旋转的角度

 

  定义子弹旋转的角度

 private Vector3 bullectEulerAugles;

 

  子弹参数的角度:当前坦克的角度+子弹应该旋转的角度

Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));

 

    private void Attack(){if(Input.GetKeyDown(KeyCode.Space)){//子弹参数的角度:当前坦克的角度+子弹应该旋转的角度Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));timeVal = 0;}}

 

  给子弹添加方向速度

    public float moveSpeed = 10;

 

  给子弹添加判断是否是友军

    public bool isPlayerBullect;

 

    void Update () {transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);}

 

  添加子弹攻击CD间隔

        if (timeVal>=0.4f){//间隔大于0.4的时候才有攻击效果
            Attack();}else{timeVal += Time.deltaTime;}

 

 

 

 

  给组件添加标签

  

 

  给子弹添加碰撞体和触发器

 

  添加Heart.cs脚本,当Heart心脏被子弹攻击时,切换死亡图片

    private SpriteRenderer sr;public Sprite BrokenSprite;   // Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}

 

  添加Heart.cs心脏死亡时方法

    private void Die(){sr.sprite = BrokenSprite; }

 

  添加Explosion.cs脚本

  当坦克销毁时触发脚本

public class Explosion : MonoBehaviour {// Use this for initializationvoid Start () {//坦克销毁后0.167秒销毁爆炸特效Destroy(gameObject,0.167f);}// Update is called once per framevoid Update () {}
}

 

  子弹触发碰撞检测

  当子弹碰撞到物体时触发OnTriggerEnter2D(Collider2D collision)方法

  子弹碰到“Tank”判断是否是友军,不是的话击毁自己

  子弹碰到"Wall"时,销毁子弹自身

  子弹碰到"Heart"时,触发基地死亡方法

  子弹碰到"Barrier"刚体时,销毁子弹

 

private void OnTriggerEnter2D(Collider2D collision){switch(collision.tag){case "Tank":if(!isPlayerBullect){collision.SendMessage("Die");}break;case "Heart":collision.SendMessage("Die");Destroy(gameObject);break;case "Enemy":break;case "Wall"://销毁自身和墙
                Destroy(collision.gameObject);Destroy(gameObject);break;case "Barrier":Destroy(gameObject);break;default:break;}}

 

  

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour {//属性值public float moveSpeed = 3;private Vector3 bullectEulerAugles;public float timeVal;private float defendTimeVal=1;private bool isDefended=true;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;public GameObject explosionPrefab;public GameObject defendEffectPrefab;// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {//保护是否处于无敌状态if(isDefended){defendEffectPrefab.SetActive(true);defendTimeVal -= Time.deltaTime;if (defendTimeVal<=0){isDefended = false;defendEffectPrefab.SetActive(false);}}//攻击的CDif (timeVal>=0.4f){//间隔大于0.4的时候才有攻击效果
            Attack();}else{timeVal += Time.deltaTime;}}private void FixedUpdate(){Move();}//坦克的攻击方法private void Attack(){if(Input.GetKeyDown(KeyCode.Space)){//子弹参数的角度:当前坦克的角度+子弹应该旋转的角度Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));timeVal = 0;}}//坦克的移动方法private void Move(){//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];bullectEulerAugles = new Vector3(0, 0, -180);}else if (v > 0){sr.sprite = tankSprite[0];bullectEulerAugles = new Vector3(0, 0, 0);}if (v != 0){return;}//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];bullectEulerAugles = new Vector3(0, 0, 90);}else if (h > 0){sr.sprite = tankSprite[1];bullectEulerAugles = new Vector3(0, 0, -90);}}//坦克的死亡方法private void Die(){if(isDefended){return;}//产生爆炸特效
        Instantiate(explosionPrefab, transform.position, transform.rotation);//死亡
        Destroy(gameObject);}
}
Player.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Explosion : MonoBehaviour {// Use this for initializationvoid Start () {//坦克销毁后0.167秒销毁爆炸特效Destroy(gameObject,0.167f);}// Update is called once per framevoid Update () {}
}
Explosion.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Heart : MonoBehaviour {private SpriteRenderer sr;public Sprite BrokenSprite;   // Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}private void Die(){sr.sprite = BrokenSprite; }
}
Heart

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Bullect : MonoBehaviour {public float moveSpeed = 10;public bool isPlayerBullect;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);}//子弹触发碰撞检测private void OnTriggerEnter2D(Collider2D collision){switch(collision.tag){case "Tank":if(!isPlayerBullect){collision.SendMessage("Die");}break;case "Heart":collision.SendMessage("Die");Destroy(gameObject);break;case "Enemy":break;case "Wall"://销毁自身和墙
                Destroy(collision.gameObject);Destroy(gameObject);break;case "Barrier":Destroy(gameObject);break;default:break;}}}
Bullect.cs

 

 

敌人的制作

 

  Ctrl+D一份玩家,修改图片渲染,制作敌人

 

  添加敌人脚本Enemy.cs

  玩家的移动和敌人的移动差不多,把Player.cs脚本中内容复制到Enemy.cs当中

  

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Enemy : MonoBehaviour {//属性值public float moveSpeed = 3;private Vector3 bullectEulerAugles;public float timeVal;private float defendTimeVal = 1;private bool isDefended = true;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;public GameObject explosionPrefab;public GameObject defendEffectPrefab;// Use this for initializationvoid Start(){sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update(){//保护是否处于无敌状态if (isDefended){defendEffectPrefab.SetActive(true);defendTimeVal -= Time.deltaTime;if (defendTimeVal <= 0){isDefended = false;defendEffectPrefab.SetActive(false);}}//攻击的CDif (timeVal >= 0.4f){//间隔大于0.4的时候才有攻击效果
            Attack();}else{timeVal += Time.deltaTime;}}private void FixedUpdate(){Move();}//坦克的攻击方法private void Attack(){if (Input.GetKeyDown(KeyCode.Space)){//子弹参数的角度:当前坦克的角度+子弹应该旋转的角度Instantiate(bullectPrefab, transform.position, Quaternion.Euler(transform.eulerAngles + bullectEulerAugles));timeVal = 0;}}//坦克的移动方法private void Move(){//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];bullectEulerAugles = new Vector3(0, 0, -180);}else if (v > 0){sr.sprite = tankSprite[0];bullectEulerAugles = new Vector3(0, 0, 0);}if (v != 0){return;}//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];bullectEulerAugles = new Vector3(0, 0, 90);}else if (h > 0){sr.sprite = tankSprite[1];bullectEulerAugles = new Vector3(0, 0, -90);}}//坦克的死亡方法private void Die(){if (isDefended){return;}//产生爆炸特效
        Instantiate(explosionPrefab, transform.position, transform.rotation);//死亡
        Destroy(gameObject);}
}
Enemy.cs

(因为敌人没有出生无敌3s,运行时无敌预制体defendEffectPrefab会出现报空)

 

  添加基地死亡时动画

    public GameObject explosionPrefab;

 

private void Die(){sr.sprite = BrokenSprite;Instantiate(explosionPrefab,transform.position,transform.rotation);}

 

  (关闭项目后爆炸脚本失活了,最后的时候再做一个补上)

 

  添加一个玩家出生时脚本Born.cs

  延时玩家出生和死亡动画

    public GameObject playerPrefab;// Use this for initializationvoid Start () {Invoke("BornTank",1f);Destroy(gameObject,1f);}private void BornTank(){Instantiate(playerPrefab,transform.position,Quaternion.identity);}

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Born : MonoBehaviour {public GameObject playerPrefab;// Use this for initializationvoid Start () {Invoke("BornTank",0.8f);Destroy(gameObject,0.8f);}// Update is called once per framevoid Update () {}private void BornTank(){Instantiate(playerPrefab,transform.position,Quaternion.identity);}
}
Born.cs

 

  制作大坦克和小坦克,添加坦克方向变化时改变坦克方向图片

  坦克改变方向顺序按上、右、下、左进行添加

 

  小敌人同打敌人设置当坦克方向改变时切换自身图片

  将大敌人和小敌人设置成预制体

  小敌人速度调大一些,改为5

 

  编写Born.cs脚本判断是否产生敌人

    public bool createPlay;

 

    private void BornTank(){if (createPlay){Instantiate(playerPrefab, transform.position, Quaternion.identity);}else{int num = Random.Range(0, 2);Instantiate(enemyPrefabList[num], transform.position, Quaternion.identity);}}

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Born : MonoBehaviour {public GameObject playerPrefab;public GameObject[] enemyPrefabList;//判断是否产生敌人public bool createPlay;// Use this for initializationvoid Start () {Invoke("BornTank",1f);Destroy(gameObject,1f);}private void Update(){}private void BornTank(){if (createPlay){Instantiate(playerPrefab, transform.position, Quaternion.identity);}else{int num = Random.Range(0, 2);Instantiate(enemyPrefabList[num], transform.position, Quaternion.identity);}}
}
Born.cs

 

 

编写敌人AI

 

  子弹间3s攻击一次

 void Update(){//攻击的时间间隔if (timeVal >= 0.3f){//间隔大于0.4的时候才有攻击效果
            Attack();}else{timeVal += Time.deltaTime;}}

 

    //坦克的攻击方法private void Attack(){//子弹参数的角度:当前坦克的角度+子弹应该旋转的角度Instantiate(bullectPrefab, transform.position, Quaternion.Euler(transform.eulerAngles + bullectEulerAugles));timeVal = 0;}

 

  坦克的移动不需要按下上下左右键盘,只需要管理V和H的值对敌人AI进行方向的控制

  定义两个计时器

    public float timeVal;public float timeValChangeDirection;

 

  修改敌人移动的方法

  

private void Move(){if(timeValChangeDirection>=4){int num = Random.Range(0,8);if(num>5){v = -1;h = 0;}else if (num == 0){v = 1;h = 0;}else if (num > 0 && num <= 2){h = -1;v = 0;}else if (num > 2 && num <= 4){h = 1;v = 0;}timeValChangeDirection = 0;}else{timeValChangeDirection += Time.fixedDeltaTime;}//监听玩家垂直轴输入
      transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];bullectEulerAugles = new Vector3(0, 0, -180);}else if (v > 0){sr.sprite = tankSprite[0];bullectEulerAugles = new Vector3(0, 0, 0);}if (v != 0){return;}//监听玩家水平轴输入
     transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];bullectEulerAugles = new Vector3(0, 0, 90);}else if (h > 0){sr.sprite = tankSprite[1];bullectEulerAugles = new Vector3(0, 0, -90);}}

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Enemy : MonoBehaviour {//属性值public float moveSpeed = 3;private Vector3 bullectEulerAugles;private float v;private float h;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;public GameObject explosionPrefab;//计时器public float timeVal;public float timeValChangeDirection=4;// Use this for initializationvoid Start(){sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update(){//攻击的时间间隔if (timeVal >= 0.3f){//间隔大于0.4的时候才有攻击效果
            Attack();}else{timeVal += Time.deltaTime;}}private void FixedUpdate(){Move();}//坦克的攻击方法private void Attack(){//子弹参数的角度:当前坦克的角度+子弹应该旋转的角度Instantiate(bullectPrefab, transform.position, Quaternion.Euler(transform.eulerAngles + bullectEulerAugles));timeVal = 0;}//坦克的移动方法private void Move(){if(timeValChangeDirection>=4){int num = Random.Range(0,8);if(num>5){v = -1;h = 0;}else if (num == 0){v = 1;h = 0;}else if (num > 0 && num <= 2){h = -1;v = 0;}else if (num > 2 && num <= 4){h = 1;v = 0;}timeValChangeDirection = 0;}else{timeValChangeDirection += Time.fixedDeltaTime;}//监听玩家垂直轴输入
      transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];bullectEulerAugles = new Vector3(0, 0, -180);}else if (v > 0){sr.sprite = tankSprite[0];bullectEulerAugles = new Vector3(0, 0, 0);}if (v != 0){return;}//监听玩家水平轴输入
     transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];bullectEulerAugles = new Vector3(0, 0, 90);}else if (h > 0){sr.sprite = tankSprite[1];bullectEulerAugles = new Vector3(0, 0, -90);}}//坦克的死亡方法private void Die(){//产生爆炸特效
        Instantiate(explosionPrefab, transform.position, transform.rotation);//死亡
        Destroy(gameObject);}
}
Enemy.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Bullect : MonoBehaviour {public float moveSpeed = 10;public bool isPlayerBullect;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);}//子弹触发碰撞检测private void OnTriggerEnter2D(Collider2D collision){switch(collision.tag){case "Tank":if(!isPlayerBullect){collision.SendMessage("Die");}Destroy(gameObject);break;case "Heart":collision.SendMessage("Die");Destroy(gameObject);break;case "Enemy":if(isPlayerBullect){collision.SendMessage("Die");}Destroy(gameObject);break;case "Wall"://销毁自身和墙
                Destroy(collision.gameObject);Destroy(gameObject);break;case "Barrier":Destroy(gameObject);break;default:break;}}}
Bullect.cs

 

 

初始化地图工具

 

  判断地图长度

 

  地图大小:长20  宽16

 

  添加MapCreation.cs地图管理器来控制草和地图等建筑物

public class MapCreation : MonoBehaviour {//用来装饰初始化地图所需物体的数组//0.老家  1.墙  2.障碍  3.出生效果  4.河流    5.草  6.空气墙public GameObject[] item;}

 

 

  制作老家心脏和心脏周围的围墙

private void Awake(){//实例化老家Instantiate(item[0], new Vector3(0, -8, -0), Quaternion.identity);//用墙把老家围起来Instantiate(item[1], new Vector3(-1, -8, -0), Quaternion.identity);Instantiate(item[1], new Vector3(1, -8, -0), Quaternion.identity);for(int i=-1;i<2;i++){Instantiate(item[1],new Vector3(i,-7,0),Quaternion.identity);}}

 

 

  对同一个位置上进行判断,判断是否有障碍物在上面,如果在上面那不再额外生成其它建筑物

  已经有东西位置的列表

 private List<Vector3> itemPositionList = new List<Vector3>();

 

    private void CreateItem(GameObject createGameObject,Vector3 createPosition,Quaternion createRotate){GameObject itemGo = Instantiate(createGameObject, createPosition, createRotate);itemGo.transform.SetParent(gameObject.transform);itemPositionList.Add(createPosition);}

 

  制作外围墙,也就是游戏边界

 for(int i=-11;i<12;i++){CreateItem(item[6], new Vector3(i, 9, 0), Quaternion.identity);}for(int i=-11;i<12;i++){CreateItem(item[6], new Vector3(i, -9, 0), Quaternion.identity);}for(int i=-8;i<9;i++){CreateItem(item[6], new Vector3(-11, i, 0), Quaternion.identity);}for(int i=-8;i<9;i++){CreateItem(item[6], new Vector3(-11, i, 0), Quaternion.identity);}

 

  产生随机位置的方法

 private Vector3 CreateRamdomPosition(){//不生成x=-10,10的两列,y=-8和8这两行的位置while(true){Vector3 createPosition = new Vector3(Random.Range(-9, 10), Random.Range(-7, 8),0);if(!HasThePosition(createPosition)){return createPosition;}}}

 

  用来判断位置列表中是否有这个位置

private bool HasThePosition(Vector3 createPos){for(int i=0;i<itemPositionList.Count;i++){if(createPos==itemPositionList[i]){return true;}}return false;}

 

 

  修复子弹触发碰撞检测

private void OnTriggerEnter2D(Collider2D collision){switch(collision.tag){case "Tank":if(!isPlayerBullect){collision.SendMessage("Die");Destroy(gameObject);}break;case "Heart":collision.SendMessage("Die");Destroy(gameObject);break;case "Enemy":if(isPlayerBullect){collision.SendMessage("Die");Destroy(gameObject);}break;case "Wall"://销毁自身和墙
                Destroy(collision.gameObject);Destroy(gameObject);break;case "Barrier":Destroy(gameObject);break;default:break;}}

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Bullect : MonoBehaviour {public float moveSpeed = 10;public bool isPlayerBullect;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);}//子弹触发碰撞检测private void OnTriggerEnter2D(Collider2D collision){switch(collision.tag){case "Tank":if(!isPlayerBullect){collision.SendMessage("Die");Destroy(gameObject);}break;case "Heart":collision.SendMessage("Die");Destroy(gameObject);break;case "Enemy":if(isPlayerBullect){collision.SendMessage("Die");Destroy(gameObject);}break;case "Wall"://销毁自身和墙
                Destroy(collision.gameObject);Destroy(gameObject);break;case "Barrier":Destroy(gameObject);break;default:break;}}}
Bullect.cs

 

  实例化地图

for(int i=0;i<20;i++){CreateItem(item[1], CreateRamdomPosition(), Quaternion.identity);}for(int i=0;i<20;i++){CreateItem(item[2], CreateRamdomPosition(), Quaternion.identity);}for (int i = 0; i < 20; i++){CreateItem(item[4], CreateRamdomPosition(), Quaternion.identity);}for (int i = 0; i < 20; i++){CreateItem(item[5], CreateRamdomPosition(), Quaternion.identity);}

 

  

 

  初始化玩家

GameObject go = Instantiate(item[3], new Vector3(-2, -8, 0), Quaternion.identity);
go.GetComponent<Born>().createPlay = true;

 

  产生敌人

CreateItem(item[3], new Vector3(-10,8,0),Quaternion.identity);
CreateItem(item[3], new Vector3(0, 8, 0), Quaternion.identity);
CreateItem(item[3], new Vector3(10, 8, 0), Quaternion.identity);

 

  实例化地图并且让围墙的数量尽可能的多

for (int i=0;i<60;i++){CreateItem(item[1], CreateRamdomPosition(), Quaternion.identity);}for(int i=0;i<20;i++){CreateItem(item[2], CreateRamdomPosition(), Quaternion.identity);}for (int i = 0; i < 20; i++){CreateItem(item[4], CreateRamdomPosition(), Quaternion.identity);}for (int i = 0; i < 20; i++){CreateItem(item[5], CreateRamdomPosition(), Quaternion.identity);}

 

  产生敌人的方法

 private void CreateEnemy(){int num = Random.Range(0, 3);Vector3 EnemyPos = new Vector3();if(num==0){EnemyPos = new Vector3(-10, 8, 0);}else if(num==1){EnemyPos = new Vector3(0, 8, 0);}else{EnemyPos = new Vector3(10, 8, 0);}CreateItem(item[3],EnemyPos,Quaternion.identity);}

 

  每隔5s产生一波敌人

 InvokeRepeating("CreateEnemy",4,5);

 

  优化一下敌人AI

  敌人AI碰到一起时切换一次方向

private void OnCollisionEnter2D(Collision2D collision){if(collision.gameObject.tag=="Enemy"){timeValChangeDirection = 4;}}

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour {//属性值public float moveSpeed = 3;private Vector3 bullectEulerAugles;public float timeVal;private float defendTimeVal=3;private bool isDefended=true;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;public GameObject explosionPrefab;public GameObject defendEffectPrefab;// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {//保护是否处于无敌状态if(isDefended){defendEffectPrefab.SetActive(true);defendTimeVal -= Time.deltaTime;if (defendTimeVal<=0){isDefended = false;defendEffectPrefab.SetActive(false);}}//攻击的CDif (timeVal>=0.4f){//间隔大于0.4的时候才有攻击效果
            Attack();}else{timeVal += Time.deltaTime;}}private void FixedUpdate(){Move();}//坦克的攻击方法private void Attack(){if(Input.GetKeyDown(KeyCode.Space)){//子弹参数的角度:当前坦克的角度+子弹应该旋转的角度Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));timeVal = 0;}}//坦克的移动方法private void Move(){//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];bullectEulerAugles = new Vector3(0, 0, -180);}else if (v > 0){sr.sprite = tankSprite[0];bullectEulerAugles = new Vector3(0, 0, 0);}if (v != 0){return;}//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];bullectEulerAugles = new Vector3(0, 0, 90);}else if (h > 0){sr.sprite = tankSprite[1];bullectEulerAugles = new Vector3(0, 0, -90);}}//坦克的死亡方法private void Die(){if(isDefended){return;}//产生爆炸特效
        Instantiate(explosionPrefab, transform.position, transform.rotation);//死亡
        Destroy(gameObject);}
}
Player.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class MapCreation : MonoBehaviour {//用来装饰初始化地图所需物体的数组//0.老家  1.墙  2.障碍  3.出生效果  4.河流    5.草  6.空气墙public GameObject[] item;//已经有东西位置的列表private List<Vector3> itemPositionList = new List<Vector3>();private void Awake(){//实例化老家CreateItem(item[0], new Vector3(0, -8, -0), Quaternion.identity);//用墙把老家围起来CreateItem(item[1], new Vector3(-1, -8, -0), Quaternion.identity);CreateItem(item[1], new Vector3(1, -8, -0), Quaternion.identity);for(int i=-1;i<2;i++){Instantiate(item[1],new Vector3(i,-7,0),Quaternion.identity);}//实例化外围墙for(int i=-11;i<12;i++){CreateItem(item[6], new Vector3(i, 9, 0), Quaternion.identity);}for(int i=-11;i<12;i++){CreateItem(item[6], new Vector3(i, -9, 0), Quaternion.identity);}for(int i=-8;i<9;i++){CreateItem(item[6], new Vector3(-11, i, 0), Quaternion.identity);}for(int i=-8;i<9;i++){CreateItem(item[6], new Vector3(11, i, 0), Quaternion.identity);}//初始化玩家GameObject go = Instantiate(item[3], new Vector3(-2, -8, 0), Quaternion.identity);go.GetComponent<Born>().createPlay = true;//产生敌人CreateItem(item[3], new Vector3(-10,8,0),Quaternion.identity);CreateItem(item[3], new Vector3(0, 8, 0), Quaternion.identity);CreateItem(item[3], new Vector3(10, 8, 0), Quaternion.identity);//第一次调用CreateEnemy用4s,每隔5s开调用InvokeRepeating("CreateEnemy",4,5);//实例化地图for (int i=0;i<60;i++){CreateItem(item[1], CreateRamdomPosition(), Quaternion.identity);}for(int i=0;i<20;i++){CreateItem(item[2], CreateRamdomPosition(), Quaternion.identity);}for (int i = 0; i < 20; i++){CreateItem(item[4], CreateRamdomPosition(), Quaternion.identity);}for (int i = 0; i < 20; i++){CreateItem(item[5], CreateRamdomPosition(), Quaternion.identity);}}private void CreateItem(GameObject createGameObject,Vector3 createPosition,Quaternion createRotate){GameObject itemGo = Instantiate(createGameObject, createPosition, createRotate);itemGo.transform.SetParent(gameObject.transform);itemPositionList.Add(createPosition);}//产生随机位置的方法private Vector3 CreateRamdomPosition(){//不生成x=-10,10的两列,y=-8和8这两行的位置while(true){Vector3 createPosition = new Vector3(Random.Range(-9, 10), Random.Range(-7, 8),0);if(!HasThePosition(createPosition)){return createPosition;}}}//用来判断位置列表中是否有这个位置private bool HasThePosition(Vector3 createPos){for(int i=0;i<itemPositionList.Count;i++){if(createPos==itemPositionList[i]){return true;}}return false;}//产生敌人的方法private void CreateEnemy(){int num = Random.Range(0, 3);Vector3 EnemyPos = new Vector3();if(num==0){EnemyPos = new Vector3(-10, 8, 0);}else if(num==1){EnemyPos = new Vector3(0, 8, 0);}else{EnemyPos = new Vector3(10, 8, 0);}CreateItem(item[3],EnemyPos,Quaternion.identity);}}
MapCreation.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Born : MonoBehaviour {public GameObject playerPrefab;public GameObject[] enemyPrefabList;//判断是否产生敌人public bool createPlay;// Use this for initializationvoid Start () {Invoke("BornTank",1f);Destroy(gameObject,1f);}private void Update(){}private void BornTank(){if (createPlay){Instantiate(playerPrefab, transform.position, Quaternion.identity);}else{int num = Random.Range(0, 2);Instantiate(enemyPrefabList[num], transform.position, Quaternion.identity);}}
}
Born.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Enemy : MonoBehaviour {//属性值public float moveSpeed = 3;private Vector3 bullectEulerAugles;private float v;private float h;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;public GameObject explosionPrefab;//计时器public float timeVal;public float timeValChangeDirection=4;// Use this for initializationvoid Start(){sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update(){//攻击的时间间隔if (timeVal >= 0.3f){//间隔大于0.4的时候才有攻击效果
            Attack();}else{timeVal += Time.deltaTime;}}private void FixedUpdate(){Move();}//坦克的攻击方法private void Attack(){//子弹参数的角度:当前坦克的角度+子弹应该旋转的角度Instantiate(bullectPrefab, transform.position, Quaternion.Euler(transform.eulerAngles + bullectEulerAugles));timeVal = 0;}//坦克的移动方法private void Move(){if(timeValChangeDirection>=4){int num = Random.Range(0,8);if(num>5){v = -1;h = 0;}else if (num == 0){v = 1;h = 0;}else if (num > 0 && num <= 2){h = -1;v = 0;}else if (num > 2 && num <= 4){h = 1;v = 0;}timeValChangeDirection = 0;}else{timeValChangeDirection += Time.fixedDeltaTime;}//监听玩家垂直轴输入
      transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];bullectEulerAugles = new Vector3(0, 0, -180);}else if (v > 0){sr.sprite = tankSprite[0];bullectEulerAugles = new Vector3(0, 0, 0);}if (v != 0){return;}//监听玩家水平轴输入
     transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];bullectEulerAugles = new Vector3(0, 0, 90);}else if (h > 0){sr.sprite = tankSprite[1];bullectEulerAugles = new Vector3(0, 0, -90);}}//坦克的死亡方法private void Die(){//产生爆炸特效
        Instantiate(explosionPrefab, transform.position, transform.rotation);//死亡
        Destroy(gameObject);}//优化敌人AIprivate void OnCollisionEnter2D(Collision2D collision){if(collision.gameObject.tag=="Enemy"){timeValChangeDirection = 4;}}}
Enemy.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Explosion : MonoBehaviour {// Use this for initializationvoid Start () {//坦克销毁后0.167秒销毁爆炸特效Destroy(gameObject,0.167f);}// Update is called once per framevoid Update () {}
}
Explosion

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Heart : MonoBehaviour {private SpriteRenderer sr;public GameObject explosionPrefab;public Sprite BrokenSprite;   // Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}private void Die(){sr.sprite = BrokenSprite;Instantiate(explosionPrefab,transform.position,transform.rotation);}
}
Heart.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Bullect : MonoBehaviour {public float moveSpeed = 10;public bool isPlayerBullect;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);}//子弹触发碰撞检测private void OnTriggerEnter2D(Collider2D collision){switch(collision.tag){case "Tank":if(!isPlayerBullect){collision.SendMessage("Die");Destroy(gameObject);}break;case "Heart":collision.SendMessage("Die");Destroy(gameObject);break;case "Enemy":if(isPlayerBullect){collision.SendMessage("Die");Destroy(gameObject);}break;case "Wall"://销毁自身和墙
                Destroy(collision.gameObject);Destroy(gameObject);break;case "Barrier":Destroy(gameObject);break;default:break;}}}
Bullect.cs

 

 

玩家状态管理

 

  游戏中添加空物体PlayerManager对象

  添加游戏的属性值

    public int lifeVale = 3;public int playerScore = 0;public bool isDead;

 

  坦克的死亡方法

private void Die(){if(isDefended){return;}PlayerManager.Instance.isDead = true;//产生爆炸特效
        Instantiate(explosionPrefab, transform.position, transform.rotation);//死亡
        Destroy(gameObject);}

 

  玩家状态管理类监听玩家状态,当玩家被子弹击中时,生命值开始降低

void Update () {if(isDead){Recover();}}private void Recover(){if (lifeVale < 0){//游戏失败,返回主界面
SceneManager.LoadScene("Game");}else{lifeVale--;GameObject go = Instantiate(born,new Vector3(-2,-8,0),Quaternion.identity);go.GetComponent<Born>().createPlay = true;isDead = false;}}

 

 

 

游戏源代码

 

  

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour {//属性值public float moveSpeed = 3;private Vector3 bullectEulerAugles;public float timeVal;private float defendTimeVal=3;private bool isDefended=true;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;public GameObject explosionPrefab;public GameObject defendEffectPrefab;// Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update () {//保护是否处于无敌状态if(isDefended){defendEffectPrefab.SetActive(true);defendTimeVal -= Time.deltaTime;if (defendTimeVal<=0){isDefended = false;defendEffectPrefab.SetActive(false);}}}private void FixedUpdate(){if(PlayerManager.Instance.isDefeat){return;}Move();//攻击的CDif (timeVal >= 0.4f){//间隔大于0.4的时候才有攻击效果
            Attack();}else{timeVal += Time.fixedDeltaTime;}}//坦克的攻击方法private void Attack(){if(Input.GetKeyDown(KeyCode.Space)){//子弹参数的角度:当前坦克的角度+子弹应该旋转的角度Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));timeVal = 0;}}//坦克的移动方法private void Move(){//监听玩家垂直轴输入float v = Input.GetAxisRaw("Vertical");transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];bullectEulerAugles = new Vector3(0, 0, -180);}else if (v > 0){sr.sprite = tankSprite[0];bullectEulerAugles = new Vector3(0, 0, 0);}if (v != 0){return;}//监听玩家水平轴输入float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];bullectEulerAugles = new Vector3(0, 0, 90);}else if (h > 0){sr.sprite = tankSprite[1];bullectEulerAugles = new Vector3(0, 0, -90);}}//坦克的死亡方法private void Die(){if(isDefended){return;}PlayerManager.Instance.isDead = true;//产生爆炸特效
        Instantiate(explosionPrefab, transform.position, transform.rotation);//死亡
        Destroy(gameObject);}
}
Player.cs 游戏玩家

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;public class PlayerManager : MonoBehaviour {//属性值public int lifeVale = 3;public int playerScore = 0;public bool isDead=false;public bool isDefeat;//引用public GameObject born;//单例private static PlayerManager instance;public static PlayerManager Instance{get{return instance;}set{instance = value;}}public void Awake(){Instance = this;}// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {if(isDead){Recover();}}private void Recover(){if (lifeVale < 0){//游戏失败,返回主界面
SceneManager.LoadScene("Game");}else{lifeVale--;GameObject go = Instantiate(born,new Vector3(-2,-8,0),Quaternion.identity);go.GetComponent<Born>().createPlay = true;isDead = false;}}
}
PlayerManager.cs 游戏玩家状态管理

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class MapCreation : MonoBehaviour {//用来装饰初始化地图所需物体的数组//0.老家  1.墙  2.障碍  3.出生效果  4.河流    5.草  6.空气墙public GameObject[] item;//已经有东西位置的列表private List<Vector3> itemPositionList = new List<Vector3>();private void Awake(){//实例化老家CreateItem(item[0], new Vector3(0, -8, -0), Quaternion.identity);//用墙把老家围起来CreateItem(item[1], new Vector3(-1, -8, -0), Quaternion.identity);CreateItem(item[1], new Vector3(1, -8, -0), Quaternion.identity);for(int i=-1;i<2;i++){Instantiate(item[1],new Vector3(i,-7,0),Quaternion.identity);}//坦克一开始就向下太难了,就直接给老家前面加了一顶墙CreateItem(item[2], new Vector3(0, -4, -0), Quaternion.identity);//实例化外围墙for (int i=-11;i<12;i++){CreateItem(item[6], new Vector3(i, 9, 0), Quaternion.identity);}for(int i=-11;i<12;i++){CreateItem(item[6], new Vector3(i, -9, 0), Quaternion.identity);}for(int i=-8;i<9;i++){CreateItem(item[6], new Vector3(-11, i, 0), Quaternion.identity);}for(int i=-8;i<9;i++){CreateItem(item[6], new Vector3(11, i, 0), Quaternion.identity);}//初始化玩家GameObject go = Instantiate(item[3], new Vector3(-2, -8, 0), Quaternion.identity);go.GetComponent<Born>().createPlay = true;//产生敌人CreateItem(item[3], new Vector3(-10,8,0),Quaternion.identity);CreateItem(item[3], new Vector3(0, 8, 0), Quaternion.identity);CreateItem(item[3], new Vector3(10, 8, 0), Quaternion.identity);//第一次调用CreateEnemy用4s,每隔5s开调用InvokeRepeating("CreateEnemy",4,5);//实例化地图for (int i=0;i<60;i++){CreateItem(item[1], CreateRamdomPosition(), Quaternion.identity);}for(int i=0;i<20;i++){CreateItem(item[2], CreateRamdomPosition(), Quaternion.identity);}for (int i = 0; i < 20; i++){CreateItem(item[4], CreateRamdomPosition(), Quaternion.identity);}for (int i = 0; i < 20; i++){CreateItem(item[5], CreateRamdomPosition(), Quaternion.identity);}}private void CreateItem(GameObject createGameObject,Vector3 createPosition,Quaternion createRotate){GameObject itemGo = Instantiate(createGameObject, createPosition, createRotate);itemGo.transform.SetParent(gameObject.transform);itemPositionList.Add(createPosition);}//产生随机位置的方法private Vector3 CreateRamdomPosition(){//不生成x=-10,10的两列,y=-8和8这两行的位置while(true){Vector3 createPosition = new Vector3(Random.Range(-9, 10), Random.Range(-7, 8),0);if(!HasThePosition(createPosition)){return createPosition;}}}//用来判断位置列表中是否有这个位置private bool HasThePosition(Vector3 createPos){for(int i=0;i<itemPositionList.Count;i++){if(createPos==itemPositionList[i]){return true;}}return false;}//产生敌人的方法private void CreateEnemy(){int num = Random.Range(0, 3);Vector3 EnemyPos = new Vector3();if(num==0){EnemyPos = new Vector3(-10, 8, 0);}else if(num==1){EnemyPos = new Vector3(0, 8, 0);}else{EnemyPos = new Vector3(10, 8, 0);}CreateItem(item[3],EnemyPos,Quaternion.identity);}}
MapCreation.cs 初始化地图

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Born : MonoBehaviour {public GameObject playerPrefab;public GameObject[] enemyPrefabList;//判断是否产生敌人public bool createPlay;// Use this for initializationvoid Start () {Invoke("BornTank",1f);Destroy(gameObject,1f);}private void Update(){}private void BornTank(){if (createPlay){Instantiate(playerPrefab, transform.position, Quaternion.identity);}else{int num = Random.Range(0, 2);Instantiate(enemyPrefabList[num], transform.position, Quaternion.identity);}}
}
Born.cs 玩家敌人坦克出生

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Enemy : MonoBehaviour {//属性值public float moveSpeed = 3;private Vector3 bullectEulerAugles;private float v=-1;private float h;//引用private SpriteRenderer sr;public Sprite[] tankSprite; //上 右 下 左public GameObject bullectPrefab;public GameObject explosionPrefab;//计时器public float timeVal;public float timeValChangeDirection=0;// Use this for initializationvoid Start(){sr = GetComponent<SpriteRenderer>();}// Update is called once per framevoid Update(){//攻击的时间间隔if (timeVal >= 0.3f){//间隔大于0.4的时候才有攻击效果
            Attack();}else{timeVal += Time.deltaTime;}}private void FixedUpdate(){Move();}//坦克的攻击方法private void Attack(){//子弹参数的角度:当前坦克的角度+子弹应该旋转的角度Instantiate(bullectPrefab, transform.position, Quaternion.Euler(transform.eulerAngles + bullectEulerAugles));timeVal = 0;}//坦克的移动方法private void Move(){if(timeValChangeDirection>=4){int num = Random.Range(0,8);if(num>5){v = -1;h = 0;}else if (num == 0){v = 1;h = 0;}else if (num > 0 && num <= 2){h = -1;v = 0;}else if (num > 2 && num <= 4){h = 1;v = 0;}timeValChangeDirection = 0;}else{timeValChangeDirection += Time.fixedDeltaTime;}//监听玩家垂直轴输入
      transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);if (v < 0){sr.sprite = tankSprite[2];bullectEulerAugles = new Vector3(0, 0, -180);}else if (v > 0){sr.sprite = tankSprite[0];bullectEulerAugles = new Vector3(0, 0, 0);}if (v != 0){return;}//监听玩家水平轴输入
     transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);if (h < 0){sr.sprite = tankSprite[3];bullectEulerAugles = new Vector3(0, 0, 90);}else if (h > 0){sr.sprite = tankSprite[1];bullectEulerAugles = new Vector3(0, 0, -90);}}//坦克的死亡方法private void Die(){PlayerManager.Instance.playerScore++;//产生爆炸特效
        Instantiate(explosionPrefab, transform.position, transform.rotation);//死亡
        Destroy(gameObject);}//优化敌人AIprivate void OnCollisionEnter2D(Collision2D collision){if(collision.gameObject.tag=="Enemy"){timeValChangeDirection = 4;}}}
Enemy.cs 敌人坦克

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Explosion : MonoBehaviour {// Use this for initializationvoid Start () {//坦克销毁后0.167秒销毁爆炸特效Destroy(gameObject,0.167f);}// Update is called once per framevoid Update () {}
}
Explosion.cs 游戏销毁特效

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Heart : MonoBehaviour {private SpriteRenderer sr;public GameObject explosionPrefab;public Sprite BrokenSprite;   // Use this for initializationvoid Start () {sr = GetComponent<SpriteRenderer>();}private void Die(){sr.sprite = BrokenSprite;Instantiate(explosionPrefab,transform.position,transform.rotation);PlayerManager.Instance.isDefeat = true;}
}
Heart.cs 心脏

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;public class Bullect : MonoBehaviour {public float moveSpeed = 10;public bool isPlayerBullect;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);}//子弹触发碰撞检测private void OnTriggerEnter2D(Collider2D collision){switch(collision.tag){case "Tank":if(!isPlayerBullect){collision.SendMessage("Die");Destroy(gameObject);}break;case "Heart":collision.SendMessage("Die");Destroy(gameObject);SceneManager.LoadScene("Game");break;case "Enemy":if(isPlayerBullect){collision.SendMessage("Die");Destroy(gameObject);}break;case "Wall"://销毁自身和墙
                Destroy(collision.gameObject);Destroy(gameObject);break;case "Barrier":Destroy(gameObject);break;default:break;}}}
Bullect.cs 子弹

 

转载于:https://www.cnblogs.com/1138720556Gary/p/9795316.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/366895.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

认识Skeleton Screen【屏幕加载骨架】

一直以来&#xff0c;无论是web还是iOS、android的应用中&#xff0c;为了提升应用的加载等待这段时间的用户感知体验&#xff0c;各种奇门遁甲之术层出不穷。其中&#xff0c;菊花图以及由它衍生各种加载动画是一个非常大的流派&#xff0c;如下图所示&#xff1a;由它衍生而出…

使用Apache Zookeeper进行协调和服务发现

面向服务的设计已被证明是针对各种不同的分布式系统的成功解决方案。 如果使用得当&#xff0c;它会带来很多好处。 但是随着服务数量的增加&#xff0c;了解部署什么以及部署在何处变得更加困难。 而且&#xff0c;由于我们正在构建可靠且高度可用的系统&#xff0c;因此还需要…

微信小程序无埋点数据采集方案

作者&#xff1a;lxj&#xff0c;点餐终端团队成员前言 相信业务团队对这样的场景不会太陌生&#xff1a;打点需求&#xff1a; 每新上一个功能&#xff0c;数据产品便会同步加上打点需求&#xff0c;当数据打点上线后一段时间&#xff0c;数据产品/业务产品便会针对数据的转化…

php异步请求$.post,如何用PHP实现异步请求、忽略返回值

本篇文章的主要内容是用PHP实现异步请求、忽略返回值&#xff0c;具有一定的参考价值&#xff0c;有需要的朋友可以看看&#xff0c;希望能对你有帮助。项目需要&#xff0c;场景如下&#xff1a;某个条件下需要调用接口发送多个请求执行脚本&#xff0c;但是由于每个请求下的脚…

Linux NTP

ntpd服务的设置: ntpd服务的相关设置文件如下&#xff1a; /etc/ntp.conf&#xff1a;这个是NTP daemon的主要设文件&#xff0c;也是 NTP 唯一的设定文件。/usr /share/zoneinfo/:在这个目录下的文件其实是规定了各主要时区的时间设定文件&#xff0c;例如北京地区的时区设定文…

《React 学习之道》The Road to learn React (简体中文版)

通往 React 实战大师之旅&#xff1a;掌握 React 最简单&#xff0c;且最实用的教程。 前言 《React 学习之道》这本书使用路线图中的精华部分用于传授 React&#xff0c;并将其融入一个独具吸引力的真实世界 App的具体代码实现。 如何掌握 React 存在特别多的路线图。本书提…

vue.js(三)

这里该记到vue的组件了&#xff0c;组件基础篇 1.vue组件的基本书写方式 Vue.component(button-counter, {data: function () {return {count: 0}},template: <button v-on:click"count">You clicked me {{ count }} times.</button> }) 上面定义了一个名…

Nuxt中如何使用Vuex-Store异步获取数据

Nuxt是一个基于Vue.js的通用型框架&#xff0c;它集成了使用Vue开发的绝大数组件/框架。 长话短说如何在Vuex-store中获取异步数据呢&#xff1f; 在Nuxt中由于集合了Vuex还有其他的一些配置&#xff0c;大大的方便了我们使用Vuex&#xff1b;在Nuxt官方文档中写到&#xff1a;…

Struts2面试问答

Struts2是用Java开发Web应用程序的著名框架之一。 最近&#xff0c;我写了很多Struts2教程 &#xff0c;在这篇文章中&#xff0c;我列出了一些重要的Struts2面试问题以及答案&#xff0c;以帮助您进行面试。 什么是Struts2&#xff1f; Struts1和Struts2之间有什么区别&…

基于canvas的骨骼动画

最近学习到了一种关于canvas的骨骼动画&#xff0c;听这个名字就知道他和canvas之前的动画不同&#xff0c;不知道你有没有兴趣了解一下呢&#xff1f;关于骨骼动画最初是无意间在腾讯团队上看到的&#xff0c;但是由于他官网的教程是在是少之又少&#xff0c;也就仅有一个小de…

Python APSchedule安装使用与源码分析

我们的项目中用apschedule作为核心定时调度模块。所以对apschedule进行了一些调查和源码级的分析。 1、为什么选择apschedule&#xff1f; 听信了一句话&#xff0c;apschedule之于python就像是quartz之于java。实际用起来还是不错的。 2、安装 # pip安装方式 $ pip install ap…

NetBeans 7.4的本机Java打包

成为“ NetBeans 74 NewAndNoteworthy ”页面的NetBeans 7.4的新功能之一是“本机打包 ”&#xff0c;在该页面上被描述为“ JavaSE项目现在支持使用JavaFX提供的本机打包技术来创建本机包。 ” 我将使用一个非常简单的示例来演示NetBeans 7.4中的本机打包功能。 下一个代码清…

基于Vue开发一个日历组件

最近在做一个类似课程表的需求&#xff0c;需要自制一个日历来支持功能及展现&#xff0c;就顺便研究一下应该怎么开发日历组件。 更新 2.23修复了2026年2月份会渲染多一行的bug&#xff0c;谢谢深蓝一人童鞋提出的bug&#xff0c;解决方案是给二月份的日历做特殊处理&#xf…

php 打开word乱码怎么办,如何解决php word 乱码问题

php word乱码的解决办法&#xff1a;首先打开“/Writer/Word2007/Base.php”文件&#xff1b;然后添加“$objWriter->writeAttribute(‘w:eastAsia’, $font)”内容&#xff1b;最后保存修改即可。PHPword解决中文乱码一、增加东亚字体支持打开并编辑路径/Writer/Word2007/B…

Java开发人员访谈的MindMap

多年来&#xff0c;我曾在许多Java开发人员访谈中担任小组成员。 之前&#xff0c;我曾写过一篇标题为“成功进行软件工程师技术面试的7大技巧”的文章&#xff0c;其中涵盖了很少的一般准则。 在本文中&#xff0c;我将分享一个思维导图&#xff0c;其中包含Java开发人员访谈中…

送给大家一个好看的简历神器

很多人看到里边有好看的东西就习惯性的点进来看看&#xff0c;还一边点一边想 —— 好看的简历我见多了&#xff0c;你这个又能好看到哪里去。我想差不多可以&#xff1a; 哪里吧因为最近有在准备简历&#xff0c;就习惯性的找一找有没有现成的简历模板。结果全是付费的&#x…

PHP简单实现单点登录功能示例

1.准备两个虚拟域名 127.0.0.1 www.openpoor.com127.0.0.1 www.myspace.com 2.在openpoor的根目录下创建以下文件 index.PHP 123456789101112131415161718<?phpsession_start();?><!DOCTYPE html><html><head><meta charset"UTF-8"/&…

JUNG 计算图属性,中心度,偏心率,直径,半径

本文介绍利用Java的第三方API JUNG 计算图中&#xff1a; closeness centrality&#xff1b;// 图中某节点的 接近中心性/亲密中心性 betweenness centrality&#xff1b;// 图中某节点的 中介中心性/介数中心性 distance; // 图中两节点的最短距离 eccentricity; // 图中某节…

Java VM –提防YoungGen空间

您可能从我们以前的面向性能的文章中看到&#xff0c;健康的JVM是实现最佳应用程序性能和稳定性的最重要目标之一。 这样的健康评估通常仅关注主要收集的频率&#xff08;避免&#xff09;或检测内存泄漏的存在。 年轻一代空间或短寿命物体的大小和足迹如何&#xff1f; 本文…

小程序绘图工具painter-json文件绘制保存分享图-可点击任意元素触发函数

Painter是由酷家乐移动前端团队打造的一款小程序绘图组件。 原项目地址&#xff1a;https://github.com/Kujiale-Mobile/Painter 新版地址&#xff1a;https://github.com/shesw/Painter 这款交互版原来是为了针对业务中的新需求而由我自己开发的&#xff0c;后来需求改动&a…