1 line
9.0 KiB
C#
1 line
9.0 KiB
C#
using Gameplay;
|
|
using System;
|
|
using Gameplay.Skill;
|
|
using UnityEngine;
|
|
|
|
|
|
[ExecuteAlways]
|
|
public class CameraController : MonoBehaviour
|
|
{
|
|
public float leftMargin = 1.5f;
|
|
|
|
public float rightMargin = 1.5f;
|
|
|
|
public float topMargin = 0.9f;
|
|
|
|
public float bottomMargin = 0.9f;
|
|
|
|
public float moveSpeedX = 0.19f;
|
|
|
|
public float moveSpeedY = 0.3f;
|
|
|
|
public float unitPerPixel = 0.01f;
|
|
|
|
public int CameraMinSize = 6;
|
|
|
|
public int CameraMaxSize = 12;
|
|
|
|
private const int CameraStartY = 25;
|
|
|
|
private Vector3 cameraStartRotation = new Vector3(37.5f, -10f, 0f);
|
|
|
|
private Vector3 cameraDefaultRotation = new Vector3(90, 0, 0);
|
|
|
|
public const int CameraStartSize = 12;
|
|
|
|
private const float NearClipPlane = 0.03f;
|
|
|
|
private const float FarClipPlane = 60;
|
|
|
|
private const bool IsOrthographic = true;
|
|
|
|
private Camera mainCamera;
|
|
|
|
private bool isIgnoreZoomLimit;
|
|
|
|
public Map Map
|
|
{
|
|
get => map;
|
|
set { map = value; }
|
|
}
|
|
|
|
private Map map;
|
|
|
|
private void Awake()
|
|
{
|
|
mainCamera = GetComponent<Camera>();
|
|
|
|
mainCamera.transform.SetPositionAndRotation(new Vector3(0, CameraStartY, 0),
|
|
Quaternion.Euler(cameraStartRotation));
|
|
|
|
mainCamera.orthographic = IsOrthographic;
|
|
|
|
mainCamera.orthographicSize = CameraStartSize;
|
|
|
|
mainCamera.nearClipPlane = NearClipPlane;
|
|
|
|
mainCamera.farClipPlane = FarClipPlane;
|
|
|
|
AdjustSelf();
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
if (Application.isPlaying)
|
|
{
|
|
InputManager.Instance.OnFingerMove += OnFingerMove2;
|
|
InputManager.Instance.OnFingersMove += OnFingersMove;
|
|
}
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
if (Application.isPlaying)
|
|
{
|
|
InputManager.Instance.OnFingerMove -= OnFingerMove2;
|
|
InputManager.Instance.OnFingersMove -= OnFingersMove;
|
|
}
|
|
}
|
|
|
|
private void OnFingerMove2(Vector2 delta)
|
|
{
|
|
// if (SkillManager.instance != null && SkillManager.instance.needSkillPaused) return;
|
|
var touchDeltaPosition = -delta;
|
|
var ratio = mainCamera.orthographicSize * unitPerPixel;
|
|
var cameraMove = new Vector2(touchDeltaPosition.x * moveSpeedX * ratio,
|
|
touchDeltaPosition.y * moveSpeedY * ratio);
|
|
|
|
var cameraTransform = transform;
|
|
var moveY = cameraTransform.up;
|
|
moveY.y = 0;
|
|
moveY = moveY.normalized * cameraMove.y;
|
|
|
|
var moveX = cameraTransform.right;
|
|
moveX.y = 0;
|
|
moveX = moveX.normalized * cameraMove.x;
|
|
|
|
transform.Translate(moveX + moveY, Space.World);
|
|
AdjustSelf();
|
|
}
|
|
|
|
private void OnFingersMove(float delta)
|
|
{
|
|
// if (SkillManager.instance != null && SkillManager.instance.needSkillPaused) return;
|
|
if (delta < 0)
|
|
{
|
|
var endPosition = AdjustPosition(mainCamera.orthographicSize + 1, out var canZoom);
|
|
if ((canZoom && mainCamera.orthographicSize < CameraMaxSize) || isIgnoreZoomLimit)
|
|
{
|
|
mainCamera.orthographicSize++;
|
|
mainCamera.transform.position = endPosition;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (mainCamera.orthographicSize > CameraMinSize)
|
|
{
|
|
mainCamera.orthographicSize--;
|
|
}
|
|
}
|
|
}
|
|
|
|
Vector3 CalculateHitHorizontalPosition(Vector3 startPosition, Vector3 dir, float y)
|
|
{
|
|
if (dir.y == 0)
|
|
return Vector3.zero;
|
|
|
|
var p1 = startPosition; // 直线上一点
|
|
var v = dir; // 直线的方向向量
|
|
float x, z;
|
|
|
|
// 已知直线上一点 p1(x1, y1, z1) 和 直线的方向向量 v(m, n, p)
|
|
// 根据点向式
|
|
// (x - x1) / m = (y - y1) / n = (z - z1) / p
|
|
// 有:
|
|
// (x - p1.x) / v.x = (y - p1.y) / v.y = (z - p1.z) / v.z
|
|
// 有:
|
|
// x = p1.x + v.x * (y - p1.y) / v.y
|
|
// z = p1.z + v.z * (y - p1.y) / v.y
|
|
// 与平面 y = y 的交点坐标为
|
|
|
|
x = p1.x + v.x * (y - p1.y) / v.y;
|
|
z = p1.z + v.z * (y - p1.y) / v.y;
|
|
return new Vector3(x, y, z);
|
|
}
|
|
|
|
public void InitializeCameraPosition(Vector2Int targetPosition)
|
|
{
|
|
var cellPos = map.BlockPosition2WorldPosition(targetPosition);
|
|
mainCamera.transform.SetPositionAndRotation(
|
|
CalculateCell2CameraPosition(cellPos), Quaternion.Euler(cameraStartRotation));
|
|
AdjustSelf();
|
|
}
|
|
|
|
private Vector3 CalculateCell2CameraPosition(Vector3 targetPosition)
|
|
{
|
|
var cameraTransform = mainCamera.transform;
|
|
var startPosition = cameraTransform.position;
|
|
var v = cameraTransform.forward;
|
|
|
|
float x, z;
|
|
z = targetPosition.z - v.z * (targetPosition.y - startPosition.y) / v.y;
|
|
x = targetPosition.x - v.x * (targetPosition.y - startPosition.y) / v.y;
|
|
|
|
return new Vector3(x, startPosition.y, z);
|
|
}
|
|
|
|
public void AdjustSelf()
|
|
{
|
|
mainCamera.transform.position = AdjustPosition(mainCamera.orthographicSize, out var canZoom);
|
|
}
|
|
|
|
private Vector3 AdjustPosition(float size, out bool canZoom)
|
|
{
|
|
var position = transform.position;
|
|
if (map?.TerrainGridSystem == null)
|
|
{
|
|
canZoom = false;
|
|
return position;
|
|
}
|
|
|
|
var center = CalculateHitHorizontalPosition(position, transform.forward, 0);
|
|
var left = center.x - leftMargin * size;
|
|
var right = center.x + rightMargin * size;
|
|
var top = center.z + topMargin * size;
|
|
var bottom = center.z - bottomMargin * size;
|
|
var mapBounds = map.TerrainGridSystem.bounds;
|
|
|
|
if (right - left < mapBounds.max.x - mapBounds.min.x)
|
|
{
|
|
if (left < mapBounds.min.x)
|
|
{
|
|
center.x = mapBounds.min.x + leftMargin * size;
|
|
canZoom = false;
|
|
//DebugUtil.LogG($"left < mapBounds.min.x, {left} < {mapBounds.min.x}");
|
|
}
|
|
else if (right > mapBounds.max.x)
|
|
{
|
|
center.x = mapBounds.max.x - rightMargin * size;
|
|
//DebugUtil.LogG($"right > mapBounds.max.x, {right} > {mapBounds.max.x}");
|
|
canZoom = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
center.x = mapBounds.center.x;
|
|
canZoom = false;
|
|
}
|
|
|
|
if (top - bottom < mapBounds.max.z - mapBounds.min.z)
|
|
{
|
|
if (bottom < mapBounds.min.z)
|
|
{
|
|
center.z = mapBounds.min.z + bottomMargin * size;
|
|
//DebugUtil.LogG($"bottom < mapBounds.min.x, {bottom} < {mapBounds.min.x}");
|
|
canZoom = false;
|
|
}
|
|
else if (top > mapBounds.max.z)
|
|
{
|
|
center.z = mapBounds.max.z - topMargin * size;
|
|
//DebugUtil.LogG($"top > mapBounds.max.x, {top} > {mapBounds.max.x}");
|
|
canZoom = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
center.z = mapBounds.center.z;
|
|
canZoom = false;
|
|
}
|
|
|
|
position = CalculateHitHorizontalPosition(center, transform.forward, position.y);
|
|
canZoom = true;
|
|
return position;
|
|
}
|
|
|
|
public void SwitchCameraView(bool isGameView)
|
|
{
|
|
if (!isGameView)
|
|
{
|
|
isIgnoreZoomLimit = true;
|
|
mainCamera.transform.SetPositionAndRotation(new Vector3(0, CameraStartY, 0),
|
|
Quaternion.Euler(cameraDefaultRotation));
|
|
}
|
|
else
|
|
{
|
|
isIgnoreZoomLimit = false;
|
|
mainCamera.transform.SetPositionAndRotation(new Vector3(0, CameraStartY, 0),
|
|
Quaternion.Euler(cameraStartRotation));
|
|
}
|
|
mainCamera.orthographicSize = CameraMaxSize;
|
|
mainCamera.nearClipPlane = NearClipPlane;
|
|
mainCamera.farClipPlane = FarClipPlane;
|
|
|
|
AdjustSelf();
|
|
}
|
|
|
|
private void OnDrawGizmos()
|
|
{
|
|
if (map != null && mainCamera != null)
|
|
{
|
|
Gizmos.color = Color.red;
|
|
var cameraTransform = transform;
|
|
var position = cameraTransform.position;
|
|
var size = mainCamera.orthographicSize;
|
|
var center = CalculateHitHorizontalPosition(position, cameraTransform.forward, 0);
|
|
var left = center.x - leftMargin * size;
|
|
var right = center.x + rightMargin * size;
|
|
var top = center.z + topMargin * size;
|
|
var bottom = center.z - bottomMargin * size;
|
|
|
|
Gizmos.DrawLineList(new ReadOnlySpan<Vector3>(new[]
|
|
{
|
|
new Vector3(left, 0.5f, top), new Vector3(left, 0.5f, bottom),
|
|
new Vector3(left, 0.5f, bottom), new Vector3(right, 0.5f, bottom),
|
|
new Vector3(right, 0.5f, bottom), new Vector3(right, 0.5f, top),
|
|
new Vector3(right, 0.5f, top), new Vector3(left, 0.5f, top),
|
|
}
|
|
)
|
|
);
|
|
|
|
var mapBounds = map.TerrainGridSystem.bounds;
|
|
Gizmos.DrawWireCube(mapBounds.center, mapBounds.size);
|
|
}
|
|
}
|
|
} |