Forest_Client/Forest/Assets/Scripts/Gameplay/Manager/LevelManager.cs

711 lines
25 KiB
C#

using cfg.BI;
using System;
using PhxhSDK;
using cfg.Prop;
using UnityEngine;
using System.Linq;
using Framework.BI;
using Framework.UI;
using Gameplay.Level;
using Framework.Event;
using Framework.Manager;
using Framework.Constants;
using Event = cfg.BI.Event;
using Cysharp.Threading.Tasks;
using Gameplay.Level.Operation;
using System.Collections.Generic;
using Constants = Framework.Constants.Constants;
namespace Gameplay.Manager
{
public class LevelManager : Singlenton<LevelManager>, IUpdatable
{
private GameObject _destroyPlankRoot;
private UndoOperation _undoOperation;
private List<string> _destroyPlanks;
public UndoState CurUndoState;
public float RemainingTime;
public bool IsPause;
public bool IsOver;
public bool IsTimeEnd;
public int Step;
public float ElapsedTime;
public Level.Level CurrentLevel { get; private set; }
public int LastPassLevel = 0;
public bool IsNewbieGuide;
public bool IsFail2AddTime;
public bool IsWatchAD;
private int _levelLoseTime;
private string _lastLevelID = "";
public string ADGetPropTips = "";
private GameObject _gfxUndo;
private ParticleSystem _particleUndo;
private GameObject _gfxOpenHole;
private ParticleSystem _particleOpen;
private GameObject _gfxWin;
private ParticleSystem _particleWin;
private GameObject _gfxBgSunny;
//飞金币
public GameObject CoinObj;
public Vector3 CoinTargetPos;
public List<Coin> GfxCoins;
public bool CanGfxCoin;
public class Coin
{
public GameObject CoinObj;
private float _moveTime;
private const float MoveSpawnInterval = 0.5f;
private const float MoveSpeed = 300f;
public Coin(GameObject obj)
{
CoinObj = obj;
}
public void Update(float deltaTime)
{
_moveTime += deltaTime;
if (CoinObj && _moveTime > MoveSpawnInterval)
{
CoinObj.transform.position = Vector3.MoveTowards(CoinObj.transform.position,
Instance.CoinTargetPos, MoveSpeed * Time.deltaTime);
}
if (CoinObj && CoinObj.transform.position.Equals(Instance.CoinTargetPos))
{
CoinObj.SetActive(false);
CoinObj.Destroy();
_moveTime = 0.0f;
}
}
public void Release()
{
if (CoinObj)
CoinObj.Destroy();
}
}
public async UniTask Init()
{
await InitUI();
RegisterEvent();
ReLoadLevelValue();
CurUndoState = new UndoState();
_undoOperation = new UndoOperation();
_destroyPlanks = new List<string>();
GfxCoins = new List<Coin>();
await InitGfx();
CoinObj = await AssetManager.Instance.LoadAssetAsync<GameObject>(string.Format(Constants.ItemPrefabPath,
"GfxCoin"));
}
private async UniTask InitUI()
{
UIManager.Instance.CloseWindow(UIConstants.ImgLoading);
await UIManager.Instance.OpenBgWindow(UIConstants.UILevelBg);
}
private async UniTask InitGfx()
{
_gfxUndo = await GfxManager.Instance.PreLoadGfx("gfx_undo");
_particleUndo = _gfxUndo.GetComponent<ParticleSystem>();
_gfxOpenHole = await GfxManager.Instance.PreLoadGfx("gfx_openhole");
_particleOpen = _gfxOpenHole.GetComponent<ParticleSystem>();
_gfxWin = await GfxManager.Instance.PreLoadGfx("gfx_win_firework");
_particleWin = _gfxWin.GetComponent<ParticleSystem>();
await GfxManager.Instance.PreLoadGfx("gfx_bg_sunny");
_gfxBgSunny = await GfxManager.Instance.LoadGfx("gfx_bg_sunny");
}
public void ReLoadLevelValue()
{
Step = 0;
ElapsedTime = 0f;
RemainingTime = LevelConstants.RemainingTime;
}
#region Game Start Part
public async UniTask LoadLevel(string id)
{
if (IsLevelExist(id))
{
CurrentLevel = new Level.Level(id);
await CurrentLevel.Load(id);
await UniTask.NextFrame();
}
else
{
await CurrentLevel.Load(CurrentLevel.ID);
await UniTask.NextFrame();
}
if (!_lastLevelID.Equals(CurrentLevel.ID))
{
DebugUtil.LogWarning("开启新关卡:{0}", CurrentLevel.ID);
_lastLevelID = CurrentLevel.ID;
_levelLoseTime = 0;
}
if (RandomProp != PropType.None)
{
switch (RandomProp)
{
case PropType.Undo:
CurrentLevel.LevelData.undoCount++;
break;
case PropType.OpenHole:
CurrentLevel.LevelData.openHoleCount++;
break;
}
RandomProp = PropType.None;
}
}
public bool IsLevelExist(string id)
{
var levels = LevelSelectManager.Instance.CurAllLevelDatas.Select(data => data.LevelID).ToList();
return levels.Contains(id);
}
public void ReportEnterLevel()
{
BIManager.Instance.TrackStringEventOnce(string.Format(LevelConstants.FteLevelEnter,
CurrentLevel.GetLevelIndex()));
}
#endregion
#region Game In Process Part
private void HideGfx()
{
GfxManager.Instance.ReturnGfxObj("gfx_undo");
GfxManager.Instance.ReturnGfxObj("gfx_openhole");
GfxManager.Instance.ReturnGfxObj("gfx_bg_sunny");
GfxManager.Instance.ReturnGfxObj("gfx_win_firework");
}
private void ShowGfx()
{
_gfxBgSunny.SetActive(true);
}
public void PushUndoState()
{
if (CurUndoState.LastModifiedKong == null || CurUndoState.PreModifiedKong == null) return;
if (CurUndoState != null)
{
_undoOperation.UndoStack.Push(CurUndoState);
CurUndoState = new UndoState();
}
}
public void Update(float deltaTime)
{
if (CurrentLevel != null)
{
CurrentLevel.Update(deltaTime);
}
if (_isGetPropSuccess)
{
_isGetPropSuccess = false;
EventManager.Instance.Send(EventManager.EventName.WatchADSuccessToGetProp);
}
if (_isGetTimeSuccess)
{
_isGetTimeSuccess = false;
EventManager.Instance.Send(EventManager.EventName.WatchADSuccessToGetTime);
}
if (_isGetRandomPropSuccess)
{
_isGetRandomPropSuccess = false;
EventManager.Instance.Send(EventManager.EventName.WatchADSuccessToGetRandomProp);
}
if (GfxCoins != null)
{
foreach (var coin in GfxCoins)
{
coin.Update(deltaTime);
}
}
/*
if (GfxCoins != null && !GfxCoins[^1].Show)
{
EventManager.Instance.Send(EventManager.EventName.WinGfxFinish);
}
*/
Time.timeScale = IsOver || IsPause ? 0f : 1f;
}
#endregion
#region Game End Part
public void CachePlank(string cachePlank)
{
PlankManager.Instance.GetPlank(cachePlank).Obj.SetActive(false);
if (!_destroyPlanks.Contains(cachePlank))
{
_destroyPlanks.Add(cachePlank);
if (_destroyPlanks.Count.Equals(PlankManager.Instance.Planks.Count))
{
foreach (var plank in PlankManager.Instance.Planks.Keys)
{
if (!_destroyPlanks.Contains(plank)) return;
}
EventManager.Instance.Send(EventManager.EventName.LevelGameWin);
}
}
}
private void WinGfxFinish()
{
}
private void WinGame()
{
/*if (IsOver) return;
IsOver = true;*/
GfxManager.Instance.ReturnGfxObj("gfx_bg_sunny", true);
CommonUIUtils.DestroyScreenshot();
CommonUIUtils.CaptureScreenshot();
AudioManager.Instance.PlaySound(AudioType.SOUND, "S_Win", new UnityAudio(false));
GfxManager.Instance.ShowGfxOnce(_particleWin, _gfxWin);
IsTimeEnd = true;
if (IsNewbieGuide)
{
IsNewbieGuide = false;
EventManager.Instance.Send(EventManager.EventName.NewBieGuideFinish);
}
ReportPassLevel();
var oldCoin = ShopManager.Instance.CurCoin;
LevelSelectManager.Instance.SaveNewPassLevel(CurrentLevel.ID);
BIManager.Instance.TrackEventLevel(Event.level_success);
UIManager.Instance.OpenWindow(UIConstants.UIWinPanel, oldCoin);
}
private void LoseGame()
{
if (IsOver) return;
IsOver = true;
GfxManager.Instance.ReturnGfxObj("gfx_bg_sunny", true);
CommonUIUtils.DestroyScreenshot();
CommonUIUtils.CaptureScreenshot();
BIManager.Instance.TrackEventLevel(Event.level_fail);
_levelLoseTime++;
DebugUtil.LogWarning("输掉关卡:{0},已经{1}次了", _lastLevelID, _levelLoseTime);
if (_levelLoseTime >= 2 && ADManager.Instance.CanShow(103))
{
AudioManager.Instance.PlaySound(AudioType.SOUND, "S_Reward", new UnityAudio(false));
UIManager.Instance.OpenWindow(UIConstants.UIADPOPUP);
}
else
{
AudioManager.Instance.PlaySound(AudioType.SOUND, "S_Lose", new UnityAudio(false));
UIManager.Instance.OpenWindow(UIConstants.UILosePanel);
}
}
private void ReportPassLevel()
{
BIManager.Instance.TrackStringEventOnce(string.Format(LevelConstants.FteLevelSuccess,
CurrentLevel.GetLevelIndex()));
}
#endregion
#region Prop Function Part
public bool PlayAnimation;
public bool CanUndo()
{
return !IsNewbieGuide && _undoOperation.UndoStack.Count > 0;
}
public void SureUndo()
{
if (IsNewbieGuide) return;
if (!CanUndo())
{
IsPause = true;
CommonUIUtils.DestroyScreenshot();
CommonUIUtils.CaptureScreenshot();
UIManager.Instance.OpenWindow(UIConstants.UITips, "Tip_Undo", () => { IsPause = false; });
}
else
{
if (CurrentLevel.LevelData.undoCount > 0)
{
Undo();
}
else
{
CommonUIUtils.DestroyScreenshot();
CommonUIUtils.CaptureScreenshot();
UIManager.Instance.OpenWindow(UIConstants.UIBuyGoods, PropType.Undo, Undo);
}
}
}
private void Undo()
{
if (_undoOperation.UndoStack.Count <= 0) return;
try
{
BIManager.Instance.TrackEventLevel(Event.level_step_back, BIManager.Reason.ByUsingItem.ToString());
Step -= 1;
CurrentLevel.LevelData.undoCount--;
ShopManager.Instance.UseProp(PropType.Undo);
EventManager.Instance.Send(EventManager.EventName.RefreshProp);
var undoState = _undoOperation.UndoStack.Pop();
//改变表现
GfxManager.Instance.ShowGfxOnce(_particleUndo, _gfxUndo);
AudioManager.Instance.PlaySound(AudioType.SOUND, "S_Undo", new UnityAudio(false));
var undoThumbtack = undoState.LastModifiedKong.LevelThumbtack;
undoThumbtack.Obj.transform.position = undoState.PreModifiedKong.Obj.transform.position;
foreach (var undo in undoState.AffectPlanks)
{
undo.Key.Obj.SetActive(true);
undo.Key.StopDetect = false;
}
undoState.PreModifiedKong.LevelThumbtack = undoThumbtack;
foreach (var plank in undoState.ReplacePlanks)
{
PlankManager.Instance.ReplaceAnchor(plank, undoState.LastModifiedKong.LevelThumbtack);
}
foreach (var undo in undoState.AffectPlanks)
{
undo.Key.Obj.transform.rotation = undo.Value.Value;
undo.Key.Obj.transform.position = undo.Value.Key;
if (undoState.RemoveH2DjPlanks.Contains(undo.Key))
PlankManager.Instance.AddHingJoint2D(undo.Key, undoState.PreModifiedKong.LevelThumbtack);
}
foreach (var plank in undoState.AddH2DjPlanks)
{
PlankManager.Instance.RemoveHingJoint2D(plank, undoState.LastModifiedKong.LevelThumbtack);
}
undoState.LastModifiedKong.LevelThumbtack = null;
undoState.LastModifiedKong = null;
undoState.PreModifiedKong = null;
}
catch (Exception e)
{
DebugUtil.LogError("LevelManager.Undo Fail. Error: {0}", e);
}
}
public void SureAddTime()
{
if (IsNewbieGuide) return;
if (CurrentLevel.LevelData.addTimeCount > 0)
{
AddTime();
}
else
{
CommonUIUtils.DestroyScreenshot();
CommonUIUtils.CaptureScreenshot();
UIManager.Instance.OpenWindow(UIConstants.UIBuyGoods, PropType.AddTime, AddTime);
}
}
private void AddTime()
{
BIManager.Instance.TrackEventLevel(Event.level_add_time, BIManager.Reason.ByUsingItem.ToString());
EventManager.Instance.Send(EventManager.EventName.AddTime);
RemainingTime += LevelConstants.AddPropTime;
CurrentLevel.LevelData.addTimeCount--;
ShopManager.Instance.UseProp(PropType.AddTime);
EventManager.Instance.Send(EventManager.EventName.RefreshProp);
PlayAnimation = true;
AudioManager.Instance.PlaySound(AudioType.SOUND, "S_AddTime", new UnityAudio(false));
}
public bool CanOpenHole()
{
return !IsNewbieGuide && !KongManager.Instance.CanAddNewHole().Equals(Vector3.zero);
}
public void SureOpenHole()
{
if (IsNewbieGuide) return;
if (!CanOpenHole())
{
IsPause = true;
CommonUIUtils.DestroyScreenshot();
CommonUIUtils.CaptureScreenshot();
UIManager.Instance.OpenWindow(UIConstants.UITips, "Tip_OpenHole", () => { IsPause = false; });
}
else
{
if (CurrentLevel.LevelData.openHoleCount > 0)
{
OpenHoleAfterGfx();
}
else
{
CommonUIUtils.DestroyScreenshot();
CommonUIUtils.CaptureScreenshot();
UIManager.Instance.OpenWindow(UIConstants.UIBuyGoods, PropType.OpenHole, OpenHoleAfterGfx);
}
}
}
private void OpenHoleAfterGfx()
{
var pos = KongManager.Instance.CanAddNewHole();
if (!pos.Equals(Vector3.zero))
{
CurrentLevel.LevelData.openHoleCount--;
ShopManager.Instance.UseProp(PropType.OpenHole);
EventManager.Instance.Send(EventManager.EventName.RefreshProp);
_gfxOpenHole.transform.position = pos;
AudioManager.Instance.PlaySound(AudioType.SOUND, "S_OpenHole", new UnityAudio(false));
GfxManager.Instance.ShowGfxOnce(_particleOpen, _gfxOpenHole, OpenHole);
}
}
private void OpenHole()
{
KongManager.Instance.AddNewHole();
BIManager.Instance.TrackEventLevel(Event.level_add_hole, BIManager.Reason.ByUsingItem.ToString());
}
public void SureResetLevel()
{
if (IsNewbieGuide) return;
IsPause = true;
CommonUIUtils.DestroyScreenshot();
CommonUIUtils.CaptureScreenshot();
UIManager.Instance.OpenWindow(UIConstants.UITips, "Tip_Reset_Confirm", ResetLevel,
() => { IsPause = false; });
return;
if (CurrentLevel.LevelData.resetCount > 0)
{
GameStateManager.Instance.ChangeState(new LevelState(CurrentLevel.ID));
CurrentLevel.LevelData.resetCount--;
BIManager.Instance.TrackEventLevel(Event.level_retry, BIManager.Reason.ClickOnLevelScene.ToString());
EventManager.Instance.Send(EventManager.EventName.RefreshProp);
}
}
public void ResetLevel()
{
BIManager.Instance.TrackEventLevel(Event.level_retry, BIManager.Reason.ClickOnLevelScene.ToString());
GameStateManager.Instance.ChangeState(new LevelState(CurrentLevel.ID));
}
#endregion
#region AD Part
private Action _adGetPropSuccess;
private Action _adGetTimeSuccess;
private Action _adGetRandomPropSuccess;
private bool _isGetPropSuccess;
private bool _isGetTimeSuccess;
private bool _isGetRandomPropSuccess;
private PropType _adProp;
public PropType RandomProp = PropType.None;
//失败获取随即道具
public void WatchADGetRandomProp(Action getSuccess, Action getFail)
{
_adGetRandomPropSuccess = getSuccess;
BIManager.Instance.TrackEventLevel(Event.level_click_ad, "103");
BIManager.Instance.TrackEventLevelOnce(EventFirst.fte_level_click_ad, "103");
ADManager.Instance.ShowAdWithPreLoad(103, () => { _isGetRandomPropSuccess = true; }, getFail);
}
private void ADGetRandomProp()
{
while (RandomProp != PropType.Undo && RandomProp != PropType.OpenHole)
{
RandomProp = Utils.GetRandomEnum<PropType>();
}
BIManager.Instance.TrackEventLevel(Event.level_ad_show_success, "103", RandomProp.ToString());
BIManager.Instance.TrackEventLevelOnce(EventFirst.fte_level_ad_show_success, "103", RandomProp.ToString());
DebugUtil.LogWarning("获取到的道具是:{0}", RandomProp);
_levelLoseTime = 0;
_adGetRandomPropSuccess?.Invoke();
}
//失败看广告获取时间
public void WatchADGetTime(Action getSuccess, Action getFail = null)
{
_adGetTimeSuccess = getSuccess;
BIManager.Instance.TrackEventLevel(Event.level_click_ad, "102");
BIManager.Instance.TrackEventLevelOnce(EventFirst.fte_level_click_ad, "102");
ADManager.Instance.ShowAdWithPreLoad(102,
() => { _isGetTimeSuccess = true; }, getFail);
}
private void ADGetTime()
{
BIManager.Instance.TrackEventLevel(cfg.BI.Event.level_add_time,
BIManager.Reason.ClickOnLosePanel.ToString());
RemainingTime = 15f;
IsOver = false;
IsFail2AddTime = true;
BIManager.Instance.TrackEventLevel(Event.level_ad_show_success, "102", "AddTime");
BIManager.Instance.TrackEventLevelOnce(EventFirst.fte_level_ad_show_success, "102", "AddTime");
AudioManager.Instance.PlaySound(AudioType.SOUND, "S_AddTime", new UnityAudio(false));
PlayAnimation = true;
_adGetTimeSuccess?.Invoke();
}
//关卡内看广告获取指定道具
public void WatchADGetProp(PropType prop, Action rewardSuccess, Action rewardFail = null)
{
_adProp = prop;
_adGetPropSuccess = rewardSuccess;
BIManager.Instance.TrackEventLevel(Event.level_click_ad, "101");
BIManager.Instance.TrackEventLevelOnce(EventFirst.fte_level_click_ad, "101");
ADManager.Instance.ShowAdWithPreLoad(101, () => { _isGetPropSuccess = true; }, rewardFail);
}
private void ADGetProp()
{
_adGetPropSuccess?.Invoke();
UIManager.Instance.OpenWindow(UIConstants.UITips, ADGetPropTips,
() =>
{
switch (_adProp)
{
case PropType.Undo:
{
Undo();
break;
}
case PropType.OpenHole:
{
OpenHoleAfterGfx();
break;
}
case PropType.AddTime:
{
AddTime();
break;
}
}
IsPause = false;
BIManager.Instance.TrackEventLevel(Event.level_ad_show_success, "101", _adProp.ToString());
BIManager.Instance.TrackEventLevelOnce(EventFirst.fte_level_ad_show_success, "101",
_adProp.ToString());
IsWatchAD = true;
EventManager.Instance.Send(EventManager.EventName.RefreshProp);
});
DebugUtil.LogWarning("Use Prop: {0}", _adProp);
}
#endregion
public void Release()
{
IsPause = false;
IsOver = false;
IsTimeEnd = false;
IsFail2AddTime = false;
IsWatchAD = false;
foreach (var gfxCoin in GfxCoins)
{
gfxCoin.Release();
}
CanGfxCoin = false;
GfxCoins = null;
ReleaseGfx();
UnRegisterEvent();
//ShopManager.Instance.SettleCoins();
KongManager.Instance.Release();
PlankManager.Instance.Release();
CommonUIUtils.DestroyScreenshot();
}
private void ReleaseGfx()
{
GfxManager.Instance.ReturnGfxObj("gfx_undo", true);
GfxManager.Instance.ReturnGfxObj("gfx_openhole", true);
GfxManager.Instance.ReturnGfxObj("gfx_bg_sunny", true);
GfxManager.Instance.ReturnGfxObj("gfx_win_firework", true);
_gfxUndo = null;
_particleUndo = null;
_gfxOpenHole = null;
_particleOpen = null;
_gfxWin = null;
_particleWin = null;
_gfxBgSunny = null;
}
private void RegisterEvent()
{
EventManager.Instance.Register(EventManager.EventName.LevelGameWin, WinGame);
EventManager.Instance.Register(EventManager.EventName.LevelGameLose, LoseGame);
EventManager.Instance.Register(EventManager.EventName.WatchADSuccessToGetProp, ADGetProp);
EventManager.Instance.Register(EventManager.EventName.WatchADSuccessToGetTime, ADGetTime);
EventManager.Instance.Register(EventManager.EventName.WatchADSuccessToGetRandomProp, ADGetRandomProp);
EventManager.Instance.Register(EventManager.EventName.HideGfx, HideGfx);
EventManager.Instance.Register(EventManager.EventName.ShowGfx, ShowGfx);
}
private void UnRegisterEvent()
{
EventManager.Instance.Unregister(EventManager.EventName.LevelGameWin, WinGame);
EventManager.Instance.Unregister(EventManager.EventName.LevelGameLose, LoseGame);
EventManager.Instance.Unregister(EventManager.EventName.WatchADSuccessToGetProp, ADGetProp);
EventManager.Instance.Unregister(EventManager.EventName.WatchADSuccessToGetTime, ADGetTime);
EventManager.Instance.Unregister(EventManager.EventName.WatchADSuccessToGetRandomProp, ADGetRandomProp);
EventManager.Instance.Unregister(EventManager.EventName.HideGfx, HideGfx);
EventManager.Instance.Unregister(EventManager.EventName.ShowGfx, ShowGfx);
}
//Debug
public void AddUndoProp()
{
CurrentLevel.LevelData.undoCount = 999;
EventManager.Instance.Send(EventManager.EventName.RefreshProp);
}
}
}