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 = ;
监听玩家水平轴输入
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 = ; // Use this for initialization
void Start () { } // Update is called once per frame
void Update () {
//监听玩家水平轴输入
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);
}
}
Player.cs
控制图片的移动和切换
制作坦克渲染
添加精灵数组的引用
private SpriteRenderer sr;
public Sprite[] tankSprite;
(上 右 下 左)
玩家按上下左右控制坦克方向的移动
//监听玩家水平轴输入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1
transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);
if (h < )
{
sr.sprite = tankSprite[];
}else if (h>)
{
sr.sprite = tankSprite[];
} //监听玩家垂直轴输入
float v = Input.GetAxisRaw("Vertical");
transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);
if (v < )
{
sr.sprite = tankSprite[];
}
else if (v > )
{
sr.sprite = tankSprite[];
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class Player : MonoBehaviour { public float moveSpeed = ; private SpriteRenderer sr;
public Sprite[] tankSprite; //上 右 下 左 // Use this for initialization
void Start () {
sr = GetComponent<SpriteRenderer>();
} // Update is called once per frame
void Update () {
//监听玩家水平轴输入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1
transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);
if (h < )
{
sr.sprite = tankSprite[];
}else if (h>)
{
sr.sprite = tankSprite[];
} //监听玩家垂直轴输入
float v = Input.GetAxisRaw("Vertical");
transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);
if (v < )
{
sr.sprite = tankSprite[];
}
else if (v > )
{
sr.sprite = tankSprite[];
}
}
}
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 1
transform.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 = ; private SpriteRenderer sr;
public Sprite[] tankSprite; //上 右 下 左 // Use this for initialization
void Start () {
sr = GetComponent<SpriteRenderer>();
} // Update is called once per frame
void Update () {
//监听玩家水平轴输入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1
transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);
if (h < )
{
sr.sprite = tankSprite[];
}else if (h>)
{
sr.sprite = tankSprite[];
} //监听玩家垂直轴输入
float v = Input.GetAxisRaw("Vertical");
transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
if (v < )
{
sr.sprite = tankSprite[];
}
else if (v > )
{
sr.sprite = tankSprite[];
}
} //
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 < )
{
sr.sprite = tankSprite[];
}
else if (v > )
{
sr.sprite = tankSprite[];
} if(v!=)
{
return;
} //监听玩家水平轴输入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1
transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);
if (h < )
{
sr.sprite = tankSprite[];
}else if (h>)
{
sr.sprite = tankSprite[];
}
整理一下Player.cs脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class Player : MonoBehaviour { //属性值
public float moveSpeed = ; //引用
private SpriteRenderer sr;
public Sprite[] tankSprite; //上 右 下 左 // Use this for initialization
void Start () {
sr = GetComponent<SpriteRenderer>();
} // Update is called once per frame
void 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 < )
{
sr.sprite = tankSprite[];
}
else if (v > )
{
sr.sprite = tankSprite[];
} if (v != )
{
return;
} //监听玩家水平轴输入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1
transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
if (h < )
{
sr.sprite = tankSprite[];
}
else if (h > )
{
sr.sprite = tankSprite[];
}
}
}
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 = ; //引用
private SpriteRenderer sr;
public Sprite[] tankSprite; //上 右 下 左
public GameObject bullectPrefab; // Use this for initialization
void Start () {
sr = GetComponent<SpriteRenderer>();
} // Update is called once per frame
void 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 < )
{
sr.sprite = tankSprite[];
}
else if (v > )
{
sr.sprite = tankSprite[];
} if (v != )
{
return;
} //监听玩家水平轴输入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1
transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
if (h < )
{
sr.sprite = tankSprite[];
}
else if (h > )
{
sr.sprite = tankSprite[];
}
}
}
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 = ;
监听玩家水平轴输入
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 = ; // Use this for initialization
void Start () { } // Update is called once per frame
void Update () {
//监听玩家水平轴输入
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);
}
}
Player.cs
控制图片的移动和切换
制作坦克渲染
添加精灵数组的引用
private SpriteRenderer sr;
public Sprite[] tankSprite;
(上 右 下 左)
玩家按上下左右控制坦克方向的移动
//监听玩家水平轴输入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1
transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);
if (h < )
{
sr.sprite = tankSprite[];
}else if (h>)
{
sr.sprite = tankSprite[];
} //监听玩家垂直轴输入
float v = Input.GetAxisRaw("Vertical");
transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);
if (v < )
{
sr.sprite = tankSprite[];
}
else if (v > )
{
sr.sprite = tankSprite[];
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class Player : MonoBehaviour { public float moveSpeed = ; private SpriteRenderer sr;
public Sprite[] tankSprite; //上 右 下 左 // Use this for initialization
void Start () {
sr = GetComponent<SpriteRenderer>();
} // Update is called once per frame
void Update () {
//监听玩家水平轴输入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1
transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);
if (h < )
{
sr.sprite = tankSprite[];
}else if (h>)
{
sr.sprite = tankSprite[];
} //监听玩家垂直轴输入
float v = Input.GetAxisRaw("Vertical");
transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);
if (v < )
{
sr.sprite = tankSprite[];
}
else if (v > )
{
sr.sprite = tankSprite[];
}
}
}
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 1
transform.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 = ; private SpriteRenderer sr;
public Sprite[] tankSprite; //上 右 下 左 // Use this for initialization
void Start () {
sr = GetComponent<SpriteRenderer>();
} // Update is called once per frame
void Update () {
//监听玩家水平轴输入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1
transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);
if (h < )
{
sr.sprite = tankSprite[];
}else if (h>)
{
sr.sprite = tankSprite[];
} //监听玩家垂直轴输入
float v = Input.GetAxisRaw("Vertical");
transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
if (v < )
{
sr.sprite = tankSprite[];
}
else if (v > )
{
sr.sprite = tankSprite[];
}
} //
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 < )
{
sr.sprite = tankSprite[];
}
else if (v > )
{
sr.sprite = tankSprite[];
} if(v!=)
{
return;
} //监听玩家水平轴输入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1
transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);
if (h < )
{
sr.sprite = tankSprite[];
}else if (h>)
{
sr.sprite = tankSprite[];
}
整理一下Player.cs脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class Player : MonoBehaviour { //属性值
public float moveSpeed = ; //引用
private SpriteRenderer sr;
public Sprite[] tankSprite; //上 右 下 左 // Use this for initialization
void Start () {
sr = GetComponent<SpriteRenderer>();
} // Update is called once per frame
void 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 < )
{
sr.sprite = tankSprite[];
}
else if (v > )
{
sr.sprite = tankSprite[];
} if (v != )
{
return;
} //监听玩家水平轴输入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1
transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
if (h < )
{
sr.sprite = tankSprite[];
}
else if (h > )
{
sr.sprite = tankSprite[];
}
}
}
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 = ; //引用
private SpriteRenderer sr;
public Sprite[] tankSprite; //上 右 下 左
public GameObject bullectPrefab; // Use this for initialization
void Start () {
sr = GetComponent<SpriteRenderer>();
} // Update is called once per frame
void 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 < )
{
sr.sprite = tankSprite[];
}
else if (v > )
{
sr.sprite = tankSprite[];
} if (v != )
{
return;
} //监听玩家水平轴输入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1
transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
if (h < )
{
sr.sprite = tankSprite[];
}
else if (h > )
{
sr.sprite = tankSprite[];
}
}
}
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 = ;
}
}
给子弹添加方向速度
public float moveSpeed = ;
给子弹添加判断是否是友军
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 initialization
void Start () {
sr = GetComponent<SpriteRenderer>();
}
添加Heart.cs心脏死亡时方法
private void Die()
{
sr.sprite = BrokenSprite;
}
添加Explosion.cs脚本
当坦克销毁时触发脚本
public class Explosion : MonoBehaviour { // Use this for initialization
void Start () {
//坦克销毁后0.167秒销毁爆炸特效
Destroy(gameObject,0.167f);
} // Update is called once per frame
void 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 = ;
private Vector3 bullectEulerAugles;
public float timeVal;
private float defendTimeVal=;
private bool isDefended=true; //引用
private SpriteRenderer sr;
public Sprite[] tankSprite; //上 右 下 左
public GameObject bullectPrefab;
public GameObject explosionPrefab;
public GameObject defendEffectPrefab; // Use this for initialization
void Start () {
sr = GetComponent<SpriteRenderer>();
} // Update is called once per frame
void Update () {
//保护是否处于无敌状态
if(isDefended)
{
defendEffectPrefab.SetActive(true);
defendTimeVal -= Time.deltaTime;
if (defendTimeVal<=)
{
isDefended = false;
defendEffectPrefab.SetActive(false);
}
} //攻击的CD
if (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 = ;
}
} //坦克的移动方法
private void Move()
{
//监听玩家垂直轴输入
float v = Input.GetAxisRaw("Vertical");
transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
if (v < )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , -);
}
else if (v > )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , );
} if (v != )
{
return;
} //监听玩家水平轴输入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1
transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
if (h < )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , );
}
else if (h > )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , -);
}
} //坦克的死亡方法
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 initialization
void Start () {
//坦克销毁后0.167秒销毁爆炸特效
Destroy(gameObject,0.167f);
} // Update is called once per frame
void 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 initialization
void 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 = ; public bool isPlayerBullect; // Use this for initialization
void Start () { } // Update is called once per frame
void 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 = ;
private Vector3 bullectEulerAugles;
public float timeVal;
private float defendTimeVal = ;
private bool isDefended = true; //引用
private SpriteRenderer sr;
public Sprite[] tankSprite; //上 右 下 左
public GameObject bullectPrefab;
public GameObject explosionPrefab;
public GameObject defendEffectPrefab; // Use this for initialization
void Start()
{
sr = GetComponent<SpriteRenderer>();
} // Update is called once per frame
void Update()
{
//保护是否处于无敌状态
if (isDefended)
{
defendEffectPrefab.SetActive(true);
defendTimeVal -= Time.deltaTime;
if (defendTimeVal <= )
{
isDefended = false;
defendEffectPrefab.SetActive(false);
}
} //攻击的CD
if (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 = ;
}
} //坦克的移动方法
private void Move()
{
//监听玩家垂直轴输入
float v = Input.GetAxisRaw("Vertical");
transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
if (v < )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , -);
}
else if (v > )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , );
} if (v != )
{
return;
} //监听玩家水平轴输入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1
transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
if (h < )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , );
}
else if (h > )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , -);
}
} //坦克的死亡方法
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 initialization
void 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 initialization
void Start () {
Invoke("BornTank",0.8f);
Destroy(gameObject,0.8f);
} // Update is called once per frame
void 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(, );
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 initialization
void 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(, );
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 = ;
}
坦克的移动不需要按下上下左右键盘,只需要管理V和H的值对敌人AI进行方向的控制
定义两个计时器
public float timeVal;
public float timeValChangeDirection;
修改敌人移动的方法
private void Move()
{ if(timeValChangeDirection>=)
{
int num = Random.Range(,);
if(num>)
{
v = -;
h = ;
}else if (num == )
{
v = ;
h = ;
}else if (num > && num <= )
{
h = -;
v = ;
}else if (num > && num <= )
{
h = ;
v = ;
} timeValChangeDirection = ;
}
else
{
timeValChangeDirection += Time.fixedDeltaTime;
} //监听玩家垂直轴输入 transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World); if (v < )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , -);
}
else if (v > )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , );
} if (v != )
{
return;
} //监听玩家水平轴输入 transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
if (h < )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , );
}
else if (h > )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , -);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class Enemy : MonoBehaviour { //属性值
public float moveSpeed = ;
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=; // Use this for initialization
void Start()
{
sr = GetComponent<SpriteRenderer>();
} // Update is called once per frame
void 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 = ;
} //坦克的移动方法
private void Move()
{ if(timeValChangeDirection>=)
{
int num = Random.Range(,);
if(num>)
{
v = -;
h = ;
}else if (num == )
{
v = ;
h = ;
}else if (num > && num <= )
{
h = -;
v = ;
}else if (num > && num <= )
{
h = ;
v = ;
} timeValChangeDirection = ;
}
else
{
timeValChangeDirection += Time.fixedDeltaTime;
} //监听玩家垂直轴输入 transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World); if (v < )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , -);
}
else if (v > )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , );
} if (v != )
{
return;
} //监听玩家水平轴输入 transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
if (h < )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , );
}
else if (h > )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , -);
}
} //坦克的死亡方法
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 = ; public bool isPlayerBullect; // Use this for initialization
void Start () { } // Update is called once per frame
void 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[], new Vector3(, -, -), Quaternion.identity);
//用墙把老家围起来
Instantiate(item[], new Vector3(-, -, -), Quaternion.identity);
Instantiate(item[], new Vector3(, -, -), Quaternion.identity);
for(int i=-;i<;i++)
{
Instantiate(item[],new Vector3(i,-,),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=-;i<;i++)
{
CreateItem(item[], new Vector3(i, , ), Quaternion.identity);
}
for(int i=-;i<;i++)
{
CreateItem(item[], new Vector3(i, -, ), Quaternion.identity);
}
for(int i=-;i<;i++)
{
CreateItem(item[], new Vector3(-, i, ), Quaternion.identity);
}
for(int i=-;i<;i++)
{
CreateItem(item[], new Vector3(-, i, ), Quaternion.identity);
}
产生随机位置的方法
private Vector3 CreateRamdomPosition()
{
//不生成x=-10,10的两列,y=-8和8这两行的位置
while(true)
{
Vector3 createPosition = new Vector3(Random.Range(-, ), Random.Range(-, ),);
if(!HasThePosition(createPosition))
{
return createPosition;
} }
}
用来判断位置列表中是否有这个位置
private bool HasThePosition(Vector3 createPos)
{
for(int i=;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 = ; public bool isPlayerBullect; // Use this for initialization
void Start () { } // Update is called once per frame
void 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=;i<;i++)
{
CreateItem(item[], CreateRamdomPosition(), Quaternion.identity);
}
for(int i=;i<;i++)
{
CreateItem(item[], CreateRamdomPosition(), Quaternion.identity);
}
for (int i = ; i < ; i++)
{
CreateItem(item[], CreateRamdomPosition(), Quaternion.identity);
}
for (int i = ; i < ; i++)
{
CreateItem(item[], CreateRamdomPosition(), Quaternion.identity);
}
初始化玩家
GameObject go = Instantiate(item[], new Vector3(-, -, ), Quaternion.identity);
go.GetComponent<Born>().createPlay = true;
产生敌人
CreateItem(item[], new Vector3(-,,),Quaternion.identity);
CreateItem(item[], new Vector3(, , ), Quaternion.identity);
CreateItem(item[], new Vector3(, , ), Quaternion.identity);
实例化地图并且让围墙的数量尽可能的多
for (int i=;i<;i++)
{
CreateItem(item[], CreateRamdomPosition(), Quaternion.identity);
}
for(int i=;i<;i++)
{
CreateItem(item[], CreateRamdomPosition(), Quaternion.identity);
}
for (int i = ; i < ; i++)
{
CreateItem(item[], CreateRamdomPosition(), Quaternion.identity);
}
for (int i = ; i < ; i++)
{
CreateItem(item[], CreateRamdomPosition(), Quaternion.identity);
}
产生敌人的方法
private void CreateEnemy()
{
int num = Random.Range(, );
Vector3 EnemyPos = new Vector3();
if(num==)
{
EnemyPos = new Vector3(-, , );
}else if(num==)
{
EnemyPos = new Vector3(, , );
}
else
{
EnemyPos = new Vector3(, , );
} CreateItem(item[],EnemyPos,Quaternion.identity);
}
每隔5s产生一波敌人
InvokeRepeating("CreateEnemy",,);
优化一下敌人AI
敌人AI碰到一起时切换一次方向
private void OnCollisionEnter2D(Collision2D collision)
{
if(collision.gameObject.tag=="Enemy")
{
timeValChangeDirection = ;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class Player : MonoBehaviour { //属性值
public float moveSpeed = ;
private Vector3 bullectEulerAugles;
public float timeVal;
private float defendTimeVal=;
private bool isDefended=true; //引用
private SpriteRenderer sr;
public Sprite[] tankSprite; //上 右 下 左
public GameObject bullectPrefab;
public GameObject explosionPrefab;
public GameObject defendEffectPrefab; // Use this for initialization
void Start () {
sr = GetComponent<SpriteRenderer>();
} // Update is called once per frame
void Update () {
//保护是否处于无敌状态
if(isDefended)
{
defendEffectPrefab.SetActive(true);
defendTimeVal -= Time.deltaTime;
if (defendTimeVal<=)
{
isDefended = false;
defendEffectPrefab.SetActive(false);
}
} //攻击的CD
if (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 = ;
}
} //坦克的移动方法
private void Move()
{
//监听玩家垂直轴输入
float v = Input.GetAxisRaw("Vertical");
transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
if (v < )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , -);
}
else if (v > )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , );
} if (v != )
{
return;
} //监听玩家水平轴输入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1
transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
if (h < )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , );
}
else if (h > )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , -);
}
} //坦克的死亡方法
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[], new Vector3(, -, -), Quaternion.identity);
//用墙把老家围起来
CreateItem(item[], new Vector3(-, -, -), Quaternion.identity);
CreateItem(item[], new Vector3(, -, -), Quaternion.identity);
for(int i=-;i<;i++)
{
Instantiate(item[],new Vector3(i,-,),Quaternion.identity);
}
//实例化外围墙
for(int i=-;i<;i++)
{
CreateItem(item[], new Vector3(i, , ), Quaternion.identity);
}
for(int i=-;i<;i++)
{
CreateItem(item[], new Vector3(i, -, ), Quaternion.identity);
}
for(int i=-;i<;i++)
{
CreateItem(item[], new Vector3(-, i, ), Quaternion.identity);
}
for(int i=-;i<;i++)
{
CreateItem(item[], new Vector3(, i, ), Quaternion.identity);
} //初始化玩家
GameObject go = Instantiate(item[], new Vector3(-, -, ), Quaternion.identity);
go.GetComponent<Born>().createPlay = true; //产生敌人
CreateItem(item[], new Vector3(-,,),Quaternion.identity);
CreateItem(item[], new Vector3(, , ), Quaternion.identity);
CreateItem(item[], new Vector3(, , ), Quaternion.identity); //第一次调用CreateEnemy用4s,每隔5s开调用
InvokeRepeating("CreateEnemy",,); //实例化地图
for (int i=;i<;i++)
{
CreateItem(item[], CreateRamdomPosition(), Quaternion.identity);
}
for(int i=;i<;i++)
{
CreateItem(item[], CreateRamdomPosition(), Quaternion.identity);
}
for (int i = ; i < ; i++)
{
CreateItem(item[], CreateRamdomPosition(), Quaternion.identity);
}
for (int i = ; i < ; i++)
{
CreateItem(item[], 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(-, ), Random.Range(-, ),);
if(!HasThePosition(createPosition))
{
return createPosition;
} }
} //用来判断位置列表中是否有这个位置
private bool HasThePosition(Vector3 createPos)
{
for(int i=;i<itemPositionList.Count;i++)
{
if(createPos==itemPositionList[i])
{
return true;
}
}
return false;
} //产生敌人的方法
private void CreateEnemy()
{
int num = Random.Range(, );
Vector3 EnemyPos = new Vector3();
if(num==)
{
EnemyPos = new Vector3(-, , );
}else if(num==)
{
EnemyPos = new Vector3(, , );
}
else
{
EnemyPos = new Vector3(, , );
} CreateItem(item[],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 initialization
void 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(, );
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 = ;
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=; // Use this for initialization
void Start()
{
sr = GetComponent<SpriteRenderer>();
} // Update is called once per frame
void 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 = ;
} //坦克的移动方法
private void Move()
{ if(timeValChangeDirection>=)
{
int num = Random.Range(,);
if(num>)
{
v = -;
h = ;
}else if (num == )
{
v = ;
h = ;
}else if (num > && num <= )
{
h = -;
v = ;
}else if (num > && num <= )
{
h = ;
v = ;
} timeValChangeDirection = ;
}
else
{
timeValChangeDirection += Time.fixedDeltaTime;
} //监听玩家垂直轴输入 transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World); if (v < )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , -);
}
else if (v > )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , );
} if (v != )
{
return;
} //监听玩家水平轴输入 transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
if (h < )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , );
}
else if (h > )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , -);
}
} //坦克的死亡方法
private void Die()
{
//产生爆炸特效
Instantiate(explosionPrefab, transform.position, transform.rotation);
//死亡
Destroy(gameObject);
} //优化敌人AI
private void OnCollisionEnter2D(Collision2D collision)
{
if(collision.gameObject.tag=="Enemy")
{
timeValChangeDirection = ;
}
} }
Enemy.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class Explosion : MonoBehaviour { // Use this for initialization
void Start () {
//坦克销毁后0.167秒销毁爆炸特效
Destroy(gameObject,0.167f);
} // Update is called once per frame
void 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 initialization
void 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 = ; public bool isPlayerBullect; // Use this for initialization
void Start () { } // Update is called once per frame
void 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 = ;
public int playerScore = ;
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 = ;
private Vector3 bullectEulerAugles;
public float timeVal;
private float defendTimeVal=;
private bool isDefended=true; //引用
private SpriteRenderer sr;
public Sprite[] tankSprite; //上 右 下 左
public GameObject bullectPrefab;
public GameObject explosionPrefab;
public GameObject defendEffectPrefab; // Use this for initialization
void Start () {
sr = GetComponent<SpriteRenderer>();
} // Update is called once per frame
void Update () {
//保护是否处于无敌状态
if(isDefended)
{
defendEffectPrefab.SetActive(true);
defendTimeVal -= Time.deltaTime;
if (defendTimeVal<=)
{
isDefended = false;
defendEffectPrefab.SetActive(false);
}
} } private void FixedUpdate()
{
if(PlayerManager.Instance.isDefeat)
{
return;
}
Move();
//攻击的CD
if (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 = ;
}
} //坦克的移动方法
private void Move()
{
//监听玩家垂直轴输入
float v = Input.GetAxisRaw("Vertical");
transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
if (v < )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , -);
}
else if (v > )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , );
} if (v != )
{
return;
} //监听玩家水平轴输入
float h = Input.GetAxisRaw("Horizontal"); //返回-1 0 1
transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
if (h < )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , );
}
else if (h > )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , -);
}
} //坦克的死亡方法
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 = ;
public int playerScore = ;
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 initialization
void Start () { } // Update is called once per frame
void Update () {
if(isDead)
{
Recover();
}
} private void Recover()
{
if (lifeVale < )
{
//游戏失败,返回主界面 SceneManager.LoadScene("Game");
}
else
{
lifeVale--;
GameObject go = Instantiate(born,new Vector3(-,-,),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[], new Vector3(, -, -), Quaternion.identity);
//用墙把老家围起来
CreateItem(item[], new Vector3(-, -, -), Quaternion.identity);
CreateItem(item[], new Vector3(, -, -), Quaternion.identity);
for(int i=-;i<;i++)
{
Instantiate(item[],new Vector3(i,-,),Quaternion.identity);
} //坦克一开始就向下太难了,就直接给老家前面加了一顶墙
CreateItem(item[], new Vector3(, -, -), Quaternion.identity); //实例化外围墙
for (int i=-;i<;i++)
{
CreateItem(item[], new Vector3(i, , ), Quaternion.identity);
}
for(int i=-;i<;i++)
{
CreateItem(item[], new Vector3(i, -, ), Quaternion.identity);
}
for(int i=-;i<;i++)
{
CreateItem(item[], new Vector3(-, i, ), Quaternion.identity);
}
for(int i=-;i<;i++)
{
CreateItem(item[], new Vector3(, i, ), Quaternion.identity);
} //初始化玩家
GameObject go = Instantiate(item[], new Vector3(-, -, ), Quaternion.identity);
go.GetComponent<Born>().createPlay = true; //产生敌人
CreateItem(item[], new Vector3(-,,),Quaternion.identity);
CreateItem(item[], new Vector3(, , ), Quaternion.identity);
CreateItem(item[], new Vector3(, , ), Quaternion.identity); //第一次调用CreateEnemy用4s,每隔5s开调用
InvokeRepeating("CreateEnemy",,); //实例化地图
for (int i=;i<;i++)
{
CreateItem(item[], CreateRamdomPosition(), Quaternion.identity);
}
for(int i=;i<;i++)
{
CreateItem(item[], CreateRamdomPosition(), Quaternion.identity);
}
for (int i = ; i < ; i++)
{
CreateItem(item[], CreateRamdomPosition(), Quaternion.identity);
}
for (int i = ; i < ; i++)
{
CreateItem(item[], 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(-, ), Random.Range(-, ),);
if(!HasThePosition(createPosition))
{
return createPosition;
} }
} //用来判断位置列表中是否有这个位置
private bool HasThePosition(Vector3 createPos)
{
for(int i=;i<itemPositionList.Count;i++)
{
if(createPos==itemPositionList[i])
{
return true;
}
}
return false;
} //产生敌人的方法
private void CreateEnemy()
{
int num = Random.Range(, );
Vector3 EnemyPos = new Vector3();
if(num==)
{
EnemyPos = new Vector3(-, , );
}else if(num==)
{
EnemyPos = new Vector3(, , );
}
else
{
EnemyPos = new Vector3(, , );
} CreateItem(item[],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 initialization
void 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(, );
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 = ;
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=; // Use this for initialization
void Start()
{
sr = GetComponent<SpriteRenderer>();
} // Update is called once per frame
void 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 = ;
} //坦克的移动方法
private void Move()
{ if(timeValChangeDirection>=)
{
int num = Random.Range(,);
if(num>)
{
v = -;
h = ;
}else if (num == )
{
v = ;
h = ;
}else if (num > && num <= )
{
h = -;
v = ;
}else if (num > && num <= )
{
h = ;
v = ;
} timeValChangeDirection = ;
}
else
{
timeValChangeDirection += Time.fixedDeltaTime;
} //监听玩家垂直轴输入 transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World); if (v < )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , -);
}
else if (v > )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , );
} if (v != )
{
return;
} //监听玩家水平轴输入 transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
if (h < )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , );
}
else if (h > )
{
sr.sprite = tankSprite[];
bullectEulerAugles = new Vector3(, , -);
}
} //坦克的死亡方法
private void Die()
{
PlayerManager.Instance.playerScore++;
//产生爆炸特效
Instantiate(explosionPrefab, transform.position, transform.rotation);
//死亡
Destroy(gameObject);
} //优化敌人AI
private void OnCollisionEnter2D(Collision2D collision)
{
if(collision.gameObject.tag=="Enemy")
{
timeValChangeDirection = ;
}
} }
Enemy.cs 敌人坦克
using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class Explosion : MonoBehaviour { // Use this for initialization
void Start () {
//坦克销毁后0.167秒销毁爆炸特效
Destroy(gameObject,0.167f);
} // Update is called once per frame
void 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 initialization
void 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 = ; public bool isPlayerBullect; // Use this for initialization
void Start () { } // Update is called once per frame
void 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 子弹
Unity3D_(游戏)2D坦克大战 像素版的更多相关文章
- 简易坦克大战python版
#! /usr/bin/env python # -*- coding:utf8 -*- ''' *author:wasua *purpose:学习python语言,其中的类以及pygame应用 ...
- pygame小游戏之坦克大战
以前在学校的时候无聊的学了会pygame.看了大概一周的教学视频,做出来个坦克大战的小游戏 Python3.5 pycharm import pygame,sys,time from random ...
- 坦克大战java版
吃了可以加血的血块类 import java.awt.*; public class Blood { //血块移动的路径 int[][] pos = { {450,250},{450,252},{45 ...
- Unity3D_(游戏)2D简单游戏制作过程:捕获高空掉落保龄球
游戏介绍:通过鼠标的左右移动,可以控制帽子的移动,当帽子接到下落的保龄球时,会出现火花效果.没有接到保龄球时,保龄球落到草地上,过10S后会自动消失. 实现效果: 素材+Unity3D源代码:传送 ...
- 【SIKIA计划】_07_Unity3D游戏开发-坦克大战笔记
[新增分类][AudioClips]音频剪辑[AudioMixers]音频混合器[Editor][Fonts]字体[Materials]材质[Models]模型[Standard Assets] [渲 ...
- 基于HTML5坦克大战游戏简化版
之前我们有分享过不少经典的HTML5游戏,有些还是很有意思的,比如HTML5版切水果游戏和HTML5中国象棋游戏.今天要分享的是一款简化版的HTML5坦克大战游戏,方向键控制坦克的行进方向,空格键发射 ...
- 《HTML5经典坦克大战》游戏(代码)
前几天粗略地学了HTML5,然后就用它写了一个<经典坦克大战>游戏. 现在想分享一下我写的代码,写得不好请大家多多指教. 给大家推荐一个网站,这个网站是为大学生而做,为方便学习编程的同学而 ...
- 小强的HTML5移动开发之路(7)——坦克大战游戏1
来自:http://blog.csdn.net/dawanganban/article/details/17693145 上一篇中我们介绍了关于Canvas的基础知识,用Canvas绘制各种图形和图片 ...
- 坦克大战-C语言-详注版
代码地址如下:http://www.demodashi.com/demo/14259.html 坦克大战-C语言-详注版 概述 本文详述了C语言版坦克大战游戏的原理以及实现方法,对游戏代码进行了详细的 ...
随机推荐
- Win10开机后内存突然飙升
欢迎关注微信公众号:猫的尾巴有墨水 Win10开机后内存突然飙升 先停掉Windows Update自动更新 停掉同步主机,也就是同步服务
- 关于echarts中南海诸岛的显示问题
1.china.js 文件中 echarts.registerMap('china', //名字要是'china',不能写成'中国' 2.echarts 配置中地图名称 mapName: ...
- 03 Redis发布与订阅
以qq群的公告,单个发布者,多个收听者为例 发布/订阅 实验 发布订阅的命令 PUBLISH channel msg 将信息 message 发送到指定的频道 channel SUBSCRIBE ch ...
- npm操作命令
查看所有高级的npm moudles npm list --depth= 查看所有全局安装的模块 npm list --depth= -global 查找npm全局安装模块路径 npm config ...
- ES6入门之Proxy
1. 概述 Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种『元编程』即对编程语言进行编程. 1.1 理解 Proxy 是在目标对象之前架设一层『拦截』,外部对对象的访问 ...
- Nginx(web服务器)与Tomcat(应用服务器)搭建集群
Nginx作为互联网最常用的web服务器,高性能的HTTP和反向代理使它经常作为Tomcat集群的方案.Nginx官方只支持使用HTTP协议的集成,但是如果你想使用AJP协议集成,可以使用阿里开源的n ...
- rabbitmq一键部署脚本
1.新建一个名字叫 auto_install_rabbitmq.sh 的文件 2.将下面脚本拷贝到文件中,具体操作步骤在注释里面 #环境 linux #一键安装rabitmq,在linux环境中使用 ...
- Gh0st与云安全
黑产攻击途径升级,云服务成重灾区 在我们的印象里,黑产以及相关的肉鸡DDOS攻击总是离我们很远.可实际情况并非如此,特别是在云服务大行其道的今天. 日前,腾讯反病毒实验室就观察到了国内云服务中Gh0s ...
- 码流回调过快导致下方处理不及时socket阻塞问题
在一个情形中遇到下面一个情况 简述下该图片,对sdk进行二次开发,通过第三方sdk接口获取码流信息.具体实现方式是通过回调函数CallBack_SDK来不停的回调第三方服务的视频流.起初实现逻辑如下: ...
- keras多gpu训练
使用multi_gpu_model即可.观察了一下GPU的利用率,非常的低,大部分时候都是0,估计在相互等待,同步更新模型: 当然了,使用多GPU最明显的好处是可以使用更大的batch size im ...