Replace continuous free-form movement with discrete 20x50 grid-based gameplay featuring asymmetric movement mechanics: - Blue/Red teams with 3 units each - Zone-based movement: orthogonal (4 dir) in offense, diagonal (8 dir) in defense - Alternating turns with click-to-select, click-to-move input - Fog of war: 3-cell Chebyshev vision radius per unit - Defense speed nerf: skip every 4th move in own zone - AI opponent that chases flag carriers and advances toward enemy flag - Collision resolution: defender wins in their zone, lower ID wins in neutral Implements all 3 phases from the plan: - Phase 1: Playable grid with hot-seat two-player - Phase 2: Fog of war + defense speed nerf - Phase 3: AI opponent Deleted obsolete files: Flag.cs, Unit.cs, RouteDrawer.cs, SimpleAI.cs, Visibility.cs Co-Authored-By: Claude <noreply@anthropic.com>
148 lines
5.2 KiB
C#
148 lines
5.2 KiB
C#
using UnityEngine;
|
|
using TMPro;
|
|
|
|
public class Game : MonoBehaviour
|
|
{
|
|
// Auto-bootstrap when game starts - no Editor setup needed
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
|
static void Bootstrap()
|
|
{
|
|
if (Instance != null) return;
|
|
|
|
var gameGO = new GameObject("Game");
|
|
gameGO.AddComponent<Game>();
|
|
}
|
|
|
|
// ===========================================
|
|
// CONFIGURATION
|
|
// ===========================================
|
|
|
|
// Camera settings for grid view
|
|
public const float CameraZoom = 28f; // Fits 20x50 grid
|
|
public const float CameraMinZoom = 15f;
|
|
public const float CameraMaxZoom = 35f;
|
|
|
|
// References
|
|
public static Game Instance { get; private set; }
|
|
|
|
GridBoard gridBoard;
|
|
TextMeshProUGUI scoreText;
|
|
TextMeshProUGUI gameOverText;
|
|
TextMeshProUGUI turnText;
|
|
|
|
void Awake()
|
|
{
|
|
Instance = this;
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
SetupCamera();
|
|
CreateUI();
|
|
CreateGridBoard();
|
|
}
|
|
|
|
void SetupCamera()
|
|
{
|
|
var cam = Camera.main;
|
|
if (cam != null)
|
|
{
|
|
cam.orthographic = true;
|
|
cam.orthographicSize = CameraZoom;
|
|
cam.transform.position = new Vector3(0, 0, -10);
|
|
cam.backgroundColor = new Color(0.1f, 0.1f, 0.15f);
|
|
|
|
// Add camera controller for zoom/pan
|
|
var controller = cam.gameObject.AddComponent<CameraController>();
|
|
controller.minZoom = CameraMinZoom;
|
|
controller.maxZoom = CameraMaxZoom;
|
|
}
|
|
}
|
|
|
|
void CreateUI()
|
|
{
|
|
// Create Canvas
|
|
var canvasGO = new GameObject("Canvas");
|
|
var canvas = canvasGO.AddComponent<Canvas>();
|
|
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
|
canvasGO.AddComponent<UnityEngine.UI.CanvasScaler>();
|
|
canvasGO.AddComponent<UnityEngine.UI.GraphicRaycaster>();
|
|
|
|
// Score text (top center)
|
|
var scoreGO = new GameObject("ScoreText");
|
|
scoreGO.transform.SetParent(canvasGO.transform, false);
|
|
scoreText = scoreGO.AddComponent<TextMeshProUGUI>();
|
|
scoreText.text = "0 - 0";
|
|
scoreText.fontSize = 48;
|
|
scoreText.alignment = TextAlignmentOptions.Center;
|
|
scoreText.color = Color.white;
|
|
|
|
var scoreRect = scoreGO.GetComponent<RectTransform>();
|
|
scoreRect.anchorMin = new Vector2(0.5f, 1f);
|
|
scoreRect.anchorMax = new Vector2(0.5f, 1f);
|
|
scoreRect.pivot = new Vector2(0.5f, 1f);
|
|
scoreRect.anchoredPosition = new Vector2(0, -20);
|
|
scoreRect.sizeDelta = new Vector2(200, 60);
|
|
|
|
// Turn indicator (below score)
|
|
var turnGO = new GameObject("TurnText");
|
|
turnGO.transform.SetParent(canvasGO.transform, false);
|
|
turnText = turnGO.AddComponent<TextMeshProUGUI>();
|
|
turnText.text = "BLUE'S TURN";
|
|
turnText.fontSize = 32;
|
|
turnText.alignment = TextAlignmentOptions.Center;
|
|
turnText.color = Color.blue;
|
|
|
|
var turnRect = turnGO.GetComponent<RectTransform>();
|
|
turnRect.anchorMin = new Vector2(0.5f, 1f);
|
|
turnRect.anchorMax = new Vector2(0.5f, 1f);
|
|
turnRect.pivot = new Vector2(0.5f, 1f);
|
|
turnRect.anchoredPosition = new Vector2(0, -80);
|
|
turnRect.sizeDelta = new Vector2(300, 50);
|
|
|
|
// Instructions (bottom)
|
|
var instructionsGO = new GameObject("InstructionsText");
|
|
instructionsGO.transform.SetParent(canvasGO.transform, false);
|
|
var instructionsText = instructionsGO.AddComponent<TextMeshProUGUI>();
|
|
instructionsText.text = "Click unit to select, then click destination to move";
|
|
instructionsText.fontSize = 20;
|
|
instructionsText.alignment = TextAlignmentOptions.Center;
|
|
instructionsText.color = new Color(0.7f, 0.7f, 0.7f);
|
|
|
|
var instrRect = instructionsGO.GetComponent<RectTransform>();
|
|
instrRect.anchorMin = new Vector2(0.5f, 0f);
|
|
instrRect.anchorMax = new Vector2(0.5f, 0f);
|
|
instrRect.pivot = new Vector2(0.5f, 0f);
|
|
instrRect.anchoredPosition = new Vector2(0, 20);
|
|
instrRect.sizeDelta = new Vector2(500, 40);
|
|
|
|
// Game over text (hidden initially)
|
|
var gameOverGO = new GameObject("GameOverText");
|
|
gameOverGO.transform.SetParent(canvasGO.transform, false);
|
|
gameOverText = gameOverGO.AddComponent<TextMeshProUGUI>();
|
|
gameOverText.text = "";
|
|
gameOverText.fontSize = 72;
|
|
gameOverText.alignment = TextAlignmentOptions.Center;
|
|
gameOverText.color = Color.white;
|
|
gameOverText.gameObject.SetActive(false);
|
|
|
|
var gameOverRect = gameOverGO.GetComponent<RectTransform>();
|
|
gameOverRect.anchorMin = new Vector2(0.5f, 0.5f);
|
|
gameOverRect.anchorMax = new Vector2(0.5f, 0.5f);
|
|
gameOverRect.pivot = new Vector2(0.5f, 0.5f);
|
|
gameOverRect.anchoredPosition = Vector2.zero;
|
|
gameOverRect.sizeDelta = new Vector2(400, 100);
|
|
}
|
|
|
|
void CreateGridBoard()
|
|
{
|
|
var boardGO = new GameObject("GridBoard");
|
|
gridBoard = boardGO.AddComponent<GridBoard>();
|
|
|
|
// Pass UI references
|
|
gridBoard.scoreText = scoreText;
|
|
gridBoard.gameOverText = gameOverText;
|
|
gridBoard.turnText = turnText;
|
|
}
|
|
}
|