diff --git a/levels/BasicLevel.png b/levels/BasicLevel.png new file mode 100644 index 0000000..94ee8a4 Binary files /dev/null and b/levels/BasicLevel.png differ diff --git a/levels/BasicLevel.png.import b/levels/BasicLevel.png.import new file mode 100644 index 0000000..4d11cba --- /dev/null +++ b/levels/BasicLevel.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dam8r48qo0qqh" +path="res://.godot/imported/BasicLevel.png-b10569d186ecf038de4843414924eabd.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://levels/BasicLevel.png" +dest_files=["res://.godot/imported/BasicLevel.png-b10569d186ecf038de4843414924eabd.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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/levels/BasicLevel.tscn b/levels/BasicLevel.tscn index f6c4bfa..555082d 100644 --- a/levels/BasicLevel.tscn +++ b/levels/BasicLevel.tscn @@ -4,7 +4,7 @@ [ext_resource type="PackedScene" uid="uid://bnmtyc1kkt6ku" path="res://scenes/PlatformB.tscn" id="2_alvfs"] [ext_resource type="PackedScene" uid="uid://cc521i07ajufm" path="res://entities/SpawnPoint.tscn" id="3_5ocaq"] -[node name="Level" type="Node3D"] +[node name="BasicLevel" type="Node3D"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6.76534, 0, 5.93242) [node name="Platforms" parent="." instance=ExtResource("1_ljufl")] @@ -39,8 +39,12 @@ transform = Transform3D(-0.851736, 0, 0.523971, 0, 1, 0, -0.523971, 0, -0.851736 [node name="SpawnPointPlayer1" parent="." instance=ExtResource("3_5ocaq")] [node name="SpawnPointPlayer2" parent="." instance=ExtResource("3_5ocaq")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 9.48618, 0, -11.2001) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.83554, 0, -13.291) player_index = 1 [node name="SpawnPointPlayer3" parent="." instance=ExtResource("3_5ocaq")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 9.55561, 0, 3.26255) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 10.4298, 0, 1.74365) + +[node name="SpawnPointPlayer4" parent="." instance=ExtResource("3_5ocaq")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 16.0431, 0, -9.95279) +player_index = 1 diff --git a/levels/Platforms.png b/levels/Platforms.png new file mode 100644 index 0000000..120f2e7 Binary files /dev/null and b/levels/Platforms.png differ diff --git a/levels/Platforms.png.import b/levels/Platforms.png.import new file mode 100644 index 0000000..c6c2d46 --- /dev/null +++ b/levels/Platforms.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b5ah0ej10awd5" +path="res://.godot/imported/Platforms.png-6509e9f078e654ad679ba5a9350838f2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://levels/Platforms.png" +dest_files=["res://.godot/imported/Platforms.png-6509e9f078e654ad679ba5a9350838f2.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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/levels/BridgedPlatforms.tscn b/levels/Platforms.tscn similarity index 63% rename from levels/BridgedPlatforms.tscn rename to levels/Platforms.tscn index 40fc997..b4c4c70 100644 --- a/levels/BridgedPlatforms.tscn +++ b/levels/Platforms.tscn @@ -1,52 +1,52 @@ -[gd_scene load_steps=6 format=3 uid="uid://b1twlocviffui"] +[gd_scene load_steps=6 format=3 uid="uid://87rik2jwk38y"] -[ext_resource type="PackedScene" uid="uid://7a2ma10hq0qa" path="res://scenes/PlatformA.tscn" id="1_p40sa"] -[ext_resource type="PackedScene" uid="uid://bnmtyc1kkt6ku" path="res://scenes/PlatformB.tscn" id="2_wxrkl"] -[ext_resource type="PackedScene" uid="uid://cc521i07ajufm" path="res://entities/SpawnPoint.tscn" id="3_sf7e8"] -[ext_resource type="PackedScene" uid="uid://0fxjod84sli" path="res://scenes/PlatformParts/heptagon_platform_medium.tscn" id="4_mhnm5"] -[ext_resource type="PackedScene" uid="uid://deod1xpjlgljl" path="res://scenes/PlatformParts/heptagon_platform_small.tscn" id="5_3ax6r"] +[ext_resource type="PackedScene" uid="uid://7a2ma10hq0qa" path="res://scenes/PlatformA.tscn" id="1_t5xh4"] +[ext_resource type="PackedScene" uid="uid://bnmtyc1kkt6ku" path="res://scenes/PlatformB.tscn" id="2_20hf0"] +[ext_resource type="PackedScene" uid="uid://cc521i07ajufm" path="res://entities/SpawnPoint.tscn" id="3_63ckc"] +[ext_resource type="PackedScene" uid="uid://0fxjod84sli" path="res://scenes/PlatformParts/heptagon_platform_medium.tscn" id="4_yewb1"] +[ext_resource type="PackedScene" uid="uid://deod1xpjlgljl" path="res://scenes/PlatformParts/heptagon_platform_small.tscn" id="5_deyyw"] -[node name="Level" type="Node3D"] +[node name="Platforms" type="Node3D"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6.76534, 0, 5.93242) -[node name="Platforms" parent="." instance=ExtResource("1_p40sa")] +[node name="Platforms" parent="." instance=ExtResource("1_t5xh4")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.14317, 0, -7.62714) -[node name="Platforms2" parent="." instance=ExtResource("1_p40sa")] +[node name="Platforms2" parent="." instance=ExtResource("1_t5xh4")] transform = Transform3D(0.960162, 0, 0.279444, 0, 1, 0, -0.279444, 0, 0.960162, 8.23778, 0, -2.69178) -[node name="Platforms3" parent="." instance=ExtResource("2_wxrkl")] +[node name="Platforms3" parent="." instance=ExtResource("2_20hf0")] transform = Transform3D(0.998982, 0, -0.0451189, 0, 1, 0, 0.0451189, 0, 0.998982, 7.95994, 0, -17.2561) -[node name="Platforms4" parent="." instance=ExtResource("2_wxrkl")] +[node name="Platforms4" parent="." instance=ExtResource("2_20hf0")] transform = Transform3D(0.922066, 0, 0.387033, 0, 1, 0, -0.387033, 0, 0.922066, -5.98415, 0, -9.7244) -[node name="Platforms5" parent="." instance=ExtResource("1_p40sa")] +[node name="Platforms5" parent="." instance=ExtResource("1_t5xh4")] transform = Transform3D(0.923846, 0, -0.382764, 0, 1, 0, 0.382764, 0, 0.923846, 2.31558, 0, -23.054) -[node name="SpawnPoint" parent="." instance=ExtResource("3_sf7e8")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6.08035, 0, -0.0552721) +[node name="SpawnPoint" parent="." instance=ExtResource("3_63ckc")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.01383, 0, -1.93276) -[node name="SpawnPoint2" parent="." instance=ExtResource("3_sf7e8")] +[node name="SpawnPoint2" parent="." instance=ExtResource("3_63ckc")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4.21992, 0, -7.43863) -[node name="SpawnPoint3" parent="." instance=ExtResource("3_sf7e8")] +[node name="SpawnPoint3" parent="." instance=ExtResource("3_63ckc")] transform = Transform3D(0.998982, 0, -0.0451189, 0, 1, 0, 0.0451189, 0, 0.998982, 3.70248, 0, -22.6231) -[node name="Platforms6" parent="." instance=ExtResource("2_wxrkl")] +[node name="Platforms6" parent="." instance=ExtResource("2_20hf0")] transform = Transform3D(0.886317, 0, -0.463079, 0, 1, 0, 0.463079, 0, 0.886317, 16.7673, 0, -9.85118) -[node name="SpawnPoint4" parent="." instance=ExtResource("3_sf7e8")] +[node name="SpawnPoint4" parent="." instance=ExtResource("3_63ckc")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 16.6107, 0, -8.04518) -[node name="HeptagonPlatform" parent="." instance=ExtResource("4_mhnm5")] +[node name="HeptagonPlatform" parent="." instance=ExtResource("4_yewb1")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.28917, 0, -10.1963) -[node name="HeptagonPlatform2" parent="." instance=ExtResource("4_mhnm5")] +[node name="HeptagonPlatform2" parent="." instance=ExtResource("4_yewb1")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6.15056, 0, -9.08093) -[node name="HeptagonPlatform3" parent="." instance=ExtResource("5_3ax6r")] +[node name="HeptagonPlatform3" parent="." instance=ExtResource("5_deyyw")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5.78291, 0, -10.8037) -[node name="HeptagonPlatform4" parent="." instance=ExtResource("4_mhnm5")] +[node name="HeptagonPlatform4" parent="." instance=ExtResource("4_yewb1")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.07311, 0, -10.3168) diff --git a/scenes/Game.tscn b/scenes/Game.tscn index 371ee76..1cb4a5e 100644 --- a/scenes/Game.tscn +++ b/scenes/Game.tscn @@ -1,8 +1,11 @@ -[gd_scene load_steps=8 format=3 uid="uid://rd48gl8k5x34"] +[gd_scene load_steps=11 format=3 uid="uid://rd48gl8k5x34"] [ext_resource type="Theme" uid="uid://bb8mjy6l7umui" path="res://themes/GameUI.tres" id="2_eun58"] [ext_resource type="PackedScene" uid="uid://b1nm5h3yccr16" path="res://scenes/World.tscn" id="2_voimb"] +[ext_resource type="ButtonGroup" uid="uid://ctqarf04xdj1" path="res://ui/LevelSelectButtonGroup.tres" id="4_0dlh8"] +[ext_resource type="Texture2D" uid="uid://b5ah0ej10awd5" path="res://levels/Platforms.png" id="4_0en0p"] [ext_resource type="Script" path="res://scenes/GameUI.gd" id="4_2tdl1"] +[ext_resource type="Texture2D" uid="uid://dam8r48qo0qqh" path="res://levels/BasicLevel.png" id="4_l63m5"] [sub_resource type="World3D" id="World3D_5g233"] @@ -307,10 +310,35 @@ layout_mode = 2 text = "00:30:00" horizontal_alignment = 1 -[node name="LevelSelect" type="Panel" parent="GameUI"] +[node name="GameLevelSelectWidgets" type="Panel" parent="GameUI"] layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 + +[node name="LevelListContainer" type="HBoxContainer" parent="GameUI/GameLevelSelectWidgets"] +layout_mode = 1 +anchors_preset = 14 +anchor_top = 0.5 +anchor_right = 1.0 +anchor_bottom = 0.5 +grow_horizontal = 2 +grow_vertical = 2 +focus_next = NodePath("BasicLevelButton") +focus_mode = 2 +theme_override_constants/separation = 32 +alignment = 1 + +[node name="BasicLevelButton" type="Button" parent="GameUI/GameLevelSelectWidgets/LevelListContainer"] +layout_mode = 2 +toggle_mode = true +button_group = ExtResource("4_0dlh8") +icon = ExtResource("4_l63m5") + +[node name="PlatformLevelButton" type="Button" parent="GameUI/GameLevelSelectWidgets/LevelListContainer"] +layout_mode = 2 +toggle_mode = true +button_group = ExtResource("4_0dlh8") +icon = ExtResource("4_0en0p") diff --git a/scenes/GameUI.gd b/scenes/GameUI.gd index 49abe17..4b97e40 100644 --- a/scenes/GameUI.gd +++ b/scenes/GameUI.gd @@ -5,6 +5,9 @@ extends Control @onready var game_running_widgets : Control = $'GameRunningWidgets' @onready var game_startup_widgets : Control = $'GameStartupWidgets' @onready var game_finished_widgets : Control = $'GameFinishedWidgets' +@onready var game_level_select_widgets : Control = $'GameLevelSelectWidgets' + +@onready var level_list_container: HBoxContainer = $'GameLevelSelectWidgets/LevelListContainer' @onready var player1_score_label : Label = $'GameRunningWidgets/Player1Widgets/ScoreLabel' @onready var player1_energy_progressbar : ProgressBar = $'GameRunningWidgets/Player1Widgets/EnergyProgressBar' @@ -24,6 +27,10 @@ var world : World = null func _ready(): world = get_node(world_path) + initialize_level_buttons() + + game_level_select_widgets.connect("visibility_changed", on_game_level_select_visibility_changed) + if world.players.size() == 1: player2_widgets.visible = false @@ -32,10 +39,17 @@ func _process(_delta): game_startup_widgets.visible = true game_running_widgets.visible = false game_finished_widgets.visible = false + game_level_select_widgets.visible = false + elif world.game_state == World.GameState.LevelSelect: + game_startup_widgets.visible = false + game_running_widgets.visible = false + game_finished_widgets.visible = false + game_level_select_widgets.visible = true elif world.game_state == World.GameState.Running: game_startup_widgets.visible = false game_running_widgets.visible = true game_finished_widgets.visible = false + game_level_select_widgets.visible = false var minutes = floor(world.time_left / 60.) var seconds = fmod(floor(world.time_left), 60) @@ -50,6 +64,7 @@ func _process(_delta): game_startup_widgets.visible = false game_running_widgets.visible = false game_finished_widgets.visible = true + game_level_select_widgets.visible = false player1_score_label.text = str(world.players[0].score) player1_energy_progressbar.value = world.players[0].energy @@ -70,8 +85,46 @@ func _process(_delta): func _input(event): if event.is_action_pressed("ui_accept"): if world.game_state == World.GameState.Startup: - world.game_state = World.GameState.Running + world.game_state = World.GameState.LevelSelect if event.is_action_pressed("ui_menu"): if world.game_state == World.GameState.Finished: world.game_state = World.GameState.Startup + if event.is_action_pressed("ui_cancel"): + if world.game_state == World.GameState.LevelSelect: + world.game_state = World.GameState.Startup +func initialize_level_buttons(): + var level_button : Button = level_list_container.get_child(0) + if level_button == null: + push_error("Cannot initialize level selection: no level button found!") + return + + var level_select_button_group : ButtonGroup = level_button.button_group + level_select_button_group.connect("pressed", on_level_button_pressed) + +func update_selected_level(): + var level_button: Button = level_list_container.get_child(0) + if level_button == null: + push_error("Cannot update selected level: no level found") + + var button_index: int = -1 + for button: Button in level_button.button_group.get_buttons(): + button_index += 1 + if button_index == world.level_index: + button.grab_focus() + return + +func on_level_button_pressed(button: Button): + print("level button " + str(button) + " pressed") + var button_index: int = -1 + for level_button : Button in level_list_container.get_children(): + button_index += 1 + print(str(level_button) + " toggled: " + str(level_button.is_hovered())) + if level_button == button: + world.level_index = button_index + + print("level index: " + str(world.level_index)) + world.game_state = World.GameState.Running + +func on_game_level_select_visibility_changed(): + update_selected_level() diff --git a/scenes/World.gd b/scenes/World.gd index c3a044e..19faacb 100644 --- a/scenes/World.gd +++ b/scenes/World.gd @@ -12,6 +12,13 @@ var players: Array var player_scene = preload("res://entities/Player.tscn") +var level_scenes : Array = [ + preload("res://levels/BasicLevel.tscn"), + preload("res://levels/Platforms.tscn") +] +var level_index = 0 +var last_level_index = -1 + const GAME_DURATION_SECONDS = 20 var camera_position: Vector3; @@ -21,6 +28,7 @@ var spawn_points: Array = Array() enum GameState { Startup, + LevelSelect, Running, Finished } @@ -35,17 +43,15 @@ func _ready(): score_update_timer.connect("timeout", update_score) - find_spawn_points(level) - - spawn_players() - apply_world_coloring_recursive(level) - + load_level() # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(_delta): if game_state_last != game_state: if game_state == GameState.Startup: on_game_startup() + elif game_state == GameState.LevelSelect: + on_game_level_select() elif game_state == GameState.Running: on_game_running() elif game_state == GameState.Finished: @@ -86,6 +92,9 @@ func _process(_delta): camera.global_position = camera_position func _physics_process(_delta): + if level_index != last_level_index: + load_level() + world_coloring_material.set_shader_parameter("world_color_texture", world_coloring_viewport.get_texture()) if game_state != GameState.Running: @@ -110,8 +119,29 @@ func _unhandled_input(event): if event.is_action_pressed("ui_accept"): game_state = GameState.Running -func find_spawn_points (node): +func load_level(): + print("Loading level " + str(level_scenes[level_index])) + + for node in level.get_children(): + node.queue_free() + + var level_instance = level_scenes[level_index].instantiate() + print("Loaded level " + level_instance.name) + level.add_child(level_instance) + + spawn_points.clear() + find_spawn_points(level) + print("Found " + str(spawn_points.size()) + " spawn points.") + spawn_players() + apply_world_coloring_recursive(level) + + last_level_index = level_index + +func find_spawn_points (node: Node3D): for child in node.get_children(): + if child.is_queued_for_deletion(): + continue + var spawn_point = child as SpawnPoint if spawn_point: spawn_points.append(spawn_point) @@ -202,6 +232,15 @@ func on_game_startup(): world_coloring_viewport.render_target_clear_mode = SubViewport.CLEAR_MODE_ONCE world_coloring_viewport.render_target_update_mode = SubViewport.UPDATE_ONCE +func on_game_level_select(): + print("Switching to level select") + stop_gameplay() + + music_stream_player.stop() + + world_coloring_viewport.render_target_clear_mode = SubViewport.CLEAR_MODE_ONCE + world_coloring_viewport.render_target_update_mode = SubViewport.UPDATE_ONCE + func on_game_running(): print("Switching to gameplay") start_gameplay() @@ -228,7 +267,7 @@ func stop_gameplay(): player.set_physics_process(false) func start_gameplay(): - print("Starting ggameplay") + print("Starting gameplay") time_left = GAME_DURATION_SECONDS for player: Player in players: diff --git a/scenes/World.tscn b/scenes/World.tscn index c08b3ff..57e6038 100644 --- a/scenes/World.tscn +++ b/scenes/World.tscn @@ -4,8 +4,8 @@ [ext_resource type="AudioStream" uid="uid://5da1smwywxdk" path="res://assets/music/Run-Amok(chosic.com).mp3" id="3_owwdt"] [ext_resource type="Texture2D" uid="uid://bnsrnuuq28p4d" path="res://assets/textures/player_draw_mask.png" id="4_dipd5"] [ext_resource type="Texture2D" uid="uid://vcebfpqo2ko7" path="res://assets/textures/player_bomb_mask.png" id="5_17c1g"] -[ext_resource type="PackedScene" uid="uid://b1twlocviffui" path="res://levels/BridgedPlatforms.tscn" id="6_14y2b"] [ext_resource type="PackedScene" path="res://scenes/PixelCountComputeShader.tscn" id="6_75vqy"] +[ext_resource type="PackedScene" uid="uid://87rik2jwk38y" path="res://levels/Platforms.tscn" id="6_n6e0v"] [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_5gauv"] sky_energy_multiplier = 5.0 @@ -83,4 +83,5 @@ texture = ExtResource("5_17c1g") [node name="Level" type="Node3D" parent="."] -[node name="Level" parent="Level" instance=ExtResource("6_14y2b")] +[node name="Platforms" parent="Level" instance=ExtResource("6_n6e0v")] +transform = Transform3D(1, 3.19189e-15, 0, -2.16493e-15, 1, -9.99201e-16, 0, -1.33227e-15, 1, -6.76534, 0, 5.93242) diff --git a/ui/LevelSelectButtonGroup.tres b/ui/LevelSelectButtonGroup.tres new file mode 100644 index 0000000..253c425 --- /dev/null +++ b/ui/LevelSelectButtonGroup.tres @@ -0,0 +1,3 @@ +[gd_resource type="ButtonGroup" format=3 uid="uid://ctqarf04xdj1"] + +[resource]