Initial commit: SpaceshipTest, a top-down space RTS in Godot 4.7.1
A fleet of neon-outlined ships explores a procedurally generated, seeded infinite world: tap/joystick steering, pinch zoom, formation pivoting, planet landings, an ore economy with extractors and haulers, and player built structures (mothership, ship crafter, command centre). All art is hand-drawn with draw_* calls rather than textures, and the backgrounds are camera-relative shaders so they stay precise at large world coordinates. Includes a 35-test headless suite (tests/run_tests.sh) plus screenshot tooling that renders real frames through Xvfb and Mesa softpipe, since --headless has no GPU. Excluded from version control: .godot/ (import cache, and it holds export credentials), builds/, android/build/ and packaged APKs - all regenerable, and ~325 MB combined. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
commit
85814ce88c
192 changed files with 9602 additions and 0 deletions
93
WorldMap.gd
Normal file
93
WorldMap.gd
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
extends Control
|
||||
|
||||
@export var min_zoom: float = 0.3
|
||||
@export var max_zoom: float = 3.0
|
||||
|
||||
@onready var content: Node2D = $MapContent
|
||||
@onready var open_button: IconButton = get_node("../MapButton")
|
||||
@onready var recenter_button: IconButton = $RecenterButton
|
||||
@onready var close_button: IconButton = $CloseButton
|
||||
@onready var fleet: Node2D = get_node("../../Fleet")
|
||||
|
||||
var touches: Dictionary = {}
|
||||
var pinch_active: bool = false
|
||||
var pinch_start_distance: float = 0.0
|
||||
var pinch_start_zoom: float = 1.0
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
open_button.pressed.connect(open_map)
|
||||
recenter_button.pressed.connect(recenter_view)
|
||||
close_button.pressed.connect(close_map)
|
||||
|
||||
|
||||
func open_map() -> void:
|
||||
visible = true
|
||||
open_button.visible = false
|
||||
recenter_view()
|
||||
|
||||
|
||||
func close_map() -> void:
|
||||
visible = false
|
||||
open_button.visible = true
|
||||
touches.clear()
|
||||
pinch_active = false
|
||||
|
||||
|
||||
func recenter_view() -> void:
|
||||
var fleet_local: Vector2 = fleet.get_centroid() * content.WORLD_TO_LOCAL
|
||||
var viewport_center: Vector2 = get_viewport_rect().size / 2.0
|
||||
content.position = viewport_center - fleet_local * content.scale.x
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if not visible:
|
||||
return
|
||||
|
||||
if event is InputEventScreenTouch:
|
||||
_handle_touch(event)
|
||||
get_viewport().set_input_as_handled()
|
||||
elif event is InputEventScreenDrag:
|
||||
_handle_drag(event)
|
||||
get_viewport().set_input_as_handled()
|
||||
elif event is InputEventMagnifyGesture:
|
||||
_handle_magnify(event)
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
|
||||
func _handle_touch(event: InputEventScreenTouch) -> void:
|
||||
if event.pressed:
|
||||
touches[event.index] = event.position
|
||||
if touches.size() == 2:
|
||||
pinch_active = true
|
||||
var positions: Array = touches.values()
|
||||
pinch_start_distance = positions[0].distance_to(positions[1])
|
||||
pinch_start_zoom = content.scale.x
|
||||
else:
|
||||
touches.erase(event.index)
|
||||
if touches.size() < 2:
|
||||
pinch_active = false
|
||||
|
||||
|
||||
func _handle_drag(event: InputEventScreenDrag) -> void:
|
||||
if not touches.has(event.index):
|
||||
return
|
||||
var previous_pos: Vector2 = touches[event.index]
|
||||
touches[event.index] = event.position
|
||||
|
||||
if pinch_active and touches.size() == 2 and pinch_start_distance > 0.0:
|
||||
var positions: Array = touches.values()
|
||||
var current_distance: float = positions[0].distance_to(positions[1])
|
||||
var new_zoom: float = pinch_start_zoom * (current_distance / max(pinch_start_distance, 1.0))
|
||||
_set_zoom(new_zoom)
|
||||
elif touches.size() == 1:
|
||||
content.position += event.position - previous_pos
|
||||
|
||||
|
||||
func _handle_magnify(event: InputEventMagnifyGesture) -> void:
|
||||
_set_zoom(content.scale.x * event.factor)
|
||||
|
||||
|
||||
func _set_zoom(z: float) -> void:
|
||||
var clamped: float = clamp(z, min_zoom, max_zoom)
|
||||
content.scale = Vector2(clamped, clamped)
|
||||
Loading…
Reference in a new issue