using UnityEngine; using DG.Tweening; using System.Collections.Generic; using System.Collections; using cfg; using asap.core; public class CraneCtrl : MonoBehaviour { private DistanceJoint2D _djL, _djR; [SerializeField] private Rigidbody2D _rb; private Vector2 _direction = Vector2.zero, _craneAnchorOffset; private float _driftOffset, _craneCycleHalfDistance, _blockAnchorCoefficient, _lineThickness, _blockDepth; private Block _currentBlock = null; private bool _maxDistanceOnly, _hasAutoDistance, _needKicking = false; private Transform _focus; private List _LvlThresh; private List _craneHeightRise, _craneHeightDescend, _craneCycleTime, _craneRiseTime; private InfiniteBuildingData _data; [SerializeField] private LineRenderer _lineL, _lineR; private TbConstructionHeightEvent _tableHeightEvent; private IEventAggregator _eventAggregator; private float CraneRiseTime { get => GetDataByIBLvl(_data.Lvl, _LvlThresh, _craneRiseTime); } public Rigidbody2D Rb { get => _rb; } private float CraneAcc { get { float t = GetDataByIBLvl(_data.Lvl, _LvlThresh, _craneCycleTime) / 4; return 2 * _craneCycleHalfDistance / t / t; } } private float CraneMaxSpeed { get { float t = GetDataByIBLvl(_data.Lvl, _LvlThresh, _craneCycleTime) / 4; return 2 * _craneCycleHalfDistance / t; } } public void Init(InfiniteBuildingConf config, Transform focus, InfiniteBuildingData data, IEventAggregator ea) { _eventAggregator = ea; _tableHeightEvent = GContext.container.Resolve().TbConstructionHeightEvent; _craneCycleTime = new List(); _LvlThresh = new List(); _craneHeightRise = new List(); _craneHeightDescend = new List(); _craneRiseTime = new List(); foreach (var c in _tableHeightEvent.DataList) { _craneCycleTime.Add(c.CraneCycleTime); _LvlThresh.Add(c.Height); _craneHeightRise.Add(c.CraneHeightRise); _craneHeightDescend.Add(c.CraneHeightToFocus); _craneRiseTime.Add(c.CraneRiseTime); } _craneCycleHalfDistance = config.craneCycleHalfDistance; _craneAnchorOffset = config.craneAnchorOffset; _blockAnchorCoefficient = config.blockAnchorCoefficient; _maxDistanceOnly = config.maxDistanceOnly; _hasAutoDistance = config.hasAutoDistance; _driftOffset = config.blockDriftOffset; _lineThickness = config.craneLineThickness; _blockDepth = config.blockDepth; _focus = focus; _data = data; _lineL.startWidth = _lineL.endWidth = _lineR.startWidth = _lineR.endWidth = _lineThickness; } public void PlayerCtrlFixedUpdate() { if (_rb.position.x < 0) _direction = Vector2.right; else _direction = Vector2.left; if (_needKicking) { _needKicking = false; _rb.velocity = Mathf.Lerp(0, CraneMaxSpeed, 1 - Mathf.Abs(_rb.position.x) / _craneCycleHalfDistance) *_direction; //Debug.Log($"Kick!!!!!!!!!!{_rb.velocity}"); } _rb.velocity += CraneAcc * Time.fixedDeltaTime * _direction; //draw line if (_djL != null && _djR != null && _lineL != null && _lineR != null && _lineL.gameObject.activeSelf && _lineR.gameObject.activeSelf && _currentBlock != null) SetJointPosition(); } public void Kick() { _needKicking = true; } public void AttachJoints(Block block) { _currentBlock = block; _djL = gameObject.AddComponent(); _djR = gameObject.AddComponent(); if (_djL == null || _djR == null || _lineL == null || _lineR == null) { Debug.LogError($"Components not generated for {gameObject}"); } _lineL.gameObject.SetActive(true); _lineR.gameObject.SetActive(true); SetJointPosition(); _djL.anchor = new Vector2(-_craneAnchorOffset.x, _craneAnchorOffset.y); _djR.anchor = _craneAnchorOffset; _djL.connectedBody = block.Rb; _djR.connectedBody = block.Rb; _djL.connectedAnchor = new Vector2(-block.Width * _blockAnchorCoefficient / 2, block.Height); _djR.connectedAnchor = new Vector2(block.Width * _blockAnchorCoefficient / 2, block.Height); _djL.maxDistanceOnly = _maxDistanceOnly; _djR.maxDistanceOnly = _maxDistanceOnly; _djL.autoConfigureDistance = _hasAutoDistance; _djR.autoConfigureDistance = _hasAutoDistance; _djL.breakAction = JointBreakAction2D.Destroy; _djR.breakAction = JointBreakAction2D.Destroy; if (!_hasAutoDistance) { float jd = Mathf.Sqrt( (block.Width * 0.5f * _blockAnchorCoefficient) * (block.Width * 0.5f * _blockAnchorCoefficient) + _driftOffset * _driftOffset); _djL.distance = jd; _djR.distance = jd; } } public IEnumerator DropBlockAndRise() { _eventAggregator.Publish(new EventInfiniteBuildingPlayAudio("BlockFall")); _eventAggregator.Publish(new EventInfiniteBuildingPlayAudio("CraneRise")); _currentBlock = null; _rb.velocity = Vector2.zero; _djL.breakForce = 0; _djR.breakForce = 0; _lineL.gameObject.SetActive(false); _lineR.gameObject.SetActive(false); yield return new WaitForFixedUpdate(); //await Task.Delay((int)(Time.deltaTime * 1000 * 2)); float h = GetDataByIBLvl(_data.Lvl, _LvlThresh, _craneHeightRise); _rb.DOMoveY(_focus.position.y + h, CraneRiseTime); //await Rise(); } public void ResetPosition() { transform.position = new Vector3(0, _focus.position.y + GetDataByIBLvl(_data.Lvl, _LvlThresh, _craneHeightRise), _blockDepth); } public async System.Threading.Tasks.Task Descend() { // ResetPosition(); _eventAggregator.Publish(new EventInfiniteBuildingPlayAudio("CraneDescend")); await _rb.DOMoveY(_focus.position.y + GetDataByIBLvl(_data.Lvl, _LvlThresh, _craneHeightDescend), CraneRiseTime).AsyncWaitForCompletion(); } //public async Task Rise(float duration = 0.5f) //{ // _rb.velocity = Vector2.zero; // await _rb.DOMoveY(_focus.position.y + // GetDataByIBLvl(_data.Lvl, _LvlThresh, _craneHeightRise), // duration).AsyncWaitForCompletion(); //} private void SetJointPosition() { Vector3 cranePointL = gameObject.transform.position + (Vector3)_djL.anchor; Vector3 cranePointR = gameObject.transform.position + (Vector3)_djR.anchor; Vector3 blockPointL = _currentBlock.transform.position + Quaternion.AngleAxis( _currentBlock.Rb.rotation, Vector3.forward) * (Vector3)_djL.connectedAnchor; Vector3 blockPointR = _currentBlock.transform.position + Quaternion.AngleAxis( _currentBlock.Rb.rotation, Vector3.forward) * (Vector3)_djR.connectedAnchor; _lineL.SetPositions(new Vector3[] { cranePointL, blockPointL }); _lineR.SetPositions(new Vector3[] { cranePointR, blockPointR }); } private T GetDataByIBLvl(int lvl, List lvlThresh, List dataList) { if (lvlThresh.Count != dataList.Count) { Debug.LogError($"lvlTresh count {lvlThresh.Count} does not" + $"match dataList count {dataList.Count}"); return default(T); } for (int i = 0; i < lvlThresh.Count - 1; i++) { if (lvl < lvlThresh[i + 1]) return dataList[i]; } return dataList[^1]; } }