nodes/td_data.pyΒΆ

Part of Tower Defence.

  1"""Tower Defence constants + spawn / turret data tables.
  2
  3Translated from upstream's `constants.py`, `enemy_data.py`, `turret_data.py`.
  4Cooldowns and speeds were originally frame-counted (60 FPS); we convert
  5millisecond cooldowns into seconds and pygame px/frame speeds into px/sec
  6(`speed * 60`) so the SimVX delta-time integration is frame-rate independent.
  7"""
  8
  9from __future__ import annotations
 10
 11ROWS = 15
 12COLS = 15
 13TILE_SIZE = 48
 14SIDE_PANEL = 300
 15SCREEN_WIDTH = TILE_SIZE * COLS  # 720
 16SCREEN_HEIGHT = TILE_SIZE * ROWS  # 720
 17WINDOW_WIDTH = SCREEN_WIDTH + SIDE_PANEL
 18WINDOW_HEIGHT = SCREEN_HEIGHT
 19
 20START_HEALTH = 20
 21START_MONEY = 900
 22TOTAL_LEVELS = 15
 23
 24# Enemy spawn cadence (seconds between spawns) -- upstream is 400 ms.
 25SPAWN_COOLDOWN = 0.4
 26
 27# Turret tunables
 28TURRET_LEVELS = 4
 29BUY_COST = 200
 30UPGRADE_COST = 100
 31KILL_REWARD = 1
 32LEVEL_COMPLETE_REWARD = 100
 33ANIMATION_STEPS = 8
 34ANIMATION_FPS = 67  # upstream: 1 frame per 15 ms => ~67 FPS animation
 35DAMAGE = 5
 36
 37# Per-tower-type tunables (slow + sniper variants on top of the upstream "basic")
 38TURRET_TYPES = {
 39    # Default: balanced, animated turret from the tutorial. Ranges are bumped
 40    # ~30% over the upstream values so a single turret covers a full
 41    # adjacent path segment (the upstream values needed dense placement and
 42    # are a poor demo for a single-wave port).
 43    "basic": [
 44        {"range": 120, "cooldown": 0.9, "damage": 5, "colour": (1.0, 1.0, 1.0, 1.0)},
 45        {"range": 140, "cooldown": 0.8, "damage": 6, "colour": (1.0, 1.0, 1.0, 1.0)},
 46        {"range": 160, "cooldown": 0.7, "damage": 7, "colour": (1.0, 1.0, 1.0, 1.0)},
 47        {"range": 190, "cooldown": 0.6, "damage": 9, "colour": (1.0, 1.0, 1.0, 1.0)},
 48    ],
 49    # Slow: short range, deals less damage but applies a slow-debuff for 1 s
 50    "slow": [
 51        {
 52            "range": 70,
 53            "cooldown": 0.8,
 54            "damage": 2,
 55            "colour": (0.55, 0.85, 1.0, 1.0),
 56            "slow_factor": 0.5,
 57            "slow_seconds": 1.0,
 58        },
 59        {
 60            "range": 85,
 61            "cooldown": 0.7,
 62            "damage": 3,
 63            "colour": (0.55, 0.85, 1.0, 1.0),
 64            "slow_factor": 0.45,
 65            "slow_seconds": 1.2,
 66        },
 67        {
 68            "range": 100,
 69            "cooldown": 0.6,
 70            "damage": 3,
 71            "colour": (0.55, 0.85, 1.0, 1.0),
 72            "slow_factor": 0.4,
 73            "slow_seconds": 1.4,
 74        },
 75        {
 76            "range": 120,
 77            "cooldown": 0.5,
 78            "damage": 4,
 79            "colour": (0.55, 0.85, 1.0, 1.0),
 80            "slow_factor": 0.35,
 81            "slow_seconds": 1.6,
 82        },
 83    ],
 84    # Sniper: long range, slow rate, big damage
 85    "sniper": [
 86        {"range": 200, "cooldown": 2.4, "damage": 14, "colour": (1.0, 0.65, 0.35, 1.0)},
 87        {"range": 230, "cooldown": 2.1, "damage": 18, "colour": (1.0, 0.65, 0.35, 1.0)},
 88        {"range": 260, "cooldown": 1.8, "damage": 24, "colour": (1.0, 0.65, 0.35, 1.0)},
 89        {"range": 300, "cooldown": 1.5, "damage": 30, "colour": (1.0, 0.65, 0.35, 1.0)},
 90    ],
 91}
 92
 93TURRET_COSTS = {"basic": 200, "slow": 250, "sniper": 350}
 94TURRET_LABELS = {"basic": "BASIC", "slow": "SLOW", "sniper": "SNIPER"}
 95
 96ENEMY_DATA = {
 97    "weak": {"health": 10, "speed": 120.0},  # upstream 2 px/frame * 60 = 120 px/s
 98    "medium": {"health": 15, "speed": 180.0},
 99    "strong": {"health": 20, "speed": 240.0},
100    "elite": {"health": 30, "speed": 360.0},
101}
102
103ENEMY_COLOURS = {
104    "weak": (1.0, 1.0, 1.0, 1.0),
105    "medium": (0.85, 1.0, 0.85, 1.0),
106    "strong": (1.0, 0.85, 0.85, 1.0),
107    "elite": (1.0, 0.92, 0.4, 1.0),
108}
109
110# Spawn schedule per level (count per type). Trimmed slightly from upstream
111# to keep early waves snappier for testing.
112ENEMY_SPAWN_DATA = [
113    {"weak": 8, "medium": 0, "strong": 0, "elite": 0},  # 1
114    {"weak": 12, "medium": 0, "strong": 0, "elite": 0},  # 2
115    {"weak": 10, "medium": 4, "strong": 0, "elite": 0},  # 3
116    {"weak": 12, "medium": 8, "strong": 0, "elite": 0},  # 4
117    {"weak": 5, "medium": 10, "strong": 1, "elite": 0},  # 5
118    {"weak": 8, "medium": 8, "strong": 3, "elite": 0},  # 6
119    {"weak": 10, "medium": 12, "strong": 4, "elite": 0},  # 7
120    {"weak": 6, "medium": 10, "strong": 6, "elite": 1},  # 8
121    {"weak": 8, "medium": 8, "strong": 8, "elite": 2},  # 9
122    {"weak": 0, "medium": 20, "strong": 0, "elite": 0},  # 10
123    {"weak": 4, "medium": 8, "strong": 8, "elite": 2},  # 11
124    {"weak": 0, "medium": 10, "strong": 8, "elite": 4},  # 12
125    {"weak": 12, "medium": 0, "strong": 14, "elite": 6},  # 13
126    {"weak": 10, "medium": 10, "strong": 10, "elite": 8},  # 14
127    {"weak": 12, "medium": 12, "strong": 12, "elite": 12},  # 15
128]