429 lines
13 KiB
C#
429 lines
13 KiB
C#
using asap.core;
|
|
using Game;
|
|
using GameCore;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.AddressableAssets;
|
|
|
|
namespace game
|
|
{
|
|
public class PinballFiringPin : MonoBehaviour
|
|
{
|
|
[SerializeField] private Collider2D m_Collider2D;
|
|
[SerializeField] private PinballPellet m_PelletBase;
|
|
|
|
private EventPinballDataManager m_DataManager;
|
|
|
|
private PinballPellet m_Pellet;
|
|
|
|
private void CreateNewPellet()
|
|
{
|
|
if (m_PelletBase.gameObject.activeSelf == true)
|
|
{
|
|
m_PelletBase.gameObject.SetActive(false);
|
|
}
|
|
|
|
if (m_Pellet != null)
|
|
{
|
|
GameObject tmp = m_Pellet.gameObject;
|
|
tmp.SetActive(false);
|
|
GameObject.Destroy(tmp);
|
|
m_Pellet = null;
|
|
}
|
|
GameObject gameObject = Instantiate(m_PelletBase.gameObject, m_PelletBase.transform.position, m_PelletBase.transform.rotation, m_PelletBase.transform.parent);
|
|
m_Pellet = gameObject.GetComponent<PinballPellet>();
|
|
m_Pellet.gameObject.SetActive(true);
|
|
m_Pellet.InitPellet(m_RecordTimes);
|
|
|
|
FishingPinballAct.Publish(new EventPinballSetDummyPelletData()
|
|
{
|
|
Pellet = m_Pellet
|
|
});
|
|
}
|
|
|
|
|
|
#region 声音相关
|
|
[Header("声音设置")]
|
|
[SerializeField] private AudioClip m_FiringPinPullAudioClip;
|
|
[SerializeField] private AssetReferenceT<AudioClip> m_FiringPinSpringAudioClip;
|
|
private Sound m_FiringPinPullSound;
|
|
public void PlayPullSound()
|
|
{
|
|
if (m_FiringPinPullSound != null)
|
|
{
|
|
m_FiringPinPullSound.audioSource.Play();
|
|
}
|
|
}
|
|
public void PlaySpringSound()
|
|
{
|
|
if (m_FiringPinPullSound != null)
|
|
{
|
|
m_FiringPinPullSound.audioSource.Stop();
|
|
}
|
|
|
|
GContext.Publish(new AssetReferenceAudioClip(m_FiringPinSpringAudioClip, time: 0f));
|
|
}
|
|
#endregion
|
|
|
|
#region 撞针操作
|
|
[Header("开关设置")]
|
|
[SerializeField] private Transform m_InitialTransform;
|
|
[SerializeField] private Transform m_FarthestTransform;
|
|
[SerializeField] private float m_ReturnSpeed = 50f; // 回弹速度
|
|
[SerializeField] private float m_DeferTime = 0.1f;
|
|
[SerializeField] private float m_ProtectedRatio = 0.1f;
|
|
|
|
//#if UNITY_EDITOR
|
|
[Header("物理设置/模拟数据设置")]
|
|
[SerializeField] private float m_MinForce = 7f;
|
|
[SerializeField] private float m_ForceStep = 0.0001f;
|
|
//#endif
|
|
|
|
private float m_MaxDragDistance = 0f; // 最大拖动距离
|
|
private float m_MaxDragDistancePositive = 0f; // 最大拖动距离
|
|
private Vector3 m_InitialPosition; // 初始位置
|
|
private Vector3 m_FarthestPosition; // 最远位置
|
|
private bool isDragging = false; // 拖动状态
|
|
private float m_LastTouchDownTime = -1f;
|
|
private Camera mainCamera; // 主摄像机
|
|
|
|
private void OnMouseDown()
|
|
{
|
|
isDragging = true;
|
|
m_LastTouchDownTime = Time.time;
|
|
|
|
PlayPullSound();
|
|
}
|
|
|
|
private void OnMouseDrag()
|
|
{
|
|
if (!isDragging) return;
|
|
|
|
// 将屏幕坐标转为世界坐标
|
|
Vector3 touchPos = mainCamera.ScreenToWorldPoint(Input.mousePosition);
|
|
touchPos.x = m_InitialPosition.x;
|
|
touchPos.z = m_InitialPosition.z; // 保持Z轴不变
|
|
|
|
// 计算允许移动的位置
|
|
Vector3 targetPos = m_InitialPosition;
|
|
float deltaY = Mathf.Clamp(
|
|
touchPos.y - m_InitialPosition.y,
|
|
m_MaxDragDistance,
|
|
0f
|
|
);
|
|
targetPos.y = m_InitialPosition.y + deltaY;
|
|
|
|
transform.position = targetPos;
|
|
|
|
float ratio = GetDragRatio();
|
|
FishingPinballAct.Publish(new EventPinballEnergyArrowData()
|
|
{
|
|
Energy = ratio
|
|
});
|
|
|
|
FishingPinballAct.Publish<EventPinballSpringUpdateData>(new EventPinballSpringUpdateData()
|
|
{
|
|
Ratio = 1.0f - ratio
|
|
});
|
|
}
|
|
|
|
private void OnMouseUp()
|
|
{
|
|
if (isDragging == false)
|
|
{
|
|
FishingPinballAct.Publish(new EventPinballEnergyArrowRestoreData());
|
|
return;
|
|
}
|
|
|
|
isDragging = false;
|
|
|
|
StartCoroutine(BounceBack());
|
|
}
|
|
|
|
public float GetDragRatio()
|
|
{
|
|
Vector3 startPos = transform.position;
|
|
|
|
float deadzone = m_MaxDragDistancePositive * m_ProtectedRatio;
|
|
|
|
float distance = Mathf.Abs(startPos.y - m_InitialPosition.y) - deadzone;
|
|
if (distance <= 0f) return 0f;
|
|
|
|
float totalDistance = m_MaxDragDistancePositive - deadzone;
|
|
if (totalDistance <= 0f) return 0f;
|
|
|
|
return distance / totalDistance;
|
|
}
|
|
|
|
private void ShowChainPack()
|
|
{
|
|
if (GContext.container.Resolve<FishingEventData>().ChainPackWithProgressMigrationData.IsChainPackDepleted)
|
|
{
|
|
ToastPanel.Show(LocalizationMgr.GetText("UI_ToastPanel_103"));
|
|
}
|
|
GContext.container.Resolve<FishingEventData>().ChainPackWithProgressMigrationData.ShowChainPack();
|
|
}
|
|
|
|
IEnumerator BounceBack()
|
|
{
|
|
float elapsed = 0f;
|
|
Vector3 startPos = transform.position;
|
|
|
|
float ratio = GetDragRatio();
|
|
|
|
while (elapsed < 1f)
|
|
{
|
|
elapsed += m_ReturnSpeed * Time.deltaTime;
|
|
// 使用缓动函数实现弹性
|
|
transform.position = Vector3.Lerp(
|
|
startPos,
|
|
m_InitialPosition,
|
|
Mathf.SmoothStep(0, 1, elapsed)
|
|
);
|
|
|
|
float tmpRatio = GetDragRatio();
|
|
|
|
FishingPinballAct.Publish<EventPinballSpringUpdateData>(new EventPinballSpringUpdateData()
|
|
{
|
|
Ratio = 1.0f - tmpRatio
|
|
});
|
|
|
|
yield return null;
|
|
}
|
|
|
|
float tmpLastTouchDownTime = m_LastTouchDownTime;
|
|
|
|
m_LastTouchDownTime = -1f;
|
|
|
|
if (ratio <= 0f)
|
|
{
|
|
FishingPinballAct.Publish(new EventPinballEnergyArrowRestoreData());
|
|
yield break;
|
|
}
|
|
|
|
|
|
if (tmpLastTouchDownTime < 0f)
|
|
{
|
|
FishingPinballAct.Publish(new EventPinballEnergyArrowRestoreData());
|
|
yield break;
|
|
}
|
|
|
|
if (Time.time - tmpLastTouchDownTime < m_DeferTime)
|
|
{
|
|
FishingPinballAct.Publish(new EventPinballEnergyArrowRestoreData());
|
|
yield break;
|
|
}
|
|
|
|
PlaySpringSound();
|
|
|
|
if (m_IsPelletRunning)
|
|
{
|
|
yield break;
|
|
}
|
|
|
|
var dataManager = GContext.container.Resolve<EventPinballDataManager>();
|
|
|
|
//dataManager.InitGameRound();
|
|
|
|
if (!dataManager.ConsumeTemporaryTokensDefault())
|
|
{
|
|
FishingPinballAct.Publish(new EventPinballEnergyArrowRestoreData());
|
|
|
|
ShowChainPack();
|
|
|
|
yield break;
|
|
}
|
|
|
|
if (m_DataManager != null)
|
|
{
|
|
m_DataManager.IsSimulatorMode = m_IsSimulatorMode;
|
|
}
|
|
|
|
//CreateNewPellet();
|
|
|
|
//float force = Mathf.Lerp(m_MinForce, m_MaxForce, ratio);
|
|
float force = dataManager.GetRandomForce(ratio);
|
|
m_Pellet.LaunchPellet(force, m_RecordTimes);
|
|
FishingPinballAct.Publish(new EventPinballEnergyArrowRestoreData());
|
|
|
|
//#if AGG
|
|
// using (var e = GEvent.GameEvent("event_pinball"))
|
|
// {
|
|
// e.AddContent("force", force)
|
|
// .AddContent("item_consume", m_DataManager.TemporaryConsumedToken);
|
|
// }
|
|
//#endif
|
|
}
|
|
|
|
bool IsTouchingSwitch(Vector2 screenPos)
|
|
{
|
|
RaycastHit2D hit = Physics2D.Raycast(
|
|
mainCamera.ScreenToWorldPoint(screenPos),
|
|
Vector2.zero
|
|
);
|
|
return hit.collider != null && hit.collider.gameObject == gameObject;
|
|
}
|
|
#endregion
|
|
|
|
#region 运行模式相关(模拟数据模式/正常玩家模式)
|
|
[SerializeField] private bool m_IsSimulatorMode = false;
|
|
[SerializeField] private bool m_IsProcessingSimulatedData = false;
|
|
private int m_RecordTimes = 0;
|
|
#endregion
|
|
|
|
#region 事件相关
|
|
private void InitEvent()
|
|
{
|
|
FishingPinballAct.Subscribe<EventPinballResetPelletStatusData>(ResetPelletInFiringPin);
|
|
FishingPinballAct.Subscribe<EventPinballLaunchPelletStatusData>(LaunchPelletInFiringPin);
|
|
FishingPinballAct.Subscribe<EventPinballResumePelletData>(ResumePellet);
|
|
FishingPinballAct.Subscribe<EventPinballLaunchPelletData>(OnLaunchPelletDataEvent);
|
|
}
|
|
public void ResumePellet(EventPinballResumePelletData data)
|
|
{
|
|
CreateNewPellet();
|
|
float force = m_MinForce + m_ForceStep * m_RecordTimes;
|
|
|
|
m_Pellet.ResumePellet(force, m_RecordTimes);
|
|
|
|
if (m_IsProcessingSimulatedData)
|
|
{
|
|
m_RecordTimes++;
|
|
}
|
|
}
|
|
|
|
public void OnLaunchPelletDataEvent(EventPinballLaunchPelletData data)
|
|
{
|
|
if (data == null) return;
|
|
if (m_Pellet != null)
|
|
{
|
|
m_Pellet.LaunchPellet(data.Force, m_RecordTimes);
|
|
}
|
|
}
|
|
|
|
private bool m_IsPelletRunning = false;
|
|
public void LaunchPelletInFiringPin(EventPinballLaunchPelletStatusData data)
|
|
{
|
|
m_IsPelletRunning = true;
|
|
}
|
|
public void ResetPelletInFiringPin(EventPinballResetPelletStatusData data)
|
|
{
|
|
m_IsPelletRunning = false;
|
|
}
|
|
#endregion
|
|
|
|
#region 生命周期
|
|
// Start is called before the first frame update
|
|
void Start()
|
|
{
|
|
m_DataManager = GContext.container.Resolve<EventPinballDataManager>();
|
|
|
|
m_InitialPosition = m_InitialTransform.position;
|
|
m_FarthestPosition = m_FarthestTransform.position;
|
|
|
|
m_MaxDragDistance = m_FarthestTransform.position.y - m_InitialPosition.y;
|
|
m_MaxDragDistancePositive = Mathf.Abs(m_MaxDragDistance);
|
|
|
|
mainCamera = Camera.main;
|
|
m_LastTouchDownTime = -1f;
|
|
|
|
m_FiringPinPullSound = GContext.container.Resolve<ISoundService>().GetNewUISound(m_FiringPinPullAudioClip);
|
|
|
|
m_IsSimulatorMode = false;
|
|
m_IsPelletRunning = false;
|
|
|
|
InitEvent();
|
|
|
|
CreateNewPellet();
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
if (m_Collider2D == null) return;
|
|
|
|
bool isTriggered = false, isDown = false, isDrag = false, isUp = false;
|
|
Vector2 screenPosition = Vector2.zero;
|
|
|
|
#if UNITY_EDITOR
|
|
if (Input.GetKeyUp(KeyCode.F1))
|
|
{
|
|
if (m_DataManager != null)
|
|
{
|
|
m_DataManager.IsSimulatorMode = m_IsSimulatorMode;
|
|
}
|
|
//CreateNewPellet();
|
|
m_Pellet.InitPellet(m_RecordTimes);
|
|
//m_Pellet.ResetPellet();
|
|
m_Pellet.SetState(EventPinballState.Prepare);
|
|
m_Pellet.LaunchPellet(m_MinForce, m_RecordTimes);
|
|
return;
|
|
}
|
|
else if (Input.GetKeyUp(KeyCode.F2))
|
|
{
|
|
FishingPinballAct.Publish(new EventPinballResumePelletData());
|
|
return;
|
|
}
|
|
|
|
isDown = Input.GetMouseButtonDown(0);
|
|
isDrag = Input.GetMouseButton(0);
|
|
isUp = Input.GetMouseButtonUp(0);
|
|
|
|
screenPosition = Input.mousePosition;
|
|
|
|
isTriggered = isDown || isDrag || isUp;
|
|
#elif UNITY_IOS || UNITY_ANDROID
|
|
isTriggered = Input.touchCount > 0;
|
|
|
|
if (isTriggered)
|
|
{
|
|
Touch touch = Input.GetTouch(0);
|
|
screenPosition = touch.position;
|
|
switch (touch.phase)
|
|
{
|
|
case TouchPhase.Began:
|
|
{
|
|
isDown = true;
|
|
}
|
|
break;
|
|
|
|
case TouchPhase.Moved:
|
|
{
|
|
isDrag = true;
|
|
}
|
|
break;
|
|
|
|
case TouchPhase.Ended:
|
|
{
|
|
isUp = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (isTriggered && IsTouchingSwitch(screenPosition))
|
|
{
|
|
if (isDown)
|
|
{
|
|
OnMouseDown();
|
|
}
|
|
else if (isUp)
|
|
{
|
|
OnMouseUp();
|
|
}
|
|
else if (isDrag)
|
|
{
|
|
OnMouseDrag();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OnMouseUp();
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
}
|