151 lines
6.0 KiB
GDScript
151 lines
6.0 KiB
GDScript
extends Node2D
|
|
|
|
const SYSTEM_GENERATOR := preload("res://scripts/levels/system_generator.gd")
|
|
const LEVEL_BALANCE := preload("res://scripts/levels/level_balance.gd")
|
|
const CELESTIAL_BODY := preload("res://scripts/levels/celestial_body.gd")
|
|
const SERVICES_MENU := preload("res://scenes/ui/planet_services_menu.tscn")
|
|
const PLANET_MARKER := preload("res://scripts/ui/protected_planet_marker.gd")
|
|
const WORLD_SIZE := SYSTEM_GENERATOR.WORLD_SIZE
|
|
const SERVICE_APPROACH_DISTANCE := 180.0
|
|
const BOSS_TEXTURE := preload("res://assets/alien ship/Mega_boss.png")
|
|
const ENEMY_SCENE := preload("res://scenes/game/enemy_ship.tscn")
|
|
const ENEMY_TEXTURES: Array[Texture2D] = [
|
|
preload("res://assets/alien ship/Ship_1.png"),
|
|
preload("res://assets/alien ship/Ship_2.png"),
|
|
preload("res://assets/alien ship/Ship_3.png"),
|
|
preload("res://assets/alien ship/Ship_4.png"),
|
|
preload("res://assets/alien ship/Ship_5.png"),
|
|
preload("res://assets/alien ship/Ship_6.png"),
|
|
preload("res://assets/alien ship/Ship_7.png"),
|
|
preload("res://assets/alien ship/Ship_8.png"),
|
|
preload("res://assets/alien ship/Ship_9.png"),
|
|
preload("res://assets/alien ship/Ship_10.png"),
|
|
preload("res://assets/alien ship/Ship_11.png"),
|
|
]
|
|
|
|
@onready var player: CharacterBody2D = $PlayerShip
|
|
|
|
var system_data: Dictionary = {}
|
|
var protected_planet: Node2D
|
|
var services_menu: Control
|
|
var system_cleared := false
|
|
var _services_dismissed := false
|
|
var _transitioning := false
|
|
|
|
func _ready() -> void:
|
|
GameState.system_level = clampi(GameState.system_level, 1, LEVEL_BALANCE.MAX_LEVEL)
|
|
if GameState.system_seed == 0:
|
|
GameState.system_seed = GameState.create_system_seed()
|
|
system_data = SYSTEM_GENERATOR.generate(GameState.system_level, GameState.system_seed)
|
|
player.position = system_data["player_start"]
|
|
var camera := player.get_node_or_null("Camera2D") as Camera2D
|
|
if camera:
|
|
camera.limit_left = int(-WORLD_SIZE.x * 0.5)
|
|
camera.limit_right = int(WORLD_SIZE.x * 0.5)
|
|
camera.limit_top = int(-WORLD_SIZE.y * 0.5)
|
|
camera.limit_bottom = int(WORLD_SIZE.y * 0.5)
|
|
_spawn_celestial_bodies()
|
|
_spawn_enemies()
|
|
var marker := Control.new()
|
|
marker.set_script(PLANET_MARKER)
|
|
marker.name = "ProtectedPlanetMarker"
|
|
marker.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
marker.set("game", self)
|
|
$HUD/HUDRoot.add_child(marker)
|
|
marker.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
services_menu = SERVICES_MENU.instantiate() as Control
|
|
$HUD/HUDRoot.add_child(services_menu)
|
|
services_menu.connect("next_level_requested", advance_to_next_level)
|
|
services_menu.connect("closed", _on_services_closed)
|
|
|
|
func _spawn_celestial_bodies() -> void:
|
|
var bodies := Node2D.new()
|
|
bodies.name = "CelestialBodies"
|
|
bodies.z_index = -10
|
|
add_child(bodies)
|
|
var star := Node2D.new()
|
|
star.set_script(CELESTIAL_BODY)
|
|
star.name = "CentralStar"
|
|
star.set("display_name", system_data["star_name"])
|
|
star.set("body_texture", system_data["star_texture"])
|
|
star.set("radius", 140.0)
|
|
star.set("is_star", true)
|
|
bodies.add_child(star)
|
|
for index in system_data["planets"].size():
|
|
var data: Dictionary = system_data["planets"][index]
|
|
var planet := Node2D.new()
|
|
planet.set_script(CELESTIAL_BODY)
|
|
planet.name = "Planet%d" % (index + 1)
|
|
planet.set("display_name", data["name"])
|
|
planet.position = data["position"]
|
|
planet.set("body_texture", data["texture"])
|
|
planet.set("radius", data["radius"])
|
|
planet.set("is_protected", data["protected"])
|
|
bodies.add_child(planet)
|
|
if data["protected"]:
|
|
protected_planet = planet
|
|
|
|
func _spawn_enemies() -> void:
|
|
for data in system_data["enemies"]:
|
|
var enemy := ENEMY_SCENE.instantiate() as CharacterBody2D
|
|
enemy.position = data["position"]
|
|
enemy.call("apply_level_settings", GameState.system_level, int(data["tier"]))
|
|
add_child(enemy)
|
|
var texture := BOSS_TEXTURE if int(data["tier"]) == 2 else ENEMY_TEXTURES[int(data["texture_index"])]
|
|
enemy.call("configure", player, texture)
|
|
|
|
func get_remaining_enemies() -> int:
|
|
var remaining := 0
|
|
for enemy in get_tree().get_nodes_in_group("enemies"):
|
|
if is_ancestor_of(enemy) and not enemy.is_queued_for_deletion() and float(enemy.get("hull")) > 0.0:
|
|
remaining += 1
|
|
return remaining
|
|
|
|
func _physics_process(_delta: float) -> void:
|
|
if _transitioning or bool(player.get("_is_destroyed")):
|
|
return
|
|
if not system_cleared and get_remaining_enemies() == 0:
|
|
system_cleared = true
|
|
protected_planet.call("set_safe", true)
|
|
var near_planet := is_near_protected_planet()
|
|
if not near_planet:
|
|
_services_dismissed = false
|
|
if system_cleared and near_planet and not _services_dismissed and not services_menu.visible:
|
|
player.velocity = Vector2.ZERO
|
|
player.set("angular_velocity", 0.0)
|
|
player.set("is_docked", true)
|
|
$HUD/HUDRoot/ShipInventoryPanel.hide()
|
|
services_menu.call("show_services", GameState.system_level >= LEVEL_BALANCE.MAX_LEVEL)
|
|
|
|
func is_near_protected_planet() -> bool:
|
|
return player.global_position.distance_to(protected_planet.global_position) <= float(protected_planet.get("radius")) + SERVICE_APPROACH_DISTANCE
|
|
|
|
func _on_services_closed() -> void:
|
|
player.set("is_docked", false)
|
|
_services_dismissed = true
|
|
|
|
func advance_to_next_level() -> bool:
|
|
if _transitioning or not system_cleared or not services_menu.visible or not is_near_protected_planet():
|
|
return false
|
|
if bool(player.get("_is_destroyed")) or GameState.system_level >= LEVEL_BALANCE.MAX_LEVEL:
|
|
return false
|
|
_transitioning = true
|
|
services_menu.get_node("Center/Panel/Contents/NextButton").set("disabled", true)
|
|
_load_next_level.call_deferred()
|
|
return true
|
|
|
|
func _load_next_level() -> void:
|
|
var previous_level := GameState.system_level
|
|
var previous_seed := GameState.system_seed
|
|
player.get_node("ShipInventory").call("preserve_for_restart")
|
|
GameState.system_level += 1
|
|
GameState.system_seed = GameState.create_system_seed()
|
|
var error := get_tree().reload_current_scene()
|
|
if error != OK:
|
|
GameState.system_level = previous_level
|
|
GameState.system_seed = previous_seed
|
|
GameState.restart_inventory.clear()
|
|
_transitioning = false
|
|
services_menu.call("show_services", false)
|
|
push_error("Could not enter next system: %s" % error_string(error))
|