Implement Bombs
This commit is contained in:
@@ -5,31 +5,105 @@ using UnityEngine;
|
||||
namespace Services {
|
||||
public class InputService : MonoBehaviour, IInputService
|
||||
{
|
||||
public event Action<Vector2> OnPointerDown;
|
||||
public event Action<Vector2> OnPointerUp;
|
||||
public event Action<Vector2Int, Vector2Int> OnSwapRequested;
|
||||
|
||||
private bool wasDown;
|
||||
private Camera inputCamera;
|
||||
private Vector2 pointerDownScreenPos;
|
||||
private bool isPointerDown;
|
||||
|
||||
private readonly Vector2 boardOrigin = Vector2.zero;
|
||||
private readonly float minDrag = 0.35f;
|
||||
private readonly float cellSize = 1f;
|
||||
|
||||
private void Awake() {
|
||||
this.inputCamera = Camera.main;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// Mouse
|
||||
var isDown = Input.GetMouseButton(0);
|
||||
if (!wasDown && isDown)
|
||||
OnPointerDown?.Invoke(Input.mousePosition);
|
||||
if (TryGetPrimaryPointerState(out var isDown, out var screenPos))
|
||||
{
|
||||
if (!this.isPointerDown && isDown) {
|
||||
pointerDownScreenPos = screenPos;
|
||||
}
|
||||
|
||||
if (wasDown && !isDown)
|
||||
OnPointerUp?.Invoke(Input.mousePosition);
|
||||
if (this.isPointerDown && !isDown) {
|
||||
TryEmitSwap(pointerDownScreenPos, screenPos);
|
||||
}
|
||||
|
||||
wasDown = isDown;
|
||||
this.isPointerDown = isDown;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No pointer available this frame (rare). Ensure we don't get stuck.
|
||||
this.isPointerDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Optional: Touch (if you want both, you can merge logic more carefully)
|
||||
if (Input.touchCount <= 0) return;
|
||||
private void TryEmitSwap(Vector2 downScreen, Vector2 upScreen)
|
||||
{
|
||||
if (this.inputCamera == null) return;
|
||||
|
||||
var t = Input.GetTouch(0);
|
||||
if (t.phase == TouchPhase.Began)
|
||||
OnPointerDown?.Invoke(t.position);
|
||||
else if (t.phase == TouchPhase.Ended || t.phase == TouchPhase.Canceled)
|
||||
OnPointerUp?.Invoke(t.position);
|
||||
Vector2 downWorld = this.inputCamera.ScreenToWorldPoint(downScreen);
|
||||
Vector2 upWorld = this.inputCamera.ScreenToWorldPoint(upScreen);
|
||||
Vector2 dragWorld = upWorld - downWorld;
|
||||
|
||||
if (dragWorld.magnitude < this.minDrag)
|
||||
return;
|
||||
|
||||
Vector2Int fromCell = WorldToCell(downWorld);
|
||||
Vector2Int dir = DragToCardinalDirection(dragWorld);
|
||||
Vector2Int toCell = fromCell + dir;
|
||||
|
||||
// Adjacency is guaranteed by construction (to = from + dir).
|
||||
// Debug.Log($"Swap {fromCell} -> {toCell}");
|
||||
OnSwapRequested?.Invoke(fromCell, toCell);
|
||||
}
|
||||
|
||||
private Vector2Int WorldToCell(Vector2 worldPos)
|
||||
{
|
||||
// Convert to board-local coords first
|
||||
Vector2 local = (worldPos - this.boardOrigin) / this.cellSize;
|
||||
|
||||
// Assumes cell centers lie on integer coordinates in local space
|
||||
int x = Mathf.FloorToInt(local.x + 0.5f);
|
||||
int y = Mathf.FloorToInt(local.y + 0.5f);
|
||||
|
||||
return new Vector2Int(x, y);
|
||||
}
|
||||
|
||||
private static Vector2Int DragToCardinalDirection(Vector2 dragWorld)
|
||||
{
|
||||
if (Mathf.Abs(dragWorld.x) >= Mathf.Abs(dragWorld.y))
|
||||
return dragWorld.x >= 0 ? Vector2Int.right : Vector2Int.left;
|
||||
|
||||
return dragWorld.y >= 0 ? Vector2Int.up : Vector2Int.down;
|
||||
}
|
||||
|
||||
private static bool TryGetPrimaryPointerState(out bool isDown, out Vector2 screenPosition)
|
||||
{
|
||||
// Prefer touch when present (mobile)
|
||||
if (Input.touchCount > 0)
|
||||
{
|
||||
Touch touch = Input.GetTouch(0);
|
||||
screenPosition = touch.position;
|
||||
|
||||
// Treat "Moved/Stationary" as still down, and "Began" as down.
|
||||
isDown = touch.phase == TouchPhase.Began
|
||||
|| touch.phase == TouchPhase.Moved
|
||||
|| touch.phase == TouchPhase.Stationary;
|
||||
|
||||
// Ended/Canceled => not down (we still report position)
|
||||
if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)
|
||||
isDown = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fallback to mouse (editor/desktop)
|
||||
screenPosition = Input.mousePosition;
|
||||
isDown = Input.GetMouseButton(0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user