Files
back_cantanBuilding/Assets/Scripts/InfiniteBuilding/CraneCtrl.cs
2026-05-26 16:15:54 +08:00

194 lines
7.8 KiB
C#

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<int> _LvlThresh;
private List<float> _craneHeightRise, _craneHeightDescend, _craneCycleTime, _craneRiseTime;
private InfiniteBuildingData _data;
[SerializeField] private LineRenderer _lineL, _lineR;
private TbConstructionHeightEvent _tableHeightEvent;
private IEventAggregator _eventAggregator;
private float CraneRiseTime { get => GetDataByIBLvl<float>(_data.Lvl, _LvlThresh, _craneRiseTime); }
public Rigidbody2D Rb { get => _rb; }
private float CraneAcc {
get
{
float t = GetDataByIBLvl<float>(_data.Lvl, _LvlThresh, _craneCycleTime) / 4;
return 2 * _craneCycleHalfDistance / t / t;
}
}
private float CraneMaxSpeed
{
get
{
float t = GetDataByIBLvl<float>(_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<Tables>().TbConstructionHeightEvent;
_craneCycleTime = new List<float>();
_LvlThresh = new List<int>();
_craneHeightRise = new List<float>();
_craneHeightDescend = new List<float>();
_craneRiseTime = new List<float>();
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<DistanceJoint2D>();
_djR = gameObject.AddComponent<DistanceJoint2D>();
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<float>(_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<float>(_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<float>(_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<float>(_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<T>(int lvl, List<int> lvlThresh, List<T> 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];
}
}