373 lines
9.5 KiB
C#
373 lines
9.5 KiB
C#
using System.Collections;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
using UnityEngine.SceneManagement;
|
|
using UnityEngine.UI;
|
|
|
|
public class ClientGameSticksSceneController : MonoBehaviour
|
|
{
|
|
public static ClientGameSticksSceneController Instance;
|
|
|
|
public GameObject introPanel;
|
|
public GameObject playPanel;
|
|
public GameObject stopPanel;
|
|
public GameObject finishPanel;
|
|
|
|
public TMP_Text playCountdownText;
|
|
public Transform incenseTransform;
|
|
public Transform incenseHolderTransform;
|
|
|
|
private Image sincerityMeterFill;
|
|
|
|
|
|
private float minAngle = 30f;
|
|
private float maxAngle = 150f;
|
|
private float dragSensitivity = 0.5f;
|
|
|
|
private bool isDragging = false;
|
|
private float currentAngle = 90f;
|
|
private Camera mainCamera;
|
|
private Coroutine windCoroutine;
|
|
private bool gameActive = true;
|
|
|
|
public Button finishGoToNextButton;
|
|
public Button finishBackToMenuButton;
|
|
|
|
private int playCountdownSecVal = 30;
|
|
|
|
private void Awake()
|
|
{
|
|
Instance = this;
|
|
}
|
|
|
|
public void init()
|
|
{
|
|
processStep(1);
|
|
gameActive = false;
|
|
}
|
|
|
|
IEnumerator StatusCountdown()
|
|
{
|
|
yield return new WaitForSeconds(1f);
|
|
|
|
playCountdownSecVal--;
|
|
|
|
playCountdownText.text = "時間倒數 " + playCountdownSecVal.ToString() + "秒";
|
|
|
|
if (playCountdownSecVal > 0)
|
|
{
|
|
StartCoroutine(StatusCountdown());
|
|
}
|
|
else
|
|
{
|
|
processStep(3);
|
|
}
|
|
|
|
}
|
|
|
|
IEnumerator NextStep(int step, int waitSec)
|
|
{
|
|
yield return new WaitForSeconds(waitSec);
|
|
processStep(step);
|
|
}
|
|
|
|
|
|
public void processStep(int step)
|
|
{
|
|
if (introPanel)
|
|
{
|
|
introPanel.SetActive(step == 1);
|
|
if (step == 1)
|
|
{
|
|
playCountdownSecVal = 10;
|
|
StartCoroutine(NextStep(2, 3));
|
|
}
|
|
}
|
|
if (playPanel)
|
|
{
|
|
playPanel.SetActive(step == 2);
|
|
if (step == 2)
|
|
{
|
|
StartCoroutine(StatusCountdown());
|
|
ResetIncense();
|
|
}
|
|
else
|
|
{
|
|
gameActive = false;
|
|
}
|
|
}
|
|
if (stopPanel)
|
|
{
|
|
stopPanel.SetActive(step == 3);
|
|
if (step == 3)
|
|
{
|
|
if (ClientMessageHandler.Instance)
|
|
{
|
|
ClientMessageHandler.Instance.SendMessageToServer("gameSticksFinish", "");
|
|
}
|
|
StartCoroutine(NextStep(4, 3));
|
|
}
|
|
}
|
|
if (finishPanel)
|
|
{
|
|
finishPanel.SetActive(step == 4);
|
|
}
|
|
}
|
|
|
|
|
|
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
|
void Start()
|
|
{
|
|
if (finishGoToNextButton)
|
|
{
|
|
finishGoToNextButton.onClick.AddListener(finishGoToNextButton_onClicked);
|
|
}
|
|
if (finishBackToMenuButton)
|
|
{
|
|
finishBackToMenuButton.onClick.AddListener(finishBackToMenuButton_onClicked);
|
|
}
|
|
init();
|
|
|
|
}
|
|
private void finishGoToNextButton_onClicked()
|
|
{
|
|
|
|
if (ClientMessageHandler.Instance)
|
|
{
|
|
ClientMessageHandler.Instance.SendMessageToServer("getWords", "");
|
|
}
|
|
StartCoroutine(LoadNextScene("ClientGameBackToRealScene"));
|
|
}
|
|
|
|
private void finishBackToMenuButton_onClicked()
|
|
{
|
|
StartCoroutine(LoadNextScene("ClientGameScene"));
|
|
}
|
|
|
|
IEnumerator LoadNextScene(string sceneName)
|
|
{
|
|
yield return new WaitForSeconds(0f);
|
|
SceneManager.LoadScene(sceneName);
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
if (gameActive)
|
|
{
|
|
HandleInput();
|
|
}
|
|
}
|
|
|
|
void HandleInput()
|
|
{
|
|
// 滑鼠/觸控輸入 (使用新輸入系統)
|
|
if (Mouse.current != null && Mouse.current.leftButton.wasPressedThisFrame)
|
|
{
|
|
Vector2 pointerPosition = Mouse.current.position.ReadValue();
|
|
if (IsPointerOverIncense(pointerPosition))
|
|
{
|
|
StopGame();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (Mouse.current != null && Mouse.current.leftButton.isPressed && isDragging)
|
|
{
|
|
Vector2 pointerPosition = Mouse.current.position.ReadValue();
|
|
UpdateAngleFromPointer(pointerPosition);
|
|
}
|
|
|
|
if (Mouse.current != null && Mouse.current.leftButton.wasReleasedThisFrame)
|
|
{
|
|
isDragging = false;
|
|
}
|
|
|
|
// 觸控輸入支援
|
|
if (Touchscreen.current != null)
|
|
{
|
|
var touches = Touchscreen.current.touches;
|
|
|
|
for (int i = 0; i < touches.Count; i++)
|
|
{
|
|
var touch = touches[i];
|
|
|
|
if (!touch.isInProgress)
|
|
continue;
|
|
|
|
var phase = touch.phase.ReadValue();
|
|
var position = touch.position.ReadValue();
|
|
|
|
if (phase == UnityEngine.InputSystem.TouchPhase.Began)
|
|
{
|
|
if (IsPointerOverIncense(position))
|
|
{
|
|
StopGame();
|
|
return;
|
|
}
|
|
}
|
|
else if (phase == UnityEngine.InputSystem.TouchPhase.Moved && isDragging)
|
|
{
|
|
UpdateAngleFromPointer(position);
|
|
}
|
|
else if (phase == UnityEngine.InputSystem.TouchPhase.Ended ||
|
|
phase == UnityEngine.InputSystem.TouchPhase.Canceled)
|
|
{
|
|
isDragging = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool IsPointerOverIncense(Vector2 screenPosition)
|
|
{
|
|
Ray ray = mainCamera.ScreenPointToRay(screenPosition);
|
|
RaycastHit2D hit = Physics2D.Raycast(ray.origin, ray.direction);
|
|
|
|
if (hit.collider != null && hit.collider.transform == incenseTransform)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void UpdateAngleFromPointer(Vector2 screenPosition)
|
|
{
|
|
// 將螢幕座標轉換為世界座標
|
|
Vector3 worldPosition = mainCamera.ScreenToWorldPoint(screenPosition);
|
|
Vector3 holderPosition = incenseHolderTransform.position;
|
|
|
|
// 計算角度
|
|
Vector2 direction = new Vector2(worldPosition.x - holderPosition.x,
|
|
worldPosition.y - holderPosition.y);
|
|
|
|
float angle = Mathf.Atan2(direction.x, direction.y) * Mathf.Rad2Deg;
|
|
angle = 90f + angle;
|
|
|
|
// 限制角度範圍
|
|
angle = Mathf.Clamp(angle, minAngle, maxAngle);
|
|
|
|
UpdateDisplay(angle);
|
|
}
|
|
|
|
void UpdateDisplay(float angle)
|
|
{
|
|
currentAngle = angle;
|
|
|
|
// 更新香的旋轉 (從底部旋轉)
|
|
float rotationAngle = 90f - angle;
|
|
incenseTransform.localRotation = Quaternion.Euler(0, 0, rotationAngle);
|
|
|
|
// 更新角度顯示
|
|
//if (angleText != null)
|
|
//{
|
|
// angleText.text = $"{Mathf.Round(angle)}°";
|
|
//}
|
|
|
|
// 計算誠意指數
|
|
float sincerity = Mathf.Clamp01(angle / 90f) * 100f;
|
|
|
|
// 更新誠意條
|
|
if (sincerityMeterFill != null)
|
|
{
|
|
sincerityMeterFill.fillAmount = sincerity / 100f;
|
|
}
|
|
|
|
// 更新分數
|
|
//if (scoreText != null)
|
|
//{
|
|
// scoreText.text = $"{Mathf.Round(sincerity)}%";
|
|
//}
|
|
|
|
// 更新訊息
|
|
UpdateMessage(sincerity);
|
|
}
|
|
|
|
void UpdateMessage(float sincerity)
|
|
{
|
|
//if (messageText == null) return;
|
|
|
|
// 如果遊戲已停止,顯示特殊訊息
|
|
if (!gameActive)
|
|
{
|
|
//messageText.text = "🛑 遊戲已停止!點擊重置按鈕重新開始";
|
|
//messageText.color = new Color(1f, 0.5f, 0f);
|
|
return;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
// 公開方法供按鈕調用
|
|
public void ResetIncense()
|
|
{
|
|
if (windCoroutine != null)
|
|
{
|
|
StopCoroutine(windCoroutine);
|
|
windCoroutine = null;
|
|
}
|
|
gameActive = true;
|
|
isDragging = false;
|
|
UpdateDisplay(90f);
|
|
}
|
|
|
|
public void StopGame()
|
|
{
|
|
gameActive = false;
|
|
isDragging = false;
|
|
|
|
if (windCoroutine != null)
|
|
{
|
|
StopCoroutine(windCoroutine);
|
|
windCoroutine = null;
|
|
}
|
|
|
|
// 更新訊息顯示
|
|
//if (messageText != null)
|
|
//{
|
|
// messageText.text = "🛑 遊戲已停止!點擊重置按鈕重新開始";
|
|
// messageText.color = new Color(1f, 0.5f, 0f);
|
|
//}
|
|
|
|
Debug.Log("遊戲已停止 - 香被觸碰");
|
|
}
|
|
|
|
public void RandomChallenge()
|
|
{
|
|
if (windCoroutine != null)
|
|
{
|
|
StopCoroutine(windCoroutine);
|
|
windCoroutine = null;
|
|
}
|
|
float randomAngle = Random.Range(minAngle, maxAngle);
|
|
UpdateDisplay(randomAngle);
|
|
}
|
|
|
|
public void ToggleWindMode()
|
|
{
|
|
if (windCoroutine != null)
|
|
{
|
|
StopCoroutine(windCoroutine);
|
|
windCoroutine = null;
|
|
}
|
|
else
|
|
{
|
|
windCoroutine = StartCoroutine(WindModeCoroutine());
|
|
}
|
|
}
|
|
|
|
IEnumerator WindModeCoroutine()
|
|
{
|
|
while (true)
|
|
{
|
|
float windForce = Random.Range(-5f, 5f);
|
|
float newAngle = Mathf.Clamp(currentAngle + windForce, minAngle, maxAngle);
|
|
UpdateDisplay(newAngle);
|
|
|
|
yield return new WaitForSeconds(0.2f);
|
|
}
|
|
}
|
|
}
|