From a04f8196f93121ecd6dac0fec8f7116a389b8ab4 Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Sat, 27 Jan 2024 23:12:04 +0100 Subject: [PATCH] Game States kind of working --- entities/Player.gd | 33 +++++++++--- entities/SpawnPoint.gd | 2 +- project.godot | 14 +++++ scenes/Game.tscn | 118 ++++++++++++++++++++++++++++++++--------- scenes/GameUI.gd | 40 ++++++++++++-- scenes/World.gd | 80 +++++++++++++++++++++++++++- scenes/World.tscn | 7 ++- themes/GameUI.tres | 7 +++ 8 files changed, 262 insertions(+), 39 deletions(-) create mode 100644 themes/GameUI.tres diff --git a/entities/Player.gd b/entities/Player.gd index a8f1149..90932d1 100644 --- a/entities/Player.gd +++ b/entities/Player.gd @@ -26,6 +26,7 @@ enum PlayerState { var score : int = 0 var energy : float = 1.0 var state : PlayerState = PlayerState.Alive +var state_last : PlayerState = PlayerState.Dead var radius = 0.15 var angle = 0 @@ -36,7 +37,6 @@ var coloring_sprite : Sprite2D var coloring_bomb_sprite : Sprite2D const SPEED = 5.0 -const JUMP_VELOCITY = 4.5 const DASH_SPEED: float = 20 const DASH_DURATION: float = 0.2 const BOMB_DURATION: float = 0.1 @@ -53,8 +53,19 @@ func _ready(): coloring_bomb_sprite.visible = false func _physics_process(delta): - # Add the gravity. - if not is_on_floor(): + if state_last != state: + if state == PlayerState.Alive: + on_player_spawn() + elif state == PlayerState.Falling: + on_player_falling() + elif state == PlayerState.Dead: + on_player_dead() + + state_last = state + + if global_position.y < -5: + state = PlayerState.Dead + elif not is_on_floor(): if not is_dashing: velocity.y -= gravity * delta state = PlayerState.Falling @@ -62,15 +73,12 @@ func _physics_process(delta): state = PlayerState.Alive elif state == PlayerState.Dead: visible = false + return elif state == PlayerState.Alive: visible = true coloring_sprite.visible = state == PlayerState.Alive - # Handle jump. - if Input.is_action_just_pressed("ui_accept") and is_on_floor(): - velocity.y = JUMP_VELOCITY - if bomb_time > 0: bomb_time -= delta if bomb_time <= 0: @@ -95,7 +103,7 @@ func _physics_process(delta): velocity.z = move_toward(velocity.z, 0, SPEED) geometry.global_basis = Basis.from_euler(Vector3(0, -angle, 0)) - if Input.is_action_just_pressed(dash_action): + if state == PlayerState.Alive and Input.is_action_just_pressed(dash_action): is_dashing = true; dash_time = DASH_DURATION @@ -117,3 +125,12 @@ func _physics_process(delta): func calc_coloring_position(): var result = Vector2 (global_position.x * 10 + 512, global_position.z * 10 + 512) return result; + +func on_player_spawn(): + print ("Player " + str(self) + ": spawning") + +func on_player_falling(): + print ("Player " + str(self) + ": falling") + +func on_player_dead(): + print ("Player " + str(self) + ": death") diff --git a/entities/SpawnPoint.gd b/entities/SpawnPoint.gd index a131e74..11c2039 100644 --- a/entities/SpawnPoint.gd +++ b/entities/SpawnPoint.gd @@ -16,7 +16,7 @@ func on_player_enter(node: Node3D): if node == null: return - if not near_players.find(player): + if near_players.find(player) == -1: near_players.append(player) func on_player_exited(node: Node3D): diff --git a/project.godot b/project.godot index 4d6f93d..e05125e 100644 --- a/project.godot +++ b/project.godot @@ -21,6 +21,20 @@ project/assembly_name="DashBoomColorClash" [input] +ui_accept={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194309,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194310,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":32,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":true,"script":null) +] +} +ui_cancel={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194305,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":true,"script":null) +] +} move_up_p1={ "deadzone": 0.5, "events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":-1.0,"script":null) diff --git a/scenes/Game.tscn b/scenes/Game.tscn index fc8a8bc..044ced1 100644 --- a/scenes/Game.tscn +++ b/scenes/Game.tscn @@ -1,8 +1,7 @@ -[gd_scene load_steps=8 format=3 uid="uid://rd48gl8k5x34"] +[gd_scene load_steps=6 format=3 uid="uid://rd48gl8k5x34"] -[ext_resource type="Script" path="res://Game.gd" id="1_7jqda"] +[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="FontFile" uid="uid://bf6q51e8x2s1h" path="res://assets/fonts/Bangers-Regular/Bangers-Regular.ttf" id="3_52dp0"] [ext_resource type="Script" path="res://scenes/GameUI.gd" id="4_2tdl1"] [sub_resource type="World3D" id="World3D_5g233"] @@ -10,12 +9,7 @@ [sub_resource type="ViewportTexture" id="ViewportTexture_2lmj8"] viewport_path = NodePath("Viewport") -[sub_resource type="Theme" id="Theme_qtmht"] -default_font = ExtResource("3_52dp0") -default_font_size = 30 - [node name="Game" type="Node"] -script = ExtResource("1_7jqda") [node name="Viewport" type="SubViewport" parent="."] own_world_3d = true @@ -54,12 +48,6 @@ grow_horizontal = 2 size_flags_horizontal = 4 size_flags_vertical = 4 -[node name="Panel2" type="Panel" parent="."] -custom_minimum_size = Vector2(0, 80) -anchors_preset = 10 -anchor_right = 1.0 -grow_horizontal = 2 - [node name="GameUI" type="Control" parent="."] layout_mode = 3 anchors_preset = 15 @@ -67,39 +55,121 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -theme = SubResource("Theme_qtmht") +theme = ExtResource("2_eun58") script = ExtResource("4_2tdl1") world_path = NodePath("../Viewport/World") -[node name="Player1Widgets" type="VBoxContainer" parent="GameUI"] +[node name="GameStartupWidgets" type="Panel" parent="GameUI"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = ExtResource("2_eun58") + +[node name="Label" type="Label" parent="GameUI/GameStartupWidgets"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -27.5 +offset_top = -11.5 +offset_right = 27.5 +offset_bottom = 11.5 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_font_sizes/font_size = 120 +text = "Ready?" +horizontal_alignment = 1 + +[node name="GameFinishedWidgets" type="Panel" parent="GameUI"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = ExtResource("2_eun58") + +[node name="Label" type="Label" parent="GameUI/GameFinishedWidgets"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -27.5 +offset_top = -11.5 +offset_right = 27.5 +offset_bottom = 11.5 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_font_sizes/font_size = 120 +text = "Game Over!" +horizontal_alignment = 1 + +[node name="GameRunningWidgets" type="Panel" parent="GameUI"] +visible = false +custom_minimum_size = Vector2(0, 80) +layout_mode = 1 +anchors_preset = 10 +anchor_right = 1.0 +offset_bottom = 80.0 +grow_horizontal = 2 + +[node name="Player1Widgets" type="VBoxContainer" parent="GameUI/GameRunningWidgets"] layout_mode = 1 offset_right = 49.0 offset_bottom = 77.0 alignment = 1 -[node name="NameLabel" type="Label" parent="GameUI/Player1Widgets"] +[node name="NameLabel" type="Label" parent="GameUI/GameRunningWidgets/Player1Widgets"] layout_mode = 2 text = "Red" -[node name="ScoreLabel" type="Label" parent="GameUI/Player1Widgets"] +[node name="ScoreLabel" type="Label" parent="GameUI/GameRunningWidgets/Player1Widgets"] layout_mode = 2 text = "0 " -[node name="Player2Widgets" type="VBoxContainer" parent="GameUI"] +[node name="Player2Widgets" type="VBoxContainer" parent="GameUI/GameRunningWidgets"] layout_direction = 3 -layout_mode = 0 -offset_left = 7.0 -offset_right = 56.0 +layout_mode = 1 +offset_right = 49.0 offset_bottom = 77.0 size_flags_horizontal = 8 alignment = 1 -[node name="NameLabel" type="Label" parent="GameUI/Player2Widgets"] +[node name="NameLabel" type="Label" parent="GameUI/GameRunningWidgets/Player2Widgets"] layout_mode = 2 text = "Blue" -[node name="ScoreLabel" type="Label" parent="GameUI/Player2Widgets"] +[node name="ScoreLabel" type="Label" parent="GameUI/GameRunningWidgets/Player2Widgets"] layout_mode = 2 text = "0 " + +[node name="TimeWidgets" type="VBoxContainer" parent="GameUI/GameRunningWidgets"] +layout_mode = 1 +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = -48.0 +offset_right = 48.0 +offset_bottom = 70.0 +grow_horizontal = 2 + +[node name="Label" type="Label" parent="GameUI/GameRunningWidgets/TimeWidgets"] +layout_mode = 2 +text = "Time Left" +horizontal_alignment = 1 + +[node name="TimeLeftLabel" type="Label" parent="GameUI/GameRunningWidgets/TimeWidgets"] +layout_mode = 2 +text = "00:30:00" +horizontal_alignment = 1 diff --git a/scenes/GameUI.gd b/scenes/GameUI.gd index 9f3d47c..ee30712 100644 --- a/scenes/GameUI.gd +++ b/scenes/GameUI.gd @@ -2,9 +2,15 @@ extends Control @export var world_path : NodePath = NodePath() -@onready var player1_score_label : Label = $'Player1Widgets/ScoreLabel' -@onready var player2_score_label : Label = $'Player2Widgets/ScoreLabel' -@onready var player2_widgets : Control = $'Player2Widgets' +@onready var game_running_widgets : Control = $'GameRunningWidgets' +@onready var game_startup_widgets : Control = $'GameStartupWidgets' +@onready var game_finished_widgets : Control = $'GameFinishedWidgets' + +@onready var player1_score_label : Label = $'GameRunningWidgets/Player1Widgets/ScoreLabel' +@onready var player2_score_label : Label = $'GameRunningWidgets/Player2Widgets/ScoreLabel' +@onready var player2_widgets : Control = $'GameRunningWidgets/Player2Widgets' + +@onready var time_left_label : Label = $'GameRunningWidgets/TimeWidgets/TimeLeftLabel' var world : World = null @@ -16,7 +22,35 @@ func _ready(): player2_widgets.visible = false func _process(_delta): + if world.game_state == World.GameState.Startup: + game_startup_widgets.visible = true + game_running_widgets.visible = false + game_finished_widgets.visible = false + elif world.game_state == World.GameState.Running: + game_startup_widgets.visible = false + game_running_widgets.visible = true + game_finished_widgets.visible = false + + var minutes = floor(world.time_left / 60.) + var seconds = fmod(floor(world.time_left), 60) + var milliseconds = floor((world.time_left - floor(world.time_left)) * 10) + + time_left_label.text = str(minutes) + ":" + str(seconds) + ":" + str(milliseconds) + elif world.game_state == World.GameState.Finished: + game_startup_widgets.visible = false + game_running_widgets.visible = false + game_finished_widgets.visible = true + player1_score_label.text = str(world.players[0].score) if player2_widgets.visible: player2_score_label.text = str(world.players[1].score) + +func _input(event): + if event.is_action_pressed("ui_accept"): + if world.game_state == World.GameState.Startup: + world.game_state = World.GameState.Running + if event.is_action_pressed("ui_cancel"): + if world.game_state == World.GameState.Finished: + world.game_state = World.GameState.Startup + diff --git a/scenes/World.gd b/scenes/World.gd index b438eec..857778e 100644 --- a/scenes/World.gd +++ b/scenes/World.gd @@ -9,11 +9,23 @@ class_name World extends Node3D @onready var level: Node3D = $Level @onready var world_coloring_viewport: SubViewport = $WorldColoringViewport +const GAME_DURATION_SECONDS = 10 + var camera_position: Vector3; var world_coloring_material: ShaderMaterial var world_plane: Plane = Plane(Vector3.UP, Vector3.ZERO) var spawn_points: Array = Array() +enum GameState { + Startup, + Running, + Finished +} + +var time_left = GAME_DURATION_SECONDS +var game_state : GameState = GameState.Startup +var game_state_last : GameState = GameState.Finished + # Called when the node enters the scene tree for the first time. func _ready(): var player1: CharacterBody3D = $Player1 @@ -42,6 +54,23 @@ func _ready(): # 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.Running: + on_game_running() + elif game_state == GameState.Finished: + on_game_finished() + game_state_last = game_state + + if game_state == GameState.Running: + time_left -= _delta; + else: + return + + if time_left <= 0: + game_state = GameState.Finished + var player1 : Player = players[0] var player_center = Vector3.ZERO var player_coords_rect : Rect2 = Rect2( @@ -66,11 +95,13 @@ func _process(_delta): camera_position = player_center - camera_direction * camera_dist camera.global_position = camera_position - pass func _physics_process(_delta): world_coloring_material.set_shader_parameter("world_color_texture", world_coloring_viewport.get_texture()) + if game_state != GameState.Running: + return + for player: Player in players: if player.state == Player.PlayerState.Dead: var occupied = true @@ -85,6 +116,11 @@ func _physics_process(_delta): player.state = Player.PlayerState.Alive spawn_point.near_players.append(player) +func _unhandled_input(event): + if game_state == GameState.Startup: + if event.is_action_pressed("ui_accept"): + game_state = GameState.Running + func find_spawn_points (node): for child in node.get_children(): var spawn_point = child as SpawnPoint @@ -113,3 +149,45 @@ func update_score(): if players.size() > 1: players[1].score = pixel_count_compute_shader.blue_score + +func on_game_startup(): + print("Switching to startup") + stop_gameplay() + + 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() + + world_coloring_viewport.render_target_clear_mode = SubViewport.CLEAR_MODE_NEVER + world_coloring_viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS + +func on_game_finished(): + print("Switching to finished") + stop_gameplay() + + world_coloring_viewport.render_target_clear_mode = SubViewport.CLEAR_MODE_NEVER + world_coloring_viewport.render_target_update_mode = SubViewport.UPDATE_ONCE + +func stop_gameplay(): + print("Stopping gameplay") + for player: Player in players: + player.coloring_sprite.visible = false + player.coloring_bomb_sprite.visible = false + player.set_process(false) + player.set_process_input(false) + player.set_physics_process(false) + +func start_gameplay(): + print("Starting gameplay") + time_left = GAME_DURATION_SECONDS + + for player: Player in players: + player.coloring_sprite.visible = true + player.coloring_bomb_sprite.visible = false + player.set_process(true) + player.set_process_input(true) + player.set_physics_process(true) + player.state = Player.PlayerState.Dead diff --git a/scenes/World.tscn b/scenes/World.tscn index ce79a7d..4085a1d 100644 --- a/scenes/World.tscn +++ b/scenes/World.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=13 format=3 uid="uid://b1nm5h3yccr16"] +[gd_scene load_steps=14 format=3 uid="uid://b1nm5h3yccr16"] [ext_resource type="Script" path="res://scenes/World.gd" id="1_gtcjp"] [ext_resource type="PackedScene" uid="uid://bfyjtfdko3l7o" path="res://entities/Player.tscn" id="2_a343a"] @@ -8,6 +8,7 @@ [ext_resource type="PackedScene" uid="uid://7a2ma10hq0qa" path="res://scenes/PlatformA.tscn" id="6_83plb"] [ext_resource type="PackedScene" uid="uid://bnmtyc1kkt6ku" path="res://scenes/PlatformB.tscn" id="7_cld3m"] [ext_resource type="PackedScene" uid="uid://cc521i07ajufm" path="res://entities/SpawnPoint.tscn" id="8_ykvyf"] +[ext_resource type="PackedScene" uid="uid://0lrpepyejfxg" path="res://scenes/TestObstacles.tscn" id="9_eml1e"] [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_5gauv"] sky_energy_multiplier = 5.0 @@ -105,7 +106,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6.76534, 0, 5.93242) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.68666, 0, 5.21494) [node name="Platforms3" parent="Level" instance=ExtResource("6_83plb")] -transform = Transform3D(0.768741, 0, -0.63956, 0, 1, 0, 0.63956, 0, 0.768741, 9.90471, 0, 3.31265) +transform = Transform3D(0.768741, 0, -0.63956, 0, 1, 0, 0.63956, 0, 0.768741, 8.83345, 0, 2.90911) [node name="Platforms4" parent="Level" instance=ExtResource("6_83plb")] transform = Transform3D(-0.99988, 0, -0.0155154, 0, 1, 0, 0.0155154, 0, -0.99988, 13.9505, -4.76837e-07, -0.629952) @@ -136,3 +137,5 @@ player_index = 1 [node name="SpawnPointPlayer3" parent="Level" instance=ExtResource("8_ykvyf")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 9.55561, 0, 3.26255) + +[node name="Obstacles" parent="Level" instance=ExtResource("9_eml1e")] diff --git a/themes/GameUI.tres b/themes/GameUI.tres new file mode 100644 index 0000000..14e4dba --- /dev/null +++ b/themes/GameUI.tres @@ -0,0 +1,7 @@ +[gd_resource type="Theme" load_steps=2 format=3 uid="uid://bb8mjy6l7umui"] + +[ext_resource type="FontFile" uid="uid://bf6q51e8x2s1h" path="res://assets/fonts/Bangers-Regular/Bangers-Regular.ttf" id="1_k4p25"] + +[resource] +default_font = ExtResource("1_k4p25") +default_font_size = 30