feat/teaser-prototype-playable-core (#1)

Co-authored-by: John Lamb <j.lamb13@gmail.com>
Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
2026-02-05 02:30:45 +00:00
parent b1b3e4d0b3
commit 0de174eb1a
21 changed files with 1780 additions and 14 deletions

View File

@@ -0,0 +1,187 @@
using UnityEngine;
using UnityEngine.InputSystem;
public class CameraController : MonoBehaviour
{
// Zoom settings
public float minZoom = 5f;
public float maxZoom = 25f;
public float zoomSpeed = 2f;
public float pinchZoomSpeed = 0.1f;
// Pan settings
public float panSpeed = 1f;
Camera cam;
Vector2 lastPanPosition;
bool isPanning;
float lastPinchDistance;
bool isPinching;
// Track if we started on a unit (don't pan if drawing route)
bool startedOnUnit;
void Start()
{
cam = Camera.main;
}
void Update()
{
HandleMouseInput();
HandleTouchInput();
ClampCameraPosition();
}
void HandleMouseInput()
{
var mouse = Mouse.current;
if (mouse == null) return;
// Scroll wheel zoom
float scroll = mouse.scroll.ReadValue().y;
if (Mathf.Abs(scroll) > 0.01f)
{
Zoom(-scroll * zoomSpeed * Time.deltaTime * 10f);
}
// Right-click pan (left-click is for route drawing)
if (mouse.rightButton.wasPressedThisFrame)
{
lastPanPosition = mouse.position.ReadValue();
isPanning = true;
}
else if (mouse.rightButton.wasReleasedThisFrame)
{
isPanning = false;
}
if (isPanning && mouse.rightButton.isPressed)
{
Vector2 currentPos = mouse.position.ReadValue();
Vector2 delta = currentPos - lastPanPosition;
Pan(-delta);
lastPanPosition = currentPos;
}
}
void HandleTouchInput()
{
var touch = Touchscreen.current;
if (touch == null) return;
int touchCount = 0;
foreach (var t in touch.touches)
{
if (t.press.isPressed) touchCount++;
}
if (touchCount == 2)
{
// Two finger pinch zoom and pan
var touch0 = touch.touches[0];
var touch1 = touch.touches[1];
Vector2 pos0 = touch0.position.ReadValue();
Vector2 pos1 = touch1.position.ReadValue();
float currentDistance = Vector2.Distance(pos0, pos1);
if (!isPinching)
{
isPinching = true;
lastPinchDistance = currentDistance;
lastPanPosition = (pos0 + pos1) / 2f;
}
else
{
// Pinch zoom
float deltaDistance = lastPinchDistance - currentDistance;
Zoom(deltaDistance * pinchZoomSpeed);
lastPinchDistance = currentDistance;
// Two-finger pan
Vector2 currentCenter = (pos0 + pos1) / 2f;
Vector2 delta = currentCenter - lastPanPosition;
Pan(-delta);
lastPanPosition = currentCenter;
}
isPanning = false; // Don't single-finger pan while pinching
}
else if (touchCount == 1)
{
isPinching = false;
var primaryTouch = touch.primaryTouch;
Vector2 touchPos = primaryTouch.position.ReadValue();
// Check if touch started on a unit
if (primaryTouch.press.wasPressedThisFrame)
{
Vector2 worldPos = cam.ScreenToWorldPoint(touchPos);
var hit = Physics2D.OverlapPoint(worldPos);
startedOnUnit = hit != null && hit.GetComponent<Unit>() != null;
if (!startedOnUnit)
{
lastPanPosition = touchPos;
isPanning = true;
}
}
else if (primaryTouch.press.wasReleasedThisFrame)
{
isPanning = false;
startedOnUnit = false;
}
// Single finger pan (only if not drawing route)
if (isPanning && !startedOnUnit && primaryTouch.press.isPressed)
{
Vector2 delta = touchPos - lastPanPosition;
Pan(-delta);
lastPanPosition = touchPos;
}
}
else
{
isPinching = false;
isPanning = false;
}
}
void Zoom(float delta)
{
float newSize = cam.orthographicSize + delta;
cam.orthographicSize = Mathf.Clamp(newSize, minZoom, maxZoom);
}
void Pan(Vector2 screenDelta)
{
// Convert screen delta to world delta
float worldUnitsPerPixel = cam.orthographicSize * 2f / Screen.height;
Vector3 worldDelta = new Vector3(
screenDelta.x * worldUnitsPerPixel * panSpeed,
screenDelta.y * worldUnitsPerPixel * panSpeed,
0
);
cam.transform.position += worldDelta;
}
void ClampCameraPosition()
{
// Keep camera within map bounds (with some padding for zoom)
float halfHeight = cam.orthographicSize;
float halfWidth = halfHeight * cam.aspect;
float minX = -Game.MapWidth / 2f + halfWidth;
float maxX = Game.MapWidth / 2f - halfWidth;
float minY = -Game.MapHeight / 2f + halfHeight;
float maxY = Game.MapHeight / 2f - halfHeight;
Vector3 pos = cam.transform.position;
pos.x = Mathf.Clamp(pos.x, minX, maxX);
pos.y = Mathf.Clamp(pos.y, minY, maxY);
cam.transform.position = pos;
}
}