diff --git a/assets/materials/gummy_material.tres b/assets/materials/gummy_material.tres index de5d4e3..123ee71 100644 --- a/assets/materials/gummy_material.tres +++ b/assets/materials/gummy_material.tres @@ -28,7 +28,7 @@ noise = SubResource("FastNoiseLite_bxk71") [resource] render_priority = 0 shader = ExtResource("1_jx055") -shader_parameter/albedo = Color(1, 0.6, 1, 0.34902) +shader_parameter/albedo = Color(1, 0.6, 1, 0.392157) shader_parameter/roughness = 0.55 shader_parameter/refraction = 0.0500008 shader_parameter/refraction_texture_channel = Vector4(1, 0, 0, 0) diff --git a/assets/sprites/gfolfer.png.import b/assets/sprites/gfolfer.png.import index c3c5615..7dddf42 100644 --- a/assets/sprites/gfolfer.png.import +++ b/assets/sprites/gfolfer.png.import @@ -3,25 +3,26 @@ importer="texture" type="CompressedTexture2D" uid="uid://cwjf4nfloebqj" -path="res://.godot/imported/gfolfer.png-b34e06369b2077c1d994a9ec2e4fe8a8.ctex" +path.s3tc="res://.godot/imported/gfolfer.png-b34e06369b2077c1d994a9ec2e4fe8a8.s3tc.ctex" metadata={ -"vram_texture": false +"imported_formats": ["s3tc_bptc"], +"vram_texture": true } [deps] source_file="res://assets/sprites/gfolfer.png" -dest_files=["res://.godot/imported/gfolfer.png-b34e06369b2077c1d994a9ec2e4fe8a8.ctex"] +dest_files=["res://.godot/imported/gfolfer.png-b34e06369b2077c1d994a9ec2e4fe8a8.s3tc.ctex"] [params] -compress/mode=0 +compress/mode=2 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/generate=true mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" @@ -31,4 +32,4 @@ 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 +detect_3d/compress_to=0 diff --git a/levels/debug_level/debug_level.tscn b/levels/debug_level/debug_level.tscn index b9aa802..57413cf 100644 --- a/levels/debug_level/debug_level.tscn +++ b/levels/debug_level/debug_level.tscn @@ -190,4 +190,4 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -2, 0) mesh = SubResource("PlaneMesh_2ywhk") [node name="ShotSetup" parent="." instance=ExtResource("8_h44v5")] -transform = Transform3D(-0.82092, 0, -0.571043, 0, 1, 0, 0.571043, 0, -0.82092, 0, 0, 0) +transform = Transform3D(-0.82092, 0, -0.571043, 0, 1, 0, 0.571043, 0, -0.82092, 153.8, 0, 225.951) diff --git a/project.godot b/project.godot index 082dbb9..9931bdc 100644 --- a/project.godot +++ b/project.godot @@ -44,7 +44,7 @@ enabled=PackedStringArray("res://addons/format_on_save/plugin.cfg", "res://addon [game] -config/controls/camera/free_camera_speed=10.0 +config/controls/camera/free_camera_speed=16.0 config/controls/camera/x_axis_sensitivity=0.45 config/controls/camera/y_axis_sensitivity=0.45 config/controls/camera/x_axis_acceleration=30.0 @@ -88,6 +88,11 @@ camera_sprint={ "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":4194325,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) ] } +camera_cancel={ +"deadzone": 0.5, +"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":81,"key_label":0,"unicode":113,"location":0,"echo":false,"script":null) +] +} shot_zoom_in={ "deadzone": 0.5, "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":4,"canceled":false,"pressed":false,"double_click":false,"script":null) diff --git a/src/player/free_camera/free_camera.gd b/src/player/free_camera/free_camera.gd index bf81ab9..2668aec 100644 --- a/src/player/free_camera/free_camera.gd +++ b/src/player/free_camera/free_camera.gd @@ -1,6 +1,6 @@ class_name FreeCamera extends CharacterBody3D -const SPRINT_MULT := 2.0 +const SPRINT_MULT := 3.0 const PITCH_LIMIT := deg_to_rad(85.0) var base_speed: float = ProjectSettings.get_setting("game/config/controls/camera/free_camera_speed") @@ -22,6 +22,8 @@ var invert_pitch: bool = ProjectSettings.get_setting("game/config/controls/camer @onready var _target := Vector2(rotation.x, rotation.y) +static var scene := preload("res://src/player/free_camera/free_camera.tscn") + func _unhandled_input(event: InputEvent) -> void: if event is InputEventMouseButton: @@ -60,3 +62,9 @@ func _physics_process(delta: float) -> void: velocity = velocity.move_toward(Vector3.ZERO, speed) move_and_slide() + + +static func create(snap_point: Node3D) -> FreeCamera: + var instance: FreeCamera = FreeCamera.scene.instantiate() + instance.global_transform = snap_point.global_transform + return instance diff --git a/src/player/free_camera/free_camera.tscn b/src/player/free_camera/free_camera.tscn index 42af172..40cc3fd 100644 --- a/src/player/free_camera/free_camera.tscn +++ b/src/player/free_camera/free_camera.tscn @@ -11,3 +11,4 @@ script = ExtResource("1_3gm3q") shape = SubResource("SphereShape3D_wmusx") [node name="Camera3D" type="Camera3D" parent="."] +current = true diff --git a/src/player/physics_ball/physics_ball.tscn b/src/player/physics_ball/physics_ball.tscn new file mode 100644 index 0000000..0854e3d --- /dev/null +++ b/src/player/physics_ball/physics_ball.tscn @@ -0,0 +1,75 @@ +[gd_scene load_steps=12 format=3 uid="uid://dfttci386ohip"] + +[sub_resource type="Gradient" id="Gradient_66vtd"] +offsets = PackedFloat32Array(0, 0.213823) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_p7iuu"] +noise_type = 2 +frequency = 0.06 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_wcxf4"] +width = 1024 +seamless = true +color_ramp = SubResource("Gradient_66vtd") +noise = SubResource("FastNoiseLite_p7iuu") + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_lplu7"] +noise_type = 2 +frequency = 0.06 +fractal_type = 2 +fractal_lacunarity = 1.0 +fractal_weighted_strength = 1.0 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_rvc1j"] +width = 1024 +seamless = true +as_normal_map = true +noise = SubResource("FastNoiseLite_lplu7") + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_3hdir"] +noise_type = 2 +frequency = 0.06 +fractal_type = 2 +fractal_lacunarity = 1.0 +fractal_weighted_strength = 1.0 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_lb1l7"] +width = 1024 +invert = true +seamless = true +noise = SubResource("FastNoiseLite_3hdir") + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_bhmcr"] +albedo_texture = SubResource("NoiseTexture2D_wcxf4") +metallic = 0.27 +roughness = 0.4 +roughness_texture = SubResource("NoiseTexture2D_lb1l7") +normal_enabled = true +normal_texture = SubResource("NoiseTexture2D_rvc1j") +clearcoat_roughness = 0.0 + +[sub_resource type="SphereMesh" id="SphereMesh_l3o3t"] +material = SubResource("StandardMaterial3D_bhmcr") +radius = 0.05 +height = 0.1 + +[sub_resource type="SphereShape3D" id="SphereShape3D_0hvq6"] +radius = 0.05 + +[sub_resource type="SeparationRayShape3D" id="SeparationRayShape3D_psmc6"] + +[node name="PhysicsBall" type="RigidBody3D"] + +[node name="BallMesh" type="MeshInstance3D" parent="."] +mesh = SubResource("SphereMesh_l3o3t") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("SphereShape3D_0hvq6") + +[node name="SpringArm3D" type="SpringArm3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 0.823711, 0.56701, 0, -0.56701, 0.823711, 0, 0, 0) +shape = SubResource("SeparationRayShape3D_psmc6") +spring_length = 2.0 + +[node name="Camera3D" type="Camera3D" parent="SpringArm3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 2) diff --git a/src/player/shot_setup/shot_setup.gd b/src/player/shot_setup/shot_setup.gd index 2ddea85..9fd0384 100644 --- a/src/player/shot_setup/shot_setup.gd +++ b/src/player/shot_setup/shot_setup.gd @@ -1,5 +1,13 @@ class_name ShotSetup extends Node3D +enum Phase { + AIM, + POWER_ADJUST, + CURVE_ADJUST, + SHOT, + FINISHED, +} + const PITCH_MIN := deg_to_rad(-60.0) const PITCH_MAX := deg_to_rad(-5.0) const ZOOM_LENGTH := 0.1 @@ -7,12 +15,11 @@ const ZOOM_LENGTH := 0.1 const ZOOM_MIN := 1.0 const ZOOM_MAX := 12.0 -enum Phase { - AIMING, - LATERAL, - POWER, - FINISHED, -} +const ARROW_ACCELERATION := 8.0 + +const FREE_CAM_RETURN_TIME := 1.0 + +@export var control_disabled := false var base_speed: float = ProjectSettings.get_setting("game/config/controls/camera/free_camera_speed") @@ -31,11 +38,25 @@ var y_acceleration: float = ProjectSettings.get_setting( var invert_pitch: bool = ProjectSettings.get_setting("game/config/controls/camera/invert_pitch") -var _phase: Phase = Phase.AIMING +var phase: Phase: + set(value): + if value != phase: + _on_phase_change(value) + phase = value + +var _free_camera: FreeCamera +var _returning_free_camera := false @onready var direction: Node3D = %Direction @onready var pitch: Node3D = %Pitch @onready var camera: Camera3D = %Camera +@onready var arrow: Node3D = %Arrow + +@onready var power_bar: ProgressBar = %PowerBar +@onready var power_animation: AnimationPlayer = %PowerAnimation + +@onready var curve_bar: ProgressBar = %CurveBar +@onready var curve_animation: AnimationPlayer = %CurveAnimation @onready var camera_distance := camera.position.z: set = _set_camera_distance @@ -60,7 +81,7 @@ func _unhandled_input(event: InputEvent) -> void: func camera_motion(motion: Vector2) -> void: - if _phase == Phase.AIMING: + if not control_disabled and phase == Phase.AIM: # Can only control camera while aiming _target_rotation.y = _target_rotation.y - deg_to_rad(motion.x * x_sensitivity) _target_rotation.x = clampf( @@ -70,20 +91,105 @@ func camera_motion(motion: Vector2) -> void: ) -func _physics_process(delta: float) -> void: - if _phase == Phase.AIMING: - # Camera zoom - if Input.is_action_just_pressed("shot_zoom_in"): - camera_distance = max(camera_distance - 1.0, ZOOM_MIN) - if Input.is_action_just_pressed("shot_zoom_out"): - camera_distance = min(camera_distance + 1.0, ZOOM_MAX) +func take_shot() -> void: + print("WHACK!") + print("Power: ", power_bar.value) + print("Curve: ", curve_bar.value) - # Advance to next phase - if Input.is_action_just_pressed("shot_accept"): - _phase = Phase.LATERAL +func _on_phase_change(new_phase: Phase) -> void: + match new_phase: + Phase.AIM: + print("AIM PHASE") + power_bar.hide() + curve_bar.hide() + Phase.POWER_ADJUST: + curve_bar.hide() + + power_bar.show() + power_animation.stop() # Reset if needed + Phase.CURVE_ADJUST: + curve_bar.show() + curve_animation.play("fill") + Phase.SHOT: + power_bar.hide() + curve_bar.hide() + take_shot() + + +func insert_free_cam() -> void: + _free_camera = FreeCamera.create(camera) + add_sibling(_free_camera) + control_disabled = true + + +func return_free_cam() -> void: + # TODO alter shot aim based on free camera selection + _free_camera.queue_free() + _free_camera = null + control_disabled = false + _returning_free_camera = false + + +func _process(delta: float) -> void: # Rotation direction.rotation.y = lerp_angle( direction.rotation.y, _target_rotation.y, delta * x_acceleration ) pitch.rotation.x = lerp_angle(pitch.rotation.x, _target_rotation.x, delta * y_acceleration) + + arrow.rotation.y = lerp_angle(arrow.rotation.y, _target_rotation.y, delta * ARROW_ACCELERATION) + + # Input Handling + if control_disabled: + if Input.is_action_just_pressed("camera_cancel"): + if is_instance_valid(_free_camera) and not _returning_free_camera: + _returning_free_camera = true + var tween := get_tree().create_tween() + ( + tween + . tween_property( + _free_camera, + "global_transform", + camera.global_transform, + FREE_CAM_RETURN_TIME + ) + . set_trans(Tween.TRANS_SINE) + ) + tween.tween_callback(return_free_cam) + return + + match phase: + Phase.AIM: + # Camera zoom + if Input.is_action_just_pressed("shot_zoom_in"): + camera_distance = max(camera_distance - 1.0, ZOOM_MIN) + if Input.is_action_just_pressed("shot_zoom_out"): + camera_distance = min(camera_distance + 1.0, ZOOM_MAX) + + # Switch to free cam + if ( + Input.is_action_just_pressed("camera_back") + or Input.is_action_just_pressed("camera_forward") + or Input.is_action_just_pressed("camera_left") + or Input.is_action_just_pressed("camera_right") + ): + insert_free_cam() + + # Advance to next phase + if Input.is_action_just_pressed("shot_accept"): + phase = Phase.POWER_ADJUST + Phase.POWER_ADJUST: + if Input.is_action_just_pressed("shot_accept"): + # TODO set power gauge parameters if needed + power_animation.play("fill") + if Input.is_action_just_released("shot_accept") and power_bar.value > 0: + power_animation.pause() + phase = Phase.CURVE_ADJUST + Phase.CURVE_ADJUST: + if Input.is_action_just_pressed("shot_accept"): + curve_animation.pause() + phase = Phase.SHOT + Phase.SHOT: + # DEBUG: reset to AIM phase + phase = Phase.AIM diff --git a/src/player/shot_setup/shot_setup.tscn b/src/player/shot_setup/shot_setup.tscn index f5be9f4..155d679 100644 --- a/src/player/shot_setup/shot_setup.tscn +++ b/src/player/shot_setup/shot_setup.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=5 format=3 uid="uid://cy7t2tc4y3b4"] +[gd_scene load_steps=11 format=3 uid="uid://cy7t2tc4y3b4"] [ext_resource type="Script" path="res://src/player/shot_setup/shot_setup.gd" id="1_r6ei4"] [ext_resource type="PackedScene" uid="uid://c2k88ns0h5ie1" path="res://src/ui/arrow.tscn" id="2_s70wl"] @@ -9,6 +9,77 @@ height = 0.1 [sub_resource type="CapsuleMesh" id="CapsuleMesh_5uovl"] +[sub_resource type="Animation" id="Animation_67gmp"] +resource_name = "fill" +length = 1.618 +tracks/0/type = "bezier" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:value") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"handle_modes": PackedInt32Array(0, 0), +"points": PackedFloat32Array(0, -0.25, 0, 0.233333, 0.0884774, 1, -0.267469, -0.483539, 0.25, 0), +"times": PackedFloat32Array(0, 1.618) +} + +[sub_resource type="Animation" id="Animation_pk1s7"] +length = 0.001 +tracks/0/type = "bezier" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:value") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"handle_modes": PackedInt32Array(0), +"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0) +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_coah5"] +_data = { +"RESET": SubResource("Animation_pk1s7"), +"fill": SubResource("Animation_67gmp") +} + +[sub_resource type="Animation" id="Animation_uo6s7"] +resource_name = "fill" +length = 0.618 +loop_mode = 2 +tracks/0/type = "bezier" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("%CurveBar:value") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"handle_modes": PackedInt32Array(0, 0), +"points": PackedFloat32Array(-1, -0.25, 0, 0.3, 0, 1, -0.3, 0, 0.25, 0), +"times": PackedFloat32Array(0, 0.618) +} + +[sub_resource type="Animation" id="Animation_noa0w"] +length = 0.001 +tracks/0/type = "bezier" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("%CurveBar:value") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"handle_modes": PackedInt32Array(0), +"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0) +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_dicse"] +_data = { +"RESET": SubResource("Animation_noa0w"), +"fill": SubResource("Animation_uo6s7") +} + [node name="ShotSetup" type="Node3D"] script = ExtResource("1_r6ei4") @@ -18,7 +89,7 @@ mesh = SubResource("SphereMesh_bvjn0") [node name="PlayerReference" type="MeshInstance3D" parent="."] unique_name_in_owner = true -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.212, 1, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.212, 1, 0) mesh = SubResource("CapsuleMesh_5uovl") [node name="Direction" type="Node3D" parent="."] @@ -32,10 +103,11 @@ transform = Transform3D(1, 0, 0, 0, 0.907777, 0.419452, 0, -0.419452, 0.907777, unique_name_in_owner = true transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 6) -[node name="Arrow" type="Node3D" parent="Direction"] +[node name="Arrow" type="Node3D" parent="."] +unique_name_in_owner = true transform = Transform3D(1, 0, 0, 0, 0.337095, 0.941471, 0, -0.941471, 0.337095, 0, 0.1, 0) -[node name="Arrow" parent="Direction/Arrow" instance=ExtResource("2_s70wl")] +[node name="ArrowMesh" parent="Arrow" instance=ExtResource("2_s70wl")] transform = Transform3D(0.2, 0, 0, 0, 1, 0, 0, 0, 0.2, 0, 1, 0) loop_animation = 1 @@ -53,7 +125,7 @@ layout_mode = 1 anchor_left = 0.4 anchor_top = 0.3 anchor_right = 0.6 -anchor_bottom = 0.7 +anchor_bottom = 0.85 offset_left = -20.0 offset_top = -20.0 offset_right = 20.0 @@ -62,23 +134,68 @@ grow_horizontal = 2 grow_vertical = 2 mouse_filter = 1 -[node name="LateralGauge" type="Control" parent="ShotUI/ShotGauges"] +[node name="PowerGauge" type="Control" parent="ShotUI/ShotGauges"] layout_mode = 1 -anchors_preset = 12 -anchor_top = 1.0 -anchor_right = 1.0 +anchor_left = 0.5 +anchor_top = 0.382 +anchor_right = 0.5 anchor_bottom = 1.0 grow_horizontal = 2 -grow_vertical = 0 +grow_vertical = 2 mouse_filter = 1 -[node name="ProgressBar" type="ProgressBar" parent="ShotUI/ShotGauges/LateralGauge"] -custom_minimum_size = Vector2(128, 32) +[node name="PowerBar" type="ProgressBar" parent="ShotUI/ShotGauges/PowerGauge"] +unique_name_in_owner = true +visible = false +custom_minimum_size = Vector2(30, 0) +layout_mode = 1 +anchors_preset = 13 +anchor_left = 0.5 +anchor_right = 0.5 +anchor_bottom = 1.0 +offset_left = -2.0 +offset_right = 2.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 1 +max_value = 1.0 +fill_mode = 2 + +[node name="PowerAnimation" type="AnimationPlayer" parent="ShotUI/ShotGauges/PowerGauge"] +unique_name_in_owner = true +root_node = NodePath("../PowerBar") +libraries = { +"": SubResource("AnimationLibrary_coah5") +} + +[node name="CurveGauge" type="Control" parent="ShotUI/ShotGauges"] +layout_mode = 1 +anchor_top = 0.25 +anchor_right = 1.0 +anchor_bottom = 0.25 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 1 + +[node name="CurveBar" type="ProgressBar" parent="ShotUI/ShotGauges/CurveGauge"] +unique_name_in_owner = true +visible = false layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 +offset_top = -13.5 +offset_bottom = 13.5 grow_horizontal = 2 grow_vertical = 2 -step = 1.0 -show_percentage = false +min_value = -1.0 +max_value = 1.0 + +[node name="CurveAnimation" type="AnimationPlayer" parent="ShotUI/ShotGauges/CurveGauge"] +unique_name_in_owner = true +libraries = { +"": SubResource("AnimationLibrary_dicse") +} + +[node name="GaugeFlasher" type="AnimationPlayer" parent="ShotUI/ShotGauges"] +unique_name_in_owner = true