灵魂画师上线:
这是比较直白的草图也叫灵魂图,中间大方框周围的小方框代表鱼的生成位置,鱼通过这七个点来生成,并且游向屏幕中央,
来让玩家看到这种效果:
而单纯的只给鱼向前游是不行的,那样看着会很机械,所以要模仿鱼的左右移动,也就是弧线移动。
弧线移动的实现方式也很简单,说白了就是让他边扭着身子边直线跑,这样就是弧线移动了。
把这两个运动分解成可以复用的两个脚本,一个直线移动,一个掌控自身的增量旋转。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
作者:琦玉老师的二弟子
*/
namespace JumpAgent{
public class AutoMove : MonoBehaviour
{
public float speed = 1f;
public Vector3 Dir = Vector3.right;
private void Update()
{
transform.Translate(Dir * speed * Time.deltaTime);
}
}//类
}//命名空间
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
作者:琦玉老师的二弟子
*/
namespace JumpAgent{
public class AutoRotate : MonoBehaviour
{
public float speed = 10f;
private void Update()
{
transform.Rotate(Vector3.forward, speed * Time.deltaTime);
}
}//类
}//命名空间
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
作者:琦玉老师的二弟子
*/
namespace JumpAgent
{
public class FishMaker : MonoBehaviour
{
public Transform[] genPositions;//鱼的生成位置
public GameObject[] fishPrefabs;//所有鱼的预制体
public Transform fishHolder;//收纳鱼的clone,防止散乱
private void Start()
{
InvokeRepeating("MakeFish", 0, 0.1f);
}
void MakeFish()
{
//在什么位置生成什么鱼
int genPosIndex = Random.Range(0, genPositions.Length);
int fishPreIndex = Random.Range(0, fishPrefabs.Length);
//获取鱼的最大生成数量和最大速度
int maxNum = fishPrefabs[fishPreIndex].GetComponent().maxNuml;
int maxSpeed = fishPrefabs[fishPreIndex].GetComponent().maxSpeed;
//决定鱼的生成数量和速度
int num = Random.Range((maxNum / 2) + 1, maxNum);
int speed = Random.Range(maxSpeed / 2, maxSpeed);
//鱼的行为轨迹,0代表直线,1代表弧线
int moveType = Random.Range(0, 2);
//直走的倾斜角
int angOffset;
//转弯速度
int angSpeed;
if (moveType == 0)
{
//直线鱼
angOffset = Random.Range(-22, 22);
StartCoroutine(GreatLineFish(genPosIndex, fishPreIndex, num, speed, angOffset));
}
else
{
//弧线
angSpeed = Random.Range(8, 13);
int direct= Random.Range(0, 2);
if (direct==0)
{
StartCoroutine(GreatcurveFish(genPosIndex, fishPreIndex, num, speed, angSpeed));
}
else
{
StartCoroutine(GreatcurveFish(genPosIndex, fishPreIndex, num, speed, angSpeed));
}
}
}
IEnumerator GreatLineFish(int genPosIndex, int fishPreIndex, int num, int speed, int angOffset)
{
for (int i = 0; i < num; i++)
{
GameObject fish = GameObject.Instantiate(fishPrefabs[fishPreIndex]);
fish.transform.SetParent(fishHolder, false);
fish.transform.localPosition = genPositions[genPosIndex].localPosition;
fish.transform.localRotation = genPositions[genPosIndex].localRotation;
fish.transform.Rotate(0, 0, angOffset);
fish.GetComponent().sortingOrder += i;
fish.AddComponent().speed = speed;
yield return new WaitForSeconds(0.5f);
}
}
IEnumerator GreatcurveFish(int genPosIndex, int fishPreIndex, int num, int speed, int angSpeed)
{
for (int i = 0; i < num; i++)
{
GameObject fish = GameObject.Instantiate(fishPrefabs[fishPreIndex]);
fish.transform.SetParent(fishHolder, false);
fish.transform.localPosition = genPositions[genPosIndex].localPosition;
fish.transform.localRotation = genPositions[genPosIndex].localRotation;
fish.GetComponent().sortingOrder += i;
fish.AddComponent().speed = angSpeed;//添加旋转组件
fish.AddComponent().speed = speed;//添加移动组件
yield return new WaitForSeconds(0.5f);
}
}
}//类
}//命名空间
首先,炮台会跟随我们的手指的输入坐标来进行转动,然后,是炮台的伤害,炮台的伤害根据我们所选择的伤害来执行,也就是操作一个int类型的伤害数组,然后可以把这个伤害数组里面的元素平均分组,然后每到一个分组里就给我们的换一个炮台(隐藏和显示)。
其次,我们的炮台发射子弹是要钱的,根据不同的金额,对鱼造成不同的伤害,当时并不是直接通过子弹对其造成伤害,是炮台放出去子弹,子弹碰到鱼,然后在子弹处生成网子,在把子弹应该造成的伤害赋值给网子,网子存在一定时间,然后由网子再和鱼做碰撞检测,每个enter进去的鱼都会收到网子发送给鱼的伤害,也就是说每次鱼碰到网子生命值都会减少,直到鱼死亡。
再根据每只鱼的死亡,去更新相应的UI数据即可。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
/*
作者:琦玉老师的二弟子
*/
namespace JumpAgent
{
public class GameController : MonoBehaviour
{
public static GameController _instance;
private void Awake()
{
_instance = this;
}
public GameObject Waterwave;
public GameObject bg;
public Sprite[] BGSprite;
public Text oneShootCostText;
public Text goldText;
public Text lvText;
public Text lvNameText;
public Text smallCuttondownText;
public Text bigCuttondownText;
public Button bigCountdownButton;
public Button BackButton;
public Button SettingButton;
public GameObject[] BulletPrefabs;
public GameObject[] Guns;
public Slider ExpSlider;
private int[] ShootCost = { 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 };
private string[] lvName = { "坚韧黑铁", "倔强青铜", "不屈白银", "荣耀黄金", "华贵铂金", "永恒钻石","璀璨星耀","最强王者","荣耀王者","巅峰王者"};
public Text ShootCostText;
private int CostIndex = 0;
public Transform bulletHorder;
public int lv = 0;
public int exp=0;
public int gold = 500;
private const float bigCountdown = 240f;
private const float smallCountdown = 60f;
private float bigTimer= bigCountdown;
private float smallTimer= smallCountdown;
///
/// 更新UI
///
public void UpdateUI()
{
bigTimer -= Time.deltaTime;
smallTimer -= Time.deltaTime;
if (smallTimer <= 0)
{
smallTimer = smallCountdown;
gold += 100;
}
if (bigTimer<=0&& bigCountdownButton.gameObject.activeSelf==false)
{
bigCuttondownText.gameObject.SetActive(false);
bigCountdownButton.gameObject.SetActive(true);
}
while (exp>=1000+200*lv)
{
lv++;
if (lv%10==0)//每十级生成一次大浪花,并且更新一次背景
{
GameObject.Instantiate(Waterwave);
bg.gameObject.GetComponent().sprite = BGSprite[Random.Range(0, BGSprite.Length)];
}
exp= exp - (1000 + 200 * lv);
}
goldText.text = "$" + gold;
lvText.text = lv.ToString();
if (lv/10<=9)
{
lvNameText.text = lvName[lv / 10];
}
else
{
lvNameText.text = lvName[9];
}
smallCuttondownText.text = (int)smallTimer / 10 + " " + (int)smallTimer % 10;
bigCuttondownText.text = (int)bigTimer + "s";
ExpSlider.value = ((float)exp) / (1000 + 200 * lv);
}
///
/// 开火
///
public void Fire()
{
if (Input.GetMouseButton(0) && EventSystem.current.IsPointerOverGameObject() == false)
{
//这里当没钱打子弹的时候给一个提示
if (gold- ShootCost[CostIndex]>=0)
{
goldText.color = Color.yellow;
gold -= ShootCost[CostIndex];
}
else
{
goldText.color = Color.red;
return;
}
GameObject bullet = GameObject.Instantiate(BulletPrefabs[Random.Range(0, BulletPrefabs.Length)]);
bullet.transform.SetParent(bulletHorder, false);
bullet.transform.position = Guns[CostIndex / 4].transform.Find("FirePosition").position;
bullet.transform.rotation = Guns[CostIndex / 4].transform.Find("FirePosition").rotation;
bullet.GetComponent().damage = ShootCost[CostIndex];
bullet.AddComponent().Dir = Vector3.up;
bullet.GetComponent().speed = 10f;
bullet.AddComponent().DestoryTime = 3f;
}
}
///
/// 右上角大奖金点击
///
public void OnBigCountdownButtonDown()
{
gold += 500;
bigCountdownButton.gameObject.SetActive(false);
bigCuttondownText.gameObject.SetActive(true);
bigTimer = bigCountdown;
}
//换枪操作--------------------------
public void OnRDButtonClick()
{
Guns[CostIndex / 4].SetActive(false);
CostIndex++;
CostIndex = (CostIndex > ShootCost.Length - 1) ? 0 : CostIndex;
ShootCostText.text = "$" + ShootCost[CostIndex];
Guns[CostIndex / 4].SetActive(true);
}
public void OnLDButtonClick()
{
Guns[CostIndex / 4].SetActive(false);
CostIndex--;
CostIndex = (CostIndex < 0) ? ShootCost.Length - 1 : CostIndex;
ShootCostText.text = "$" + ShootCost[CostIndex];
Guns[CostIndex / 4].SetActive(true);
}
void hualun()
{
if (Input.GetAxis("Mouse ScrollWheel") > 0)
{
OnRDButtonClick();
}
if (Input.GetAxis("Mouse ScrollWheel") < 0)
{
OnLDButtonClick();
}
}
//---------------------------------
private void Update()
{
hualun();
Fire();
UpdateUI();
}
}//类
}//命名空间
其实这个游戏和打飞机的原理基本一样,不同的是模拟了下捕鱼的动作之类的。