commit e1410c234abd629618cbe2b6f88bb62480cab6f4 Author: Edwin Eames Date: Fri Jul 10 20:26:48 2026 -0400 Initial commit before folder reorganization Checkpoint of the existing flat file layout prior to restructuring into autoload/, menu/, ships/, world/, and assets/ folders. Co-Authored-By: Claude Sonnet 5 diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..6296567 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,32 @@ +# Spacewar + +2D multiplayer space shooter inspired by Subspace Continuum. Built in **Godot 4.7** (GDScript). Target platform: Steam Deck + PC. Three races fight for galaxy control across casual (25v25) and ranked (5v5) modes. + +## Design Docs (`overview/`) + +| File | Contents | +|------|----------| +| `overview.md` | Concept, core loop, game flow, match sizes | +| `racesclasses.md` | 3 chosen races, 5 ship classes each | +| `multiplayer.md` | Maps, game modes, galaxy war meta | +| `bots.md` | Bot fill rules for casual matches | +| `tech.md` | Engine, networking architecture, checklist | +| `money.md` | Monetization strategy | +| `structure.md` | Project file tree, scene graph, input map | + +## Completed + +1. **Server browser** — player name input, race toggles, server list (Trench Wars 0/32), JOIN button; stores name + race in `GameConfig` autoload +2. **Main menu** — CASUAL / RANKED (disabled) buttons, callsign input, rank badge, QUIT; clears player state on load +3. **In-game pause menu** — ESC / controller Start button toggles overlay; game keeps running; RESUME, SETTINGS (stub), SELECT TEAM (stub), QUIT TO MENU, QUIT TO DESKTOP +4. **Team & ship selection** — shows on world load before player spawns; 2 races randomly offered per match; ship grid with sprites; player spawns with chosen ship after selection + +## Current Tasks + +- [ ] Replace placeholder race names + ship sprites with the 3 chosen races (see `racesclasses.md`) +- [ ] Asteroids and environment hazards +- [ ] Bot fill for casual (minimum 7v7, bots fill empty slots — see `bots.md`) +- [ ] Sound effects (thrust, shoot, explosion, UI) +- [ ] Multiplayer networking — ENet authoritative server (see `tech.md`) +- [ ] Galaxy war meta / sector control for casual (see `multiplayer.md`) +- [ ] Ranked matchmaking + MMR diff --git a/overview/bots.md b/overview/bots.md new file mode 100644 index 0000000..cc51357 --- /dev/null +++ b/overview/bots.md @@ -0,0 +1,21 @@ +# Bots — Casual Mode Fill + +## Rules + +- Each casual match picks **2 of the 3 races** at random +- Bots fill empty slots until the match reaches **7v7** (14 total) +- Once 7v7 is reached, **no more bots are added** — additional human players replace bots as they join +- Bots are removed when real players join their team slot + +## Why 7v7 Minimum + +- Ensures the match feels active even at low population +- Avoids the ghost-town feeling of a 25v25 map with 3 players +- Bots are not added beyond 7v7 so human players always dominate strategy + +## Implementation Notes (not yet built) + +- Bots use simplified AI: thrust toward nearest enemy, shoot when in range +- Bot difficulty: intentionally easy (this is casual — bots are filler, not challenge) +- Bot names: procedurally generated callsigns so they're not obviously bots in the HUD +- Server tracks human vs bot count per team and manages swap-in on player join diff --git a/overview/issue.md b/overview/issue.md new file mode 100644 index 0000000..30a05af --- /dev/null +++ b/overview/issue.md @@ -0,0 +1,5 @@ +# Dev Notes + +- First Godot project — learning the engine while building +- GDScript is the primary language; UI is built programmatically in `_ready()` rather than in the editor scene tree +- Steam Deck is the primary target: fixed 1280×800, controller support required alongside keyboard/mouse diff --git a/overview/money.md b/overview/money.md new file mode 100644 index 0000000..93665f9 --- /dev/null +++ b/overview/money.md @@ -0,0 +1,45 @@ +# Monetization + +## The Problem + +- Selling for **$5** reduces hacking/smurfing (small barrier to entry) +- But limits long-term revenue after launch + +--- + +## Monetization Options + +### Option A — Buy to Play + Cosmetics (Recommended) +- **$5 upfront** on Steam (barrier against hackers/smurfs) +- Free cosmetic battle pass each season (optional paid tier) +- Cosmetic shop: ship skins, thruster trails, kill effects, UI themes +- No pay-to-win — all gameplay items are free + +### Option B — Free to Play + Cosmetics +- Lower barrier to entry = more players = better matchmaking +- Revenue comes 100% from cosmetic shop and battle pass +- Risk: harder to combat hackers/smurfs without a price barrier +- Mitigation: phone verification or Steam account age requirement + +### Option C — Buy to Play + Expansions +- $5 base game +- Future paid DLC: new races, new map packs +- Risk: splits playerbase + +--- + +## Recommendation + +**Option A** is the safest starting point: +- $5 keeps bad actors out +- Cosmetics fund ongoing development +- No pay-to-win preserves competitive integrity +- Can always go F2P later if playerbase needs a boost + +--- + +## Anti-Cheat / Anti-Smurf Notes + +- $5 price is a soft deterrent, not a hard one +- Consider VAC (Steam's anti-cheat) integration via Godot Steam plugin +- Phone verification for ranked queue is another option (like Valorant) diff --git a/overview/multiplayer.md b/overview/multiplayer.md new file mode 100644 index 0000000..1eb5b6e --- /dev/null +++ b/overview/multiplayer.md @@ -0,0 +1,59 @@ +# Multiplayer — Maps & Game Modes + +## Maps + +- **10 maps total** at launch +- Design philosophy: **CSGO-tight** — intentional lanes, clear sightlines, no wasted space +- Subspace Continuum's Trench Wars maps were too large and too open — avoid this +- All maps are 2D top-down space environments (asteroid fields, space stations, nebulae, etc.) + +| Map Size | Used For | +|----------|----------| +| Small | Ranked 5v5 | +| Medium | Ranked 5v5 / Casual 25v25 | +| Large | Casual 25v25 only | + +--- + +## Ranked Mode — 5v5 + +Competitive, skill-based, MMR/ELO ladder. Penalty for leaving mid-match. Small–medium maps only. + +### Ranked Mode Ideas + +| Mode | Description | +|------|-------------| +| **Flagship Assault** | Each team has a Flagship (large ship). Destroy the enemy Flagship while defending yours. *(Recommended starting mode)* | +| **Control Point** | One central point on the map. Hold it longer than the enemy to win. First to X seconds wins. | +| **Deathmatch** | First team to X kills wins. Clean, simple, easy to understand. | +| **Relay Capture** | A neutral carrier drifts across the map. Escort it to the enemy base to score. | + +> **Suggestion:** Start with **Flagship Assault** only. It's unique, has natural tension (offense and defense), and maps can be designed around it. Add modes later as seasons. + +--- + +## Casual Mode — 25v25 + +No penalty for leaving. Larger maps. Chaotic and fun — you can drop in mid-match. + +### Casual Mode Ideas + +| Mode | Description | +|------|-------------| +| **Sector Control** | Map divided into sectors. Hold more sectors at time limit. Ties to galactic war meta. | +| **King of the Hill** | One contested zone in the center. Hold it to rack up points. | +| **Annihilation** | Pure kills. Last team standing or first to X kills. Chaos mode. | +| **Base Assault** | One team attacks a fortified base, one defends. Roles swap each round. | +| **Convoy Escort** | One team escorts a slow-moving freighter across the map, other team destroys it. | + +> **Suggestion:** Start with **Sector Control** for casual. It ties into the galaxy meta (Helldivers-style), encourages teamwork without hard requirements, and naturally scales to 25v25. + +--- + +## Galaxy Meta (Helldivers-Style) + +- The galaxy is divided into **sectors** +- Casual 25v25 matches determine which race controls which sector +- Ranked 5v5 results also contribute to sector control +- A live galaxy map on the main screen shows the current war state +- This gives low-stakes players (casual) real impact on the ongoing war diff --git a/overview/overview.md b/overview/overview.md new file mode 100644 index 0000000..b236e29 --- /dev/null +++ b/overview/overview.md @@ -0,0 +1,64 @@ +# Space Game — Project Overview + +## Concept + +A 2D pixel-art top-down space shooter inspired by **Subspace Continuum**, built for **Steam Deck and PC**. Three alien races fight for control of a galaxy. Fast matchmaking like Rocket League — quick in, quick out. + +## Core Loop + +1. Launch → Main Menu +2. Enter callsign → click CASUAL +3. World loads → pick your race (2 of 3 randomly offered per match) → pick your ship +4. Fight in a 25v25 battle +5. Return to main menu + +## Game Modes + +| Mode | Size | Status | +|------|------|--------| +| Casual | 25v25 (bots fill to 7v7 minimum) | In progress | +| Ranked | 5v5, competitive MMR | Disabled — coming later | + +## Current Game Flow (as built) + +``` +Main Menu + └─ CASUAL ──► World loads immediately (game active) + └─ TeamSelect overlay appears + ├─ Pick race (2 random of 3 offered) + └─ Pick ship (4 available, sprites shown) + └─ Player spawns centred, invincible briefly + └─ ESC / Start ──► Pause menu overlay + ├─ RESUME + ├─ SETTINGS (stub) + ├─ SELECT TEAM (stub) + ├─ QUIT TO MENU + └─ QUIT TO DESKTOP +``` + +## Races + +3 playable races chosen from a pool of 10 concepts — see `racesclasses.md`. Each race has 5 ship classes: + +| Class | Role | +|-------|------| +| Interceptor | Fast, agile generalist | +| Bomber | Area damage, slow | +| Support | Heal/rally; allies can attach | +| Stealth | Assassin, hit-and-run | +| Heavy | Tank, massive firepower | + +Races are visually distinct — critical for reading a 25v25 battlefield at a glance. + +## Match Setup + +- Each match randomly picks **2 of the 3 races** to field +- Player picks which of those 2 they fight for, then picks their ship +- Bot fill ensures a minimum of **7v7** in casual; no bots added beyond that + +## Design Philosophy + +- Maps inspired by CSGO — tight, intentional, not the sprawling Subspace Trench Wars layout +- 10 maps at launch (small for ranked, medium/large for casual) +- All art: pixel art +- Platform primary: Steam Deck (1280×800, controller-first) diff --git a/overview/racesclasses.md b/overview/racesclasses.md new file mode 100644 index 0000000..6f3139c --- /dev/null +++ b/overview/racesclasses.md @@ -0,0 +1,84 @@ +# Races & Ship Classes + +## Chosen Races: 1, 4, 5 + +From the 10 concepts below, races **1 (Terran Republic)**, **4 (Mechanos Sovereignty)**, and **5 (Void Wraiths)** were selected. + +> **Current in-game status:** The team selection screen uses temporary placeholder names ("Terran Federation", "The Collective", "Iron Order") with placeholder sprites until proper art and lore are integrated for the 3 chosen races. + +--- + +## The 3 Chosen Races + +### Race 1 — Terran Republic ✅ Chosen +**Weapon type:** Projectile / Ballistic +**Visual:** Angular gray-blue military ships, recognizable fighter jet silhouettes, clean livery +**Feel:** Standard military. Balanced and familiar. Easiest to learn. + +| # | Ship | Role | Description | +|---|------|------|-------------| +| 1 | **Falcon** | Interceptor | Fast all-rounder. Standard guns, high agility. Best 1v1 duelist. | +| 2 | **Devastator** | Bomber | Launches grenades + missiles with large splash radius. Slow, massive damage. | +| 3 | **Sentinel** | Support | Deploys repair drones + turrets. Allies can attach. Mobile spawn point. | +| 4 | **Ranger** | Stealth | Cloaks, fires a single high-damage sniper shot, recloaks. | +| 5 | **Juggernaut** | Heavy | Armored fortress. Drops proximity mines, fires suppression bursts. Near-unkillable solo. | + +--- + +### Race 4 — Mechanos Sovereignty ✅ Chosen +**Weapon type:** Railgun / Drone / EMP +**Visual:** Perfectly geometric chrome-and-gold ships. No organic curves. Modular, interchangeable parts. Clearly machine-made. +**Feel:** Pure precision AI. Railgun sniping, drone swarms, and tactical disruption. + +| # | Ship | Role | Description | +|---|------|------|-------------| +| 1 | **Warframe** | Interceptor | Fires precise railgun bursts. Fast. Rewards aim skill. | +| 2 | **Fabricator** | Bomber | Deploys explosive drone clusters — set-and-forget area denial. | +| 3 | **Core Hub** | Support | Broadcasts repair nanobots to nearby allies. Creates mobile spawn beacon. | +| 4 | **Phantom Unit** | Stealth | Hacks enemy targeting — turns off their HUD radar briefly. Hard to detect. | +| 5 | **Siege Engine** | Heavy | Locks into stationary mode for massive railgun barrage. Vulnerable while moving. | + +--- + +### Race 5 — Void Wraiths ✅ Chosen +**Weapon type:** Dark Energy / Gravity / Phase +**Visual:** Inky black ships with white particle trails. Look like holes in space. Shifting, unstable edges. Eerie. +**Feel:** Terrifying and unpredictable. Gravity wells, phase attacks, hard to pin down. + +| # | Ship | Role | Description | +|---|------|------|-------------| +| 1 | **Shade** | Interceptor | Partially phases — hard to hit. Fires void energy bolts. | +| 2 | **Rift Caster** | Bomber | Opens gravity rifts that pull nearby enemies toward the center then collapse. | +| 3 | **Nexus Wraith** | Support | Creates phase portals allies can teleport through. Ally rally point. | +| 4 | **Specter** | Stealth | Fully phased and invisible. Only visible for 0.3s when firing. | +| 5 | **Void Titan** | Heavy | Absorbs incoming damage, then releases it all in a single omni-directional burst. | + +--- + +## All 10 Race Concepts (Reference) + +
+Click to expand all 10 races + +### Race 2 — Xel'Nara Collective +**Weapon type:** Laser / Crystal Energy | **Feel:** Alien elegance, glass cannon + +### Race 3 — Vorg Swarm +**Weapon type:** Bio / Organic (acid, spores) | **Feel:** Zergs in space, DOT chaos + +### Race 6 — Solari Imperium +**Weapon type:** Plasma / Solar Fire | **Feel:** Ancient empire, slow and devastating + +### Race 7 — Kryx Hivemind +**Weapon type:** Swarm Missiles / Acid | **Feel:** Insectoid swarm, volume of fire + +### Race 8 — Nebulon Drifters +**Weapon type:** Gas Clouds / Toxin | **Feel:** Environmental control, zone denial + +### Race 9 — Iron Covenant +**Weapon type:** EMP / Railgun / Hacking | **Feel:** Disruptor faction, breaks enemy systems + +### Race 10 — Eldari Ascendancy +**Weapon type:** Psionic / Reality Distortion | **Feel:** Psychic manipulation, bullets that curve + +
diff --git a/overview/structure.md b/overview/structure.md new file mode 100644 index 0000000..2900836 --- /dev/null +++ b/overview/structure.md @@ -0,0 +1,91 @@ +# Project Structure + +## File Tree + +``` +spacewar/ ← repo root +└── spacewar/ ← Godot project root (open this in Godot editor) + ├── project.godot + ├── game_config.gd ← autoload singleton (tuning values, player state, signals) + ├── main_menu.tscn/gd ← entry point / main scene + ├── server_browser.tscn/gd ← server browser UI (built, not in active flow yet) + ├── world.tscn ← game world + ├── node_2d.tscn ← player ship scene + ├── ship_movement.gd ← player ship logic + ├── bullet.tscn/gd ← projectile + ├── pause_menu.tscn/gd ← in-game pause overlay (ESC / Start button) + ├── team_select.tscn/gd ← race + ship selection overlay (shown on world load) + ├── asteroid_movement.gd ← stub + └── images/ + ├── background/skybox/ ← 6 space background PNGs (1.png – 6.png) + └── ships/Example_ships/ ← 4 placeholder ship sprites (1.png, 1B.png, 2a.png, 3b.png) +``` + +## Scene Graph + +### `main_menu.tscn` — entry point +``` +MainMenu (Control) ← main_menu.gd builds all UI in _ready() +``` + +### `world.tscn` — game world +``` +World (Node2D) +├── TextureRect ← static space background (skybox/1.png) +├── Player ← instance of node_2d.tscn +├── HUD (CanvasLayer) +│ └── HealthLabel +├── PauseMenu (CanvasLayer, layer=10) ← pause_menu.tscn +└── TeamSelect (CanvasLayer, layer=20) ← team_select.tscn; queue_free()s after selection +``` + +### `node_2d.tscn` — player ship +``` +Player (CharacterBody2D) ← ship_movement.gd +├── CollisionShape2D ← CircleShape2D +├── Sprite2D ← texture set at runtime from GameConfig.player_ship_path +└── VisibleOnScreenNotifier2D +``` + +## Input Map + +| Action | Key | Controller | +|--------|-----|------------| +| `move_up` | W | — | +| `move_left` | A | — | +| `move_right` | D | — | +| `move_down` | S | — | +| `shoot` | Space | — | +| `toggle_pause` | Esc | Start / Options button (JoyButton 6) | + +## Game Flow + +``` +main_menu.tscn + ├── CASUAL → world.tscn + │ ├── TeamSelect overlay: pick race (2 random of 3 offered) + │ ├── TeamSelect overlay: pick ship + │ └── Player spawns → game live + └── RANKED → disabled (coming soon) +``` + +> **Note:** `server_browser.tscn` was built (Task 1) and is functional, but the current flow bypasses it — CASUAL goes directly to the world and TeamSelect handles name/race/ship. The server browser will be re-integrated when real multiplayer server listing is built. + +## Key Autoload — `GameConfig` + +| Property | Type | Set by | +|----------|------|--------| +| `player_name` | String | Main menu callsign input | +| `player_race` | int | TeamSelect race pick | +| `player_ship_path` | String | TeamSelect ship pick | +| `team_selected` | signal | Emitted by TeamSelect when done | +| `ship_thrust` | float | Tuning constant | +| `ship_max_speed` | float | Tuning constant | +| `ship_rotation_speed` | float | Tuning constant | +| `ship_fire_rate` | float | Tuning constant | +| `bullet_speed` | float | Tuning constant | +| `ship_max_health` | int | Tuning constant | +| `ship_respawn_delay` | float | Tuning constant | +| `ship_invincibility_time` | float | Tuning constant | +| `bullet_damage` | int | Tuning constant | +| `ship_wall_damage` | int | Tuning constant | diff --git a/overview/task.md b/overview/task.md new file mode 100644 index 0000000..5fead31 --- /dev/null +++ b/overview/task.md @@ -0,0 +1,29 @@ +# Task Log + +## Completed + +| # | Task | Notes | +|---|------|-------| +| 0 | Format all design docs as Markdown | Done | +| 1 | Design 10 races, pick 3 | Races 1, 4, 5 chosen — see `racesclasses.md` | +| 2 | Ranked + casual mode ideas | See `multiplayer.md` | +| 3 | Multiplayer engineering doc | See `tech.md` | +| 4 | Server browser screen | Player name, race buttons, server list, JOIN — stores in `GameConfig` | +| 5 | Main menu | CASUAL / RANKED (disabled), callsign input, rank badge, quit button | +| 6 | In-game pause menu | ESC / controller Start; game runs behind it; working: RESUME, QUIT TO MENU, QUIT TO DESKTOP | +| 7 | Team & ship selection | On world load; 2 random races offered; ship grid with real sprites; player spawns after | + +## Up Next + +| # | Task | Priority | +|---|------|----------| +| 8 | Replace placeholder races with chosen 3 (Terran Republic, Mechanos Sovereignty, Void Wraiths) | High | +| 9 | Real ship sprites for all 3 races (5 ships each) | High | +| 10 | Asteroids + environment hazards | Medium | +| 11 | Bot fill for casual (min 7v7) | Medium — see `bots.md` | +| 12 | Sound effects (thrust, shoot, explosion, UI clicks) | Medium | +| 13 | Multiplayer networking — ENet authoritative server | High (big) | +| 14 | Galaxy war meta + sector control | Low (post-networking) | +| 15 | Ranked matchmaking + MMR | Low (post-networking) | +| 16 | Settings screen (audio, controls, display) | Low | +| 17 | Select Team in pause menu (live team swap) | Low | diff --git a/overview/tech.md b/overview/tech.md new file mode 100644 index 0000000..8399373 --- /dev/null +++ b/overview/tech.md @@ -0,0 +1,89 @@ +# Tech Stack + +## Engine & Language + +- **Engine:** Godot 4.7 (Forward Plus renderer) +- **Language:** GDScript +- **Project path:** `/mnt/code/spacewar/spacewar/` (inner folder is the Godot project root) +- **Platform target:** Linux (Steam Deck native, 1280×800), Windows PC +- **Art style:** Pixel art (placeholder sprites in use currently) + +See `structure.md` for the full file tree and scene graph. + +--- + +## Multiplayer Architecture (Planned) + +``` +[Client] ──── [Matchmaking Server] ──── [Dedicated Game Server] + │ + [Backend API] + (queue, ranks, accounts) +``` + +### Authoritative Server Model + +- Dedicated game servers run the authoritative simulation (not player-hosted) +- Clients send **inputs** (movement, fire, ability) — server validates and broadcasts results +- No client-side cheating possible on critical state (position, HP, kills) +- Player position simulated server-side; clients predict locally and reconcile + +### Godot Networking Layer + +```gdscript +# Server: move a player +@rpc("authority", "call_local", "reliable") +func set_position(new_pos: Vector2) -> void: + position = new_pos + +# Client: send input to server +@rpc("any_peer", "call_remote", "unreliable") +func send_input(dir: Vector2, firing: bool) -> void: + pass +``` + +- **Transport:** ENet (UDP, built into Godot) for low-latency game data +- **Reliable channel:** critical state (HP, death, respawn) +- **Unreliable channel:** high-frequency position/velocity updates + +### Client-Side Prediction & Lag Compensation + +1. Client predicts own movement locally (feels instant) +2. Server confirms or corrects (reconciliation) +3. Other players interpolated between last two known positions +4. Lag compensation: server rewinds state slightly to validate hitscan shots + +### Matchmaking Backend + +| Component | Tech | +|-----------|------| +| API Server | Go or Node.js | +| Queue / State | Redis | +| Database (accounts, ranks) | PostgreSQL | +| Hosting | VPS (Hetzner / DigitalOcean) or self-hosted | + +**Flow:** +1. Client sends "find match" with MMR + mode +2. Backend queues player, finds lobby within MMR range +3. Lobby full → backend assigns a game server +4. Backend sends client the server IP + session token +5. Client connects directly to game server + +### Steam Integration + +- **GodotSteam** plugin (open source, wraps Steamworks SDK) +- Handles: Steam auth, VAC anti-cheat, Steam lobbies, achievements +- No separate account system needed at launch + +--- + +## Networking Checklist + +- [ ] Godot ENet server/client setup +- [ ] Player input RPC structure +- [ ] Position sync with interpolation +- [ ] Ship class registration per peer +- [ ] Server-authoritative health/death +- [ ] Matchmaking API (queue + lobby assignment) +- [ ] GodotSteam auth + VAC +- [ ] Lag compensation (basic rewind) diff --git a/spacewar/.editorconfig b/spacewar/.editorconfig new file mode 100644 index 0000000..f28239b --- /dev/null +++ b/spacewar/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*] +charset = utf-8 diff --git a/spacewar/.gitattributes b/spacewar/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/spacewar/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/spacewar/.gitignore b/spacewar/.gitignore new file mode 100644 index 0000000..0af181c --- /dev/null +++ b/spacewar/.gitignore @@ -0,0 +1,3 @@ +# Godot 4+ specific ignores +.godot/ +/android/ diff --git a/spacewar/bullet.gd b/spacewar/bullet.gd new file mode 100644 index 0000000..5dbb414 --- /dev/null +++ b/spacewar/bullet.gd @@ -0,0 +1,21 @@ +extends Area2D + +var velocity: Vector2 = Vector2.ZERO +var source: Node = null + +func _ready() -> void: + body_entered.connect(_on_body_entered) + +func _process(delta: float) -> void: + global_position += velocity * delta + var screen = get_viewport_rect().size + if (global_position.x < 0 or global_position.x > screen.x or + global_position.y < 0 or global_position.y > screen.y): + queue_free() + +func _on_body_entered(body: Node) -> void: + if body == source: + return + if body.has_method("take_damage"): + body.take_damage(GameConfig.bullet_damage) + queue_free() diff --git a/spacewar/bullet.gd.uid b/spacewar/bullet.gd.uid new file mode 100644 index 0000000..008bc22 --- /dev/null +++ b/spacewar/bullet.gd.uid @@ -0,0 +1 @@ +uid://dho8dpmkj8bdu diff --git a/spacewar/bullet.tscn b/spacewar/bullet.tscn new file mode 100644 index 0000000..0a87dfe --- /dev/null +++ b/spacewar/bullet.tscn @@ -0,0 +1,16 @@ +[gd_scene format=3] + +[ext_resource type="Script" path="res://bullet.gd" id="1"] + +[sub_resource type="CircleShape2D" id="CircleShape2D_1"] +radius = 4.0 + +[node name="Bullet" type="Area2D"] +script = ExtResource("1") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("CircleShape2D_1") + +[node name="Polygon2D" type="Polygon2D" parent="."] +color = Color(1, 0.9, 0.2, 1) +polygon = PackedVector2Array(5, 0, 4.33, 2.5, 2.5, 4.33, 0, 5, -2.5, 4.33, -4.33, 2.5, -5, 0, -4.33, -2.5, -2.5, -4.33, 0, -5, 2.5, -4.33, 4.33, -2.5) diff --git a/spacewar/bwQ7rQ.png b/spacewar/bwQ7rQ.png new file mode 100644 index 0000000..75f4ac8 Binary files /dev/null and b/spacewar/bwQ7rQ.png differ diff --git a/spacewar/bwQ7rQ.png.import b/spacewar/bwQ7rQ.png.import new file mode 100644 index 0000000..762e14d --- /dev/null +++ b/spacewar/bwQ7rQ.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dglp131j5tga6" +path="res://.godot/imported/bwQ7rQ.png-13ccf92d28893d68bca8cee95abb7d20.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://bwQ7rQ.png" +dest_files=["res://.godot/imported/bwQ7rQ.png-13ccf92d28893d68bca8cee95abb7d20.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/spacewar/game_config.gd b/spacewar/game_config.gd new file mode 100644 index 0000000..6796ba9 --- /dev/null +++ b/spacewar/game_config.gd @@ -0,0 +1,24 @@ +extends Node + +signal team_selected + +# Ship movement +var ship_thrust: float = 250.0 +var ship_max_speed: float = 300.0 +var ship_rotation_speed: float = 4.0 + +# Shooting +var ship_fire_rate: float = 0.15 +var bullet_speed: float = 450.0 + +# Health & respawn +var ship_max_health: int = 100 +var ship_respawn_delay: float = 3.0 +var ship_invincibility_time: float = 2.0 +var ship_wall_damage: int = 1 +var bullet_damage: int = 40 + +# Set before entering a game +var player_name: String = "" +var player_race: int = 0 +var player_ship_path: String = "" diff --git a/spacewar/game_config.gd.uid b/spacewar/game_config.gd.uid new file mode 100644 index 0000000..13a1f52 --- /dev/null +++ b/spacewar/game_config.gd.uid @@ -0,0 +1 @@ +uid://cdh612na2digh diff --git a/spacewar/icon.svg b/spacewar/icon.svg new file mode 100644 index 0000000..c6bbb7d --- /dev/null +++ b/spacewar/icon.svg @@ -0,0 +1 @@ + diff --git a/spacewar/icon.svg.import b/spacewar/icon.svg.import new file mode 100644 index 0000000..1d6c261 --- /dev/null +++ b/spacewar/icon.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b527hu5te2484" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/spacewar/images/background/skybox/1.png b/spacewar/images/background/skybox/1.png new file mode 100644 index 0000000..e7b65cb Binary files /dev/null and b/spacewar/images/background/skybox/1.png differ diff --git a/spacewar/images/background/skybox/1.png.import b/spacewar/images/background/skybox/1.png.import new file mode 100644 index 0000000..c376faf --- /dev/null +++ b/spacewar/images/background/skybox/1.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d0i6jwqh131b1" +path="res://.godot/imported/1.png-97f1111764d7d26127f844f9bb99447f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://images/background/skybox/1.png" +dest_files=["res://.godot/imported/1.png-97f1111764d7d26127f844f9bb99447f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/spacewar/images/background/skybox/2.png b/spacewar/images/background/skybox/2.png new file mode 100644 index 0000000..5aba731 Binary files /dev/null and b/spacewar/images/background/skybox/2.png differ diff --git a/spacewar/images/background/skybox/2.png.import b/spacewar/images/background/skybox/2.png.import new file mode 100644 index 0000000..1ac43cb --- /dev/null +++ b/spacewar/images/background/skybox/2.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://uchnddsvimku" +path="res://.godot/imported/2.png-535b6f5f8c8d79f538e82478a5ae919b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://images/background/skybox/2.png" +dest_files=["res://.godot/imported/2.png-535b6f5f8c8d79f538e82478a5ae919b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/spacewar/images/background/skybox/3.png b/spacewar/images/background/skybox/3.png new file mode 100644 index 0000000..8366b78 Binary files /dev/null and b/spacewar/images/background/skybox/3.png differ diff --git a/spacewar/images/background/skybox/3.png.import b/spacewar/images/background/skybox/3.png.import new file mode 100644 index 0000000..d2272eb --- /dev/null +++ b/spacewar/images/background/skybox/3.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://tcs117dqynbv" +path="res://.godot/imported/3.png-1ad36fe04660abf5feafa71bee86d926.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://images/background/skybox/3.png" +dest_files=["res://.godot/imported/3.png-1ad36fe04660abf5feafa71bee86d926.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/spacewar/images/background/skybox/4.png b/spacewar/images/background/skybox/4.png new file mode 100644 index 0000000..7a67e73 Binary files /dev/null and b/spacewar/images/background/skybox/4.png differ diff --git a/spacewar/images/background/skybox/4.png.import b/spacewar/images/background/skybox/4.png.import new file mode 100644 index 0000000..96a4701 --- /dev/null +++ b/spacewar/images/background/skybox/4.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://65mjcpw5rk06" +path="res://.godot/imported/4.png-f0201325d495db0494d2b1f7bbeec9a9.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://images/background/skybox/4.png" +dest_files=["res://.godot/imported/4.png-f0201325d495db0494d2b1f7bbeec9a9.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/spacewar/images/background/skybox/5.png b/spacewar/images/background/skybox/5.png new file mode 100644 index 0000000..61626da Binary files /dev/null and b/spacewar/images/background/skybox/5.png differ diff --git a/spacewar/images/background/skybox/5.png.import b/spacewar/images/background/skybox/5.png.import new file mode 100644 index 0000000..c8a731f --- /dev/null +++ b/spacewar/images/background/skybox/5.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bc1onqc7d21w7" +path="res://.godot/imported/5.png-08cd6a64e2f902af1b1785a272d9c50f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://images/background/skybox/5.png" +dest_files=["res://.godot/imported/5.png-08cd6a64e2f902af1b1785a272d9c50f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/spacewar/images/background/skybox/6.png b/spacewar/images/background/skybox/6.png new file mode 100644 index 0000000..4191f53 Binary files /dev/null and b/spacewar/images/background/skybox/6.png differ diff --git a/spacewar/images/background/skybox/6.png.import b/spacewar/images/background/skybox/6.png.import new file mode 100644 index 0000000..23256b7 --- /dev/null +++ b/spacewar/images/background/skybox/6.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cvyfcu03jdqas" +path="res://.godot/imported/6.png-21d9e30a24ce4c43ebcbe0ea36daa029.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://images/background/skybox/6.png" +dest_files=["res://.godot/imported/6.png-21d9e30a24ce4c43ebcbe0ea36daa029.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/spacewar/images/background/skybox/WTFPL.txt b/spacewar/images/background/skybox/WTFPL.txt new file mode 100644 index 0000000..0695951 --- /dev/null +++ b/spacewar/images/background/skybox/WTFPL.txt @@ -0,0 +1,13 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar + 14 rue de Plaisance, 75014 Paris, France + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. diff --git a/spacewar/images/effects/explosion1.png b/spacewar/images/effects/explosion1.png new file mode 100644 index 0000000..662153c Binary files /dev/null and b/spacewar/images/effects/explosion1.png differ diff --git a/spacewar/images/effects/explosion1.png.import b/spacewar/images/effects/explosion1.png.import new file mode 100644 index 0000000..52bc3b3 --- /dev/null +++ b/spacewar/images/effects/explosion1.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ded6ek6l7n8gb" +path="res://.godot/imported/explosion1.png-ebaaa46c76a7bf39885ed36c21d9704d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://images/effects/explosion1.png" +dest_files=["res://.godot/imported/explosion1.png-ebaaa46c76a7bf39885ed36c21d9704d.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/spacewar/images/ships/Example_ships/1.png b/spacewar/images/ships/Example_ships/1.png new file mode 100644 index 0000000..4479042 Binary files /dev/null and b/spacewar/images/ships/Example_ships/1.png differ diff --git a/spacewar/images/ships/Example_ships/1.png.import b/spacewar/images/ships/Example_ships/1.png.import new file mode 100644 index 0000000..0615cdb --- /dev/null +++ b/spacewar/images/ships/Example_ships/1.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://td2tbmkm3r6u" +path="res://.godot/imported/1.png-6cd3243048854fb354d682a18817356e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://images/ships/Example_ships/1.png" +dest_files=["res://.godot/imported/1.png-6cd3243048854fb354d682a18817356e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/spacewar/images/ships/Example_ships/1B.png b/spacewar/images/ships/Example_ships/1B.png new file mode 100644 index 0000000..e9091ec Binary files /dev/null and b/spacewar/images/ships/Example_ships/1B.png differ diff --git a/spacewar/images/ships/Example_ships/1B.png.import b/spacewar/images/ships/Example_ships/1B.png.import new file mode 100644 index 0000000..5542afb --- /dev/null +++ b/spacewar/images/ships/Example_ships/1B.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cgfd5fboa45dn" +path="res://.godot/imported/1B.png-991b0890a43069731cad413022099b02.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://images/ships/Example_ships/1B.png" +dest_files=["res://.godot/imported/1B.png-991b0890a43069731cad413022099b02.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/spacewar/images/ships/Example_ships/2a.png b/spacewar/images/ships/Example_ships/2a.png new file mode 100644 index 0000000..edee698 Binary files /dev/null and b/spacewar/images/ships/Example_ships/2a.png differ diff --git a/spacewar/images/ships/Example_ships/2a.png.import b/spacewar/images/ships/Example_ships/2a.png.import new file mode 100644 index 0000000..33fc09b --- /dev/null +++ b/spacewar/images/ships/Example_ships/2a.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://wnrdhn33ce50" +path="res://.godot/imported/2a.png-9bfe77c7bec5a2e8a116acfd3eb6380a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://images/ships/Example_ships/2a.png" +dest_files=["res://.godot/imported/2a.png-9bfe77c7bec5a2e8a116acfd3eb6380a.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/spacewar/images/ships/Example_ships/3b.png b/spacewar/images/ships/Example_ships/3b.png new file mode 100644 index 0000000..4a04e37 Binary files /dev/null and b/spacewar/images/ships/Example_ships/3b.png differ diff --git a/spacewar/images/ships/Example_ships/3b.png.import b/spacewar/images/ships/Example_ships/3b.png.import new file mode 100644 index 0000000..77b32ec --- /dev/null +++ b/spacewar/images/ships/Example_ships/3b.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b6xkpyy1rg74v" +path="res://.godot/imported/3b.png-d95c52be2bb572cb2c8ffd7d62d1118b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://images/ships/Example_ships/3b.png" +dest_files=["res://.godot/imported/3b.png-d95c52be2bb572cb2c8ffd7d62d1118b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/spacewar/main_menu.gd b/spacewar/main_menu.gd new file mode 100644 index 0000000..27bb52f --- /dev/null +++ b/spacewar/main_menu.gd @@ -0,0 +1,338 @@ +extends Control + +var _name_input: LineEdit +var _casual_btn: Button +var _ranked_btn: Button + +const RANK_DATA := [ + {"label": "CADET", "color": Color(0.72, 0.48, 0.22)}, + {"label": "PILOT", "color": Color(0.78, 0.78, 0.82)}, + {"label": "ACE", "color": Color(1.0, 0.82, 0.22)}, + {"label": "COMMANDER", "color": Color(0.35, 0.88, 1.0)}, + {"label": "ADMIRAL", "color": Color(0.62, 0.28, 1.0)}, + {"label": "LEGEND", "color": Color(1.0, 0.28, 0.10)}, +] +const CURRENT_RANK := 0 # placeholder until backend exists + + +func _ready() -> void: + GameConfig.player_race = 0 + GameConfig.player_ship_path = "" + _build_ui() + + +func _build_ui() -> void: + _add_bg() + _add_title() + _add_play_section() + _add_rank_badge() + _add_quit_btn() + _add_version_label() + + +func _add_bg() -> void: + var bg := TextureRect.new() + bg.texture = load("res://images/background/skybox/2.png") + bg.expand_mode = TextureRect.EXPAND_FIT_WIDTH_PROPORTIONAL + bg.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_COVERED + bg.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + add_child(bg) + + var ov := ColorRect.new() + ov.color = Color(0.01, 0.02, 0.09, 0.80) + ov.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + add_child(ov) + + +func _add_title() -> void: + var title := Label.new() + title.text = "S P A C E W A R" + title.set_anchors_preset(Control.PRESET_TOP_WIDE) + title.offset_top = 72.0 + title.offset_bottom = 148.0 + title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + title.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + title.add_theme_font_size_override("font_size", 56) + title.add_theme_color_override("font_color", Color(0.45, 0.88, 1.0)) + add_child(title) + + var sub := Label.new() + sub.text = "FIGHT FOR THE GALAXY" + sub.set_anchors_preset(Control.PRESET_TOP_WIDE) + sub.offset_top = 152.0 + sub.offset_bottom = 178.0 + sub.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + sub.add_theme_font_size_override("font_size", 13) + sub.add_theme_color_override("font_color", Color(0.42, 0.54, 0.70)) + add_child(sub) + + +func _add_play_section() -> void: + const BTN_W := 480.0 + const BTN_H := 230.0 + const GAP := 40.0 + const LEFT_X := (1280.0 - (BTN_W * 2.0 + GAP)) / 2.0 # 140 + const TOP_Y := 220.0 + + _casual_btn = _make_mode_btn( + LEFT_X, TOP_Y, BTN_W, BTN_H, + "CASUAL", + "25 vs 25", + "Drop in, drop out anytime.\nNo rank at stake.", + Color(0.06, 0.22, 0.08), + Color(0.30, 0.90, 0.40), + ) + _casual_btn.pressed.connect(_on_play_casual) + add_child(_casual_btn) + + _ranked_btn = _make_mode_btn( + LEFT_X + BTN_W + GAP, TOP_Y, BTN_W, BTN_H, + "RANKED", + "5 vs 5", + "Competitive ladder.\nYour rank is on the line.", + Color(0.06, 0.10, 0.26), + Color(0.40, 0.72, 1.00), + ) + _ranked_btn.disabled = true + _ranked_btn.pressed.connect(_on_play_ranked) + add_child(_ranked_btn) + + var coming_soon := Label.new() + coming_soon.text = "— COMING SOON —" + coming_soon.set_anchor_and_offset(SIDE_LEFT, 0.0, LEFT_X + BTN_W + GAP) + coming_soon.set_anchor_and_offset(SIDE_TOP, 0.0, TOP_Y + BTN_H - 36.0) + coming_soon.set_anchor_and_offset(SIDE_RIGHT, 0.0, LEFT_X + BTN_W * 2.0 + GAP) + coming_soon.set_anchor_and_offset(SIDE_BOTTOM, 0.0, TOP_Y + BTN_H - 8.0) + coming_soon.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + coming_soon.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + coming_soon.add_theme_font_size_override("font_size", 11) + coming_soon.add_theme_color_override("font_color", Color(0.30, 0.36, 0.48, 0.70)) + coming_soon.mouse_filter = Control.MOUSE_FILTER_IGNORE + add_child(coming_soon) + + # Callsign label + var lbl := Label.new() + lbl.text = "CALLSIGN" + lbl.set_anchor_and_offset(SIDE_LEFT, 0.0, LEFT_X) + lbl.set_anchor_and_offset(SIDE_TOP, 0.0, TOP_Y + BTN_H + 26.0) + lbl.set_anchor_and_offset(SIDE_RIGHT, 0.0, LEFT_X + 95.0) + lbl.set_anchor_and_offset(SIDE_BOTTOM, 0.0, TOP_Y + BTN_H + 62.0) + lbl.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + lbl.add_theme_font_size_override("font_size", 12) + lbl.add_theme_color_override("font_color", Color(0.45, 0.55, 0.70)) + add_child(lbl) + + _name_input = LineEdit.new() + _name_input.placeholder_text = "Enter your callsign..." + _name_input.set_anchor_and_offset(SIDE_LEFT, 0.0, LEFT_X + 100.0) + _name_input.set_anchor_and_offset(SIDE_TOP, 0.0, TOP_Y + BTN_H + 26.0) + _name_input.set_anchor_and_offset(SIDE_RIGHT, 0.0, LEFT_X + BTN_W * 2.0 + GAP) + _name_input.set_anchor_and_offset(SIDE_BOTTOM, 0.0, TOP_Y + BTN_H + 62.0) + _name_input.add_theme_font_size_override("font_size", 15) + if GameConfig.player_name != "": + _name_input.text = GameConfig.player_name + _name_input.text_changed.connect(_on_name_changed) + add_child(_name_input) + + _update_play_buttons() + + +func _make_mode_btn( + x: float, y: float, w: float, h: float, + mode: String, fmt: String, desc: String, + bg: Color, accent: Color) -> Button: + + var btn := Button.new() + btn.text = "" + btn.set_anchor_and_offset(SIDE_LEFT, 0.0, x) + btn.set_anchor_and_offset(SIDE_TOP, 0.0, y) + btn.set_anchor_and_offset(SIDE_RIGHT, 0.0, x + w) + btn.set_anchor_and_offset(SIDE_BOTTOM, 0.0, y + h) + + var sn := _flat(bg.lightened(0.05), 12) + sn.set_border_width_all(2) + sn.border_color = accent.darkened(0.45) + var sh := _flat(bg.lightened(0.18), 12) + sh.set_border_width_all(2) + sh.border_color = accent + var sd := _flat(Color(0.04, 0.04, 0.06, 0.5), 12) + sd.set_border_width_all(1) + sd.border_color = Color(0.2, 0.22, 0.28, 0.5) + btn.add_theme_stylebox_override("normal", sn) + btn.add_theme_stylebox_override("hover", sh) + btn.add_theme_stylebox_override("pressed", sh) + btn.add_theme_stylebox_override("disabled", sd) + + var vb := VBoxContainer.new() + vb.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + vb.offset_left = 24.0 + vb.offset_top = 20.0 + vb.offset_right = -24.0 + vb.offset_bottom = -20.0 + vb.alignment = BoxContainer.ALIGNMENT_CENTER + vb.add_theme_constant_override("separation", 12) + vb.mouse_filter = Control.MOUSE_FILTER_IGNORE + btn.add_child(vb) + + var mode_lbl := Label.new() + mode_lbl.text = mode + mode_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + mode_lbl.add_theme_font_size_override("font_size", 40) + mode_lbl.add_theme_color_override("font_color", accent) + mode_lbl.mouse_filter = Control.MOUSE_FILTER_IGNORE + vb.add_child(mode_lbl) + + var fmt_lbl := Label.new() + fmt_lbl.text = fmt + fmt_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + fmt_lbl.add_theme_font_size_override("font_size", 22) + fmt_lbl.add_theme_color_override("font_color", Color(0.85, 0.90, 0.96)) + fmt_lbl.mouse_filter = Control.MOUSE_FILTER_IGNORE + vb.add_child(fmt_lbl) + + var sep := HSeparator.new() + sep.add_theme_color_override("color", accent.darkened(0.5)) + sep.mouse_filter = Control.MOUSE_FILTER_IGNORE + vb.add_child(sep) + + var desc_lbl := Label.new() + desc_lbl.text = desc + desc_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + desc_lbl.add_theme_font_size_override("font_size", 13) + desc_lbl.add_theme_color_override("font_color", Color(0.55, 0.63, 0.76)) + desc_lbl.autowrap_mode = TextServer.AUTOWRAP_WORD + desc_lbl.mouse_filter = Control.MOUSE_FILTER_IGNORE + vb.add_child(desc_lbl) + + return btn + + +func _add_rank_badge() -> void: + const W := 210.0 + const H := 60.0 + const MARGIN := 16.0 + + var panel := Panel.new() + panel.set_anchors_preset(Control.PRESET_TOP_RIGHT) + panel.offset_left = -(W + MARGIN) + panel.offset_top = MARGIN + panel.offset_right = -MARGIN + panel.offset_bottom = MARGIN + H + var ps := _flat(Color(0.04, 0.07, 0.16, 0.92), 8) + ps.set_border_width_all(1) + ps.border_color = Color(0.18, 0.36, 0.62, 0.85) + panel.add_theme_stylebox_override("panel", ps) + add_child(panel) + + var rank := RANK_DATA[CURRENT_RANK] + + # Colored badge block on the left + var badge := Panel.new() + badge.set_anchor_and_offset(SIDE_LEFT, 0.0, 8.0) + badge.set_anchor_and_offset(SIDE_TOP, 0.0, 8.0) + badge.set_anchor_and_offset(SIDE_RIGHT, 0.0, 50.0) + badge.set_anchor_and_offset(SIDE_BOTTOM, 1.0, -8.0) + var bs := _flat(rank.color.darkened(0.45), 5) + bs.set_border_width_all(2) + bs.border_color = rank.color + badge.add_theme_stylebox_override("panel", bs) + panel.add_child(badge) + + var init_lbl := Label.new() + init_lbl.text = rank.label.left(1) + init_lbl.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + init_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + init_lbl.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + init_lbl.add_theme_font_size_override("font_size", 20) + init_lbl.add_theme_color_override("font_color", rank.color) + badge.add_child(init_lbl) + + # Rank name + var rank_lbl := Label.new() + rank_lbl.text = rank.label + rank_lbl.set_anchor_and_offset(SIDE_LEFT, 0.0, 58.0) + rank_lbl.set_anchor_and_offset(SIDE_TOP, 0.0, 0.0) + rank_lbl.set_anchor_and_offset(SIDE_RIGHT, 1.0, -8.0) + rank_lbl.set_anchor_and_offset(SIDE_BOTTOM, 0.0, H / 2.0 + 2.0) + rank_lbl.vertical_alignment = VERTICAL_ALIGNMENT_BOTTOM + rank_lbl.add_theme_font_size_override("font_size", 15) + rank_lbl.add_theme_color_override("font_color", rank.color) + panel.add_child(rank_lbl) + + var rating_lbl := Label.new() + rating_lbl.text = "Rating: —" + rating_lbl.set_anchor_and_offset(SIDE_LEFT, 0.0, 58.0) + rating_lbl.set_anchor_and_offset(SIDE_TOP, 0.0, H / 2.0) + rating_lbl.set_anchor_and_offset(SIDE_RIGHT, 1.0, -8.0) + rating_lbl.set_anchor_and_offset(SIDE_BOTTOM, 1.0, -6.0) + rating_lbl.vertical_alignment = VERTICAL_ALIGNMENT_TOP + rating_lbl.add_theme_font_size_override("font_size", 11) + rating_lbl.add_theme_color_override("font_color", Color(0.45, 0.54, 0.68)) + panel.add_child(rating_lbl) + + +func _add_quit_btn() -> void: + const W := 110.0 + const H := 38.0 + const MARGIN := 20.0 + + var btn := Button.new() + btn.text = "QUIT" + btn.set_anchors_preset(Control.PRESET_BOTTOM_RIGHT) + btn.offset_left = -(W + MARGIN) + btn.offset_top = -(H + MARGIN) + btn.offset_right = -MARGIN + btn.offset_bottom = -MARGIN + btn.add_theme_font_size_override("font_size", 13) + btn.add_theme_color_override("font_color", Color(0.48, 0.54, 0.65)) + + var sn := _flat(Color(0.05, 0.06, 0.11, 0.80), 6) + sn.set_border_width_all(1) + sn.border_color = Color(0.18, 0.22, 0.33, 0.70) + var sh := _flat(Color(0.10, 0.12, 0.20, 0.90), 6) + sh.set_border_width_all(1) + sh.border_color = Color(0.32, 0.38, 0.52) + btn.add_theme_stylebox_override("normal", sn) + btn.add_theme_stylebox_override("hover", sh) + btn.pressed.connect(func(): get_tree().quit()) + add_child(btn) + + +func _add_version_label() -> void: + var lbl := Label.new() + lbl.text = "v0.1-dev" + lbl.set_anchor_and_offset(SIDE_LEFT, 0.0, 14.0) + lbl.set_anchor_and_offset(SIDE_TOP, 1.0, -30.0) + lbl.set_anchor_and_offset(SIDE_RIGHT, 0.0, 100.0) + lbl.set_anchor_and_offset(SIDE_BOTTOM, 1.0, -10.0) + lbl.add_theme_font_size_override("font_size", 11) + lbl.add_theme_color_override("font_color", Color(0.3, 0.35, 0.45)) + add_child(lbl) + + +func _flat(col: Color, radius: int = 0) -> StyleBoxFlat: + var s := StyleBoxFlat.new() + s.bg_color = col + s.set_corner_radius_all(radius) + return s + + +func _on_name_changed(_text: String) -> void: + _update_play_buttons() + + +func _update_play_buttons() -> void: + var ok := not _name_input.text.strip_edges().is_empty() + _casual_btn.disabled = not ok + _ranked_btn.disabled = true + + +func _on_play_casual() -> void: + GameConfig.player_name = _name_input.text.strip_edges() + get_tree().change_scene_to_file("res://world.tscn") + + +func _on_play_ranked() -> void: + GameConfig.player_name = _name_input.text.strip_edges() + GameConfig.player_race = 1 # TODO: race selection screen + get_tree().change_scene_to_file("res://world.tscn") diff --git a/spacewar/main_menu.gd.uid b/spacewar/main_menu.gd.uid new file mode 100644 index 0000000..8d73a95 --- /dev/null +++ b/spacewar/main_menu.gd.uid @@ -0,0 +1 @@ +uid://3it6fh07tirl diff --git a/spacewar/main_menu.tscn b/spacewar/main_menu.tscn new file mode 100644 index 0000000..5e87808 --- /dev/null +++ b/spacewar/main_menu.tscn @@ -0,0 +1,8 @@ +[gd_scene format=3 uid="uid://bmainmenu001"] + +[ext_resource type="Script" path="res://main_menu.gd" id="1_script"] + +[node name="MainMenu" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource("1_script") diff --git a/spacewar/node_2d.tscn b/spacewar/node_2d.tscn new file mode 100644 index 0000000..8f59c11 --- /dev/null +++ b/spacewar/node_2d.tscn @@ -0,0 +1,17 @@ +[gd_scene format=3 uid="uid://dygtdlkvo6ofl"] + +[ext_resource type="Script" uid="uid://c4kj3i73wjdcj" path="res://ship_movement.gd" id="1_0e48y"] +[ext_resource type="Texture2D" uid="uid://td2tbmkm3r6u" path="res://images/ships/Example_ships/1.png" id="2_epypp"] + +[sub_resource type="CircleShape2D" id="CircleShape2D_2uxl3"] + +[node name="Player" type="CharacterBody2D" unique_id=1973248732] +script = ExtResource("1_0e48y") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=188418093] +shape = SubResource("CircleShape2D_2uxl3") + +[node name="Sprite2D" type="Sprite2D" parent="." unique_id=2083904209] +texture = ExtResource("2_epypp") + +[node name="VisibleOnScreenNotifier2D" type="VisibleOnScreenNotifier2D" parent="." unique_id=1504818491] diff --git a/spacewar/pause_menu.gd b/spacewar/pause_menu.gd new file mode 100644 index 0000000..f399697 --- /dev/null +++ b/spacewar/pause_menu.gd @@ -0,0 +1,124 @@ +extends CanvasLayer + +var _root: Control + + +func _ready() -> void: + layer = 10 + _build_ui() + _root.visible = false + + +func _input(event: InputEvent) -> void: + if event.is_action_pressed("toggle_pause"): + _toggle() + get_viewport().set_input_as_handled() + + +func _toggle() -> void: + _root.visible = not _root.visible + + +func _build_ui() -> void: + _root = Control.new() + _root.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + add_child(_root) + + # Dim overlay — blocks mouse clicks reaching the game + var overlay := ColorRect.new() + overlay.color = Color(0.0, 0.0, 0.0, 0.58) + overlay.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + overlay.mouse_filter = Control.MOUSE_FILTER_STOP + _root.add_child(overlay) + + # Center panel (360 × 490) + var panel := Panel.new() + panel.set_anchors_preset(Control.PRESET_CENTER) + panel.offset_left = -180 + panel.offset_top = -245 + panel.offset_right = 180 + panel.offset_bottom = 245 + + var ps := StyleBoxFlat.new() + ps.bg_color = Color(0.04, 0.07, 0.16, 0.97) + ps.set_corner_radius_all(10) + ps.set_border_width_all(1) + ps.border_color = Color(0.18, 0.38, 0.65, 0.9) + panel.add_theme_stylebox_override("panel", ps) + _root.add_child(panel) + + var vb := VBoxContainer.new() + vb.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + vb.offset_left = 28 + vb.offset_top = 28 + vb.offset_right = -28 + vb.offset_bottom = -28 + vb.add_theme_constant_override("separation", 10) + panel.add_child(vb) + + var title := Label.new() + title.text = "MENU" + title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + title.add_theme_font_size_override("font_size", 26) + title.add_theme_color_override("font_color", Color(0.4, 0.85, 1.0)) + vb.add_child(title) + + vb.add_child(_hsep()) + + var gap := Control.new() + gap.custom_minimum_size = Vector2(0, 4) + vb.add_child(gap) + + _add_btn(vb, "RESUME", true).pressed.connect(_toggle) + _add_btn(vb, "SETTINGS", false) + _add_btn(vb, "SELECT TEAM", false) + + vb.add_child(_hsep()) + + _add_btn(vb, "QUIT TO MENU", true).pressed.connect(_on_quit_to_menu) + _add_btn(vb, "QUIT TO DESKTOP", true).pressed.connect(_on_quit_to_desktop) + + +func _add_btn(parent: VBoxContainer, label_text: String, active: bool) -> Button: + var btn := Button.new() + btn.text = label_text + btn.custom_minimum_size = Vector2(0, 54) + btn.add_theme_font_size_override("font_size", 16) + + if active: + btn.add_theme_color_override("font_color", Color(0.92, 0.95, 1.0)) + var sn := _flat(Color(0.07, 0.13, 0.25, 1.0), 6) + var sh := _flat(Color(0.13, 0.24, 0.42, 1.0), 6) + sh.set_border_width_all(1) + sh.border_color = Color(0.3, 0.65, 1.0) + btn.add_theme_stylebox_override("normal", sn) + btn.add_theme_stylebox_override("hover", sh) + else: + btn.add_theme_color_override("font_color", Color(0.35, 0.40, 0.50)) + var sn := _flat(Color(0.04, 0.06, 0.10, 1.0), 6) + btn.add_theme_stylebox_override("normal", sn) + btn.add_theme_stylebox_override("hover", sn) + + parent.add_child(btn) + return btn + + +func _hsep() -> HSeparator: + var sep := HSeparator.new() + sep.add_theme_color_override("color", Color(0.18, 0.28, 0.45, 0.7)) + return sep + + +func _flat(col: Color, radius: int = 0) -> StyleBoxFlat: + var s := StyleBoxFlat.new() + s.bg_color = col + s.set_corner_radius_all(radius) + return s + + +func _on_quit_to_menu() -> void: + get_tree().change_scene_to_file("res://main_menu.tscn") + + +func _on_quit_to_desktop() -> void: + get_tree().quit() diff --git a/spacewar/pause_menu.gd.uid b/spacewar/pause_menu.gd.uid new file mode 100644 index 0000000..fecf755 --- /dev/null +++ b/spacewar/pause_menu.gd.uid @@ -0,0 +1 @@ +uid://lqjtib7jlqg0 diff --git a/spacewar/pause_menu.tscn b/spacewar/pause_menu.tscn new file mode 100644 index 0000000..83d59db --- /dev/null +++ b/spacewar/pause_menu.tscn @@ -0,0 +1,6 @@ +[gd_scene format=3 uid="uid://cpausemenu01a"] + +[ext_resource type="Script" path="res://pause_menu.gd" id="1_script"] + +[node name="PauseMenu" type="CanvasLayer"] +script = ExtResource("1_script") diff --git a/spacewar/project.godot b/spacewar/project.godot new file mode 100644 index 0000000..378000c --- /dev/null +++ b/spacewar/project.godot @@ -0,0 +1,68 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="spacewar" +run/main_scene="res://main_menu.tscn" +config/features=PackedStringArray("4.7", "Forward Plus") +config/icon="res://icon.svg" + +[autoload] + +GameConfig="*res://game_config.gd" + +[display] + +window/size/viewport_width=1280 +window/size/viewport_height=800 +window/size/resizable=false + +[input] + +move_up={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null) +] +} +move_left={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null) +] +} +move_right={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null) +] +} +move_down={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) +] +} +shoot={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null) +] +} +toggle_pause={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":27,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":6,"pressure":0.0,"pressed":false,"script":null) +] +} + +[physics] + +3d/physics_engine="Jolt Physics" + +[rendering] + +rendering_device/driver.windows="d3d12" diff --git a/spacewar/server_browser.gd b/spacewar/server_browser.gd new file mode 100644 index 0000000..d24591a --- /dev/null +++ b/spacewar/server_browser.gd @@ -0,0 +1,283 @@ +extends Control + +var _selected_race: int = 0 +var _selected_server: String = "" + +var _name_input: LineEdit +var _join_button: Button +var _race_buttons: Array[Button] = [] +var _server_btn: Button + + +func _ready() -> void: + _build_ui() + + +func _build_ui() -> void: + var bg := TextureRect.new() + bg.texture = load("res://images/background/skybox/1.png") + bg.expand_mode = TextureRect.EXPAND_FIT_WIDTH_PROPORTIONAL + bg.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_COVERED + bg.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + add_child(bg) + + var overlay := ColorRect.new() + overlay.color = Color(0.02, 0.03, 0.1, 0.72) + overlay.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + add_child(overlay) + + var header := _make_panel(0, 0, 1280, 60) + add_child(header) + var title_lbl := Label.new() + title_lbl.text = "S P A C E W A R — SERVER BROWSER" + title_lbl.anchor_left = 0.0 + title_lbl.anchor_top = 0.0 + title_lbl.anchor_right = 1.0 + title_lbl.anchor_bottom = 1.0 + title_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + title_lbl.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + title_lbl.add_theme_font_size_override("font_size", 26) + title_lbl.add_theme_color_override("font_color", Color(0.4, 0.85, 1.0)) + header.add_child(title_lbl) + + var left := _make_panel(10, 70, 745, 720) + add_child(left) + _build_server_list(left) + + var right := _make_panel(765, 70, 505, 720) + add_child(right) + _build_player_setup(right) + + +func _make_panel(x: float, y: float, w: float, h: float) -> Panel: + var p := Panel.new() + p.anchor_left = 0.0 + p.anchor_top = 0.0 + p.anchor_right = 0.0 + p.anchor_bottom = 0.0 + p.offset_left = x + p.offset_top = y + p.offset_right = x + w + p.offset_bottom = y + h + var style := StyleBoxFlat.new() + style.bg_color = Color(0.04, 0.07, 0.16, 0.92) + style.set_corner_radius_all(8) + style.set_border_width_all(1) + style.border_color = Color(0.18, 0.38, 0.65, 0.9) + p.add_theme_stylebox_override("panel", style) + return p + + +func _vbox_in(parent: Control, margin: float = 16.0) -> VBoxContainer: + var vb := VBoxContainer.new() + vb.anchor_left = 0.0 + vb.anchor_top = 0.0 + vb.anchor_right = 1.0 + vb.anchor_bottom = 1.0 + vb.offset_left = margin + vb.offset_top = margin + vb.offset_right = -margin + vb.offset_bottom = -margin + vb.add_theme_constant_override("separation", 10) + parent.add_child(vb) + return vb + + +func _section_label(txt: String) -> Label: + var lbl := Label.new() + lbl.text = txt + lbl.add_theme_font_size_override("font_size", 18) + lbl.add_theme_color_override("font_color", Color(0.55, 0.82, 1.0)) + return lbl + + +func _field_label(txt: String) -> Label: + var lbl := Label.new() + lbl.text = txt + lbl.add_theme_font_size_override("font_size", 14) + lbl.add_theme_color_override("font_color", Color(0.65, 0.72, 0.82)) + return lbl + + +func _flat_box(color: Color, radius: int = 0) -> StyleBoxFlat: + var s := StyleBoxFlat.new() + s.bg_color = color + s.set_corner_radius_all(radius) + return s + + +func _build_server_list(parent: Panel) -> void: + var vb := _vbox_in(parent) + + vb.add_child(_section_label("Available Servers")) + vb.add_child(HSeparator.new()) + + var col_hdr := HBoxContainer.new() + vb.add_child(col_hdr) + var h_name := _field_label("Server Name") + h_name.size_flags_horizontal = Control.SIZE_EXPAND_FILL + col_hdr.add_child(h_name) + var h_players := _field_label("Players") + h_players.custom_minimum_size = Vector2(110, 0) + h_players.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT + col_hdr.add_child(h_players) + + vb.add_child(HSeparator.new()) + + _server_btn = Button.new() + _server_btn.toggle_mode = true + _server_btn.text = " Trench Wars" + _server_btn.alignment = HORIZONTAL_ALIGNMENT_LEFT + _server_btn.custom_minimum_size = Vector2(0, 54) + _server_btn.add_theme_font_size_override("font_size", 17) + _server_btn.add_theme_color_override("font_color", Color(0.92, 0.95, 1.0)) + + var sn := _flat_box(Color(0.07, 0.13, 0.25, 1.0), 4) + sn.content_margin_left = 12.0 + var sh := _flat_box(Color(0.11, 0.21, 0.4, 1.0), 4) + sh.content_margin_left = 12.0 + var sp := _flat_box(Color(0.09, 0.27, 0.52, 1.0), 4) + sp.set_border_width_all(2) + sp.border_color = Color(0.3, 0.65, 1.0, 1.0) + sp.content_margin_left = 12.0 + _server_btn.add_theme_stylebox_override("normal", sn) + _server_btn.add_theme_stylebox_override("hover", sh) + _server_btn.add_theme_stylebox_override("pressed", sp) + + _server_btn.pressed.connect(_on_server_selected.bind("trench_wars")) + vb.add_child(_server_btn) + + # Player count label floated to the right of the server button row + # (separate non-interactive label overlaid via HBox trick) + var row_hb := HBoxContainer.new() + # We already added the button directly to vb; restructure: remove and re-add inside HBox + vb.remove_child(_server_btn) + vb.add_child(row_hb) + row_hb.add_child(_server_btn) + _server_btn.size_flags_horizontal = Control.SIZE_EXPAND_FILL + + var pc_lbl := Label.new() + pc_lbl.text = "0 / 32" + pc_lbl.custom_minimum_size = Vector2(80, 0) + pc_lbl.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + pc_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT + pc_lbl.add_theme_font_size_override("font_size", 14) + pc_lbl.add_theme_color_override("font_color", Color(0.5, 0.65, 0.8)) + row_hb.add_child(pc_lbl) + + +func _build_player_setup(parent: Panel) -> void: + var vb := _vbox_in(parent, 20.0) + vb.add_theme_constant_override("separation", 12) + + vb.add_child(_section_label("Player Setup")) + vb.add_child(HSeparator.new()) + + vb.add_child(_field_label("Player Name:")) + + _name_input = LineEdit.new() + _name_input.placeholder_text = "Enter your callsign..." + _name_input.custom_minimum_size = Vector2(0, 44) + _name_input.add_theme_font_size_override("font_size", 16) + _name_input.text_changed.connect(_on_name_changed) + vb.add_child(_name_input) + + var gap := Control.new() + gap.custom_minimum_size = Vector2(0, 6) + vb.add_child(gap) + + vb.add_child(_field_label("Select Race:")) + + var race_hb := HBoxContainer.new() + race_hb.custom_minimum_size = Vector2(0, 58) + race_hb.add_theme_constant_override("separation", 10) + vb.add_child(race_hb) + + var race_cfg: Array = [ + ["Race 1", Color(0.25, 0.5, 1.0)], + ["Race 2", Color(1.0, 0.45, 0.2)], + ["Race 3", Color(0.25, 0.9, 0.4)], + ] + for i in 3: + var btn := _make_race_button(race_cfg[i][0], race_cfg[i][1]) + btn.pressed.connect(_on_race_selected.bind(i + 1)) + race_hb.add_child(btn) + _race_buttons.append(btn) + + var filler := Control.new() + filler.size_flags_vertical = Control.SIZE_EXPAND_FILL + vb.add_child(filler) + + _join_button = Button.new() + _join_button.text = "JOIN GAME" + _join_button.custom_minimum_size = Vector2(0, 64) + _join_button.disabled = true + _join_button.add_theme_font_size_override("font_size", 22) + _join_button.add_theme_color_override("font_color", Color(0.35, 1.0, 0.45)) + _join_button.add_theme_color_override("font_color_disabled", Color(0.3, 0.35, 0.3, 0.6)) + + var jn := _flat_box(Color(0.07, 0.28, 0.1, 1.0), 7) + var jh := _flat_box(Color(0.1, 0.42, 0.14, 1.0), 7) + var jd := _flat_box(Color(0.06, 0.09, 0.07, 0.5), 7) + _join_button.add_theme_stylebox_override("normal", jn) + _join_button.add_theme_stylebox_override("hover", jh) + _join_button.add_theme_stylebox_override("disabled", jd) + + _join_button.pressed.connect(_on_join_pressed) + vb.add_child(_join_button) + + +func _make_race_button(label_text: String, col: Color) -> Button: + var btn := Button.new() + btn.text = label_text + btn.toggle_mode = true + btn.size_flags_horizontal = Control.SIZE_EXPAND_FILL + btn.custom_minimum_size = Vector2(0, 58) + btn.add_theme_font_size_override("font_size", 15) + btn.add_theme_color_override("font_color", Color.WHITE) + + var dark := Color(col.r * 0.22, col.g * 0.22, col.b * 0.22, 1.0) + var mid := Color(col.r * 0.38, col.g * 0.38, col.b * 0.38, 1.0) + var lite := Color(col.r * 0.5, col.g * 0.5, col.b * 0.5, 1.0) + + var s_n := _flat_box(dark, 6) + var s_h := _flat_box(mid, 6) + var s_p := _flat_box(lite, 6) + s_p.set_border_width_all(2) + s_p.border_color = col + + btn.add_theme_stylebox_override("normal", s_n) + btn.add_theme_stylebox_override("hover", s_h) + btn.add_theme_stylebox_override("pressed", s_p) + return btn + + +func _on_name_changed(_text: String) -> void: + _update_join() + + +func _on_race_selected(race: int) -> void: + _selected_race = race + for i in _race_buttons.size(): + _race_buttons[i].button_pressed = (i + 1 == race) + _update_join() + + +func _on_server_selected(server: String) -> void: + _selected_server = server + _server_btn.button_pressed = true + _update_join() + + +func _update_join() -> void: + _join_button.disabled = ( + _name_input.text.strip_edges().is_empty() + or _selected_race == 0 + or _selected_server.is_empty() + ) + + +func _on_join_pressed() -> void: + GameConfig.player_name = _name_input.text.strip_edges() + GameConfig.player_race = _selected_race + get_tree().change_scene_to_file("res://world.tscn") diff --git a/spacewar/server_browser.gd.uid b/spacewar/server_browser.gd.uid new file mode 100644 index 0000000..8c00144 --- /dev/null +++ b/spacewar/server_browser.gd.uid @@ -0,0 +1 @@ +uid://dg0sojl1wf8dh diff --git a/spacewar/server_browser.tscn b/spacewar/server_browser.tscn new file mode 100644 index 0000000..e1dbc5d --- /dev/null +++ b/spacewar/server_browser.tscn @@ -0,0 +1,8 @@ +[gd_scene format=3 uid="uid://doolmlvruun6o"] + +[ext_resource type="Script" path="res://server_browser.gd" id="1_script"] + +[node name="ServerBrowser" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource("1_script") diff --git a/spacewar/ship_movement.gd b/spacewar/ship_movement.gd new file mode 100644 index 0000000..986da43 --- /dev/null +++ b/spacewar/ship_movement.gd @@ -0,0 +1,110 @@ +extends CharacterBody2D + +const BULLET_SCENE = preload("res://bullet.tscn") + +var _fire_cooldown: float = 0.0 +var health: int = 0 +var _dead: bool = false +var _invincible: bool = false +var _invincible_timer: float = 0.0 + +func _ready() -> void: + if GameConfig.player_ship_path.is_empty(): + visible = false + set_physics_process(false) + GameConfig.team_selected.connect(_on_team_selected) + else: + _init_player() + + +func _on_team_selected() -> void: + _init_player() + + +func _init_player() -> void: + var sprite := get_node_or_null("Sprite2D") + if sprite and not GameConfig.player_ship_path.is_empty(): + sprite.texture = load(GameConfig.player_ship_path) + set_physics_process(true) + _respawn() + +func _physics_process(delta: float) -> void: + if _dead: + return + + # 1. INVINCIBILITY BLINK + if _invincible: + _invincible_timer -= delta + modulate.a = 0.3 if int(_invincible_timer * 8) % 2 == 0 else 1.0 + if _invincible_timer <= 0.0: + _invincible = false + modulate.a = 1.0 + + # 2. ROTATION + if Input.is_action_pressed("move_right"): + rotation += GameConfig.ship_rotation_speed * delta + if Input.is_action_pressed("move_left"): + rotation -= GameConfig.ship_rotation_speed * delta + + # 3. THRUST + if Input.is_action_pressed("move_up"): + velocity += Vector2.UP.rotated(rotation) * GameConfig.ship_thrust * delta + if Input.is_action_pressed("move_down"): + velocity += Vector2.DOWN.rotated(rotation) * GameConfig.ship_thrust * delta + + velocity = velocity.limit_length(GameConfig.ship_max_speed) + + move_and_slide() + + # 4. SHOOT + _fire_cooldown -= delta + if Input.is_action_pressed("shoot") and _fire_cooldown <= 0.0: + _fire_cooldown = GameConfig.ship_fire_rate + var bullet = BULLET_SCENE.instantiate() + bullet.global_position = global_position + Vector2.UP.rotated(rotation) * 40.0 + bullet.velocity = Vector2.UP.rotated(rotation) * GameConfig.bullet_speed + velocity + bullet.source = self + get_parent().add_child(bullet) + + # 5. WALL COLLISION + var screen = get_viewport_rect().size + if global_position.x < 0 or global_position.x > screen.x: + velocity.x = 0 + global_position.x = clamp(global_position.x, 0, screen.x) + take_damage(GameConfig.ship_wall_damage) + if global_position.y < 0 or global_position.y > screen.y: + velocity.y = 0 + global_position.y = clamp(global_position.y, 0, screen.y) + take_damage(GameConfig.ship_wall_damage) + +func take_damage(amount: int) -> void: + if _invincible or _dead: + return + health = max(0, health - amount) + _update_hud() + if health == 0: + _die() + +func _die() -> void: + _dead = true + visible = false + velocity = Vector2.ZERO + await get_tree().create_timer(GameConfig.ship_respawn_delay).timeout + _respawn() + +func _respawn() -> void: + var screen = get_viewport_rect().size + global_position = screen / 2.0 + velocity = Vector2.ZERO + rotation = 0.0 + health = GameConfig.ship_max_health + _dead = false + visible = true + _invincible = true + _invincible_timer = GameConfig.ship_invincibility_time + _update_hud() + +func _update_hud() -> void: + var label = get_node_or_null("/root/World/HUD/HealthLabel") + if label: + label.text = "HP: %d / %d" % [health, GameConfig.ship_max_health] diff --git a/spacewar/ship_movement.gd.uid b/spacewar/ship_movement.gd.uid new file mode 100644 index 0000000..5fd9dc4 --- /dev/null +++ b/spacewar/ship_movement.gd.uid @@ -0,0 +1 @@ +uid://c4kj3i73wjdcj diff --git a/spacewar/team_select.gd b/spacewar/team_select.gd new file mode 100644 index 0000000..e66fe1f --- /dev/null +++ b/spacewar/team_select.gd @@ -0,0 +1,246 @@ +extends CanvasLayer + +const RACES := [ + {"id": 1, "name": "TERRAN FEDERATION", "sub": "Speed and balanced firepower", "color": Color(0.30, 0.55, 1.00)}, + {"id": 2, "name": "THE COLLECTIVE", "sub": "Heavy armor, brute force", "color": Color(1.00, 0.45, 0.18)}, + {"id": 3, "name": "IRON ORDER", "sub": "Precision strike force", "color": Color(0.28, 0.90, 0.42)}, +] + +const SHIPS := [ + { + "name": "WARBIRD", + "role": "All-Round Fighter", + "desc": "The most versatile ship in the fleet. Solid speed, reliable firepower, and enough armor to stay in the fight. Forgiving to fly and effective in any situation — the go-to choice when you're not sure what you're up against.", + "path": "res://images/ships/Example_ships/1.png", + }, + { + "name": "JAVELIN", + "role": "Fast Interceptor", + "desc": "Built for speed above everything else. Light armor means you have to pick your fights carefully, but nothing can outrun you. Best used for hit-and-run strikes, hunting weakened targets, and escaping when things go wrong.", + "path": "res://images/ships/Example_ships/1B.png", + }, + { + "name": "SPIDER", + "role": "Heavy Support", + "desc": "Slow but extremely durable. High-volume fire makes it devastating in sustained engagements. Anchors a team by holding zones and suppressing enemy movements. Stay near allies — alone you're a target, together you're a wall.", + "path": "res://images/ships/Example_ships/2a.png", + }, + { + "name": "LANCASTER", + "role": "Stealth Bomber", + "desc": "Medium speed with high burst damage potential. Built for patience — get into position, strike hard, and fade before the enemy can respond. Excels at flanking and ambushes. Requires discipline to play but punishes mistakes severely.", + "path": "res://images/ships/Example_ships/3b.png", + }, +] + +# Row layout constants (screen is 1280×800) +const ROW_X1 := 120.0 +const ROW_X2 := 1160.0 +const ROW_H := 130.0 +const ROW_GAP := 10.0 +const ROW_START := 195.0 +const IMG_W := 130.0 + +var _root: Control +var _content: Control +var _offered: Array = [] +var _chosen_race: Dictionary = {} + + +func _ready() -> void: + layer = 20 + _offered = _pick_two_races() + _build_root() + _show_race_selection() + + +func _pick_two_races() -> Array: + var pool := RACES.duplicate() + pool.shuffle() + return [pool[0], pool[1]] + + +func _build_root() -> void: + _root = Control.new() + _root.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + add_child(_root) + + var overlay := ColorRect.new() + overlay.color = Color(0.0, 0.0, 0.0, 0.65) + overlay.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + overlay.mouse_filter = Control.MOUSE_FILTER_STOP + _root.add_child(overlay) + + +func _swap_content() -> Control: + if _content: + _content.queue_free() + _content = Control.new() + _content.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + _content.mouse_filter = Control.MOUSE_FILTER_IGNORE + _root.add_child(_content) + return _content + + +# ── Race selection ─────────────────────────────────────────────────────────── + +func _show_race_selection() -> void: + var c := _swap_content() + + _label(c, "CHOOSE YOUR FACTION", 32, Color(0.42, 0.87, 1.0), + 0, 105, 1280, 160, HORIZONTAL_ALIGNMENT_CENTER) + _label(c, "This match: %s vs %s" % [_offered[0].name, _offered[1].name], + 13, Color(0.45, 0.58, 0.72), + 0, 170, 1280, 200, HORIZONTAL_ALIGNMENT_CENTER) + + var left_btn := _make_race_btn(_offered[0]) + _place(left_btn, 150, 225, 590, 540) + left_btn.pressed.connect(_on_race_chosen.bind(_offered[0])) + c.add_child(left_btn) + + var right_btn := _make_race_btn(_offered[1]) + _place(right_btn, 690, 225, 1130, 540) + right_btn.pressed.connect(_on_race_chosen.bind(_offered[1])) + c.add_child(right_btn) + + +func _on_race_chosen(race: Dictionary) -> void: + _chosen_race = race + GameConfig.player_race = race.id + _show_ship_selection() + + +# ── Ship selection ─────────────────────────────────────────────────────────── + +func _show_ship_selection() -> void: + var c := _swap_content() + + _label(c, "SELECT YOUR SHIP", 30, Color(0.42, 0.87, 1.0), + 0, 90, 1280, 145, HORIZONTAL_ALIGNMENT_CENTER) + _label(c, "Playing as — " + _chosen_race.name, 14, _chosen_race.color, + 0, 155, 1280, 185, HORIZONTAL_ALIGNMENT_CENTER) + + for i in SHIPS.size(): + var y := ROW_START + i * (ROW_H + ROW_GAP) + var btn := _make_ship_row(SHIPS[i], _chosen_race.color) + _place(btn, ROW_X1, y, ROW_X2, y + ROW_H) + btn.pressed.connect(_on_ship_chosen.bind(SHIPS[i])) + c.add_child(btn) + + +func _on_ship_chosen(ship: Dictionary) -> void: + GameConfig.player_ship_path = ship.path + GameConfig.team_selected.emit() + queue_free() + + +# ── Button builders ────────────────────────────────────────────────────────── + +func _make_race_btn(race: Dictionary) -> Button: + var btn := Button.new() + btn.text = "" + var col: Color = race.color + + var sn := _flat(Color(col.r * 0.14, col.g * 0.14, col.b * 0.14, 0.96), 12) + sn.set_border_width_all(2) + sn.border_color = Color(col.r * 0.38, col.g * 0.38, col.b * 0.38) + var sh := _flat(Color(col.r * 0.24, col.g * 0.24, col.b * 0.24, 0.96), 12) + sh.set_border_width_all(2) + sh.border_color = col + btn.add_theme_stylebox_override("normal", sn) + btn.add_theme_stylebox_override("hover", sh) + btn.add_theme_stylebox_override("pressed", sh) + + var vb := VBoxContainer.new() + vb.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + vb.offset_left = 20; vb.offset_top = 24; vb.offset_right = -20; vb.offset_bottom = -24 + vb.alignment = BoxContainer.ALIGNMENT_CENTER + vb.add_theme_constant_override("separation", 16) + vb.mouse_filter = Control.MOUSE_FILTER_IGNORE + btn.add_child(vb) + + var name_lbl := Label.new() + name_lbl.text = race.name + name_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + name_lbl.add_theme_font_size_override("font_size", 28) + name_lbl.add_theme_color_override("font_color", col) + name_lbl.mouse_filter = Control.MOUSE_FILTER_IGNORE + vb.add_child(name_lbl) + + var sep := HSeparator.new() + sep.add_theme_color_override("color", Color(col.r * 0.4, col.g * 0.4, col.b * 0.4)) + sep.mouse_filter = Control.MOUSE_FILTER_IGNORE + vb.add_child(sep) + + var sub_lbl := Label.new() + sub_lbl.text = race.sub + sub_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + sub_lbl.add_theme_font_size_override("font_size", 15) + sub_lbl.add_theme_color_override("font_color", Color(0.60, 0.70, 0.82)) + sub_lbl.mouse_filter = Control.MOUSE_FILTER_IGNORE + vb.add_child(sub_lbl) + + var hint := Label.new() + hint.text = "CLICK TO SELECT" + hint.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + hint.add_theme_font_size_override("font_size", 11) + hint.add_theme_color_override("font_color", Color(col.r * 0.5, col.g * 0.5, col.b * 0.5)) + hint.mouse_filter = Control.MOUSE_FILTER_IGNORE + vb.add_child(hint) + + return btn + + +func _make_ship_row(ship: Dictionary, accent: Color) -> Button: + var btn := Button.new() + btn.text = "" + + var sn := _flat(Color(0.06, 0.09, 0.17, 0.95), 8) + sn.set_border_width_all(1) + sn.border_color = Color(0.18, 0.28, 0.48, 0.6) + var sh := _flat(Color(0.10, 0.16, 0.28, 0.97), 8) + sh.set_border_width_all(2) + sh.border_color = accent + btn.add_theme_stylebox_override("normal", sn) + btn.add_theme_stylebox_override("hover", sh) + btn.add_theme_stylebox_override("pressed", sh) + + var tex := TextureRect.new() + tex.texture = load(ship.path) + tex.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + tex.offset_left = 8; tex.offset_top = 6; tex.offset_right = -8; tex.offset_bottom = -6 + tex.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED + tex.expand_mode = TextureRect.EXPAND_FIT_HEIGHT_PROPORTIONAL + tex.mouse_filter = Control.MOUSE_FILTER_IGNORE + btn.add_child(tex) + + return btn + + +# ── Helpers ────────────────────────────────────────────────────────────────── + +func _label(parent: Control, text: String, font_size: int, color: Color, + x1: float, y1: float, x2: float, y2: float, + align: HorizontalAlignment = HORIZONTAL_ALIGNMENT_LEFT) -> void: + var lbl := Label.new() + lbl.text = text + lbl.horizontal_alignment = align + lbl.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + lbl.add_theme_font_size_override("font_size", font_size) + lbl.add_theme_color_override("font_color", color) + _place(lbl, x1, y1, x2, y2) + parent.add_child(lbl) + + +func _place(node: Control, x1: float, y1: float, x2: float, y2: float) -> void: + node.set_anchor_and_offset(SIDE_LEFT, 0.0, x1) + node.set_anchor_and_offset(SIDE_TOP, 0.0, y1) + node.set_anchor_and_offset(SIDE_RIGHT, 0.0, x2) + node.set_anchor_and_offset(SIDE_BOTTOM, 0.0, y2) + + +func _flat(col: Color, radius: int = 0) -> StyleBoxFlat: + var s := StyleBoxFlat.new() + s.bg_color = col + s.set_corner_radius_all(radius) + return s diff --git a/spacewar/team_select.gd.uid b/spacewar/team_select.gd.uid new file mode 100644 index 0000000..5f796f2 --- /dev/null +++ b/spacewar/team_select.gd.uid @@ -0,0 +1 @@ +uid://33672ukno060 diff --git a/spacewar/team_select.tscn b/spacewar/team_select.tscn new file mode 100644 index 0000000..7b61506 --- /dev/null +++ b/spacewar/team_select.tscn @@ -0,0 +1,6 @@ +[gd_scene format=3 uid="uid://dteamselect01"] + +[ext_resource type="Script" path="res://team_select.gd" id="1_script"] + +[node name="TeamSelect" type="CanvasLayer"] +script = ExtResource("1_script") diff --git a/spacewar/tile_map.tscn b/spacewar/tile_map.tscn new file mode 100644 index 0000000..a0a74fb --- /dev/null +++ b/spacewar/tile_map.tscn @@ -0,0 +1,1550 @@ +[gd_scene format=3 uid="uid://cxarety0nbcme"] + +[ext_resource type="Texture2D" uid="uid://dglp131j5tga6" path="res://bwQ7rQ.png" id="1_7yhko"] + +[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_1n30v"] +texture = ExtResource("1_7yhko") +0:0/0 = 0 +1:0/0 = 0 +2:0/0 = 0 +3:0/0 = 0 +4:0/0 = 0 +5:0/0 = 0 +6:0/0 = 0 +7:0/0 = 0 +8:0/0 = 0 +9:0/0 = 0 +10:0/0 = 0 +11:0/0 = 0 +12:0/0 = 0 +13:0/0 = 0 +14:0/0 = 0 +15:0/0 = 0 +16:0/0 = 0 +17:0/0 = 0 +18:0/0 = 0 +19:0/0 = 0 +20:0/0 = 0 +21:0/0 = 0 +22:0/0 = 0 +23:0/0 = 0 +24:0/0 = 0 +25:0/0 = 0 +26:0/0 = 0 +27:0/0 = 0 +28:0/0 = 0 +29:0/0 = 0 +30:0/0 = 0 +31:0/0 = 0 +32:0/0 = 0 +33:0/0 = 0 +34:0/0 = 0 +35:0/0 = 0 +36:0/0 = 0 +37:0/0 = 0 +38:0/0 = 0 +39:0/0 = 0 +40:0/0 = 0 +41:0/0 = 0 +42:0/0 = 0 +43:0/0 = 0 +44:0/0 = 0 +45:0/0 = 0 +46:0/0 = 0 +47:0/0 = 0 +0:1/0 = 0 +1:1/0 = 0 +2:1/0 = 0 +3:1/0 = 0 +4:1/0 = 0 +5:1/0 = 0 +6:1/0 = 0 +7:1/0 = 0 +8:1/0 = 0 +9:1/0 = 0 +10:1/0 = 0 +11:1/0 = 0 +12:1/0 = 0 +13:1/0 = 0 +14:1/0 = 0 +15:1/0 = 0 +16:1/0 = 0 +17:1/0 = 0 +18:1/0 = 0 +19:1/0 = 0 +20:1/0 = 0 +21:1/0 = 0 +22:1/0 = 0 +23:1/0 = 0 +24:1/0 = 0 +25:1/0 = 0 +26:1/0 = 0 +27:1/0 = 0 +28:1/0 = 0 +29:1/0 = 0 +30:1/0 = 0 +31:1/0 = 0 +32:1/0 = 0 +33:1/0 = 0 +34:1/0 = 0 +35:1/0 = 0 +36:1/0 = 0 +37:1/0 = 0 +38:1/0 = 0 +39:1/0 = 0 +40:1/0 = 0 +41:1/0 = 0 +42:1/0 = 0 +43:1/0 = 0 +44:1/0 = 0 +45:1/0 = 0 +46:1/0 = 0 +47:1/0 = 0 +0:2/0 = 0 +1:2/0 = 0 +2:2/0 = 0 +3:2/0 = 0 +4:2/0 = 0 +5:2/0 = 0 +6:2/0 = 0 +7:2/0 = 0 +8:2/0 = 0 +9:2/0 = 0 +10:2/0 = 0 +11:2/0 = 0 +12:2/0 = 0 +13:2/0 = 0 +14:2/0 = 0 +15:2/0 = 0 +16:2/0 = 0 +17:2/0 = 0 +18:2/0 = 0 +19:2/0 = 0 +20:2/0 = 0 +21:2/0 = 0 +22:2/0 = 0 +23:2/0 = 0 +24:2/0 = 0 +25:2/0 = 0 +26:2/0 = 0 +27:2/0 = 0 +28:2/0 = 0 +29:2/0 = 0 +30:2/0 = 0 +31:2/0 = 0 +32:2/0 = 0 +33:2/0 = 0 +34:2/0 = 0 +35:2/0 = 0 +36:2/0 = 0 +37:2/0 = 0 +38:2/0 = 0 +39:2/0 = 0 +40:2/0 = 0 +41:2/0 = 0 +42:2/0 = 0 +43:2/0 = 0 +44:2/0 = 0 +45:2/0 = 0 +46:2/0 = 0 +47:2/0 = 0 +0:3/0 = 0 +1:3/0 = 0 +2:3/0 = 0 +3:3/0 = 0 +4:3/0 = 0 +5:3/0 = 0 +6:3/0 = 0 +7:3/0 = 0 +8:3/0 = 0 +9:3/0 = 0 +10:3/0 = 0 +11:3/0 = 0 +12:3/0 = 0 +13:3/0 = 0 +14:3/0 = 0 +15:3/0 = 0 +16:3/0 = 0 +17:3/0 = 0 +18:3/0 = 0 +19:3/0 = 0 +20:3/0 = 0 +21:3/0 = 0 +22:3/0 = 0 +23:3/0 = 0 +24:3/0 = 0 +25:3/0 = 0 +26:3/0 = 0 +27:3/0 = 0 +28:3/0 = 0 +29:3/0 = 0 +30:3/0 = 0 +31:3/0 = 0 +32:3/0 = 0 +33:3/0 = 0 +34:3/0 = 0 +35:3/0 = 0 +36:3/0 = 0 +37:3/0 = 0 +38:3/0 = 0 +39:3/0 = 0 +40:3/0 = 0 +41:3/0 = 0 +42:3/0 = 0 +43:3/0 = 0 +44:3/0 = 0 +45:3/0 = 0 +46:3/0 = 0 +47:3/0 = 0 +0:4/0 = 0 +1:4/0 = 0 +2:4/0 = 0 +3:4/0 = 0 +4:4/0 = 0 +5:4/0 = 0 +6:4/0 = 0 +7:4/0 = 0 +8:4/0 = 0 +9:4/0 = 0 +10:4/0 = 0 +11:4/0 = 0 +12:4/0 = 0 +13:4/0 = 0 +14:4/0 = 0 +15:4/0 = 0 +16:4/0 = 0 +17:4/0 = 0 +18:4/0 = 0 +19:4/0 = 0 +20:4/0 = 0 +21:4/0 = 0 +22:4/0 = 0 +23:4/0 = 0 +24:4/0 = 0 +25:4/0 = 0 +26:4/0 = 0 +27:4/0 = 0 +28:4/0 = 0 +29:4/0 = 0 +30:4/0 = 0 +31:4/0 = 0 +32:4/0 = 0 +33:4/0 = 0 +34:4/0 = 0 +35:4/0 = 0 +36:4/0 = 0 +37:4/0 = 0 +38:4/0 = 0 +39:4/0 = 0 +40:4/0 = 0 +41:4/0 = 0 +42:4/0 = 0 +43:4/0 = 0 +44:4/0 = 0 +45:4/0 = 0 +46:4/0 = 0 +47:4/0 = 0 +0:5/0 = 0 +1:5/0 = 0 +2:5/0 = 0 +3:5/0 = 0 +4:5/0 = 0 +5:5/0 = 0 +6:5/0 = 0 +7:5/0 = 0 +8:5/0 = 0 +9:5/0 = 0 +10:5/0 = 0 +11:5/0 = 0 +12:5/0 = 0 +13:5/0 = 0 +14:5/0 = 0 +15:5/0 = 0 +16:5/0 = 0 +17:5/0 = 0 +18:5/0 = 0 +19:5/0 = 0 +20:5/0 = 0 +21:5/0 = 0 +22:5/0 = 0 +23:5/0 = 0 +24:5/0 = 0 +25:5/0 = 0 +26:5/0 = 0 +27:5/0 = 0 +28:5/0 = 0 +29:5/0 = 0 +30:5/0 = 0 +31:5/0 = 0 +32:5/0 = 0 +33:5/0 = 0 +34:5/0 = 0 +35:5/0 = 0 +36:5/0 = 0 +37:5/0 = 0 +38:5/0 = 0 +39:5/0 = 0 +40:5/0 = 0 +41:5/0 = 0 +42:5/0 = 0 +43:5/0 = 0 +44:5/0 = 0 +45:5/0 = 0 +46:5/0 = 0 +47:5/0 = 0 +0:6/0 = 0 +1:6/0 = 0 +2:6/0 = 0 +3:6/0 = 0 +4:6/0 = 0 +5:6/0 = 0 +6:6/0 = 0 +7:6/0 = 0 +8:6/0 = 0 +9:6/0 = 0 +10:6/0 = 0 +11:6/0 = 0 +12:6/0 = 0 +13:6/0 = 0 +14:6/0 = 0 +15:6/0 = 0 +16:6/0 = 0 +17:6/0 = 0 +18:6/0 = 0 +19:6/0 = 0 +20:6/0 = 0 +21:6/0 = 0 +22:6/0 = 0 +23:6/0 = 0 +24:6/0 = 0 +25:6/0 = 0 +26:6/0 = 0 +27:6/0 = 0 +28:6/0 = 0 +29:6/0 = 0 +30:6/0 = 0 +31:6/0 = 0 +32:6/0 = 0 +33:6/0 = 0 +34:6/0 = 0 +35:6/0 = 0 +36:6/0 = 0 +37:6/0 = 0 +38:6/0 = 0 +39:6/0 = 0 +40:6/0 = 0 +41:6/0 = 0 +42:6/0 = 0 +43:6/0 = 0 +44:6/0 = 0 +45:6/0 = 0 +46:6/0 = 0 +47:6/0 = 0 +0:7/0 = 0 +1:7/0 = 0 +2:7/0 = 0 +3:7/0 = 0 +4:7/0 = 0 +5:7/0 = 0 +6:7/0 = 0 +7:7/0 = 0 +8:7/0 = 0 +9:7/0 = 0 +10:7/0 = 0 +11:7/0 = 0 +12:7/0 = 0 +13:7/0 = 0 +14:7/0 = 0 +15:7/0 = 0 +16:7/0 = 0 +17:7/0 = 0 +18:7/0 = 0 +19:7/0 = 0 +20:7/0 = 0 +21:7/0 = 0 +22:7/0 = 0 +23:7/0 = 0 +24:7/0 = 0 +25:7/0 = 0 +26:7/0 = 0 +27:7/0 = 0 +28:7/0 = 0 +29:7/0 = 0 +30:7/0 = 0 +31:7/0 = 0 +32:7/0 = 0 +33:7/0 = 0 +34:7/0 = 0 +35:7/0 = 0 +36:7/0 = 0 +37:7/0 = 0 +38:7/0 = 0 +39:7/0 = 0 +40:7/0 = 0 +41:7/0 = 0 +42:7/0 = 0 +43:7/0 = 0 +44:7/0 = 0 +45:7/0 = 0 +46:7/0 = 0 +47:7/0 = 0 +0:8/0 = 0 +1:8/0 = 0 +2:8/0 = 0 +3:8/0 = 0 +4:8/0 = 0 +5:8/0 = 0 +6:8/0 = 0 +7:8/0 = 0 +8:8/0 = 0 +9:8/0 = 0 +10:8/0 = 0 +11:8/0 = 0 +12:8/0 = 0 +13:8/0 = 0 +14:8/0 = 0 +15:8/0 = 0 +16:8/0 = 0 +17:8/0 = 0 +18:8/0 = 0 +19:8/0 = 0 +20:8/0 = 0 +21:8/0 = 0 +22:8/0 = 0 +23:8/0 = 0 +24:8/0 = 0 +25:8/0 = 0 +26:8/0 = 0 +27:8/0 = 0 +28:8/0 = 0 +29:8/0 = 0 +30:8/0 = 0 +31:8/0 = 0 +32:8/0 = 0 +33:8/0 = 0 +34:8/0 = 0 +35:8/0 = 0 +36:8/0 = 0 +37:8/0 = 0 +38:8/0 = 0 +39:8/0 = 0 +40:8/0 = 0 +41:8/0 = 0 +42:8/0 = 0 +43:8/0 = 0 +44:8/0 = 0 +45:8/0 = 0 +46:8/0 = 0 +47:8/0 = 0 +0:9/0 = 0 +1:9/0 = 0 +2:9/0 = 0 +3:9/0 = 0 +4:9/0 = 0 +5:9/0 = 0 +6:9/0 = 0 +7:9/0 = 0 +8:9/0 = 0 +9:9/0 = 0 +10:9/0 = 0 +11:9/0 = 0 +12:9/0 = 0 +13:9/0 = 0 +14:9/0 = 0 +15:9/0 = 0 +16:9/0 = 0 +17:9/0 = 0 +18:9/0 = 0 +19:9/0 = 0 +20:9/0 = 0 +21:9/0 = 0 +22:9/0 = 0 +23:9/0 = 0 +24:9/0 = 0 +25:9/0 = 0 +26:9/0 = 0 +27:9/0 = 0 +28:9/0 = 0 +29:9/0 = 0 +30:9/0 = 0 +31:9/0 = 0 +32:9/0 = 0 +33:9/0 = 0 +34:9/0 = 0 +35:9/0 = 0 +36:9/0 = 0 +37:9/0 = 0 +38:9/0 = 0 +39:9/0 = 0 +40:9/0 = 0 +41:9/0 = 0 +42:9/0 = 0 +43:9/0 = 0 +44:9/0 = 0 +45:9/0 = 0 +46:9/0 = 0 +47:9/0 = 0 +0:10/0 = 0 +1:10/0 = 0 +2:10/0 = 0 +3:10/0 = 0 +4:10/0 = 0 +5:10/0 = 0 +6:10/0 = 0 +7:10/0 = 0 +8:10/0 = 0 +9:10/0 = 0 +10:10/0 = 0 +11:10/0 = 0 +12:10/0 = 0 +13:10/0 = 0 +14:10/0 = 0 +15:10/0 = 0 +16:10/0 = 0 +17:10/0 = 0 +18:10/0 = 0 +19:10/0 = 0 +20:10/0 = 0 +21:10/0 = 0 +22:10/0 = 0 +23:10/0 = 0 +24:10/0 = 0 +25:10/0 = 0 +26:10/0 = 0 +27:10/0 = 0 +28:10/0 = 0 +29:10/0 = 0 +30:10/0 = 0 +31:10/0 = 0 +32:10/0 = 0 +33:10/0 = 0 +34:10/0 = 0 +35:10/0 = 0 +36:10/0 = 0 +37:10/0 = 0 +38:10/0 = 0 +39:10/0 = 0 +40:10/0 = 0 +41:10/0 = 0 +42:10/0 = 0 +43:10/0 = 0 +44:10/0 = 0 +45:10/0 = 0 +46:10/0 = 0 +47:10/0 = 0 +0:11/0 = 0 +1:11/0 = 0 +2:11/0 = 0 +3:11/0 = 0 +4:11/0 = 0 +5:11/0 = 0 +6:11/0 = 0 +7:11/0 = 0 +8:11/0 = 0 +9:11/0 = 0 +10:11/0 = 0 +11:11/0 = 0 +12:11/0 = 0 +13:11/0 = 0 +14:11/0 = 0 +15:11/0 = 0 +16:11/0 = 0 +17:11/0 = 0 +18:11/0 = 0 +19:11/0 = 0 +20:11/0 = 0 +21:11/0 = 0 +22:11/0 = 0 +23:11/0 = 0 +24:11/0 = 0 +25:11/0 = 0 +26:11/0 = 0 +27:11/0 = 0 +28:11/0 = 0 +29:11/0 = 0 +30:11/0 = 0 +31:11/0 = 0 +32:11/0 = 0 +33:11/0 = 0 +34:11/0 = 0 +35:11/0 = 0 +36:11/0 = 0 +37:11/0 = 0 +38:11/0 = 0 +39:11/0 = 0 +40:11/0 = 0 +41:11/0 = 0 +42:11/0 = 0 +43:11/0 = 0 +44:11/0 = 0 +45:11/0 = 0 +46:11/0 = 0 +47:11/0 = 0 +0:12/0 = 0 +1:12/0 = 0 +2:12/0 = 0 +3:12/0 = 0 +4:12/0 = 0 +5:12/0 = 0 +6:12/0 = 0 +7:12/0 = 0 +8:12/0 = 0 +9:12/0 = 0 +10:12/0 = 0 +11:12/0 = 0 +12:12/0 = 0 +13:12/0 = 0 +14:12/0 = 0 +15:12/0 = 0 +16:12/0 = 0 +17:12/0 = 0 +18:12/0 = 0 +19:12/0 = 0 +20:12/0 = 0 +21:12/0 = 0 +22:12/0 = 0 +23:12/0 = 0 +24:12/0 = 0 +25:12/0 = 0 +26:12/0 = 0 +27:12/0 = 0 +28:12/0 = 0 +29:12/0 = 0 +30:12/0 = 0 +31:12/0 = 0 +32:12/0 = 0 +33:12/0 = 0 +34:12/0 = 0 +35:12/0 = 0 +36:12/0 = 0 +37:12/0 = 0 +38:12/0 = 0 +39:12/0 = 0 +40:12/0 = 0 +41:12/0 = 0 +42:12/0 = 0 +43:12/0 = 0 +44:12/0 = 0 +45:12/0 = 0 +46:12/0 = 0 +47:12/0 = 0 +0:13/0 = 0 +1:13/0 = 0 +2:13/0 = 0 +3:13/0 = 0 +4:13/0 = 0 +5:13/0 = 0 +6:13/0 = 0 +7:13/0 = 0 +8:13/0 = 0 +9:13/0 = 0 +10:13/0 = 0 +11:13/0 = 0 +12:13/0 = 0 +13:13/0 = 0 +14:13/0 = 0 +15:13/0 = 0 +16:13/0 = 0 +17:13/0 = 0 +18:13/0 = 0 +19:13/0 = 0 +20:13/0 = 0 +21:13/0 = 0 +22:13/0 = 0 +23:13/0 = 0 +24:13/0 = 0 +25:13/0 = 0 +26:13/0 = 0 +27:13/0 = 0 +28:13/0 = 0 +29:13/0 = 0 +30:13/0 = 0 +31:13/0 = 0 +32:13/0 = 0 +33:13/0 = 0 +34:13/0 = 0 +35:13/0 = 0 +36:13/0 = 0 +37:13/0 = 0 +38:13/0 = 0 +39:13/0 = 0 +40:13/0 = 0 +41:13/0 = 0 +42:13/0 = 0 +43:13/0 = 0 +44:13/0 = 0 +45:13/0 = 0 +46:13/0 = 0 +47:13/0 = 0 +0:14/0 = 0 +1:14/0 = 0 +2:14/0 = 0 +3:14/0 = 0 +4:14/0 = 0 +5:14/0 = 0 +6:14/0 = 0 +7:14/0 = 0 +8:14/0 = 0 +9:14/0 = 0 +10:14/0 = 0 +11:14/0 = 0 +12:14/0 = 0 +13:14/0 = 0 +14:14/0 = 0 +15:14/0 = 0 +16:14/0 = 0 +17:14/0 = 0 +18:14/0 = 0 +19:14/0 = 0 +20:14/0 = 0 +21:14/0 = 0 +22:14/0 = 0 +23:14/0 = 0 +24:14/0 = 0 +25:14/0 = 0 +26:14/0 = 0 +27:14/0 = 0 +28:14/0 = 0 +29:14/0 = 0 +30:14/0 = 0 +31:14/0 = 0 +32:14/0 = 0 +33:14/0 = 0 +34:14/0 = 0 +35:14/0 = 0 +36:14/0 = 0 +37:14/0 = 0 +38:14/0 = 0 +39:14/0 = 0 +40:14/0 = 0 +41:14/0 = 0 +42:14/0 = 0 +43:14/0 = 0 +44:14/0 = 0 +45:14/0 = 0 +46:14/0 = 0 +47:14/0 = 0 +0:15/0 = 0 +1:15/0 = 0 +2:15/0 = 0 +3:15/0 = 0 +4:15/0 = 0 +5:15/0 = 0 +6:15/0 = 0 +7:15/0 = 0 +8:15/0 = 0 +9:15/0 = 0 +10:15/0 = 0 +11:15/0 = 0 +12:15/0 = 0 +13:15/0 = 0 +14:15/0 = 0 +15:15/0 = 0 +16:15/0 = 0 +17:15/0 = 0 +18:15/0 = 0 +19:15/0 = 0 +20:15/0 = 0 +21:15/0 = 0 +22:15/0 = 0 +23:15/0 = 0 +24:15/0 = 0 +25:15/0 = 0 +26:15/0 = 0 +27:15/0 = 0 +28:15/0 = 0 +29:15/0 = 0 +30:15/0 = 0 +31:15/0 = 0 +32:15/0 = 0 +33:15/0 = 0 +34:15/0 = 0 +35:15/0 = 0 +36:15/0 = 0 +37:15/0 = 0 +38:15/0 = 0 +39:15/0 = 0 +40:15/0 = 0 +41:15/0 = 0 +42:15/0 = 0 +43:15/0 = 0 +44:15/0 = 0 +45:15/0 = 0 +46:15/0 = 0 +47:15/0 = 0 +0:16/0 = 0 +1:16/0 = 0 +2:16/0 = 0 +3:16/0 = 0 +4:16/0 = 0 +5:16/0 = 0 +6:16/0 = 0 +7:16/0 = 0 +8:16/0 = 0 +9:16/0 = 0 +10:16/0 = 0 +11:16/0 = 0 +12:16/0 = 0 +13:16/0 = 0 +14:16/0 = 0 +15:16/0 = 0 +16:16/0 = 0 +17:16/0 = 0 +18:16/0 = 0 +19:16/0 = 0 +20:16/0 = 0 +21:16/0 = 0 +22:16/0 = 0 +23:16/0 = 0 +24:16/0 = 0 +25:16/0 = 0 +26:16/0 = 0 +27:16/0 = 0 +28:16/0 = 0 +29:16/0 = 0 +30:16/0 = 0 +31:16/0 = 0 +32:16/0 = 0 +33:16/0 = 0 +34:16/0 = 0 +35:16/0 = 0 +36:16/0 = 0 +37:16/0 = 0 +38:16/0 = 0 +39:16/0 = 0 +40:16/0 = 0 +41:16/0 = 0 +42:16/0 = 0 +43:16/0 = 0 +44:16/0 = 0 +45:16/0 = 0 +46:16/0 = 0 +47:16/0 = 0 +0:17/0 = 0 +1:17/0 = 0 +2:17/0 = 0 +3:17/0 = 0 +4:17/0 = 0 +5:17/0 = 0 +6:17/0 = 0 +7:17/0 = 0 +8:17/0 = 0 +9:17/0 = 0 +10:17/0 = 0 +11:17/0 = 0 +12:17/0 = 0 +13:17/0 = 0 +14:17/0 = 0 +15:17/0 = 0 +16:17/0 = 0 +17:17/0 = 0 +18:17/0 = 0 +19:17/0 = 0 +20:17/0 = 0 +21:17/0 = 0 +22:17/0 = 0 +23:17/0 = 0 +24:17/0 = 0 +25:17/0 = 0 +26:17/0 = 0 +27:17/0 = 0 +28:17/0 = 0 +29:17/0 = 0 +30:17/0 = 0 +31:17/0 = 0 +32:17/0 = 0 +33:17/0 = 0 +34:17/0 = 0 +35:17/0 = 0 +36:17/0 = 0 +37:17/0 = 0 +38:17/0 = 0 +39:17/0 = 0 +40:17/0 = 0 +41:17/0 = 0 +42:17/0 = 0 +43:17/0 = 0 +44:17/0 = 0 +45:17/0 = 0 +46:17/0 = 0 +47:17/0 = 0 +0:18/0 = 0 +1:18/0 = 0 +2:18/0 = 0 +3:18/0 = 0 +4:18/0 = 0 +5:18/0 = 0 +6:18/0 = 0 +7:18/0 = 0 +8:18/0 = 0 +9:18/0 = 0 +10:18/0 = 0 +11:18/0 = 0 +12:18/0 = 0 +13:18/0 = 0 +14:18/0 = 0 +15:18/0 = 0 +16:18/0 = 0 +17:18/0 = 0 +18:18/0 = 0 +19:18/0 = 0 +20:18/0 = 0 +21:18/0 = 0 +22:18/0 = 0 +23:18/0 = 0 +24:18/0 = 0 +25:18/0 = 0 +26:18/0 = 0 +27:18/0 = 0 +28:18/0 = 0 +29:18/0 = 0 +30:18/0 = 0 +31:18/0 = 0 +32:18/0 = 0 +33:18/0 = 0 +34:18/0 = 0 +35:18/0 = 0 +36:18/0 = 0 +37:18/0 = 0 +38:18/0 = 0 +39:18/0 = 0 +40:18/0 = 0 +41:18/0 = 0 +42:18/0 = 0 +43:18/0 = 0 +44:18/0 = 0 +45:18/0 = 0 +46:18/0 = 0 +47:18/0 = 0 +0:19/0 = 0 +1:19/0 = 0 +2:19/0 = 0 +3:19/0 = 0 +4:19/0 = 0 +5:19/0 = 0 +6:19/0 = 0 +7:19/0 = 0 +8:19/0 = 0 +9:19/0 = 0 +10:19/0 = 0 +11:19/0 = 0 +12:19/0 = 0 +13:19/0 = 0 +14:19/0 = 0 +15:19/0 = 0 +16:19/0 = 0 +17:19/0 = 0 +18:19/0 = 0 +19:19/0 = 0 +20:19/0 = 0 +21:19/0 = 0 +22:19/0 = 0 +23:19/0 = 0 +24:19/0 = 0 +25:19/0 = 0 +26:19/0 = 0 +27:19/0 = 0 +28:19/0 = 0 +29:19/0 = 0 +30:19/0 = 0 +31:19/0 = 0 +32:19/0 = 0 +33:19/0 = 0 +34:19/0 = 0 +35:19/0 = 0 +36:19/0 = 0 +37:19/0 = 0 +38:19/0 = 0 +39:19/0 = 0 +40:19/0 = 0 +41:19/0 = 0 +42:19/0 = 0 +43:19/0 = 0 +44:19/0 = 0 +45:19/0 = 0 +46:19/0 = 0 +47:19/0 = 0 +0:20/0 = 0 +1:20/0 = 0 +2:20/0 = 0 +3:20/0 = 0 +4:20/0 = 0 +5:20/0 = 0 +6:20/0 = 0 +7:20/0 = 0 +8:20/0 = 0 +9:20/0 = 0 +10:20/0 = 0 +11:20/0 = 0 +12:20/0 = 0 +13:20/0 = 0 +14:20/0 = 0 +15:20/0 = 0 +16:20/0 = 0 +17:20/0 = 0 +18:20/0 = 0 +19:20/0 = 0 +20:20/0 = 0 +21:20/0 = 0 +22:20/0 = 0 +23:20/0 = 0 +24:20/0 = 0 +25:20/0 = 0 +26:20/0 = 0 +27:20/0 = 0 +28:20/0 = 0 +29:20/0 = 0 +30:20/0 = 0 +31:20/0 = 0 +32:20/0 = 0 +33:20/0 = 0 +34:20/0 = 0 +35:20/0 = 0 +36:20/0 = 0 +37:20/0 = 0 +38:20/0 = 0 +39:20/0 = 0 +40:20/0 = 0 +41:20/0 = 0 +42:20/0 = 0 +43:20/0 = 0 +44:20/0 = 0 +45:20/0 = 0 +46:20/0 = 0 +47:20/0 = 0 +0:21/0 = 0 +1:21/0 = 0 +2:21/0 = 0 +3:21/0 = 0 +4:21/0 = 0 +5:21/0 = 0 +6:21/0 = 0 +7:21/0 = 0 +8:21/0 = 0 +9:21/0 = 0 +10:21/0 = 0 +11:21/0 = 0 +12:21/0 = 0 +13:21/0 = 0 +14:21/0 = 0 +15:21/0 = 0 +16:21/0 = 0 +17:21/0 = 0 +18:21/0 = 0 +19:21/0 = 0 +20:21/0 = 0 +21:21/0 = 0 +22:21/0 = 0 +23:21/0 = 0 +24:21/0 = 0 +25:21/0 = 0 +26:21/0 = 0 +27:21/0 = 0 +28:21/0 = 0 +29:21/0 = 0 +30:21/0 = 0 +31:21/0 = 0 +32:21/0 = 0 +33:21/0 = 0 +34:21/0 = 0 +35:21/0 = 0 +36:21/0 = 0 +37:21/0 = 0 +38:21/0 = 0 +39:21/0 = 0 +40:21/0 = 0 +41:21/0 = 0 +42:21/0 = 0 +43:21/0 = 0 +44:21/0 = 0 +45:21/0 = 0 +46:21/0 = 0 +47:21/0 = 0 +0:22/0 = 0 +1:22/0 = 0 +2:22/0 = 0 +3:22/0 = 0 +4:22/0 = 0 +5:22/0 = 0 +6:22/0 = 0 +7:22/0 = 0 +8:22/0 = 0 +9:22/0 = 0 +10:22/0 = 0 +11:22/0 = 0 +12:22/0 = 0 +13:22/0 = 0 +14:22/0 = 0 +15:22/0 = 0 +16:22/0 = 0 +17:22/0 = 0 +18:22/0 = 0 +19:22/0 = 0 +20:22/0 = 0 +21:22/0 = 0 +22:22/0 = 0 +23:22/0 = 0 +24:22/0 = 0 +25:22/0 = 0 +26:22/0 = 0 +27:22/0 = 0 +28:22/0 = 0 +29:22/0 = 0 +30:22/0 = 0 +31:22/0 = 0 +32:22/0 = 0 +33:22/0 = 0 +34:22/0 = 0 +35:22/0 = 0 +36:22/0 = 0 +37:22/0 = 0 +38:22/0 = 0 +39:22/0 = 0 +40:22/0 = 0 +41:22/0 = 0 +42:22/0 = 0 +43:22/0 = 0 +44:22/0 = 0 +45:22/0 = 0 +46:22/0 = 0 +47:22/0 = 0 +0:23/0 = 0 +1:23/0 = 0 +2:23/0 = 0 +3:23/0 = 0 +4:23/0 = 0 +5:23/0 = 0 +6:23/0 = 0 +7:23/0 = 0 +8:23/0 = 0 +9:23/0 = 0 +10:23/0 = 0 +11:23/0 = 0 +12:23/0 = 0 +13:23/0 = 0 +14:23/0 = 0 +15:23/0 = 0 +16:23/0 = 0 +17:23/0 = 0 +18:23/0 = 0 +19:23/0 = 0 +20:23/0 = 0 +21:23/0 = 0 +22:23/0 = 0 +23:23/0 = 0 +24:23/0 = 0 +25:23/0 = 0 +26:23/0 = 0 +27:23/0 = 0 +28:23/0 = 0 +29:23/0 = 0 +30:23/0 = 0 +31:23/0 = 0 +32:23/0 = 0 +33:23/0 = 0 +34:23/0 = 0 +35:23/0 = 0 +36:23/0 = 0 +37:23/0 = 0 +38:23/0 = 0 +39:23/0 = 0 +40:23/0 = 0 +41:23/0 = 0 +42:23/0 = 0 +43:23/0 = 0 +44:23/0 = 0 +45:23/0 = 0 +46:23/0 = 0 +47:23/0 = 0 +0:24/0 = 0 +1:24/0 = 0 +2:24/0 = 0 +3:24/0 = 0 +4:24/0 = 0 +5:24/0 = 0 +6:24/0 = 0 +7:24/0 = 0 +8:24/0 = 0 +9:24/0 = 0 +10:24/0 = 0 +11:24/0 = 0 +12:24/0 = 0 +13:24/0 = 0 +14:24/0 = 0 +15:24/0 = 0 +16:24/0 = 0 +17:24/0 = 0 +18:24/0 = 0 +19:24/0 = 0 +20:24/0 = 0 +21:24/0 = 0 +22:24/0 = 0 +23:24/0 = 0 +24:24/0 = 0 +25:24/0 = 0 +26:24/0 = 0 +27:24/0 = 0 +28:24/0 = 0 +29:24/0 = 0 +30:24/0 = 0 +31:24/0 = 0 +32:24/0 = 0 +33:24/0 = 0 +34:24/0 = 0 +35:24/0 = 0 +36:24/0 = 0 +37:24/0 = 0 +38:24/0 = 0 +39:24/0 = 0 +40:24/0 = 0 +41:24/0 = 0 +42:24/0 = 0 +43:24/0 = 0 +44:24/0 = 0 +45:24/0 = 0 +46:24/0 = 0 +47:24/0 = 0 +0:25/0 = 0 +1:25/0 = 0 +2:25/0 = 0 +3:25/0 = 0 +4:25/0 = 0 +5:25/0 = 0 +6:25/0 = 0 +7:25/0 = 0 +8:25/0 = 0 +9:25/0 = 0 +10:25/0 = 0 +11:25/0 = 0 +12:25/0 = 0 +13:25/0 = 0 +14:25/0 = 0 +15:25/0 = 0 +16:25/0 = 0 +17:25/0 = 0 +18:25/0 = 0 +19:25/0 = 0 +20:25/0 = 0 +21:25/0 = 0 +22:25/0 = 0 +23:25/0 = 0 +24:25/0 = 0 +25:25/0 = 0 +26:25/0 = 0 +27:25/0 = 0 +28:25/0 = 0 +29:25/0 = 0 +30:25/0 = 0 +31:25/0 = 0 +32:25/0 = 0 +33:25/0 = 0 +34:25/0 = 0 +35:25/0 = 0 +36:25/0 = 0 +37:25/0 = 0 +38:25/0 = 0 +39:25/0 = 0 +40:25/0 = 0 +41:25/0 = 0 +42:25/0 = 0 +43:25/0 = 0 +44:25/0 = 0 +45:25/0 = 0 +46:25/0 = 0 +47:25/0 = 0 +0:26/0 = 0 +1:26/0 = 0 +2:26/0 = 0 +3:26/0 = 0 +4:26/0 = 0 +5:26/0 = 0 +6:26/0 = 0 +7:26/0 = 0 +8:26/0 = 0 +9:26/0 = 0 +10:26/0 = 0 +11:26/0 = 0 +12:26/0 = 0 +13:26/0 = 0 +14:26/0 = 0 +15:26/0 = 0 +16:26/0 = 0 +17:26/0 = 0 +18:26/0 = 0 +19:26/0 = 0 +20:26/0 = 0 +21:26/0 = 0 +22:26/0 = 0 +23:26/0 = 0 +24:26/0 = 0 +25:26/0 = 0 +26:26/0 = 0 +27:26/0 = 0 +28:26/0 = 0 +29:26/0 = 0 +30:26/0 = 0 +31:26/0 = 0 +32:26/0 = 0 +33:26/0 = 0 +34:26/0 = 0 +35:26/0 = 0 +36:26/0 = 0 +37:26/0 = 0 +38:26/0 = 0 +39:26/0 = 0 +40:26/0 = 0 +41:26/0 = 0 +42:26/0 = 0 +43:26/0 = 0 +44:26/0 = 0 +45:26/0 = 0 +46:26/0 = 0 +47:26/0 = 0 +0:27/0 = 0 +1:27/0 = 0 +2:27/0 = 0 +3:27/0 = 0 +4:27/0 = 0 +5:27/0 = 0 +6:27/0 = 0 +7:27/0 = 0 +8:27/0 = 0 +9:27/0 = 0 +10:27/0 = 0 +11:27/0 = 0 +12:27/0 = 0 +13:27/0 = 0 +14:27/0 = 0 +15:27/0 = 0 +16:27/0 = 0 +17:27/0 = 0 +18:27/0 = 0 +19:27/0 = 0 +20:27/0 = 0 +21:27/0 = 0 +22:27/0 = 0 +23:27/0 = 0 +24:27/0 = 0 +25:27/0 = 0 +26:27/0 = 0 +27:27/0 = 0 +28:27/0 = 0 +29:27/0 = 0 +30:27/0 = 0 +31:27/0 = 0 +32:27/0 = 0 +33:27/0 = 0 +34:27/0 = 0 +35:27/0 = 0 +36:27/0 = 0 +37:27/0 = 0 +38:27/0 = 0 +39:27/0 = 0 +40:27/0 = 0 +41:27/0 = 0 +42:27/0 = 0 +43:27/0 = 0 +44:27/0 = 0 +45:27/0 = 0 +46:27/0 = 0 +47:27/0 = 0 +0:28/0 = 0 +1:28/0 = 0 +2:28/0 = 0 +3:28/0 = 0 +4:28/0 = 0 +5:28/0 = 0 +6:28/0 = 0 +7:28/0 = 0 +8:28/0 = 0 +9:28/0 = 0 +10:28/0 = 0 +11:28/0 = 0 +12:28/0 = 0 +13:28/0 = 0 +14:28/0 = 0 +15:28/0 = 0 +16:28/0 = 0 +17:28/0 = 0 +18:28/0 = 0 +19:28/0 = 0 +20:28/0 = 0 +21:28/0 = 0 +22:28/0 = 0 +23:28/0 = 0 +24:28/0 = 0 +25:28/0 = 0 +26:28/0 = 0 +27:28/0 = 0 +28:28/0 = 0 +29:28/0 = 0 +30:28/0 = 0 +31:28/0 = 0 +32:28/0 = 0 +33:28/0 = 0 +34:28/0 = 0 +35:28/0 = 0 +36:28/0 = 0 +37:28/0 = 0 +38:28/0 = 0 +39:28/0 = 0 +40:28/0 = 0 +41:28/0 = 0 +42:28/0 = 0 +43:28/0 = 0 +44:28/0 = 0 +45:28/0 = 0 +46:28/0 = 0 +47:28/0 = 0 +0:29/0 = 0 +1:29/0 = 0 +2:29/0 = 0 +3:29/0 = 0 +4:29/0 = 0 +5:29/0 = 0 +6:29/0 = 0 +7:29/0 = 0 +8:29/0 = 0 +9:29/0 = 0 +10:29/0 = 0 +11:29/0 = 0 +12:29/0 = 0 +13:29/0 = 0 +14:29/0 = 0 +15:29/0 = 0 +16:29/0 = 0 +17:29/0 = 0 +18:29/0 = 0 +19:29/0 = 0 +20:29/0 = 0 +21:29/0 = 0 +22:29/0 = 0 +23:29/0 = 0 +24:29/0 = 0 +25:29/0 = 0 +26:29/0 = 0 +27:29/0 = 0 +28:29/0 = 0 +29:29/0 = 0 +30:29/0 = 0 +31:29/0 = 0 +32:29/0 = 0 +33:29/0 = 0 +34:29/0 = 0 +35:29/0 = 0 +36:29/0 = 0 +37:29/0 = 0 +38:29/0 = 0 +39:29/0 = 0 +40:29/0 = 0 +41:29/0 = 0 +42:29/0 = 0 +43:29/0 = 0 +44:29/0 = 0 +45:29/0 = 0 +46:29/0 = 0 +47:29/0 = 0 +0:30/0 = 0 +1:30/0 = 0 +2:30/0 = 0 +3:30/0 = 0 +4:30/0 = 0 +5:30/0 = 0 +6:30/0 = 0 +7:30/0 = 0 +8:30/0 = 0 +9:30/0 = 0 +10:30/0 = 0 +11:30/0 = 0 +12:30/0 = 0 +13:30/0 = 0 +14:30/0 = 0 +15:30/0 = 0 +16:30/0 = 0 +17:30/0 = 0 +18:30/0 = 0 +19:30/0 = 0 +20:30/0 = 0 +21:30/0 = 0 +22:30/0 = 0 +23:30/0 = 0 +24:30/0 = 0 +25:30/0 = 0 +26:30/0 = 0 +27:30/0 = 0 +28:30/0 = 0 +29:30/0 = 0 +30:30/0 = 0 +31:30/0 = 0 +32:30/0 = 0 +33:30/0 = 0 +34:30/0 = 0 +35:30/0 = 0 +36:30/0 = 0 +37:30/0 = 0 +38:30/0 = 0 +39:30/0 = 0 +40:30/0 = 0 +41:30/0 = 0 +42:30/0 = 0 +43:30/0 = 0 +44:30/0 = 0 +45:30/0 = 0 +46:30/0 = 0 +47:30/0 = 0 +0:31/0 = 0 +1:31/0 = 0 +2:31/0 = 0 +3:31/0 = 0 +4:31/0 = 0 +5:31/0 = 0 +6:31/0 = 0 +7:31/0 = 0 +8:31/0 = 0 +9:31/0 = 0 +10:31/0 = 0 +11:31/0 = 0 +12:31/0 = 0 +13:31/0 = 0 +14:31/0 = 0 +15:31/0 = 0 +16:31/0 = 0 +17:31/0 = 0 +18:31/0 = 0 +19:31/0 = 0 +20:31/0 = 0 +21:31/0 = 0 +22:31/0 = 0 +23:31/0 = 0 +24:31/0 = 0 +25:31/0 = 0 +26:31/0 = 0 +27:31/0 = 0 +28:31/0 = 0 +29:31/0 = 0 +30:31/0 = 0 +31:31/0 = 0 +32:31/0 = 0 +33:31/0 = 0 +34:31/0 = 0 +35:31/0 = 0 +36:31/0 = 0 +37:31/0 = 0 +38:31/0 = 0 +39:31/0 = 0 +40:31/0 = 0 +41:31/0 = 0 +42:31/0 = 0 +43:31/0 = 0 +44:31/0 = 0 +45:31/0 = 0 +46:31/0 = 0 +47:31/0 = 0 + +[sub_resource type="TileSet" id="TileSet_2uxl3"] +sources/0 = SubResource("TileSetAtlasSource_1n30v") + +[node name="TileMap" type="TileMap" unique_id=1815105899] +tile_set = SubResource("TileSet_2uxl3") +format = 2 +layer_0/tile_data = PackedInt32Array(-196613, 1048576, 0, -131077, 1048576, 1, -65541, 1048576, 2, -5, 1048576, 3, -196612, 1114112, 0, -131076, 1114112, 1, -65540, 1114112, 2, -4, 1114112, 3, -196611, 1179648, 0, -131075, 1179648, 1, -65539, 1179648, 2, -3, 1179648, 3, -196610, 1245184, 0, -131074, 1245184, 1, -65538, 1245184, 2, -2, 1245184, 3, -196609, 1048576, 0, -131073, 1048576, 1, -65537, 1048576, 2, -1, 1048576, 3, -262144, 1114112, 0, -196608, 1114112, 1, -131072, 1114112, 2, -65536, 1114112, 3, -262143, 1179648, 0, -196607, 1179648, 1, -131071, 1179648, 2, -65535, 1179648, 3, -262142, 1245184, 0, -196606, 1245184, 1, -131070, 1245184, 2, -65534, 1245184, 3, -262141, 1048576, 0, -196605, 1048576, 1, -131069, 1048576, 2, -65533, 1048576, 3, -262140, 1114112, 0, -196604, 1114112, 1, -131068, 1114112, 2, -65532, 1114112, 3, -262139, 1179648, 0, -196603, 1179648, 1, -131067, 1179648, 2, -65531, 1179648, 3, -262138, 1245184, 0, -196602, 1245184, 1, -131066, 1245184, 2, -65530, 1245184, 3, -262137, 1048576, 0, -196601, 1048576, 1, -131065, 1048576, 2, -65529, 1048576, 3, -262136, 1114112, 0, -196600, 1114112, 1, -131064, 1114112, 2, -65528, 1114112, 3, -262135, 1179648, 0, -196599, 1179648, 1, -131063, 1179648, 2, -65527, 1179648, 3, -262134, 1245184, 0, -196598, 1245184, 1, -131062, 1245184, 2, -65526, 1245184, 3, -262133, 1048576, 0, -196597, 1048576, 1, -131061, 1048576, 2, -65525, 1048576, 3, -262132, 1114112, 0, -196596, 1114112, 1, -131060, 1114112, 2, -65524, 1114112, 3, -262131, 1179648, 0, -196595, 1179648, 1, -131059, 1179648, 2, -65523, 1179648, 3, -262130, 1245184, 0, -196594, 1245184, 1, -131058, 1245184, 2, -65522, 1245184, 3, -262129, 1048576, 0, -196593, 1048576, 1, -131057, 1048576, 2, -65521, 1048576, 3, -262128, 1114112, 0, -196592, 1114112, 1, -131056, 1114112, 2, -65520, 1114112, 3, -262127, 1179648, 0, -196591, 1179648, 1, -131055, 1179648, 2, -65519, 1179648, 3, -262126, 1245184, 0, -196590, 1245184, 1, -131054, 1245184, 2, -65518, 1245184, 3) diff --git a/spacewar/world.tscn b/spacewar/world.tscn new file mode 100644 index 0000000..5433a45 --- /dev/null +++ b/spacewar/world.tscn @@ -0,0 +1,29 @@ +[gd_scene format=3 uid="uid://c77s15ns13p6y"] + +[ext_resource type="PackedScene" uid="uid://dygtdlkvo6ofl" path="res://node_2d.tscn" id="1_f3sb7"] +[ext_resource type="Texture2D" uid="uid://d0i6jwqh131b1" path="res://images/background/skybox/1.png" id="1_fj7yv"] +[ext_resource type="PackedScene" uid="uid://cpausemenu01a" path="res://pause_menu.tscn" id="2_pm"] +[ext_resource type="PackedScene" uid="uid://dteamselect01" path="res://team_select.tscn" id="3_ts"] + +[node name="World" type="Node2D" unique_id=1962020789] + +[node name="TextureRect" type="TextureRect" parent="." unique_id=1177783968] +offset_right = 1280.0 +offset_bottom = 800.0 +texture = ExtResource("1_fj7yv") + +[node name="Player" parent="." unique_id=2118863138 instance=ExtResource("1_f3sb7")] + +[node name="HUD" type="CanvasLayer" parent="."] + +[node name="HealthLabel" type="Label" parent="HUD"] +offset_left = 20.0 +offset_top = 20.0 +offset_right = 300.0 +offset_bottom = 60.0 +text = "HP: 100 / 100" +theme_override_font_sizes/font_size = 24 + +[node name="PauseMenu" parent="." instance=ExtResource("2_pm")] + +[node name="TeamSelect" parent="." instance=ExtResource("3_ts")]