feat/teaser-prototype-playable-core #1
187
Backyard CTF/Assets/Scripts/CameraController.cs
Normal file
187
Backyard CTF/Assets/Scripts/CameraController.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Backyard CTF/Assets/Scripts/Flag.cs.meta
Normal file
2
Backyard CTF/Assets/Scripts/Flag.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 95e5070ee05d6462bbee9fa1ca4917d9
|
||||||
@@ -24,9 +24,10 @@ public class Game : MonoBehaviour
|
|||||||
public const float UnitSpeed = 5f;
|
public const float UnitSpeed = 5f;
|
||||||
public const float UnitSize = 1f;
|
public const float UnitSize = 1f;
|
||||||
public const float UnitColliderRadius = 0.5f;
|
public const float UnitColliderRadius = 0.5f;
|
||||||
|
public const float MinGapSize = 2f; // Minimum gap between obstacles
|
||||||
|
|
||||||
// Vision & Detection
|
// Vision & Detection
|
||||||
public const float VisionRadius = 4f;
|
public const float VisionRadius = 6f;
|
||||||
public const float TagRadius = 0.75f;
|
public const float TagRadius = 0.75f;
|
||||||
public const float FlagPickupRadius = 0.75f;
|
public const float FlagPickupRadius = 0.75f;
|
||||||
|
|
||||||
@@ -37,17 +38,24 @@ public class Game : MonoBehaviour
|
|||||||
// Scoring
|
// Scoring
|
||||||
public const int WinScore = 3;
|
public const int WinScore = 3;
|
||||||
|
|
||||||
// Map - 19:9 aspect ratio for smartphone (landscape)
|
// Map - Large neighborhood (19:9 landscape, requires zoom)
|
||||||
public const float MapWidth = 38f;
|
public const float MapWidth = 80f;
|
||||||
public const float MapHeight = 18f;
|
public const float MapHeight = 40f;
|
||||||
|
|
||||||
|
// Camera
|
||||||
|
public const float CameraMinZoom = 8f;
|
||||||
|
public const float CameraMaxZoom = 22f;
|
||||||
|
public const float CameraStartZoom = 15f;
|
||||||
|
|
||||||
// Bases
|
// Bases
|
||||||
public const float BaseSize = 5f;
|
public const float BaseSize = 6f;
|
||||||
public const float BaseInset = 4f; // Distance from map edge
|
public const float BaseInset = 6f;
|
||||||
|
|
||||||
// Houses
|
// Neighborhood layout
|
||||||
public const float HouseMinSize = 2f;
|
public const float StreetWidth = 4f;
|
||||||
public const float HouseMaxSize = 4f;
|
public const float HouseWidth = 5f;
|
||||||
|
public const float HouseDepth = 4f;
|
||||||
|
public const float YardDepth = 3f;
|
||||||
|
|
||||||
// References set during setup
|
// References set during setup
|
||||||
public static Game Instance { get; private set; }
|
public static Game Instance { get; private set; }
|
||||||
@@ -73,6 +81,9 @@ public class Game : MonoBehaviour
|
|||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
|
// Seed random for consistent neighborhood layout
|
||||||
|
Random.InitState(42);
|
||||||
|
|
||||||
SetupCamera();
|
SetupCamera();
|
||||||
CreateGround();
|
CreateGround();
|
||||||
CreateObstacles();
|
CreateObstacles();
|
||||||
@@ -89,101 +100,163 @@ public class Game : MonoBehaviour
|
|||||||
if (cam != null)
|
if (cam != null)
|
||||||
{
|
{
|
||||||
cam.orthographic = true;
|
cam.orthographic = true;
|
||||||
cam.orthographicSize = MapHeight / 2f + 2f;
|
cam.orthographicSize = CameraStartZoom;
|
||||||
cam.transform.position = new Vector3(0, 0, -10);
|
cam.transform.position = new Vector3(0, 0, -10);
|
||||||
|
|
||||||
|
// Add camera controller for zoom/pan
|
||||||
|
var controller = cam.gameObject.AddComponent<CameraController>();
|
||||||
|
controller.minZoom = CameraMinZoom;
|
||||||
|
controller.maxZoom = CameraMaxZoom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateGround()
|
void CreateGround()
|
||||||
{
|
{
|
||||||
var ground = CreateSprite("Ground", new Color(0.2f, 0.4f, 0.2f), MapWidth, MapHeight);
|
// Grass background
|
||||||
|
var ground = CreateSprite("Ground", new Color(0.2f, 0.35f, 0.15f), MapWidth, MapHeight);
|
||||||
ground.transform.position = Vector3.zero;
|
ground.transform.position = Vector3.zero;
|
||||||
var sr = ground.GetComponent<SpriteRenderer>();
|
var sr = ground.GetComponent<SpriteRenderer>();
|
||||||
sr.sortingOrder = -10;
|
sr.sortingOrder = -10;
|
||||||
|
|
||||||
|
// Create streets (darker gray paths)
|
||||||
|
Color streetColor = new Color(0.3f, 0.3f, 0.32f);
|
||||||
|
|
||||||
|
// Main horizontal street (center)
|
||||||
|
var mainStreet = CreateSprite("MainStreet", streetColor, MapWidth - 20f, StreetWidth);
|
||||||
|
mainStreet.transform.position = new Vector3(0, 0, 0);
|
||||||
|
mainStreet.GetComponent<SpriteRenderer>().sortingOrder = -9;
|
||||||
|
|
||||||
|
// Upper horizontal street
|
||||||
|
var upperStreet = CreateSprite("UpperStreet", streetColor, MapWidth - 30f, StreetWidth);
|
||||||
|
upperStreet.transform.position = new Vector3(0, 10f, 0);
|
||||||
|
upperStreet.GetComponent<SpriteRenderer>().sortingOrder = -9;
|
||||||
|
|
||||||
|
// Lower horizontal street
|
||||||
|
var lowerStreet = CreateSprite("LowerStreet", streetColor, MapWidth - 30f, StreetWidth);
|
||||||
|
lowerStreet.transform.position = new Vector3(0, -10f, 0);
|
||||||
|
lowerStreet.GetComponent<SpriteRenderer>().sortingOrder = -9;
|
||||||
|
|
||||||
|
// Vertical cross streets
|
||||||
|
float[] crossStreetX = { -20f, -8f, 8f, 20f };
|
||||||
|
int streetIndex = 0;
|
||||||
|
foreach (float x in crossStreetX)
|
||||||
|
{
|
||||||
|
var crossStreet = CreateSprite($"CrossStreet_{streetIndex++}", streetColor, StreetWidth, MapHeight - 10f);
|
||||||
|
crossStreet.transform.position = new Vector3(x, 0, 0);
|
||||||
|
crossStreet.GetComponent<SpriteRenderer>().sortingOrder = -9;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateObstacles()
|
void CreateObstacles()
|
||||||
{
|
{
|
||||||
// Dense house layout for landscape 38x18 map
|
// Create realistic neighborhood layout for 80x40 map
|
||||||
// Bases on left/right, houses create horizontal lanes with cross-routes
|
// Pattern: horizontal streets with house rows, vertical cross-streets
|
||||||
|
// All gaps minimum 2.5 units for unit passage
|
||||||
|
|
||||||
Vector2[] housePositions = {
|
var obstacles = new List<(Vector2 pos, Vector2 size, Color color)>();
|
||||||
// Left section (near player base) - create 3 exit lanes
|
|
||||||
new(-14f, 5f),
|
|
||||||
new(-12f, -4f),
|
|
||||||
new(-10f, 0f),
|
|
||||||
|
|
||||||
// Left-mid section - force route decisions
|
// Street grid creates the main routes
|
||||||
new(-6f, 6f),
|
// Houses line the streets with backyards creating sneaky routes
|
||||||
new(-4f, 2f),
|
|
||||||
new(-7f, -3f),
|
|
||||||
new(-3f, -5f),
|
|
||||||
|
|
||||||
// Center section - dense, creates cat-and-mouse area
|
// === ROW 1 (Top) - y around 12-16 ===
|
||||||
new(2f, 5f),
|
CreateHouseRow(obstacles, y: 14f, xStart: -32f, xEnd: 32f, houseWidth: 5f, gapWidth: 3f, yardSide: -1);
|
||||||
new(0f, 1f),
|
|
||||||
new(-2f, -2f),
|
|
||||||
new(3f, -4f),
|
|
||||||
new(-1f, -6f),
|
|
||||||
new(1f, 6f),
|
|
||||||
|
|
||||||
// Right-mid section - mirror complexity
|
// === ROW 2 (Upper-mid) - y around 4-8 ===
|
||||||
new(6f, 5f),
|
CreateHouseRow(obstacles, y: 6f, xStart: -28f, xEnd: 28f, houseWidth: 6f, gapWidth: 3.5f, yardSide: 1);
|
||||||
new(4f, -2f),
|
|
||||||
new(7f, -5f),
|
|
||||||
new(5f, 2f),
|
|
||||||
|
|
||||||
// Right section (near enemy base) - create 3 approach lanes
|
// === ROW 3 (Center) - y around -2 to 2 ===
|
||||||
new(14f, 4f),
|
// Staggered houses creating interesting chokepoints
|
||||||
new(12f, -3f),
|
CreateHouseRow(obstacles, y: -1f, xStart: -25f, xEnd: 25f, houseWidth: 5f, gapWidth: 4f, yardSide: -1);
|
||||||
new(10f, 0f),
|
|
||||||
};
|
|
||||||
|
|
||||||
Vector2[] houseSizes = {
|
// === ROW 4 (Lower-mid) - y around -8 to -4 ===
|
||||||
// Left section
|
CreateHouseRow(obstacles, y: -8f, xStart: -28f, xEnd: 28f, houseWidth: 6f, gapWidth: 3.5f, yardSide: 1);
|
||||||
new(2.5f, 3f),
|
|
||||||
new(3f, 2.5f),
|
|
||||||
new(2f, 2f),
|
|
||||||
|
|
||||||
// Left-mid
|
// === ROW 5 (Bottom) - y around -12 to -16 ===
|
||||||
new(3f, 2.5f),
|
CreateHouseRow(obstacles, y: -14f, xStart: -32f, xEnd: 32f, houseWidth: 5f, gapWidth: 3f, yardSide: 1);
|
||||||
new(2f, 3f),
|
|
||||||
new(2.5f, 2f),
|
|
||||||
new(2.5f, 2.5f),
|
|
||||||
|
|
||||||
// Center - varied sizes for interesting gaps
|
// === Add some fences/hedges in backyards for extra cover ===
|
||||||
new(2f, 3f),
|
// These create the sneaky backyard routes
|
||||||
new(3f, 2f),
|
AddBackyardObstacles(obstacles);
|
||||||
new(2f, 2.5f),
|
|
||||||
new(2.5f, 2f),
|
|
||||||
new(2f, 2f),
|
|
||||||
new(2.5f, 2.5f),
|
|
||||||
|
|
||||||
// Right-mid
|
// Create all obstacles
|
||||||
new(2.5f, 2.5f),
|
int houseIndex = 0;
|
||||||
new(3f, 2f),
|
foreach (var (pos, size, color) in obstacles)
|
||||||
new(2.5f, 3f),
|
|
||||||
new(2f, 2f),
|
|
||||||
|
|
||||||
// Right section
|
|
||||||
new(3f, 2.5f),
|
|
||||||
new(2f, 3f),
|
|
||||||
new(2.5f, 2f),
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int i = 0; i < housePositions.Length; i++)
|
|
||||||
{
|
{
|
||||||
var house = CreateSprite($"House_{i}", new Color(0.35f, 0.35f, 0.4f), houseSizes[i].x, houseSizes[i].y);
|
var house = CreateSprite($"House_{houseIndex++}", color, size.x, size.y);
|
||||||
house.transform.position = new Vector3(housePositions[i].x, housePositions[i].y, 0);
|
house.transform.position = new Vector3(pos.x, pos.y, 0);
|
||||||
|
|
||||||
var collider = house.AddComponent<BoxCollider2D>();
|
var collider = house.AddComponent<BoxCollider2D>();
|
||||||
collider.size = Vector2.one; // Local space - scale handles actual size
|
collider.size = Vector2.one;
|
||||||
|
|
||||||
var sr = house.GetComponent<SpriteRenderer>();
|
var sr = house.GetComponent<SpriteRenderer>();
|
||||||
sr.sortingOrder = -5;
|
sr.sortingOrder = -5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CreateHouseRow(List<(Vector2, Vector2, Color)> obstacles, float y, float xStart, float xEnd,
|
||||||
|
float houseWidth, float gapWidth, int yardSide)
|
||||||
|
{
|
||||||
|
Color houseColor = new Color(0.4f, 0.35f, 0.3f); // Brown-ish houses
|
||||||
|
float houseDepth = 4f;
|
||||||
|
float x = xStart;
|
||||||
|
|
||||||
|
while (x < xEnd - houseWidth)
|
||||||
|
{
|
||||||
|
// Vary house sizes slightly for visual interest
|
||||||
|
float w = houseWidth + Random.Range(-0.5f, 0.5f);
|
||||||
|
float h = houseDepth + Random.Range(-0.3f, 0.3f);
|
||||||
|
|
||||||
|
// Skip houses near bases (leave clear zones)
|
||||||
|
if (Mathf.Abs(x) > 12f || Mathf.Abs(y) < 10f)
|
||||||
|
{
|
||||||
|
obstacles.Add((new Vector2(x + w / 2f, y), new Vector2(w, h), houseColor));
|
||||||
|
}
|
||||||
|
|
||||||
|
x += w + gapWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddBackyardObstacles(List<(Vector2, Vector2, Color)> obstacles)
|
||||||
|
{
|
||||||
|
Color fenceColor = new Color(0.5f, 0.4f, 0.3f); // Fence brown
|
||||||
|
Color hedgeColor = new Color(0.15f, 0.35f, 0.15f); // Hedge green
|
||||||
|
|
||||||
|
// Fences between yards (vertical) - create backyard maze
|
||||||
|
float[] fenceXPositions = { -22f, -14f, -6f, 6f, 14f, 22f };
|
||||||
|
foreach (float fx in fenceXPositions)
|
||||||
|
{
|
||||||
|
// Upper backyard fences
|
||||||
|
if (Random.value > 0.3f)
|
||||||
|
obstacles.Add((new Vector2(fx, 10f), new Vector2(0.5f, 3f), fenceColor));
|
||||||
|
// Lower backyard fences
|
||||||
|
if (Random.value > 0.3f)
|
||||||
|
obstacles.Add((new Vector2(fx, -10f), new Vector2(0.5f, 3f), fenceColor));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hedges along some property lines (horizontal)
|
||||||
|
float[] hedgeYPositions = { 10f, 2.5f, -4f, -11f };
|
||||||
|
foreach (float hy in hedgeYPositions)
|
||||||
|
{
|
||||||
|
float hx = Random.Range(-20f, 20f);
|
||||||
|
if (Mathf.Abs(hx) > 8f) // Not too close to center
|
||||||
|
{
|
||||||
|
obstacles.Add((new Vector2(hx, hy), new Vector2(4f, 1f), hedgeColor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some sheds/garages in backyards
|
||||||
|
Color shedColor = new Color(0.45f, 0.4f, 0.35f);
|
||||||
|
Vector2[] shedPositions = {
|
||||||
|
new(-18f, 10f), new(-10f, -10f), new(8f, 10f), new(16f, -10f),
|
||||||
|
new(-26f, 2f), new(26f, -3f)
|
||||||
|
};
|
||||||
|
foreach (var pos in shedPositions)
|
||||||
|
{
|
||||||
|
if (Random.value > 0.4f)
|
||||||
|
obstacles.Add((pos, new Vector2(2.5f, 2.5f), shedColor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CreateBases()
|
void CreateBases()
|
||||||
{
|
{
|
||||||
// Player base - left side
|
// Player base - left side
|
||||||
|
|||||||
2
Backyard CTF/Assets/Scripts/Game.cs.meta
Normal file
2
Backyard CTF/Assets/Scripts/Game.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f62c6569cd5544a03b7d7d1cee7da3f6
|
||||||
2
Backyard CTF/Assets/Scripts/RouteDrawer.cs.meta
Normal file
2
Backyard CTF/Assets/Scripts/RouteDrawer.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8c4467d56dec84c76a24b128afc73a3f
|
||||||
2
Backyard CTF/Assets/Scripts/SimpleAI.cs.meta
Normal file
2
Backyard CTF/Assets/Scripts/SimpleAI.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: faa2f6c6b185d4351829086d17055949
|
||||||
@@ -137,25 +137,25 @@ public class Unit : MonoBehaviour
|
|||||||
|
|
||||||
void HandleTagCollision(Unit other)
|
void HandleTagCollision(Unit other)
|
||||||
{
|
{
|
||||||
|
// Only process collision once - lower instance ID handles it
|
||||||
|
if (GetInstanceID() > other.GetInstanceID()) return;
|
||||||
|
|
||||||
// Determine who gets tagged: farther from their own base loses
|
// Determine who gets tagged: farther from their own base loses
|
||||||
|
// The instigator (closer to their base) is NOT captured
|
||||||
Transform myBase = Game.Instance.GetBase(team);
|
Transform myBase = Game.Instance.GetBase(team);
|
||||||
Transform theirBase = Game.Instance.GetBase(other.team);
|
Transform theirBase = Game.Instance.GetBase(other.team);
|
||||||
|
|
||||||
float myDistance = Vector2.Distance(transform.position, myBase.position);
|
float myDistance = Vector2.Distance(transform.position, myBase.position);
|
||||||
float theirDistance = Vector2.Distance(other.transform.position, theirBase.position);
|
float theirDistance = Vector2.Distance(other.transform.position, theirBase.position);
|
||||||
|
|
||||||
|
// Only the one farther from their base gets tagged
|
||||||
if (myDistance > theirDistance)
|
if (myDistance > theirDistance)
|
||||||
{
|
{
|
||||||
TagOut();
|
TagOut();
|
||||||
}
|
}
|
||||||
else if (theirDistance > myDistance)
|
|
||||||
{
|
|
||||||
other.TagOut();
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Equal distance - both get tagged (more chaos!)
|
// They are farther or equal - they get tagged
|
||||||
TagOut();
|
|
||||||
other.TagOut();
|
other.TagOut();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,9 +193,10 @@ public class Unit : MonoBehaviour
|
|||||||
{
|
{
|
||||||
yield return new WaitForSeconds(Game.RespawnDelay);
|
yield return new WaitForSeconds(Game.RespawnDelay);
|
||||||
|
|
||||||
// Respawn at base
|
// Respawn at base (landscape - horizontal offset toward center)
|
||||||
Transform baseTransform = Game.Instance.GetBase(team);
|
Transform baseTransform = Game.Instance.GetBase(team);
|
||||||
Vector3 offset = new Vector3(Random.Range(-2f, 2f), team == Team.Player ? -2f : 2f, 0);
|
float xOffset = team == Team.Player ? 2f : -2f;
|
||||||
|
Vector3 offset = new Vector3(xOffset, Random.Range(-2f, 2f), 0);
|
||||||
transform.position = baseTransform.position + offset;
|
transform.position = baseTransform.position + offset;
|
||||||
|
|
||||||
isTaggedOut = false;
|
isTaggedOut = false;
|
||||||
|
|||||||
2
Backyard CTF/Assets/Scripts/Unit.cs.meta
Normal file
2
Backyard CTF/Assets/Scripts/Unit.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6ea1fe45ed12847fdbf61f14ae451c47
|
||||||
2
Backyard CTF/Assets/Scripts/Visibility.cs.meta
Normal file
2
Backyard CTF/Assets/Scripts/Visibility.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 02e237c0633a948708044095c3dc90c5
|
||||||
Reference in New Issue
Block a user