(十一)享元模式:
当相同的角色(如多个新手士兵)共享多个不变的属性时,使不变的属性只存在一份(会变化的属性如 当前生命值、等级…),每次要使用的时候,就去储存相同属性的BaseAttr工厂中取得该属性,可减少所占用的内存。
——重构代码——
完成战士/敌人角色的构造(使用享元) :
将ICharacterAttr 中的基础属性删除,创建CharacterBaseAttr用于管理角色的相同基础属性:
/// <summary>
///管理游戏角色共有的属性
/// </summary>
public class CharacterBaseAttr
{
protected string mName;
protected int mMaxHp;
protected float mMoveSpeed;
protected string mIconSprite; // 资源加载
protected string mPrefabName;// 通过Prefab名字实例化Prefab
protected float mCritRate;//0-1暴击率
public CharacterBaseAttr(string Name, int MaxHp, float MoveSpeed, string IconSprite, string PrefabName, float CritRate)
{
this.mName = Name;
this.mMaxHp = MaxHp;
this.mMoveSpeed = MoveSpeed;
this.mIconSprite = IconSprite;
this.mPrefabName = PrefabName;
this.mCritRate = CritRate;
}
public string Name { get { return mName; } }
public int MaxHp { get { return mMaxHp; } }
public float MoveSpeed { get { return mMoveSpeed; } }
public string IconSprite { get { return mIconSprite; } }
public string PrefabName { get { return mPrefabName; } }
public float CritRate { get { return mCritRate; } }
}
创建工厂接口类IAttrFactory,写入用于得到角色基础的方法:
public interface IAttrFactory
{
CharacterBaseAttr GetCharacterBaseAttr(System.Type t);
}
创建工厂类AttrFactory(享元模式核心),用字典将 通过战士/敌人的类型来存储战士/敌人的基础属性,每次实例化战士/敌人只需要调用 得到角色基础属性的方法 ,不需要每次都在内存中存一份相同的基础属性。构造方法中将所有需要共享的对象初始化
/// <summary>
/// 享元模式核心
/// </summary>
public class AttrFactory : IAttrFactory
{
//通过角色类型来存储角色共有的属性
private Dictionary<Type, CharacterBaseAttr> mCharacterBaseAttrDict;
/// <summary>
/// 构造方法中将所有需要共享的对象初始化
/// </summary>
public AttrFactory()
{
InitCharacterBaseAttr();
}
private void InitCharacterBaseAttr()
{
//初始化字典
mCharacterBaseAttrDict = new Dictionary<Type, CharacterBaseAttr>();
mCharacterBaseAttrDict.Add(typeof(SoldierRookie), new CharacterBaseAttr("新手士兵", 80, 2.5f, "RookieIcon", "Soldier3", 0));
mCharacterBaseAttrDict.Add(typeof(SoldierSergeant), new CharacterBaseAttr("中士士兵", 90, 3, "SergeantIcon", "Soldier2", 0));
mCharacterBaseAttrDict.Add(typeof(SoldierCaptain), new CharacterBaseAttr("上尉士兵", 100, 3, "CaptainIcon", "Soldier1", 0));
mCharacterBaseAttrDict.Add(typeof(EnemyElf), new CharacterBaseAttr("小精灵", 100, 3, "ElfIcon", "Enemy1", 0.2f));
mCharacterBaseAttrDict.Add(typeof(EnemyOgre), new CharacterBaseAttr("怪物", 120, 2, "OgreIcon", "Enemy2", 0.3f));
mCharacterBaseAttrDict.Add(typeof(EnemyTroll), new CharacterBaseAttr("巨魔", 200, 1, "TrollIcon", "Enemy3", 0.2f));
}
/// <summary>
/// 得到角色基础属性
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public CharacterBaseAttr GetCharacterBaseAttr(Type t)
{
if (mCharacterBaseAttrDict.ContainsKey(t) == false)
{
Debug.LogWarning("无法根据类型["+t+"]得到角色的基础属性"); return null;
}
return mCharacterBaseAttrDict[t];
}
}
在FactoryManager中加入IAttrFactory 静态属性,可用于外界调用:
public static class FactoryManager
{
private static IAssetFactory mAssetFactory;
private static IWeaponFactory mWeaponFactory;
private static ICharacterFactory mSoldierFactory;
private static ICharacterFactory mEnemyFactory;
private static IAttrFactory mAttrFactory;
public static IAttrFactory attrFactory
{
get
{
if (mAttrFactory== null)
{
mAttrFactory= new ResourcesAssetFactory();
}
return mAttrFactory;
}
}
省略………
在ICharacterAttr中声明可被子类取得的属性 CharacterBaseAttr , 修改其构造方法,将基础属性 改为 CharacterBaseAttr类,并修改其子类的构造方法:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ICharacterAttr
{
protected CharacterBaseAttr mCharacterBaseAttr;
protected int mLv;
protected int mCurrentHP;
protected int mDmgDescValue; //减少的伤害
public int CurrentHP { get { return mCurrentHP; } }
private IAttrStrategy mStrategy;
//角色实例化时就决定属性,后续不改变
public ICharacterAttr(IAttrStrategy strategy, int lv, CharacterBaseAttr characterBaseAttr)
{
mCharacterBaseAttr = characterBaseAttr;
mLv = lv;
mStrategy = strategy;
mDmgDescValue = mStrategy.GetCritDmg(mCharacterBaseAttr.CritRate);
mCurrentHP = mCharacterBaseAttr.MaxHp + mStrategy.GetExtraHPValue(mLv);
}
public int CritValue { get { return mStrategy.GetCritDmg(mCharacterBaseAttr.CritRate); } }
/// <summary>
/// 被攻击后的处理
/// </summary>
/// <param name="damage">受到的伤害</param>
public void TakeDamege(int damage)
{
damage -= mDmgDescValue;
if (damage <= 5) damage = 5;
mCurrentHP -= damage;
}
}
修改SoldierBuilder 和 EnemyrBuilder的 AddCharacterAttr() 给角色添加属性的方法:
通过FactoryManager调用attrFactory 属性工厂的 GetCharacterBaseAttr()方法,得到角色基础属性:
public class SoldierBuilder : ICharacterBuilder
{
public SoldierBuilder(ICharacter character, Type t, WeaponType weaponType, Vector3 spawnPos, int lv) : base(character, t, weaponType, spawnPos, lv){
}
public override void AddCharacterAttr()
{
CharacterBaseAttr characterBaseAttr = FactoryManager.attrFactory.GetCharacterBaseAttr(mT);
mPrefabName = characterBaseAttr.PrefabName;
ICharacterAttr attr = new SoldierAttr(new SoldierAttrStrategy(), mLV, characterBaseAttr);
mCharacter.CharacterAttri = attr;
}
public class EnemyrBuilder : ICharacterBuilder
{
public EnemyrBuilder(ICharacter character, Type t, WeaponType weaponType, Vector3 spawnPos, int lv) : base(character, t, weaponType, spawnPos, lv){ }
public override void AddCharacterAttr()
{
CharacterBaseAttr characterBaseAttr = FactoryManager.attrFactory.GetCharacterBaseAttr(mT);
mPrefabName = characterBaseAttr.PrefabName;
ICharacterAttr attr = new EnemyAttr(new EnemyAttrStrategy(), mLV, characterBaseAttr);
mCharacter.CharacterAttri = attr;
}
省略……
将武器属性修改为享元模式 :
将IWeaponAttr 中的基础属性删除,创建CharacterBaseAttr用于管理角色的基础属性:
public class WeaponBaseAttr
{
protected string mName;
protected int mAtk;//最大攻击力
protected float mAtkRange;//最大攻击范围
protected string mAssetsName;//资源名称
public WeaponBaseAttr(string Name,int Atk,float AtkRange,string AssetsName)
{
mName = Name;
mAtk = Atk;
mAtkRange = AtkRange;
mAssetsName = AssetsName;
}
public string Name { get { return mName; } }
public int Atk { get { return Atk; } }
public float AtkRange { get { return mAtkRange; } }
public string AssetsName { get { return mAssetsName; } }
}
在IWeaponAttr 中声明可被子类取得的属性 WeaponBaseAttr , 修改其构造方法,将基础属性 改为 WeaponBaseAttr 类,并
修改其子类的构造方法
public abstract class IWeapon
{
//protected int mAtkPlusValue;//暴击
protected WeaponBaseAttr mWeaponBaseAttr;
protected GameObject mGameObject;//武器模型
protected ICharacter mOwner;//武器持有者
protected ParticleSystem mParticle;//武器特效
protected LineRenderer mLineRender;//武器射线
protected Light mLight;
protected AudioSource mAudioSource; //音效
protected float mEffectDisplayTime;//特效显示时间
public float AtkRange { get { return mWeaponBaseAttr.AtkRange; } }
public float Atk { get { return mWeaponBaseAttr.Atk; } } // 武器攻击力
public ICharacter Owner { set { mOwner = value; } }
public GameObject gameObject { get { return mGameObject; } }
public IWeapon(WeaponBaseAttr weaponBaseAttr, GameObject gameObject)
{
mWeaponBaseAttr = weaponBaseAttr;
mGameObject = gameObject;
//得到武器特效射线灯光音效的组件,在武器的子物体Effect中
Transform effect = mGameObject.transform.Find("Effect");
mParticle = effect.GetComponent<ParticleSystem>();
mLineRender = effect.GetComponent<LineRenderer>();
mLight = effect.GetComponent<Light>();
mAudioSource = effect.GetComponent<AudioSource>();
}
在IAttrFactory中加入得到武器基础属性的方法:
public interface IAttrFactory
{
CharacterBaseAttr GetCharacterBaseAttr(System.Type t);
WeaponBaseAttr GetWeaponBaseAttr(WeaponType weaponType);
}
在AttrFactory中用字典将 通过武器的类型来存储武器的基础属性,每次实例化武器只需要调用 得到角色基础属性的方法 ,不需要每次都在内存中存一份相同的基础属性。构造方法中将所有需要共享的对象初始化
/// <summary>
/// 享元模式核心
/// </summary>
public class AttrFactory : IAttrFactory
{
//通过角色类型来存储角色共有的属性
private Dictionary<Type, CharacterBaseAttr> mCharacterBaseAttrDict;
private Dictionary<WeaponType, WeaponBaseAttr> mWeaponBaseAttrDict;
/// <summary>
/// 构造方法中将所有需要共享的对象初始化
/// </summary>
public AttrFactory()
{
InitCharacterBaseAttr();
InitWeaponBaseAttr();
}
private void InitWeaponBaseAttr()
{
//初始化字典
mWeaponBaseAttrDict = new Dictionary<WeaponType, WeaponBaseAttr>();
mWeaponBaseAttrDict.Add(WeaponType.Gun, new WeaponBaseAttr("手枪",20, 5, "WeaponGun"));
mWeaponBaseAttrDict.Add(WeaponType.Rifle, new WeaponBaseAttr("长枪",30, 7, "WeaponRifle"));
mWeaponBaseAttrDict.Add(WeaponType.Rocket, new WeaponBaseAttr("火箭",40, 8, "WeaponRocket"));
}
private void InitCharacterBaseAttr()
{
//初始化字典
mCharacterBaseAttrDict = new Dictionary<Type, CharacterBaseAttr>();
mCharacterBaseAttrDict.Add(typeof(SoldierRookie), new CharacterBaseAttr("新手士兵", 80, 2.5f, "RookieIcon", "Soldier3", 0));
mCharacterBaseAttrDict.Add(typeof(SoldierSergeant), new CharacterBaseAttr("中士士兵", 90, 3, "SergeantIcon", "Soldier2", 0));
mCharacterBaseAttrDict.Add(typeof(SoldierCaptain), new CharacterBaseAttr("上尉士兵", 100, 3, "CaptainIcon", "Soldier1", 0));
mCharacterBaseAttrDict.Add(typeof(EnemyElf), new CharacterBaseAttr("小精灵", 100, 3, "ElfIcon", "Enemy1", 0.2f));
mCharacterBaseAttrDict.Add(typeof(EnemyOgre), new CharacterBaseAttr("小精灵", 120, 2, "OgreIcon", "Enemy2", 0.3f));
mCharacterBaseAttrDict.Add(typeof(EnemyElf), new CharacterBaseAttr("巨魔", 200, 1, "TrollIcon", "Enemy3", 0.2f));
}
/// <summary>
/// 得到角色基础属性
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public CharacterBaseAttr GetCharacterBaseAttr(Type t)
{
if (mCharacterBaseAttrDict.ContainsKey(t) == false)
{
Debug.LogWarning("无法根据类型["+t+"]得到角色的基础属性"); return null;
}
return mCharacterBaseAttrDict[t];
}
/// <summary>
/// 得到武器基础属性
/// </summary>
/// <param name="weaponType"></param>
/// <returns></returns>
public WeaponBaseAttr GetWeaponBaseAttr(WeaponType weaponType)
{
if(mWeaponBaseAttrDict.ContainsKey(weaponType) == false)
{
Debug.LogWarning("无法根据类型[" + weaponType + "]得到武器的基础属性"); return null;
}
return mWeaponBaseAttrDict[weaponType];
}
}
修改WeaponFactory的创建武器方法CreateWeapon():
public class WeaponFactory : IWeaponFactory
{
public IWeapon CreateWeapon(WeaponType weaponType)
{
IWeapon weapon = null;
WeaponBaseAttr weaponBaseAttr = FactoryManager.attrFactory.GetWeaponBaseAttr(weaponType);
GameObject weaponGO= FactoryManager.assetFactory.LoadWeapon(weaponBaseAttr.AssetsName);
switch (weaponType)
{
case WeaponType.Gun:
weapon = new WeaponGun(weaponBaseAttr, weaponGO);
break;
case WeaponType.Rifle:
weapon = new WeaponRifle(weaponBaseAttr, weaponGO);
break;
case WeaponType.Rocket:
weapon = new WeaponRocket(weaponBaseAttr, weaponGO);
break;
}
return weapon;
}
}
(十二)组合模式:
事例代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CompositeDM : MonoBehaviour
{
void Start()
{
DMComposite root = new DMComposite("root");
DMLeaf leaf1 = new DMLeaf("leaf1");
DMComposite c1 = new DMComposite("composite1");
DMLeaf leaf2 = new DMLeaf("leaf2");
root.AddChild(leaf1);
root.AddChild(c1);
root.AddChild(leaf2);
DMLeaf g1 = new DMLeaf("GameObject");
DMLeaf g2 = new DMLeaf("GameObject (1)");
c1.AddChild(g1);
c1.AddChild(g2);
ReadComposite(root);
}
//深度优先
private void ReadComposite(DMComponent c)
{
Debug.Log(c.name);
List<DMComponent> c1 = c.ComponentList;
if (c1 == null || c1.Count == 0) return;
foreach (DMComponent item in c1)
{
ReadComposite(item);
}
}
}
public abstract class DMComponent
{
protected List<DMComponent> mComponentList;
protected string mName;
public string name { get { return mName; } }
public List<DMComponent> ComponentList { get { return mComponentList; } }
public DMComponent(string Name)
{
mComponentList = new List<DMComponent>();
mName = Name;
}
public abstract void AddChild(DMComponent c);
public abstract void RemoveChild(DMComponent c);
public abstract DMComponent GetChild(int index);
}
public class DMLeaf : DMComponent
{
public DMLeaf(string Name) : base(Name) { }
public override void AddChild(DMComponent c)
{
return;
}
public override void RemoveChild(DMComponent c)
{
return;
}
public override DMComponent GetChild(int index)
{
return null;
}
}
public class DMComposite : DMComponent
{
public DMComposite(string Name) : base(Name) { }
public override void AddChild(DMComponent c)
{
mComponentList.Add(c);
}
public override DMComponent GetChild(int index)
{
return mComponentList[index];
}
public override void RemoveChild(DMComponent c)
{
mComponentList.Remove(c);
}
}
(十三)UI界面设计部分:
UI查找工具类:
public static class UITools {
public static T FindChild<T>(GameObject parent,string childName)
{
GameObject uiGO = UnityTools.FindChild(parent,childName);
if (uiGO == null)
{
Debug.LogError("在游戏物体" + parent + "下面查找不到" + childName);
return default(T);
}
return uiGO.GetComponent<T>();
}
}
IBaseUI部分:
public abstract class IBaseUI
{
public GameObject mRootUI;
public virtual void Init() { }
public virtual void Release() { }
public virtual void Update(){ }
public void Show()
{
mRootUI.SetActive(true);
}
public void Hide()
{
mRootUI.SetActive(false);
}
}
UI信息部分:
public class GamePauseUI : IBaseUI
{
private Text mCurrentStageLv;
private Button mContinueBtn;
private Button mBackMenuBtn;
public override void Init()
{
base.Init();
GameObject canvas = GameObject.Find("Canvas");
mRootUI = UnityTools.FindChild(canvas, "GamePauseUI");
mCurrentStageLv = UITools.FindChild<Text>(mRootUI, "CurrentStageLv");
mContinueBtn = UITools.FindChild<Button>(mRootUI, "ContinueBtn");
mBackMenuBtn = UITools.FindChild<Button>(mRootUI, "BackMenuBtn");
Hide();
}
}
public class SoldierInfoUI : IBaseUI
{
private Image mSoldierIcon;
private Image mSoldierName;
private Text mHPText;
private Slider mHPSlider;
private Text mLv;
private Text mAtk;
private Text mAtkRange;
private Text mMoveSpeed;
public override void Init()
{
base.Init();
GameObject canvas = GameObject.Find("Canvas");
mRootUI = UnityTools.FindChild(canvas, "SoldierInfoUI");
mSoldierIcon = UITools.FindChild<Image>(mRootUI, "SoldierIcon");
mSoldierName = UITools.FindChild<Image>(mRootUI, "SoldierName");
mHPText = UITools.FindChild<Text>(mRootUI, "HPNumber");
mHPSlider = UITools.FindChild<Slider>(mRootUI, "HPSlider");
mLv = UITools.FindChild<Text>(mRootUI, "Level");
mAtk = UITools.FindChild<Text>(mRootUI, "Atk");
mAtkRange = UITools.FindChild<Text>(mRootUI, "AtkRange");
mMoveSpeed = UITools.FindChild<Text>(mRootUI, "MoveSpeed");
Hide();
}
}
public class CampInfoUI : IBaseUI
{
private Image mCampIcon;
private Text mCampName;
private Text mCampLevel;
private Text mWeaponLevel;
private Button mCampUpgradeBtn;
private Button mWeaponUpgradeBtn;
private Button mTrainBtn;
private Text mTrainBtnText;
private Button mCancelTrainBtn;
private Text mAliveCount;
private Text mTrainingCount;
private Text mTrainTime;
public override void Init()
{
base.Init();
GameObject canvas = GameObject.Find("Canvas");
mRootUI = UnityTools.FindChild(canvas, "CampInfoUI");
mCampIcon = UITools.FindChild<Image>(mRootUI, "CampIcon");
mCampName = UITools.FindChild<Text>(mRootUI, "CampName");
mCampLevel = UITools.FindChild<Text>(mRootUI, "CampLv");
mWeaponLevel = UITools.FindChild<Text>(mRootUI, "WeaponLv");
mCampUpgradeBtn = UITools.FindChild<Button>(mRootUI, "CampUpgradeBtn");
mWeaponUpgradeBtn = UITools.FindChild<Button>(mRootUI, "WeaponUpgradeBtn");
mTrainBtn = UITools.FindChild<Button>(mRootUI, "TrainBtn");
mTrainBtnText = UITools.FindChild<Text>(mRootUI, "TrainBtnText");
mCancelTrainBtn = UITools.FindChild<Button>(mRootUI, "CancelTrainBtn");
mAliveCount = UITools.FindChild<Text>(mRootUI, "AliveCount");
mTrainingCount = UITools.FindChild<Text>(mRootUI, "TrainingCount");
mTrainTime = UITools.FindChild<Text>(mRootUI, "TrainTime");
Hide();
}
}
public class GameStateUI : IBaseUI
{
private List<GameObject> mHearts; //左上角星星
private Text mSoldierCount;
private Text mEnemyCount;
private Text mCurrentStage;
private Button mPauseBtn;
private GameObject mGameOverUI;
private Button mBackMenuBtn;
private Text mMessage;
private Slider mEnergySlider;
private Text mEnergyText;
public override void Init()
{
base.Init(); base.Init();
GameObject canvas = GameObject.Find("Canvas");
mRootUI = UnityTools.FindChild(canvas, "GameStateUI");
GameObject heart1 = UnityTools.FindChild(mRootUI, "Heart1");
GameObject heart2 = UnityTools.FindChild(mRootUI, "Heart2");
GameObject heart3 = UnityTools.FindChild(mRootUI, "Heart3");
mHearts = new List<GameObject> // 简化集合,即为Add():
{
heart1,
heart2,
heart3
};
mSoldierCount = UITools.FindChild<Text>(mRootUI, "SoldierCount");
mEnemyCount = UITools.FindChild<Text>(mRootUI, "EnemyCount");
mCurrentStage = UITools.FindChild<Text>(mRootUI, "StageCount");
mPauseBtn = UITools.FindChild<Button>(mRootUI, "PauseBtn");
mGameOverUI = UnityTools.FindChild(mRootUI, "GameOver");
mBackMenuBtn = UITools.FindChild<Button>(mRootUI, "BackMenuBtn");
mMessage = UITools.FindChild<Text>(mRootUI, "Message");
mEnergySlider = UITools.FindChild<Slider>(mRootUI, "EnergySlider");
mEnergyText = UITools.FindChild<Text>(mRootUI, "EnergyText");
mMessage.text = "";
mGameOverUI.SetActive(false);
}
}
(十四) :命令模式(兵营系统)
创建脚本ICamp作为兵营的父类,并声明构造方法
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class ICamp
{
protected GameObject mGameObject; //兵营
protected string mName;
protected string mIconSprite;
protected SoldierType mSoldierType;
protected Vector3 mPos; // 集合位置
protected float mTrainTime; //训练时间
public ICamp(GameObject gameObject,string name,string iconSprite,SoldierType soldierType,Vector3 pos,float trainTime)
{
mGameObject = gameObject;
mName = name;
mIconSprite = iconSprite;
mSoldierType = soldierType;
mPos = pos;
mTrainTime = trainTime;
}
public virtual void Update()
{
}
}
在ISoldier中声明SoldierType 士兵类型
public enum SoldierType
{
Rookie,
Sergeant,
Captain
}
创建SoldierCamp,继承自ICamp
public class SoldierCamp : ICamp
{
private int mMAX_Lv;
private int mLv =1;
private WeaponType mWeaponType = WeaponType.Gun;
public SoldierCamp(GameObject gameObject, string name, string iconSprite, SoldierType soldierType, Vector3 pos,float trainTime, WeaponType weaponType = WeaponType.Gun, int lv = 1)
: base(gameObject, name, iconSprite, soldierType, pos,trainTime)
{
mLv = lv;
mWeaponType = weaponType;
}
public override void Update()
{
}
}
创建兵营系统 CampSystem,管理所有兵营的更新
public class CampSystem : IGameSystem
{
private Dictionary<SoldierType, SoldierCamp> mSoldierCampDict = new Dictionary<SoldierType, SoldierCamp>();
public override void Init()
{
base.Init();
InitCamp(SoldierType.Rookie);
InitCamp(SoldierType.Sergeant);
InitCamp(SoldierType.Captain);
}
/// <summary>
/// 初始化创建兵营
/// </summary>
private void InitCamp(SoldierType soldierType)
{
GameObject gameObject = null;
string gameObjectName = null;
string name = null;
string iconSprite = null;
Vector3 pos = Vector3.zero;
float trainTime = 0;
switch (soldierType)
{
case SoldierType.Rookie:
gameObjectName = "SoldierCamp_Rookie";
name = "新手兵营";
iconSprite = "RookieCamp";
trainTime = 3;
break;
case SoldierType.Sergeant:
gameObjectName = "SoldierCamp_Sergeant";
name = "中士兵营";
iconSprite = "SergeantCamp";
trainTime = 4;
break;
case SoldierType.Captain:
gameObjectName = "SoldierCamp_Captain";
name = "上尉兵营";
iconSprite = "CaptainCamp";
trainTime = 5;
break;
default:
Debug.LogError("无法根据战士类型" + soldierType + "初始化兵营");
break;
}
gameObject = GameObject.Find(gameObjectName);
pos = UnityTools.FindChild(gameObject, "TrainPoint").transform.position;
SoldierCamp soldierCamp = new SoldierCamp(gameObject,name,iconSprite,soldierType,pos,trainTime);
mSoldierCampDict.Add(soldierType,soldierCamp);
}
public override void Update()
{
//更新所有兵营的内部游戏逻辑
foreach (SoldierCamp camp in mSoldierCampDict.Values)
{
camp.Update();
}
}
}
点击兵营显示UI界面及兵营信息:
在CampInfoUI 兵营信息显示的脚本中声明ShowCampInfoUI() 方法用于UI的显示以及显示兵营信息
public void ShowCampInfoUI(ICamp camp)
{
Show();
}
在GameFacade脚本中声明ShowCampInfoUI()方法,用于在外界调用
public void ShowCampInfoUI(ICamp camp)
{
campInfoUI.ShowCampInfoUI(camp);
}
创建脚本CampUIOnClick,继承自mono,OnMouseUpAsButton方法—> MonoBehaviour.OnMouseUpAsButton()
public class CampUIOnClick : MonoBehaviour {
private ICamp camp;
public ICamp Camp { set { camp = value; } }
void OnMouseUpAsButton()
{
GameFacade.Instance.ShowCampInfoUI(camp);
}
}
在CampSystem中初始化兵营时将CampUIOnClick 脚本添加并为CampUIOnClick的camp属性赋值:
/// <summary>
/// 初始化创建兵营
/// </summary>
private void InitCamp(SoldierType soldierType)
{
GameObject gameObject = null;
string gameObjectName = null;
string name = null;
string iconSprite = null;
Vector3 pos = Vector3.zero;
float trainTime = 0;
switch (soldierType)
{
……此处省略
}
gameObject = GameObject.Find(gameObjectName);
pos = UnityTools.FindChild(gameObject, "TrainPoint").transform.position;
SoldierCamp soldierCamp = new SoldierCamp(gameObject,name,iconSprite,soldierType,pos,trainTime);
这句——> gameObject.AddComponent<CampUIOnClick>().Camp = soldierCamp;
mSoldierCampDict.Add(soldierType,soldierCamp);
}
用get{}方法访问ICamp中的私有变量,子类的变量用abstract方法在子类中重写
ICamp:
public string Name{ get { return mName; } }
public string IconSprite { get { return mIconSprite; } }
public abstract WeaponType GetCampWeaponType();
public abstract int GetCampLv();
SoldierCamp(继承自ICamp):
public override WeaponType GetCampWeaponType()
{
return mWeaponType;
}
public override int GetCampLv()
{
return mLv;
}
修改CampInfoUI的ShowCampInfoUI()方法,使其兵营信息界面显示UI信息:
public void ShowCampInfoUI(ICamp camp)
{
Show();
mCamp = camp;
mCampIcon.sprite = FactoryManager.assetFactory.LoadSprites(camp.IconSprite);
mCampName.text = camp.Name;
ShowWeaponLevel(camp.GetCampWeaponType());
mCampLevel.text = camp.GetCampLv().ToString();
}
void ShowWeaponLevel(WeaponType weaponType)
{
switch (weaponType)
{
case WeaponType.Gun:
mWeaponLevel.text = "短枪";
break;
case WeaponType.Rifle:
mWeaponLevel.text = "长枪";
break;
case WeaponType.Rocket:
mWeaponLevel.text = "火箭";
break;
case WeaponType.MAX:
break;
default:
break;
}
}
修改资源加载工厂的方法:
public AudioClip LoadAudioClip(string name)
{
return Resources.Load<AudioClip>(AudioPath + name);
}
public Sprite LoadSprites(string name)
{
return Resources.Load<Sprite>(SpritePath+name);
}
命令模式示例脚本:
public class CommandDM : MonoBehaviour
{
private void Start()
{
IDammandDM dm1 = new ConcreteCommand1(new Receiver1DM());
InvokerDM invoker = new InvokerDM();
invoker.AddCommand(dm1);
invoker.ExcuteCommand();
}
}
public class InvokerDM
{
private List<IDammandDM> mDamandList = new List<IDammandDM>();
public void AddCommand(IDammandDM dammandDM)
{
mDamandList.Add(dammandDM);
}
public void ExcuteCommand()
{
foreach (IDammandDM item in mDamandList)
{
item.Excute();
}
mDamandList.Clear();
}
}
public abstract class IDammandDM
{
public abstract void Excute();
}
public class ConcreteCommand1 : IDammandDM
{
private Receiver1DM mReceiver;
public ConcreteCommand1(Receiver1DM receiver)
{
mReceiver = receiver;
}
public override void Excute()
{
mReceiver.Action("Command1");
}
}
public class Receiver1DM
{
public void Action(string cmd)
{
Debug.Log("命令:" + cmd + ",Receiver1执行了命令");
}
}
将命令模式应用于士兵的训练:
创建命令的抽象类 ITrainCommand
public abstract class ITrainCommand {
public abstract void Excute();
}
创建战士的命令类 SoldierTrainCommand,继承自ITrainCommand
根据不同的战士类型,调用战士工厂的创建角色方法,并声明战士工厂的创建角色时所需要的变量
public class SoldierTrainCommand : ITrainCommand
{
private SoldierType mSoldierType;
private WeaponType mWeaponType;
private Vector3 mVec;
private int mLV;
public SoldierTrainCommand(SoldierType soldierType, WeaponType weaponType, Vector3 vec, int lv)
{
mSoldierType = soldierType;
mWeaponType = weaponType;
mVec = vec;
mLV = lv;
}
public override void Excute()
{
switch (mSoldierType)
{
case SoldierType.Rookie:
FactoryManager.soldierFactory.CreateCharacter<SoldierRookie>(mWeaponType,mVec,mLV);
break;
case SoldierType.Sergeant:
FactoryManager.soldierFactory.CreateCharacter<SoldierSergeant>(mWeaponType, mVec, mLV);
break;
case SoldierType.Captain:
FactoryManager.soldierFactory.CreateCharacter<SoldierCaptain>(mWeaponType, mVec, mLV);
break;
default:
Debug.LogWarning("无法执行命令,无法根据SoldierType["+mSoldierType+"]创建角色");
break;
}
}
}
添加训练命令和命令的管理
在ICamp 中 声明 一个管理命令的集合 mTrainCommandList ,并在构造方法中初始化
并在ICamp中 声明 添加训练士兵的命令 和 取消训练士兵命令的方法 :AddTrainCommand() 和 CancelTrainCommand()
public abstract class ICamp
{
protected GameObject mGameObject; //兵营
protected string mName;
protected string mIconSprite;
protected SoldierType mSoldierType;
protected Vector3 mPos; // 集合位置
protected float mTrainTime; //训练时间
protected float mTrainTimer; //训练计时器
protected List<ITrainCommand> mTrainCommandList; // 管理训练命令集合
public ICamp(GameObject gameObject,string name,string iconSprite,SoldierType soldierType,Vector3 pos,float trainTime)
{
mGameObject = gameObject;
mName = name;
mIconSprite = iconSprite;
mSoldierType = soldierType;
mPos = pos;
mTrainTime = trainTime;
mTrainTimer = mTrainTime;
mTrainCommandList = new List<ITrainCommand>();
}
public string Name{ get { return mName; } }
public string IconSprite { get { return mIconSprite; } }
public abstract WeaponType GetCampWeaponType();
public abstract int GetCampLv();
public virtual void Update()
{
}
//训练士兵的方法
public abstract void AddTrainCommand();
//取消训练士兵的方法,在命令集合中将最后一个命令移除
public void CancelTrainCommand()
{
if (mTrainCommandList.Count > 0)
{
mTrainCommandList.RemoveAt(mTrainCommandList.Count - 1);
}
}
}
在子类 SoldierCamp 中重写 训练方法 (避免后期添加其他兵营)
public class SoldierCamp : ICamp
{
private int mMAX_Lv;
private int mLv =1;
private WeaponType mWeaponType = WeaponType.Gun;
public SoldierCamp(GameObject gameObject, string name, string iconSprite, SoldierType soldierType, Vector3 pos,float trainTime, WeaponType weaponType = WeaponType.Gun, int lv = 1)
: base(gameObject, name, iconSprite, soldierType, pos,trainTime)
{
mLv = lv;
mWeaponType = weaponType;
}
public override void Update()
{
}
public override WeaponType GetCampWeaponType()
{
return mWeaponType;
}
public override int GetCampLv()
{
return mLv;
}
public override void AddTrainCommand()
{
//添加训练命令
SoldierTrainCommand soldierTrainCommand = new SoldierTrainCommand(mSoldierType,mWeaponType,mPos,mLv);
mTrainCommandList.Add(soldierTrainCommand);
}
}
接着 在 CampInfoUI 中 对训练士兵的 button 进行 点击注册:
public class CampInfoUI : IBaseUI
{
private Image mCampIcon;
private Text mCampName;
private Text mCampLevel;
private Text mWeaponLevel;
private Button mCampUpgradeBtn;
private Button mWeaponUpgradeBtn;
private Button mTrainBtn;
private Text mTrainBtnText;
private Button mCancelTrainBtn;
private Text mAliveCount;
private Text mTrainingCount;
private Text mTrainTime;
private ICamp mCamp; // 记录兵营
public override void Init()
{
base.Init();
GameObject canvas = GameObject.Find("Canvas");
mRootUI = UnityTools.FindChild(canvas, "CampInfoUI");
mCampIcon = UITools.FindChild<Image>(mRootUI, "CampIcon");
mCampName = UITools.FindChild<Text>(mRootUI, "CampName");
mCampLevel = UITools.FindChild<Text>(mRootUI, "CampLv");
mWeaponLevel = UITools.FindChild<Text>(mRootUI, "WeaponLv");
mCampUpgradeBtn = UITools.FindChild<Button>(mRootUI, "CampUpgradeBtn");
mWeaponUpgradeBtn = UITools.FindChild<Button>(mRootUI, "WeaponUpgradeBtn");
mTrainBtn = UITools.FindChild<Button>(mRootUI, "TrainBtn");
mTrainBtnText = UITools.FindChild<Text>(mRootUI, "TrainBtnText");
mCancelTrainBtn = UITools.FindChild<Button>(mRootUI, "CancelTrainBtn");
mAliveCount = UITools.FindChild<Text>(mRootUI, "AliveCount");
mTrainingCount = UITools.FindChild<Text>(mRootUI, "TrainingCount");
mTrainTime = UITools.FindChild<Text>(mRootUI, "TrainTime");
mTrainBtn.onClick.AddListener(OnTrainClick);
mCancelTrainBtn.onClick.AddListener(OnCancelTrainClick);
Hide();
}
public void ShowCampInfoUI(ICamp camp)
{
Show();
mCamp = camp;
mCampIcon.sprite = FactoryManager.assetFactory.LoadSprites(camp.IconSprite);
mCampName.text = camp.Name;
ShowWeaponLevel(camp.GetCampWeaponType());
mCampLevel.text = camp.GetCampLv().ToString();
}
void ShowWeaponLevel(WeaponType weaponType)
{
switch (weaponType)
{
case WeaponType.Gun:
mWeaponLevel.text = "短枪";
break;
case WeaponType.Rifle:
mWeaponLevel.text = "长枪";
break;
case WeaponType.Rocket:
mWeaponLevel.text = "火箭";
break;
case WeaponType.MAX:
break;
default:
break;
}
}
public void OnTrainClick()
{
// TODO 判断能量是否足够
mCamp.Train();
}
public void OnCancelTrainClick()
{
//TODO 将消耗的能量回收
mCamp.CancelTrain();
}
}
在兵营中控制训练命令的执行
声明UpdataCommand()方法,在ICamp的Update中更新其命令
利用计时器,当计时器为0时,执行 命令集合 中的第一个命令,即 List[0].excute(),再将其从集合中删除,计时器重新计时
当 取消训练士兵的命令时 ,在命令集合中将最后一个命令移除,如果没有命令,计时器重新计时
public abstract class ICamp
{
protected GameObject mGameObject; //兵营
protected string mName;
protected string mIconSprite;
protected SoldierType mSoldierType;
protected Vector3 mPos; // 集合位置
protected float mTrainTime; //训练时间
protected float mTrainTimer; //训练计时器
protected List<ITrainCommand> mTrainCommandList; // 管理训练命令集合
public ICamp(GameObject gameObject,string name,string iconSprite,SoldierType soldierType,Vector3 pos,float trainTime)
{
mGameObject = gameObject;
mName = name;
mIconSprite = iconSprite;
mSoldierType = soldierType;
mPos = pos;
mTrainTime = trainTime;
mTrainTimer = mTrainTime;
mTrainCommandList = new List<ITrainCommand>();
}
public string Name{ get { return mName; } }
public string IconSprite { get { return mIconSprite; } }
public abstract WeaponType GetCampWeaponType();
public abstract int GetCampLv();
public virtual void Update()
{
UpdataCommand();
}
//更新命令
public void UpdataCommand()
{
if (mTrainCommandList.Count <= 0) return;
mTrainTimer -= Time.deltaTime;
if (mTrainTimer <= 0)
{
mTrainCommandList[0].Excute();
mTrainCommandList.RemoveAt(0);
mTrainTimer = mTrainTime;
}
}
// 添加训练命令
public abstract void AddTrainCommand();
//取消训练士兵的命令,在命令集合中将最后一个命令移除
public void CancelTrainCommand()
{
if (mTrainCommandList.Count > 0)
{
mTrainCommandList.RemoveAt(mTrainCommandList.Count - 1);
if (mTrainCommandList.Count == 0)
{
mTrainTimer = mTrainTime;
}
}
}
}
UI部分:
控制正在训练信息的显示
重写Update方法,从ICamp中获取计时器和命令的个数,更新训练部分的UI
public float GetTrainTimer { get { return mTrainTimer; } }
public int GetTrainCount { get { return mTrainCommandList.Count; } }
public class CampInfoUI : IBaseUI
{
private Image mCampIcon;
private Text mCampName;
private Text mCampLevel;
private Text mWeaponLevel;
private Button mCampUpgradeBtn;
private Button mWeaponUpgradeBtn;
private Button mTrainBtn;
private Text mTrainBtnText;
private Button mCancelTrainBtn;
private Text mAliveCount;
private Text mTrainingCount;
private Text mTrainTime;
private ICamp mCamp; // 记录兵营
public override void Init()
{
base.Init();
GameObject canvas = GameObject.Find("Canvas");
mRootUI = UnityTools.FindChild(canvas, "CampInfoUI");
mCampIcon = UITools.FindChild<Image>(mRootUI, "CampIcon");
mCampName = UITools.FindChild<Text>(mRootUI, "CampName");
mCampLevel = UITools.FindChild<Text>(mRootUI, "CampLv");
mWeaponLevel = UITools.FindChild<Text>(mRootUI, "WeaponLv");
mCampUpgradeBtn = UITools.FindChild<Button>(mRootUI, "CampUpgradeBtn");
mWeaponUpgradeBtn = UITools.FindChild<Button>(mRootUI, "WeaponUpgradeBtn");
mTrainBtn = UITools.FindChild<Button>(mRootUI, "TrainBtn");
mTrainBtnText = UITools.FindChild<Text>(mRootUI, "TrainBtnText");
mCancelTrainBtn = UITools.FindChild<Button>(mRootUI, "CancelTrainBtn");
mAliveCount = UITools.FindChild<Text>(mRootUI, "AliveCount");
mTrainingCount = UITools.FindChild<Text>(mRootUI, "TrainingCount");
mTrainTime = UITools.FindChild<Text>(mRootUI, "TrainTime");
mTrainBtn.onClick.AddListener(OnTrainClick);
mCancelTrainBtn.onClick.AddListener(OnCancelTrainClick);
Hide();
}
public override void Update()
{
base.Update();
if (mCamp != null)
{
ShowTrainInfo();
}
}
public void ShowCampInfoUI(ICamp camp)
{
Show();
mCamp = camp;
mCampIcon.sprite = FactoryManager.assetFactory.LoadSprites(camp.IconSprite);
mCampName.text = camp.Name;
ShowWeaponLevel(camp.GetCampWeaponType());
mCampLevel.text = camp.GetCampLv().ToString();
ShowTrainInfo();
}
//兵营训练信息
public void ShowTrainInfo()
{
mTrainingCount.text = mCamp.GetTrainCount.ToString();
mTrainTime.text = mCamp.GetTrainTimer.ToString("0.00");
if (mCamp.GetTrainCount == 0)
mCancelTrainBtn.interactable = false;
else
mCancelTrainBtn.interactable = true;
}
void ShowWeaponLevel(WeaponType weaponType)
{
switch (weaponType)
{
case WeaponType.Gun:
mWeaponLevel.text = "短枪";
break;
case WeaponType.Rifle:
mWeaponLevel.text = "长枪";
break;
case WeaponType.Rocket:
mWeaponLevel.text = "火箭";
break;
case WeaponType.MAX:
break;
default:
break;
}
}
public void OnTrainClick()
{
// TODO 判断能量是否足够
mCamp.AddTrainCommand();
}
public void OnCancelTrainClick()
{
//TODO 将消耗的能量回收
mCamp.CancelTrainCommand();
}
}
控制角色添加到角色管理系统
在GameFacade中声明添加士兵和敌人的方法
在ICharacterBuilder中添加 public abstract void AddInCharacterSystem(); 控制角色添加到角色管理系统
SoldierBuilder 、 EnemyrBuilder 中重写 AddInCharacterSystem() 方法
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class ICharacterBuilder
{
protected WeaponType mWeaponType;
protected Vector3 mSpawnPos;
protected int mLV;
protected ICharacter mCharacter;//设置给谁
protected System.Type mT;
protected string mPrefabName;
public ICharacterBuilder(ICharacter character, System.Type t,WeaponType weaponType, Vector3 spawnPos, int lv)
{
mCharacter = character;
mT = t ;
mWeaponType = weaponType;
mLV = lv;
mSpawnPos = spawnPos;
}
public abstract void AddCharacterAttr();
public abstract void AddInstGameObject();
public abstract void AddWeapon();
/// <summary>
/// 将实例化的角色添加到角色系统中
/// </summary>
public abstract void AddInCharacterSystem();
public abstract ICharacter GetResult();
}
GameFacade 中:
public void AddSoldier(ISoldier soldier)
{
characterSystem.AddSoldier(soldier);
}
public void AddEnemy(IEnemy enemy)
{
characterSystem.AddEnemy(enemy);
}
EnemyrBuilder中:
public override void AddInCharacterSystem()
{
GameFacade.Instance.AddEnemy(mCharacter as IEnemy);
}
SoldierBuilder中:
public override void AddInCharacterSystem()
{
GameFacade.Instance.AddSoldier(mCharacter as ISoldier);
}
使用策略模式计算升级和训练所需要的能量消耗值
创建IEnergyCostStategy 用策略模式计算升级和训练所需要的能量消耗值
创建SoldierEnergyCostStategy 继承自 IEnergyCostStategy
public abstract class IEnergyCostStategy {
public abstract int GetWeaponUpgradeStategy(WeaponType weaponType);
public abstract int GetSoldierTrainStategy(int lv , SoldierType soldierType);
public abstract int GetCampUpgradeStategy(int lv, SoldierType soldierType);
}
public class SoldierEnergyCostStategy : IEnergyCostStategy
{
public override int GetCampUpgradeStategy(int lv, SoldierType soldierType)
{
int energy = 0;
switch (soldierType)
{
case SoldierType.Rookie:
energy = 60;
break;
case SoldierType.Sergeant:
energy = 65;
break;
case SoldierType.Captain:
energy = 70;
break;
default:
Debug.LogError("无法获取士兵类型为" + soldierType+"升级所消耗的能力值");
break;
}
energy += (lv - 1) * 2;
if (energy >= 100) energy = 100;
return energy;
}
public override int GetSoldierTrainStategy(int lv, SoldierType soldierType)
{
int energy = 0;
switch (soldierType)
{
case SoldierType.Rookie:
energy = 10;
break;
case SoldierType.Sergeant:
energy = 15;
break;
case SoldierType.Captain:
energy = 20;
break;
default:
Debug.LogError("无法获取士兵类型为" + soldierType + "升级所消耗的能力值");
break;
}
energy += (lv - 1) * 2;
return energy;
}
public override int GetWeaponUpgradeStategy(WeaponType weaponType)
{
int energy = 0;
switch (weaponType)
{
case WeaponType.Gun:
energy = 30;
break;
case WeaponType.Rifle:
energy = 40;
break;
default:
Debug.LogError("无法获取武器类型为" + weaponType + "升级所消耗的能力值");
break;
}
return energy;
}
}
能量消耗值计算策略的调用
在ICamp中声明 能量消耗的策略类 IEnergyCostStategy mEnergyCostStategy,并在子类SoldierCamp的构造方法中new出来;
在ICamp中声明变量 mGetWeaponUpgrade 、mGetSoldierTrain、mGetCampUpgrade ,用于得到武器、士兵、兵营的更新
并声明 更新所有的能量消耗 更新武器的升级 更新兵营的升级 的抽象类方法,在子类中重写;
提供get方法获取升级和训练所需要的能量值 :
GetTrainEnergyCost { get; } GetWeaponUpgradeEnergyCost { get; } GetCampUpgradeEnergyCost{ get; }
public abstract class ICamp
{
protected GameObject mGameObject; //兵营
protected string mName;
protected string mIconSprite;
protected SoldierType mSoldierType;
protected Vector3 mPos; // 集合位置
protected float mTrainTime; //训练时间
protected float mTrainTimer; //训练计时器
protected IEnergyCostStategy mEnergyCostStategy; // 能量消耗策略
//得到武器升级的消耗值
protected int mGetWeaponUpgrade;
//得到士兵训练的消耗值
protected int mGetSoldierTrain;
//得到兵营升级的消耗值
protected int mGetCampUpgrade;
public float GetTrainTimer { get { return mTrainTimer; } }
public int GetTrainCount { get { return mTrainCommandList.Count; } }
protected List<ITrainCommand> mTrainCommandList; // 管理训练命令集合
public ICamp(GameObject gameObject,string name,string iconSprite,SoldierType soldierType,Vector3 pos,float trainTime)
{
mGameObject = gameObject;
mName = name;
mIconSprite = iconSprite;
mSoldierType = soldierType;
mPos = pos;
mTrainTime = trainTime;
mTrainTimer = mTrainTime;
mTrainCommandList = new List<ITrainCommand>();
}
public string Name{ get { return mName; } }
public string IconSprite { get { return mIconSprite; } }
//用于得到训练所消耗的能量
public abstract int GetTrainEnergyCost { get; }
//用于得到武器升级所消耗的能量
public abstract int GetWeaponUpgradeEnergyCost { get; }
//用于得到兵营升级所消耗的能量
public abstract int GetCampUpgradeEnergyCost{ get; }
public abstract WeaponType GetCampWeaponType();
public abstract int GetCampLv();
public virtual void Update()
{
UpdataCommand();
}
public void UpdataCommand()
{
if (mTrainCommandList.Count <= 0) return;
mTrainTimer -= Time.deltaTime;
if (mTrainTimer <= 0)
{
mTrainCommandList[0].Excute();
mTrainCommandList.RemoveAt(0);
mTrainTimer = mTrainTime;
}
}
// 添加训练命令
public abstract void AddTrainCommand();
//更新所有的能量消耗
public abstract void UpdateEnergyCost();
//更新武器的升级
public abstract void UpdateWeaponUpgrade();
//更新兵营的升级
public abstract void UpdateCampUpgrade();
//取消训练士兵的命令,在命令集合中将最后一个命令移除
public void CancelTrainCommand()
{
if (mTrainCommandList.Count > 0)
{
mTrainCommandList.RemoveAt(mTrainCommandList.Count - 1);
if (mTrainCommandList.Count == 0)
{
mTrainTimer = mTrainTime;
}
}
}
}
public class SoldierCamp : ICamp
{
private int mMAX_Lv;
private int mLv = 1;
private WeaponType mWeaponType = WeaponType.Gun;
public override int GetTrainEnergyCost
{
get
{
return mGetSoldierTrain;
}
}
public override int GetWeaponUpgradeEnergyCost
{
get
{
if (mWeaponType + 1 == WeaponType.MAX)
return -1;
else
return mGetWeaponUpgrade;
}
}
public override int GetCampUpgradeEnergyCost
{
get
{
if (mLv == mMAX_Lv)
return -1;
else
return mGetCampUpgrade;
}
}
public SoldierCamp(GameObject gameObject, string name, string iconSprite, SoldierType soldierType, Vector3 pos, float trainTime, WeaponType weaponType = WeaponType.Gun, int lv = 1)
: base(gameObject, name, iconSprite, soldierType, pos, trainTime)
{
mLv = lv;
mWeaponType = weaponType;
mEnergyCostStategy = new SoldierEnergyCostStategy();
UpdateEnergyCost();
}
public override void Update()
{
base.Update();
}
public override WeaponType GetCampWeaponType()
{
return mWeaponType;
}
public override int GetCampLv()
{
return mLv;
}
public override void AddTrainCommand()
{
//添加训练命令
SoldierTrainCommand soldierTrainCommand = new SoldierTrainCommand(mSoldierType, mWeaponType, mPos, mLv);
mTrainCommandList.Add(soldierTrainCommand);
}
public override void UpdateEnergyCost()
{
mGetCampUpgrade = mEnergyCostStategy.GetCampUpgradeStategy(mLv, mSoldierType);
mGetSoldierTrain = mEnergyCostStategy.GetSoldierTrainStategy(mLv, mSoldierType);
mGetWeaponUpgrade = mEnergyCostStategy.GetWeaponUpgradeStategy(mWeaponType);
}
public override void UpdateWeaponUpgrade()
{
mWeaponType = mWeaponType + 1;
UpdateEnergyCost();
}
public override void UpdateCampUpgrade()
{
mLv ++;
UpdateEnergyCost();
}
}
UI系统 -- 处理升级按钮的点击
CampInfoUI:
mWeaponUpgradeBtn.onClick.AddListener(WeaponUpgradeClick);
mCampUpgradeBtn.onClick.AddListener(CampUpgradeClick);
public void WeaponUpgradeClick()
{
int energy = mCamp.GetWeaponUpgradeEnergyCost;
if (energy < 0)
{
Debug.Log("武器已经满级");
return;
}
//TODO
mCamp.UpdateWeaponUpgrade();
ShowCampInfoUI(mCamp);
}
public void CampUpgradeClick()
{
int energy = mCamp.GetCampUpgradeEnergyCost;
if (energy < 0)
{
Debug.Log("武器已经满级");
return;
}
//TODO
mCamp.UpdateCampUpgrade();
ShowCampInfoUI(mCamp);
}
能量系统:
设计能量系统
Update中更新能量的增加 和 UI中能量的显示
声明能量消耗和返回的方法并声明在GameFacade中方便外界调用
public class EnergySystem : IGameSystem
{
private const int MAX_Energy = 100;
private float mCurrentEnergy = MAX_Energy;
private float mRecoverpeed = 3; // 能量回复速度
public override void Init()
{
base.Init();
}
public override void Update()
{
base.Update();
//更新能量条
mFacade.UpdateEnergySlider((int)mCurrentEnergy, MAX_Energy);
//增加能量
if (mCurrentEnergy >= MAX_Energy) return;
mCurrentEnergy += mRecoverpeed * Time.deltaTime;
mCurrentEnergy = Mathf.Min(mCurrentEnergy, MAX_Energy);
}
//消耗的能量
public bool TakeEnergy(int value)
{
if (mCurrentEnergy >= value)
{
mCurrentEnergy -= value;
return true;
}
return false;
}
//取消训练后返还的能量
public void RecycleEnergy(int value)
{
mCurrentEnergy += value;
mCurrentEnergy = Mathf.Min(mCurrentEnergy, MAX_Energy);
}
}
GameStateUI
声明显示提示信息和更新能量条的方法并声明在GameFacade中方便外界调用
public class GameStateUI : IBaseUI
{
private List<GameObject> mHearts; //左上角星星
private Text mSoldierCount;
private Text mEnemyCount;
private Text mCurrentStage;
private Button mPauseBtn;
private GameObject mGameOverUI;
private Button mBackMenuBtn;
private Text mMessage;
private Slider mEnergySlider;
private Text mEnergyText;
private float mMsgTimer = 0;
private float mMsgTime = 2;
public override void Init()
{
省略…
}
public override void Update()
{
base.Update();
if (mMsgTimer > 0)
{
mMsgTimer -= Time.deltaTime;
if (mMsgTimer <= 0)
{
mMessage.text = "";
}
}
}
public void ShowMsg(string msg)
{
mMessage.text = msg;
mMsgTimer = mMsgTime;
}
public void UpdateEnergySlider(int currentEnergy,int maxEnergy)
{
mEnergySlider.value =(float)currentEnergy / maxEnergy;
mEnergyText.text = "(" + currentEnergy + "/" + maxEnergy + ")";
}
}
GameFacade中:
public void UpdateEnergySlider(int currentEnergy, int maxEnergy)
{
gameStateUI.UpdateEnergySlider(currentEnergy,maxEnergy);
}
public void ShowMsg(string msg)
{
gameStateUI.ShowMsg(msg);
}
完善CampInfoUI的点击事件及其UI的更新
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CampInfoUI : IBaseUI
{
private Image mCampIcon;
private Text mCampName;
private Text mCampLevel;
private Text mWeaponLevel;
private Button mCampUpgradeBtn;
private Button mWeaponUpgradeBtn;
private Button mTrainBtn;
private Text mTrainBtnText;
private Button mCancelTrainBtn;
private Text mAliveCount;
private Text mTrainingCount;
private Text mTrainTime;
private ICamp mCamp; // 记录兵营
public override void Init()
{
base.Init();
GameObject canvas = GameObject.Find("Canvas");
mRootUI = UnityTools.FindChild(canvas, "CampInfoUI");
mCampIcon = UITools.FindChild<Image>(mRootUI, "CampIcon");
mCampName = UITools.FindChild<Text>(mRootUI, "CampName");
mCampLevel = UITools.FindChild<Text>(mRootUI, "CampLv");
mWeaponLevel = UITools.FindChild<Text>(mRootUI, "WeaponLv");
mCampUpgradeBtn = UITools.FindChild<Button>(mRootUI, "CampUpgradeBtn");
mWeaponUpgradeBtn = UITools.FindChild<Button>(mRootUI, "WeaponUpgradeBtn");
mTrainBtn = UITools.FindChild<Button>(mRootUI, "TrainBtn");
mTrainBtnText = UITools.FindChild<Text>(mRootUI, "TrainBtnText");
mCancelTrainBtn = UITools.FindChild<Button>(mRootUI, "CancelTrainBtn");
mAliveCount = UITools.FindChild<Text>(mRootUI, "AliveCount");
mTrainingCount = UITools.FindChild<Text>(mRootUI, "TrainingCount");
mTrainTime = UITools.FindChild<Text>(mRootUI, "TrainTime");
mTrainBtn.onClick.AddListener(OnTrainClick);
mCancelTrainBtn.onClick.AddListener(OnCancelTrainClick);
mWeaponUpgradeBtn.onClick.AddListener(WeaponUpgradeClick);
mCampUpgradeBtn.onClick.AddListener(CampUpgradeClick);
Hide();
}
public override void Update()
{
base.Update();
if (mCamp != null)
{
ShowTrainInfo();
}
}
public void ShowCampInfoUI(ICamp camp)
{
Show();
mCamp = camp;
mCampIcon.sprite = FactoryManager.assetFactory.LoadSprites(camp.IconSprite);
mCampName.text = camp.Name;
ShowWeaponLevel(camp.GetCampWeaponType());
mCampLevel.text = camp.GetCampLv().ToString();
mTrainBtnText.text = "训练需要" + mCamp.GetTrainEnergyCost+ "点能量";
ShowTrainInfo();
}
//兵营训练信息
public void ShowTrainInfo()
{
mTrainingCount.text = mCamp.GetTrainCount.ToString();
mTrainTime.text = mCamp.GetTrainTimer.ToString("0.00");
if (mCamp.GetTrainCount == 0)
mCancelTrainBtn.interactable = false;
else
mCancelTrainBtn.interactable = true;
}
void ShowWeaponLevel(WeaponType weaponType)
{
switch (weaponType)
{
case WeaponType.Gun:
mWeaponLevel.text = "短枪";
break;
case WeaponType.Rifle:
mWeaponLevel.text = "长枪";
break;
case WeaponType.Rocket:
mWeaponLevel.text = "火箭";
break;
case WeaponType.MAX:
break;
default:
break;
}
}
public void OnTrainClick()
{
// 判断能量是否足够
if (mGameFacade.TakeEnergy(mCamp.GetTrainEnergyCost))
{
mCamp.AddTrainCommand();
}
else
mGameFacade.ShowMsg("能量不足,无法训练新的士兵");
}
public void OnCancelTrainClick()
{
// 将消耗的能量回收
mGameFacade.RecycleEnergy(mCamp.GetTrainEnergyCost);
mCamp.CancelTrainCommand();
}
public void WeaponUpgradeClick()
{
int energy = mCamp.GetWeaponUpgradeEnergyCost;
if (energy < 0)
{
mGameFacade.ShowMsg("武器已经到最大等级,无法升级");
return;
}
if (mGameFacade.TakeEnergy(energy))
{
mCamp.UpdateWeaponUpgrade();
ShowCampInfoUI(mCamp);
}
else
{
mGameFacade.ShowMsg("能量不足,请稍后再进行升级");
}
}
public void CampUpgradeClick()
{
int energy = mCamp.GetCampUpgradeEnergyCost;
if (energy < 0)
{
mGameFacade.ShowMsg("兵营已经到最大等级,无法升级");
return;
}
if (mGameFacade.TakeEnergy(energy))
{
mCamp.UpdateCampUpgrade();
ShowCampInfoUI(mCamp);
}
else
{
mGameFacade.ShowMsg("能量不足,请稍后再进行升级");
}
}
}