generated from krampus/template-godot4
Compare commits
9 Commits
af31c3c431
...
7c9403273f
Author | SHA1 | Date |
---|---|---|
Rob Kelly | 7c9403273f | |
Rob Kelly | be07ce40ed | |
Rob Kelly | 70da540e25 | |
Rob Kelly | 960ff79b34 | |
Rob Kelly | 682850738a | |
Rob Kelly | 7201c030e6 | |
Rob Kelly | 7e7b09ff60 | |
Rob Kelly | 2517468b73 | |
Rob Kelly | 5878a2efd5 |
Binary file not shown.
|
@ -6,5 +6,5 @@
|
|||
resource_name = "Sailboat"
|
||||
cull_mode = 2
|
||||
albedo_texture = ExtResource("1_k68kk")
|
||||
roughness = 0.5
|
||||
roughness = 0.43
|
||||
texture_filter = 2
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,35 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c47bkx508biqr"
|
||||
path.s3tc="res://.godot/imported/plasma.png-0d62f2e4ae083d296fe25ccf3ab68e80.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/particles/plasma.png"
|
||||
dest_files=["res://.godot/imported/plasma.png-0d62f2e4ae083d296fe25ccf3ab68e80.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
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=true
|
||||
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=0
|
|
@ -334,6 +334,9 @@ visibility_aabb = AABB(-128, -4, -128, 256, 8, 256)
|
|||
process_material = SubResource("ParticleProcessMaterial_6nt4t")
|
||||
draw_pass_1 = SubResource("QuadMesh_l4j8a")
|
||||
|
||||
[node name="DemoCamera" type="Camera3D" parent="Course" groups=["DemoCamera"]]
|
||||
transform = Transform3D(-0.734269, 0.305072, -0.606448, 0, 0.893336, 0.44939, 0.678858, 0.329973, -0.655949, 143.463, 90.0707, 223.738)
|
||||
|
||||
[node name="CityBuildings" type="Node3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 129.404, -9.53674e-07, 309.4)
|
||||
|
||||
|
@ -385,6 +388,9 @@ transform = Transform3D(0.57763, 0, -0.816299, 0, 1, 0, 0.816299, 0, 0.57763, 0.
|
|||
[node name="PalmTree2" parent="MountainCurve" instance=ExtResource("12_sswxf")]
|
||||
transform = Transform3D(0.184826, 0, -0.982771, 0, 1, 0, 0.982771, 0, 0.184826, 1.55019, 0, -15.9243)
|
||||
|
||||
[node name="DemoCamera" type="Camera3D" parent="MountainCurve" groups=["DemoCamera"]]
|
||||
transform = Transform3D(-0.909976, -0.0858909, 0.405667, 0, 0.978312, 0.207136, -0.41466, 0.188489, -0.890241, 21.863, 16.4413, -111.296)
|
||||
|
||||
[node name="Lakeside" type="Node3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 458.103, 1.52588e-05, 204.202)
|
||||
|
||||
|
@ -419,9 +425,8 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 14.4011, 0.530239, -13.6932)
|
|||
[node name="Umineko3" parent="Lakeside/Flock2" instance=ExtResource("21_ch6qk")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -9.56348, -0.274033, -7.70535)
|
||||
|
||||
[node name="DemoCamera" type="Camera3D" parent="."]
|
||||
transform = Transform3D(-0.317113, 0.433573, -0.843477, 0, 0.88938, 0.457168, 0.948388, 0.144974, -0.282034, 461.268, 30.8271, 256.17)
|
||||
visible = false
|
||||
[node name="DemoCamera" type="Camera3D" parent="Lakeside" groups=["DemoCamera"]]
|
||||
transform = Transform3D(-0.942644, 0.108925, 0.315527, 0, 0.94526, -0.326318, -0.333799, -0.307602, -0.891044, -5.37366, 0.689307, -6.26129)
|
||||
|
||||
[node name="NorthSea" type="Node3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -179.859, -2, 1062.93)
|
||||
|
|
|
@ -63,6 +63,8 @@ config/accessibility/enable_hit_lag=true
|
|||
|
||||
WorldGroup="Singleton group for the active world instance, if any."
|
||||
GameGroup="Singleton group for the active game instance, if any."
|
||||
DemoCamera=""
|
||||
PlayerSpawn=""
|
||||
|
||||
[gui]
|
||||
|
||||
|
@ -125,6 +127,11 @@ shot_accept={
|
|||
"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":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
shot_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)
|
||||
]
|
||||
}
|
||||
select_driver={
|
||||
"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":49,"key_label":0,"unicode":49,"location":0,"echo":false,"script":null)
|
||||
|
@ -170,6 +177,11 @@ debug_4={
|
|||
"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":4194335,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
pause={
|
||||
"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":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[layer_names]
|
||||
|
||||
|
|
|
@ -25,6 +25,9 @@ const IRON_DAMPING := 9999.0
|
|||
## Base damage inflicted on impact with a player
|
||||
@export var base_damage := 15.0
|
||||
|
||||
var _last_contact_normal: Vector3 = Vector3.UP
|
||||
var _position_on_last_wake: Vector3
|
||||
var _awake := false
|
||||
var _zones: Array[BallZone] = []
|
||||
|
||||
@onready var normal_physics: PhysicsMaterial = preload(
|
||||
|
@ -34,6 +37,8 @@ var _zones: Array[BallZone] = []
|
|||
"res://src/equipment/balls/physics_ball/iron_physics.tres"
|
||||
)
|
||||
|
||||
@onready var _debug_draw: Control = %DebugDraw
|
||||
|
||||
|
||||
## Called by a water area when this ball enters it
|
||||
func enter_water() -> void:
|
||||
|
@ -47,13 +52,20 @@ func _total_terrain_angular_damping() -> float:
|
|||
|
||||
|
||||
func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
|
||||
if not _awake:
|
||||
# Triggered on first frame after waking
|
||||
_awake = true
|
||||
_position_on_last_wake = global_position
|
||||
_last_contact_normal = Vector3.UP
|
||||
|
||||
var damping := air_damping
|
||||
if iron_ball:
|
||||
damping = iron_damping
|
||||
elif state.get_contact_count():
|
||||
if state.get_contact_count():
|
||||
_last_contact_normal = state.get_contact_local_normal(0)
|
||||
damping = _total_terrain_angular_damping()
|
||||
if damping <= TERRAIN_DAMPING_EPSILON:
|
||||
damping = rough_damping
|
||||
if iron_ball:
|
||||
damping = iron_damping
|
||||
angular_damp = damping
|
||||
|
||||
|
||||
|
@ -66,3 +78,17 @@ func enter_zone(zone: BallZone) -> void:
|
|||
|
||||
func exit_zone(zone: BallZone) -> void:
|
||||
_zones.erase(zone)
|
||||
|
||||
|
||||
func get_reoriented_basis() -> Basis:
|
||||
var up := _last_contact_normal.normalized()
|
||||
var forward := (_position_on_last_wake - global_position).normalized()
|
||||
var right := up.cross(forward).normalized()
|
||||
forward = right.cross(up) # orthonormalize
|
||||
return Basis(right, up, forward)
|
||||
|
||||
|
||||
func _on_sleeping_state_changed() -> void:
|
||||
if sleeping:
|
||||
# Trigger to reassign on wake
|
||||
_awake = false
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[gd_scene load_steps=8 format=3 uid="uid://dfttci386ohip"]
|
||||
[gd_scene load_steps=9 format=3 uid="uid://dfttci386ohip"]
|
||||
|
||||
[ext_resource type="Script" path="res://src/equipment/balls/physics_ball/game_ball.gd" id="1_iwh2u"]
|
||||
[ext_resource type="PhysicsMaterial" uid="uid://3bih72l068ic" path="res://src/equipment/balls/physics_ball/normal_physics.tres" id="1_l23pw"]
|
||||
|
@ -27,9 +27,40 @@ rings = 6
|
|||
[sub_resource type="SphereShape3D" id="SphereShape3D_0hvq6"]
|
||||
radius = 0.05
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_p4v7o"]
|
||||
resource_name = "debug_draw"
|
||||
script/source = "extends Control
|
||||
|
||||
const COLOR_X := Color(1, 0, 0)
|
||||
const COLOR_Y := Color(0, 1, 0)
|
||||
const COLOR_Z := Color(0, 0, 1)
|
||||
const WIDTH := 4
|
||||
|
||||
@onready var physics_ball: GameBall = $\"..\"
|
||||
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
if visible:
|
||||
queue_redraw()
|
||||
|
||||
|
||||
func _draw() -> void:
|
||||
if physics_ball._last_contact_normal != null:
|
||||
var camera := get_viewport().get_camera_3d()
|
||||
var start := camera.unproject_position(physics_ball.global_position)
|
||||
var basis := physics_ball.get_reoriented_basis()
|
||||
var end_x := camera.unproject_position(physics_ball.global_position + basis.x)
|
||||
var end_y := camera.unproject_position(physics_ball.global_position + basis.y)
|
||||
var end_z := camera.unproject_position(physics_ball.global_position + basis.z)
|
||||
draw_line(start, end_x, COLOR_X, WIDTH)
|
||||
draw_line(start, end_y, COLOR_Y, WIDTH)
|
||||
draw_line(start, end_z, COLOR_Z, WIDTH)
|
||||
"
|
||||
|
||||
[node name="PhysicsBall" type="RigidBody3D"]
|
||||
mass = 0.05
|
||||
physics_material_override = ExtResource("1_l23pw")
|
||||
freeze = true
|
||||
continuous_cd = true
|
||||
contact_monitor = true
|
||||
max_contacts_reported = 1
|
||||
|
@ -44,3 +75,16 @@ mesh = SubResource("SphereMesh_y0d13")
|
|||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
shape = SubResource("SphereShape3D_0hvq6")
|
||||
|
||||
[node name="DebugDraw" type="Control" parent="."]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = SubResource("GDScript_p4v7o")
|
||||
|
||||
[connection signal="sleeping_state_changed" from="." to="." method="_on_sleeping_state_changed"]
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
extends GameBall
|
||||
## The plasma ball sticks to the first surface it hits
|
||||
|
||||
@onready var manual_sleep_timer: Timer = %ManualSleepTimer
|
||||
|
||||
|
||||
func _on_body_entered(_body: Node) -> void:
|
||||
print_debug("Plasma ball stuck to ", _body)
|
||||
# Freeze physics as soon as we hit something
|
||||
freeze = true
|
||||
sleeping = true
|
||||
manual_sleep_timer.start()
|
||||
|
||||
|
||||
func _fire_sleep_signal() -> void:
|
||||
sleeping_state_changed.emit()
|
|
@ -0,0 +1,64 @@
|
|||
[gd_scene load_steps=11 format=3 uid="uid://dcqxlbsrubapk"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://dfttci386ohip" path="res://src/equipment/balls/physics_ball/physics_ball.tscn" id="1_yh4fp"]
|
||||
[ext_resource type="Texture2D" uid="uid://c47bkx508biqr" path="res://assets/sprites/particles/plasma.png" id="2_8fdyx"]
|
||||
[ext_resource type="Script" path="res://src/equipment/balls/plasma_ball/plasma_ball.gd" id="2_pdts3"]
|
||||
|
||||
[sub_resource type="Curve" id="Curve_kabhn"]
|
||||
max_value = 2.0
|
||||
_data = [Vector2(0, 2), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0]
|
||||
point_count = 2
|
||||
|
||||
[sub_resource type="CurveTexture" id="CurveTexture_oxhrr"]
|
||||
curve = SubResource("Curve_kabhn")
|
||||
|
||||
[sub_resource type="Curve" id="Curve_77lhu"]
|
||||
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.249135, 1), 0.0, 0.0, 0, 0, Vector2(1, 0.598878), -0.922125, -0.922125, 0, 0]
|
||||
point_count = 3
|
||||
|
||||
[sub_resource type="CurveTexture" id="CurveTexture_vfusk"]
|
||||
curve = SubResource("Curve_77lhu")
|
||||
|
||||
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_uffe8"]
|
||||
angle_min = -720.0
|
||||
angle_max = 720.0
|
||||
direction = Vector3(0, 1, 0)
|
||||
spread = 10.0
|
||||
initial_velocity_max = 0.1
|
||||
gravity = Vector3(0, 2, 0)
|
||||
scale_curve = SubResource("CurveTexture_vfusk")
|
||||
emission_curve = SubResource("CurveTexture_oxhrr")
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_7ptri"]
|
||||
transparency = 1
|
||||
vertex_color_use_as_albedo = true
|
||||
albedo_color = Color(0.48, 1, 1, 0.384314)
|
||||
albedo_texture = ExtResource("2_8fdyx")
|
||||
emission_enabled = true
|
||||
emission = Color(0.42, 1, 1, 1)
|
||||
billboard_mode = 3
|
||||
billboard_keep_scale = true
|
||||
particles_anim_h_frames = 1
|
||||
particles_anim_v_frames = 1
|
||||
particles_anim_loop = false
|
||||
grow_amount = -0.6
|
||||
|
||||
[sub_resource type="QuadMesh" id="QuadMesh_go8iw"]
|
||||
material = SubResource("StandardMaterial3D_7ptri")
|
||||
size = Vector2(0.4, 0.4)
|
||||
|
||||
[node name="PlasmaBall" instance=ExtResource("1_yh4fp")]
|
||||
script = ExtResource("2_pdts3")
|
||||
|
||||
[node name="PlasmaFireEffect" type="GPUParticles3D" parent="BallMesh" index="0"]
|
||||
amount = 20
|
||||
lifetime = 0.6
|
||||
process_material = SubResource("ParticleProcessMaterial_uffe8")
|
||||
draw_pass_1 = SubResource("QuadMesh_go8iw")
|
||||
|
||||
[node name="ManualSleepTimer" type="Timer" parent="." index="3"]
|
||||
unique_name_in_owner = true
|
||||
one_shot = true
|
||||
|
||||
[connection signal="body_entered" from="." to="." method="_on_body_entered"]
|
||||
[connection signal="timeout" from="ManualSleepTimer" to="." method="_fire_sleep_signal"]
|
|
@ -99,3 +99,12 @@ func _process(_delta: float) -> void:
|
|||
|
||||
if not _loading_resources and loading_screen.visible:
|
||||
loader_transition.play("fade_out")
|
||||
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if what == NOTIFICATION_WM_CLOSE_REQUEST:
|
||||
# Handle close request here
|
||||
# TODO: save?
|
||||
get_tree().quit()
|
||||
elif what == NOTIFICATION_CRASH:
|
||||
print_debug("CRASHING!")
|
||||
|
|
|
@ -162,6 +162,7 @@ libraries = {
|
|||
|
||||
[node name="Rumbler" type="Control" parent="RootControl"]
|
||||
unique_name_in_owner = true
|
||||
process_mode = 1
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
|
|
|
@ -6,7 +6,6 @@ signal ball_collision(ball: GameBall)
|
|||
@export var ignored_balls: Array[GameBall] = []
|
||||
|
||||
@onready var shot_setup: ShotSetup = $".."
|
||||
@onready var physics_ball: GameBall = %PhysicsBall
|
||||
|
||||
|
||||
func _on_ball_entered(ball: GameBall) -> void:
|
||||
|
|
|
@ -22,6 +22,7 @@ const ZOOM_MAX := 12.0
|
|||
const ARROW_ACCELERATION := 8.0
|
||||
const PLAYER_ACCELERATION := 2.0
|
||||
|
||||
const FREE_CAM_GIMBAL_TWEEN_TIME := 0.2
|
||||
const FREE_CAM_RETURN_TIME := 0.618
|
||||
const BALL_RETURN_TIME := 0.618
|
||||
const CAMERA_SNAP_TIME := 0.3
|
||||
|
@ -45,8 +46,6 @@ const WATER_DAMAGE := 10.0
|
|||
@export var base_curve := 0.0
|
||||
|
||||
@export_category("Debug")
|
||||
## When enabled, the game will pause and enter free cam mode when the ball has a collision.
|
||||
@export var debug_ball_impact := false
|
||||
## When enabled, ignore curve meter and hit a perfect shot every time.
|
||||
@export var perfect_aim := false
|
||||
## Keep projection visible
|
||||
|
@ -79,9 +78,7 @@ var phase: Phase = Phase.FINISHED:
|
|||
_on_phase_change(value)
|
||||
phase = value
|
||||
|
||||
var hud: ShotHUD:
|
||||
get:
|
||||
return world.ui.shot_hud if world and world.ui else null
|
||||
var hud: ShotHUD
|
||||
|
||||
var club: Club.Type:
|
||||
set(value):
|
||||
|
@ -127,7 +124,8 @@ var _tracking_camera: OrbitalCamera
|
|||
@onready var shot_projection: ProjectileArc = %ShotProjection
|
||||
|
||||
@onready var ball_point: Node3D = %BallPoint
|
||||
@onready var physics_ball: GameBall = %PhysicsBall
|
||||
# @onready var game_ball: GameBall = %PhysicsBall
|
||||
@onready var game_ball: GameBall = %PlasmaBall
|
||||
|
||||
@onready var drive_ref: RayCast3D = %DriveRef
|
||||
@onready var drive_arrow: Node3D = %DriveArrow
|
||||
|
@ -145,8 +143,6 @@ var _tracking_camera: OrbitalCamera
|
|||
@onready var camera_distance := zoom.position.z:
|
||||
set = _set_camera_distance
|
||||
|
||||
@onready var phys_ball_scene := preload("res://src/equipment/balls/physics_ball/physics_ball.tscn")
|
||||
|
||||
@onready var world: World = get_tree().get_first_node_in_group(World.group)
|
||||
@onready var game: Game = get_tree().get_first_node_in_group(Game.group)
|
||||
|
||||
|
@ -155,13 +151,11 @@ var _tracking_camera: OrbitalCamera
|
|||
static var scene := preload("res://src/player/shot_setup/shot_setup.tscn")
|
||||
|
||||
|
||||
func _init_deferred() -> void:
|
||||
# Set up HUD
|
||||
club = initial_club
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_init_deferred.call_deferred()
|
||||
# Create & set up HUD
|
||||
hud = ShotHUD.create(player)
|
||||
world.ui.add_player_hud(hud)
|
||||
club = initial_club
|
||||
|
||||
|
||||
func _set_camera_distance(value: float) -> void:
|
||||
|
@ -233,15 +227,15 @@ func take_shot() -> void:
|
|||
Transform3D.IDENTITY.scaled(Vector3.ONE * impulse.length()).looking_at(impulse)
|
||||
)
|
||||
|
||||
physics_ball.freeze = false
|
||||
physics_ball.apply_central_impulse(impulse)
|
||||
game_ball.freeze = false
|
||||
game_ball.apply_central_impulse(impulse)
|
||||
|
||||
|
||||
## Make the shot projection widget visible, with animated transition
|
||||
func _show_shot_projection() -> void:
|
||||
shot_projection.initial_speed = 1
|
||||
shot_projection.basis = shot_ref.basis.orthonormalized()
|
||||
var shot_speed := get_shot_impulse(1.0).length() / physics_ball.mass
|
||||
var shot_speed := get_shot_impulse(1.0).length() / game_ball.mass
|
||||
var tween := get_tree().create_tween()
|
||||
tween.tween_property(shot_projection, "initial_speed", shot_speed, CAMERA_SNAP_TIME).set_trans(
|
||||
Tween.TRANS_QUAD
|
||||
|
@ -255,6 +249,9 @@ func insert_free_cam() -> void:
|
|||
hud.hide_hud()
|
||||
_free_camera = FreeCamera.create(camera)
|
||||
add_sibling(_free_camera)
|
||||
# Un-gimbal-lock ourselves: quickly tween Z rotation to 0
|
||||
var tween := get_tree().create_tween()
|
||||
tween.tween_property(_free_camera, "rotation:z", 0, FREE_CAM_GIMBAL_TWEEN_TIME)
|
||||
control_disabled = true
|
||||
camera.current = false
|
||||
|
||||
|
@ -275,12 +272,12 @@ func return_free_cam() -> void:
|
|||
|
||||
|
||||
func return_ball() -> void:
|
||||
physics_ball.freeze = true
|
||||
game_ball.freeze = true
|
||||
var tween := get_tree().create_tween()
|
||||
(
|
||||
tween
|
||||
. tween_property(
|
||||
physics_ball,
|
||||
game_ball,
|
||||
"global_transform",
|
||||
ball_point.global_transform,
|
||||
BALL_RETURN_TIME,
|
||||
|
@ -291,14 +288,22 @@ func return_ball() -> void:
|
|||
|
||||
|
||||
func travel_to_ball() -> void:
|
||||
physics_ball.freeze = true
|
||||
global_position = physics_ball.global_position
|
||||
physics_ball.global_transform = ball_point.global_transform
|
||||
game_ball.freeze = true
|
||||
global_position = game_ball.global_position
|
||||
|
||||
# Re-orient to the ball's last contact normal if there is one.
|
||||
# Normally this will just be Vector3.UP or something close to it.
|
||||
direction.rotation.y = 0
|
||||
_target_rotation.y = 0
|
||||
global_basis = game_ball.get_reoriented_basis()
|
||||
print_debug("REORIENTED BASIS: ", global_basis)
|
||||
|
||||
game_ball.global_transform = ball_point.global_transform
|
||||
|
||||
|
||||
func start_shot_track() -> void:
|
||||
if phase == Phase.SHOT:
|
||||
_tracking_camera = OrbitalCamera.create(physics_ball)
|
||||
_tracking_camera = OrbitalCamera.create(game_ball)
|
||||
_tracking_camera.rotation.y = randf_range(0.0, TAU)
|
||||
add_sibling(_tracking_camera)
|
||||
_tracking_camera.global_transform = ball_point.global_transform
|
||||
|
@ -326,7 +331,7 @@ func _on_club_change(new_club_type: Club.Type) -> void:
|
|||
wedge_arrow.hide()
|
||||
iron_arrow.hide()
|
||||
putt_arrow.hide()
|
||||
physics_ball.iron_ball = false
|
||||
game_ball.iron_ball = false
|
||||
hud.club_selector.value = new_club_type
|
||||
# TODO club change animation
|
||||
character.hold_right(new_club.get_model())
|
||||
|
@ -343,7 +348,7 @@ func _on_club_change(new_club_type: Club.Type) -> void:
|
|||
Club.Type.IRON:
|
||||
shot_ref = iron_ref
|
||||
iron_arrow.show()
|
||||
physics_ball.iron_ball = true
|
||||
game_ball.iron_ball = true
|
||||
Club.Type.SPECIAL:
|
||||
# TODO figure this out
|
||||
shot_ref = drive_ref
|
||||
|
@ -356,7 +361,6 @@ func _on_phase_change(new_phase: Phase) -> void:
|
|||
print_debug("Player ", player.name, ": change to ", Phase.keys()[new_phase])
|
||||
match new_phase:
|
||||
Phase.AIM:
|
||||
hud.set_state_for_player(player)
|
||||
hud.show_hud()
|
||||
if not arrow.visible:
|
||||
arrow_animation.play("show")
|
||||
|
@ -393,7 +397,6 @@ func _on_phase_change(new_phase: Phase) -> void:
|
|||
Phase.FINISHED:
|
||||
hud.power_bar.hide()
|
||||
hud.curve_bar.hide()
|
||||
travel_to_ball()
|
||||
finished.emit(self)
|
||||
|
||||
|
||||
|
@ -470,14 +473,14 @@ func _process(delta: float) -> void:
|
|||
# TODO set power gauge parameters if needed
|
||||
character.start_upswing()
|
||||
hud.start_power_bar()
|
||||
if Input.is_action_just_pressed("ui_cancel"):
|
||||
if Input.is_action_just_pressed("shot_cancel"):
|
||||
hud.reset_power_bar()
|
||||
phase = Phase.AIM
|
||||
if Input.is_action_just_released("shot_accept") and shot_power > 0:
|
||||
hud.stop_power_bar()
|
||||
phase = Phase.CURVE_ADJUST
|
||||
Phase.CURVE_ADJUST:
|
||||
if Input.is_action_just_pressed("ui_cancel"):
|
||||
if Input.is_action_just_pressed("shot_cancel"):
|
||||
hud.reset_curve_bar()
|
||||
phase = Phase.POWER_ADJUST
|
||||
if Input.is_action_just_pressed("shot_accept"):
|
||||
|
@ -493,33 +496,21 @@ func _process(delta: float) -> void:
|
|||
phase = Phase.AIM
|
||||
|
||||
|
||||
func _on_physics_ball_sleeping_state_changed() -> void:
|
||||
if physics_ball.sleeping and phase == Phase.SHOT:
|
||||
func _on_ball_sleeping_state_changed() -> void:
|
||||
if game_ball.sleeping and phase == Phase.SHOT:
|
||||
travel_to_ball()
|
||||
end_shot_track()
|
||||
|
||||
|
||||
func _on_ball_entered_water() -> void:
|
||||
# Should only be possible during SHOT phase, but let's check just to be sure...
|
||||
if phase == Phase.SHOT:
|
||||
physics_ball.freeze = true
|
||||
game_ball.freeze = true
|
||||
hud.play_wasted_animation()
|
||||
player.life -= WATER_DAMAGE
|
||||
ball_return_timer.start(WASTED_BALL_RETURN_DELAY)
|
||||
|
||||
|
||||
func _on_physics_ball_body_entered(_body: Node) -> void:
|
||||
print_debug("BONK!")
|
||||
if debug_ball_impact:
|
||||
get_tree().paused = true
|
||||
var snap_point: Node3D = camera
|
||||
if _tracking_camera:
|
||||
snap_point = _tracking_camera
|
||||
_free_camera = FreeCamera.create(snap_point)
|
||||
add_sibling(_free_camera)
|
||||
control_disabled = true
|
||||
camera.current = false
|
||||
|
||||
|
||||
func _on_ball_return_timer_timeout() -> void:
|
||||
return_ball()
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
[gd_scene load_steps=19 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://dfttci386ohip" path="res://src/equipment/balls/physics_ball/physics_ball.tscn" id="2_1i5j5"]
|
||||
[ext_resource type="PackedScene" uid="uid://c2k88ns0h5ie1" path="res://src/ui/3d/arrow/arrow.tscn" id="2_s70wl"]
|
||||
[ext_resource type="PackedScene" uid="uid://dcqxlbsrubapk" path="res://src/equipment/balls/plasma_ball/plasma_ball.tscn" id="3_8dte7"]
|
||||
[ext_resource type="PackedScene" uid="uid://1s3gywmoi20e" path="res://src/characters/player_characters/gfolf_girl/gfolf_girl.tscn" id="3_e4aur"]
|
||||
[ext_resource type="PackedScene" uid="uid://fht6j87o8ecr" path="res://src/ui/3d/projectile_arc/projectile_arc.tscn" id="4_ry2ho"]
|
||||
[ext_resource type="PackedScene" uid="uid://dbdul15c4oblg" path="res://src/ui/3d/projected_target.tscn" id="6_mynqj"]
|
||||
|
@ -214,10 +214,8 @@ script = ExtResource("1_r6ei4")
|
|||
unique_name_in_owner = true
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.08, 0)
|
||||
|
||||
[node name="PhysicsBall" parent="BallPoint" instance=ExtResource("2_1i5j5")]
|
||||
[node name="PlasmaBall" parent="BallPoint" instance=ExtResource("3_8dte7")]
|
||||
unique_name_in_owner = true
|
||||
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0)
|
||||
freeze = true
|
||||
|
||||
[node name="BallImpulseDebug" type="Node3D" parent="BallPoint"]
|
||||
unique_name_in_owner = true
|
||||
|
@ -234,6 +232,9 @@ unique_name_in_owner = true
|
|||
[node name="GfolfGirl" parent="PlayerPivot" instance=ExtResource("3_e4aur")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -0.555968, 0, 0.0999683)
|
||||
|
||||
[node name="DemoCamera" type="Camera3D" parent="PlayerPivot" groups=["DemoCamera"]]
|
||||
transform = Transform3D(-0.124487, 0.584637, 0.801687, 0, 0.807972, -0.589221, -0.992221, -0.0733503, -0.100582, 0.395614, 0.0284514, -0.0394773)
|
||||
|
||||
[node name="Direction" type="Node3D" parent="."]
|
||||
unique_name_in_owner = true
|
||||
|
||||
|
@ -349,7 +350,7 @@ visible = false
|
|||
initial_speed = 50.0
|
||||
time_step = 0.01
|
||||
max_steps = 800
|
||||
excluded_bodies = [NodePath("../../BallPoint/PhysicsBall")]
|
||||
excluded_bodies = [NodePath("../../BallPoint/PlasmaBall")]
|
||||
|
||||
[node name="ProjectedTarget" parent="ArrowPivot/ShotProjection" instance=ExtResource("6_mynqj")]
|
||||
|
||||
|
@ -366,14 +367,13 @@ one_shot = true
|
|||
|
||||
[node name="Hitbox" type="Area3D" parent="." node_paths=PackedStringArray("ignored_balls")]
|
||||
script = ExtResource("7_uh8kn")
|
||||
ignored_balls = [NodePath("../BallPoint/PhysicsBall")]
|
||||
ignored_balls = [NodePath("../BallPoint/PlasmaBall")]
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Hitbox"]
|
||||
shape = SubResource("SphereShape3D_xvvdi")
|
||||
|
||||
[connection signal="body_entered" from="BallPoint/PhysicsBall" to="." method="_on_physics_ball_body_entered"]
|
||||
[connection signal="entered_water" from="BallPoint/PhysicsBall" to="." method="_on_ball_entered_water"]
|
||||
[connection signal="sleeping_state_changed" from="BallPoint/PhysicsBall" to="." method="_on_physics_ball_sleeping_state_changed"]
|
||||
[connection signal="entered_water" from="BallPoint/PlasmaBall" to="." method="_on_ball_entered_water"]
|
||||
[connection signal="sleeping_state_changed" from="BallPoint/PlasmaBall" to="." method="_on_ball_sleeping_state_changed"]
|
||||
[connection signal="timeout" from="BallReturnTimer" to="." method="_on_ball_return_timer_timeout"]
|
||||
[connection signal="ball_collision" from="Hitbox" to="." method="_on_hitbox_ball_collision"]
|
||||
[connection signal="body_entered" from="Hitbox" to="Hitbox" method="_on_body_entered"]
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
[ext_resource type="Material" uid="uid://cift6p0wn1oce" path="res://assets/materials/guard_rail.tres" id="2_1s4wy"]
|
||||
[ext_resource type="PlaneMesh" uid="uid://bdcmgvgpj1e0w" path="res://src/props/scenery/highway/guard_rail/guard_rail_post_mesh.tres" id="3_hha2c"]
|
||||
|
||||
[sub_resource type="MultiMesh" id="MultiMesh_suiix"]
|
||||
[sub_resource type="MultiMesh" id="MultiMesh_1o4mq"]
|
||||
transform_format = 1
|
||||
mesh = ExtResource("3_hha2c")
|
||||
|
||||
|
@ -42,6 +42,6 @@ path_joined = false
|
|||
material = ExtResource("2_1s4wy")
|
||||
|
||||
[node name="PostMultiMesh" type="MultiMeshInstance3D" parent="."]
|
||||
multimesh = SubResource("MultiMesh_suiix")
|
||||
multimesh = SubResource("MultiMesh_1o4mq")
|
||||
|
||||
[connection signal="curve_changed" from="." to="." method="_on_curve_changed"]
|
||||
|
|
|
@ -65,7 +65,7 @@ func _reset_position() -> void:
|
|||
func _process(_delta: float) -> void:
|
||||
if _hit_lag_frames >= 0:
|
||||
if _hit_lag_frames == 0:
|
||||
content.process_mode = Node.PROCESS_MODE_INHERIT
|
||||
get_tree().paused = false
|
||||
else:
|
||||
content.process_mode = Node.PROCESS_MODE_DISABLED
|
||||
get_tree().paused = true
|
||||
_hit_lag_frames -= 1
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
[gd_resource type="Theme" load_steps=3 format=3 uid="uid://diodjft5u2cck"]
|
||||
[gd_resource type="Theme" load_steps=5 format=3 uid="uid://diodjft5u2cck"]
|
||||
|
||||
[ext_resource type="FontFile" uid="uid://dsa0oh7c0h4pu" path="res://assets/fonts/Racing_Sans_One/RacingSansOne-Regular.ttf" id="1_3rv2b"]
|
||||
[ext_resource type="FontFile" uid="uid://comihs66wounx" path="res://assets/fonts/Dokdo/Dokdo-Regular.ttf" id="1_eha6a"]
|
||||
[ext_resource type="FontFile" uid="uid://b6gxwgomstkgu" path="res://assets/fonts/Geo/Geo-Italic.ttf" id="2_5ty6u"]
|
||||
[ext_resource type="FontFile" uid="uid://s4c1kf0rk2mb" path="res://assets/fonts/Geo/Geo-Regular.ttf" id="3_cee6l"]
|
||||
|
||||
[resource]
|
||||
default_font = ExtResource("3_cee6l")
|
||||
default_font_size = 18
|
||||
ClubSelectLabel/base_type = &"Label"
|
||||
ClubSelectLabel/colors/font_color = Color(1, 0.933333, 0.894118, 1)
|
||||
ClubSelectLabel/colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
|
@ -17,6 +21,13 @@ ClubSelectLabelDisabled/base_type = &"ClubSelectLabel"
|
|||
ClubSelectLabelDisabled/colors/font_color = Color(0.4, 0.3848, 0.376, 1)
|
||||
ClubSelectLabelDisabled/colors/font_outline_color = Color(0.2, 0.2, 0.2, 1)
|
||||
ClubSelectLabelDisabled/colors/font_shadow_color = Color(0.2, 0.2, 0.2, 1)
|
||||
ClubSelectLabelDisabled/font_sizes/font_size = 84
|
||||
ClubSelectLabelDisabled/fonts/font = ExtResource("1_3rv2b")
|
||||
PauseMenuButton/base_type = &"Button"
|
||||
PauseMenuButton/colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
PauseMenuButton/constants/outline_size = 6
|
||||
PauseMenuButton/font_sizes/font_size = 32
|
||||
PauseMenuButton/fonts/font = ExtResource("2_5ty6u")
|
||||
ShotFeedback/base_type = &"RichTextLabel"
|
||||
ShotFeedback/colors/font_shadow_color = Color(0, 0, 0, 1)
|
||||
ShotFeedback/constants/shadow_offset_x = 6
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
extends Control
|
||||
## Menu shown in-game when the user presses pause.
|
||||
|
||||
@onready var menu_list: VBoxContainer = %MenuList
|
||||
@onready var quit_confirm: CenterContainer = %QuitConfirm
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
print_debug("Pause menu _ready()")
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
|
||||
|
||||
|
||||
func _exit_tree() -> void:
|
||||
print_debug("Pause menu _exit_tree()")
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
||||
|
||||
|
||||
func _unhandled_key_input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("pause"):
|
||||
get_viewport().set_input_as_handled()
|
||||
resume()
|
||||
|
||||
|
||||
func _unhide() -> void:
|
||||
menu_list.show()
|
||||
|
||||
|
||||
func _hide() -> void:
|
||||
menu_list.hide()
|
||||
|
||||
|
||||
func resume() -> void:
|
||||
print_debug("Pause menu resume()")
|
||||
queue_free()
|
||||
|
||||
|
||||
func settings() -> void:
|
||||
pass # TODO
|
||||
|
||||
|
||||
func quit() -> void:
|
||||
quit_confirm.show()
|
||||
|
||||
|
||||
func cancel_quit() -> void:
|
||||
quit_confirm.hide()
|
||||
|
||||
|
||||
func confirm_quit() -> void:
|
||||
get_tree().root.propagate_notification(NOTIFICATION_WM_CLOSE_REQUEST)
|
|
@ -0,0 +1,111 @@
|
|||
[gd_scene load_steps=3 format=3 uid="uid://byvjsvavbg5xe"]
|
||||
|
||||
[ext_resource type="FontFile" uid="uid://b6gxwgomstkgu" path="res://assets/fonts/Geo/Geo-Italic.ttf" id="1_4nw1f"]
|
||||
[ext_resource type="Script" path="res://src/ui/menus/pause_menu/pause_menu.gd" id="1_rd0j2"]
|
||||
|
||||
[node name="PauseMenu" type="Control"]
|
||||
process_mode = 3
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_rd0j2")
|
||||
|
||||
[node name="Shade" type="ColorRect" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
color = Color(0, 0, 0, 0.156863)
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 3
|
||||
anchor_left = 1.0
|
||||
anchor_top = 1.0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 0
|
||||
grow_vertical = 0
|
||||
theme_override_constants/margin_right = 160
|
||||
theme_override_constants/margin_bottom = 160
|
||||
|
||||
[node name="MenuList" type="VBoxContainer" parent="MarginContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="MarginContainer/MenuList"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(1, 1, 1, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/outline_size = 8
|
||||
theme_override_fonts/font = ExtResource("1_4nw1f")
|
||||
theme_override_font_sizes/font_size = 72
|
||||
text = "Paused"
|
||||
|
||||
[node name="ResumeButton" type="Button" parent="MarginContainer/MenuList"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"PauseMenuButton"
|
||||
text = "Resume"
|
||||
|
||||
[node name="SettingsButton" type="Button" parent="MarginContainer/MenuList"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"PauseMenuButton"
|
||||
text = "Settings"
|
||||
|
||||
[node name="QuitButton" type="Button" parent="MarginContainer/MenuList"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"PauseMenuButton"
|
||||
theme_override_colors/font_color = Color(1, 0.36, 0.36, 1)
|
||||
text = "Quit"
|
||||
|
||||
[node name="QuitConfirm" type="CenterContainer" parent="."]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="PanelContainer" type="PanelContainer" parent="QuitConfirm"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="QuitConfirm/PanelContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 8
|
||||
theme_override_constants/margin_top = 8
|
||||
theme_override_constants/margin_right = 8
|
||||
theme_override_constants/margin_bottom = 8
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="QuitConfirm/PanelContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="QuitConfirm/PanelContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Quit to desktop?"
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="QuitConfirm/PanelContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 16
|
||||
|
||||
[node name="CancelButton" type="Button" parent="QuitConfirm/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Cancel"
|
||||
|
||||
[node name="ConfirmQuitButton" type="Button" parent="QuitConfirm/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Quit"
|
||||
|
||||
[connection signal="pressed" from="MarginContainer/MenuList/ResumeButton" to="." method="resume"]
|
||||
[connection signal="pressed" from="MarginContainer/MenuList/SettingsButton" to="." method="settings"]
|
||||
[connection signal="pressed" from="MarginContainer/MenuList/QuitButton" to="." method="quit"]
|
||||
[connection signal="pressed" from="QuitConfirm/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/CancelButton" to="." method="cancel_quit"]
|
||||
[connection signal="pressed" from="QuitConfirm/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/ConfirmQuitButton" to="." method="confirm_quit"]
|
|
@ -60,16 +60,20 @@ func _reset_label_scale() -> void:
|
|||
|
||||
|
||||
func _set_value(new_value: Club.Type) -> void:
|
||||
var old_label := _get_club_label(value)
|
||||
var new_label := _get_club_label(new_value)
|
||||
value = new_value
|
||||
if not (old_label or new_label):
|
||||
return
|
||||
|
||||
var tween := get_tree().create_tween()
|
||||
tween.set_parallel()
|
||||
|
||||
var old_label := _get_club_label(value)
|
||||
if old_label:
|
||||
tween.tween_property(old_label, "scale", UNSELECTED_SCALE, LABEL_SCALE_TIME).set_trans(
|
||||
Tween.TRANS_SINE
|
||||
)
|
||||
|
||||
var new_label := _get_club_label(new_value)
|
||||
if new_label:
|
||||
tween.tween_property(new_label, "scale", SELECTED_SCALE, LABEL_SCALE_TIME).set_trans(
|
||||
Tween.TRANS_SINE
|
||||
|
@ -78,5 +82,3 @@ func _set_value(new_value: Club.Type) -> void:
|
|||
tween.tween_property(club_hub, "rotation_degrees", theta, HUB_ROTATION_TIME).set_trans(
|
||||
Tween.TRANS_QUAD
|
||||
)
|
||||
|
||||
value = new_value
|
||||
|
|
|
@ -6,7 +6,7 @@ const LIFE_BAR_DAMAGE_RUMBLE_SCALE := 0.2
|
|||
## Time it takes to dampen the life bar rumble on taking damage, in seconds
|
||||
const LIFE_BAR_DAMAGE_RUMBLE_TIME := 0.2
|
||||
|
||||
var _life_signal: Signal
|
||||
var player: WorldPlayer
|
||||
|
||||
@onready var power_bar: TextureProgressBar = %PowerBar
|
||||
@onready var curve_bar: ProgressBar = %CurveBar
|
||||
|
@ -14,47 +14,45 @@ var _life_signal: Signal
|
|||
|
||||
@onready var club_selector: ClubSelector = %ClubSelector
|
||||
|
||||
@onready var hud_state_machine: AnimationTree = %HUDStateMachine
|
||||
|
||||
@onready var _curve_animation: AnimationPlayer = %CurveAnimation
|
||||
@onready var _power_animation: AnimationPlayer = %PowerAnimation
|
||||
|
||||
@onready var _nice_animation: AnimationPlayer = %NiceAnimation
|
||||
@onready var _wasted_animation: AnimationPlayer = %WastedAnimation
|
||||
|
||||
@onready var _club_selector_animation: AnimationPlayer = %ClubSelectorAnimation
|
||||
@onready var _sw_animation: AnimationPlayer = %SWAnimation
|
||||
|
||||
@onready var _player_name: Label = %PlayerName
|
||||
|
||||
@onready var _life_bar_rumbler: Rumbler = %LifeBarRumbler
|
||||
|
||||
@onready var _state: AnimationNodeStateMachinePlayback = hud_state_machine["parameters/playback"]
|
||||
static var scene: PackedScene = preload("res://src/ui/shot_hud/shot_hud.tscn")
|
||||
|
||||
|
||||
## Set any HUD state specific to the player.
|
||||
func set_state_for_player(player: WorldPlayer) -> void:
|
||||
print_debug("Setting HUD for player ", player.name)
|
||||
func _ready() -> void:
|
||||
club_selector.set_state_for_player(player)
|
||||
_player_name.text = player.name
|
||||
# TODO animate on life loss?
|
||||
life_bar.value = player.life
|
||||
life_bar.tint_progress = player.color
|
||||
|
||||
# TODO this is soooooo wack...
|
||||
# TODO we should just revert to having distinct ShotHUDs for each player
|
||||
if _life_signal and _life_signal.is_connected(set_life_value):
|
||||
_life_signal.disconnect(set_life_value)
|
||||
_life_signal = player.on_life_changed
|
||||
_life_signal.connect(set_life_value)
|
||||
|
||||
player.on_life_changed.connect(set_life_value)
|
||||
# TODO special equipment
|
||||
# TODO abilities
|
||||
|
||||
|
||||
func show_hud() -> void:
|
||||
_state.travel("visible")
|
||||
_club_selector_animation.play("show")
|
||||
_sw_animation.play("show")
|
||||
|
||||
|
||||
func hide_hud() -> void:
|
||||
_state.travel("hidden")
|
||||
_club_selector_animation.play("hide")
|
||||
_sw_animation.play("hide")
|
||||
|
||||
|
||||
func peek_life_bar() -> void:
|
||||
_sw_animation.play("peek")
|
||||
|
||||
|
||||
func start_power_bar() -> void:
|
||||
|
@ -96,6 +94,7 @@ func set_life_value(new_value: float) -> void:
|
|||
var difference := new_value - life_bar.value
|
||||
if difference < 0:
|
||||
# Taking damage
|
||||
peek_life_bar()
|
||||
_life_bar_rumbler.intensity = LIFE_BAR_DAMAGE_RUMBLE_SCALE * abs(difference)
|
||||
var tween := get_tree().create_tween()
|
||||
(
|
||||
|
@ -108,3 +107,10 @@ func set_life_value(new_value: float) -> void:
|
|||
# TODO: something for this?
|
||||
pass
|
||||
life_bar.value = new_value
|
||||
|
||||
|
||||
static func create(player: WorldPlayer) -> ShotHUD:
|
||||
var instance: ShotHUD = scene.instantiate()
|
||||
instance.player = player
|
||||
|
||||
return instance
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[gd_scene load_steps=33 format=3 uid="uid://c4ifdiohng830"]
|
||||
[gd_scene load_steps=32 format=3 uid="uid://c4ifdiohng830"]
|
||||
|
||||
[ext_resource type="Script" path="res://src/ui/shot_hud/shot_hud.gd" id="1_x5b4c"]
|
||||
[ext_resource type="Shader" path="res://src/shaders/canvas_retro.gdshader" id="1_ybxxp"]
|
||||
|
@ -376,12 +376,13 @@ _data = {
|
|||
"fill": SubResource("Animation_uo6s7")
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_3cn2c"]
|
||||
[sub_resource type="Animation" id="Animation_4h8gq"]
|
||||
resource_name = "RESET"
|
||||
length = 0.001
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("ClubSelector:rotation")
|
||||
tracks/0/path = NodePath(".:rotation")
|
||||
tracks/0/interp = 4
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
|
@ -391,14 +392,14 @@ tracks/0/keys = {
|
|||
"values": [0.0]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_dt1yq"]
|
||||
resource_name = "hide"
|
||||
[sub_resource type="Animation" id="Animation_w7dmn"]
|
||||
resource_name = "hide_selector"
|
||||
length = 0.4
|
||||
step = 0.02
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("ClubSelector:rotation")
|
||||
tracks/0/path = NodePath(".:rotation")
|
||||
tracks/0/interp = 4
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
|
@ -408,14 +409,14 @@ tracks/0/keys = {
|
|||
"values": [0.0, 0.0872665, -1.5708]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_0maif"]
|
||||
[sub_resource type="Animation" id="Animation_x6kyr"]
|
||||
resource_name = "show"
|
||||
length = 0.4
|
||||
step = 0.02
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("ClubSelector:rotation")
|
||||
tracks/0/path = NodePath(".:rotation")
|
||||
tracks/0/interp = 4
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
|
@ -425,45 +426,144 @@ tracks/0/keys = {
|
|||
"values": [-1.5708, 0.0872665, 0.0]
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_5nauw"]
|
||||
_data = {
|
||||
"RESET": SubResource("Animation_4h8gq"),
|
||||
"hide": SubResource("Animation_w7dmn"),
|
||||
"show": SubResource("Animation_x6kyr")
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_3cn2c"]
|
||||
resource_name = "RESET"
|
||||
length = 0.001
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("SouthWest:position")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Vector2(0, 982)]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("SouthWest:visible")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 1,
|
||||
"values": [true]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_yis4x"]
|
||||
resource_name = "hide_health_bar"
|
||||
length = 0.4
|
||||
step = 0.02
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("SouthWest:position")
|
||||
tracks/0/interp = 2
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.1, 0.4),
|
||||
"transitions": PackedFloat32Array(1.618, 1.618, 1),
|
||||
"update": 0,
|
||||
"values": [Vector2(0, 982), Vector2(0, 960), Vector2(0, 1100)]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("SouthWest:visible")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0.4),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 1,
|
||||
"values": [false]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_nicro"]
|
||||
resource_name = "show_life_bar"
|
||||
length = 0.4
|
||||
step = 0.02
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("SouthWest:position")
|
||||
tracks/0/interp = 2
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.34, 0.4),
|
||||
"transitions": PackedFloat32Array(1.618, 1.618, 1),
|
||||
"update": 0,
|
||||
"values": [Vector2(0, 1100), Vector2(0, 960), Vector2(0, 982)]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("SouthWest:visible")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 1,
|
||||
"values": [true]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_jugqx"]
|
||||
resource_name = "peek"
|
||||
length = 2.4
|
||||
step = 0.02
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("SouthWest:position")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.1, 2.3, 2.4),
|
||||
"transitions": PackedFloat32Array(1.618, 1, 1.618, 1),
|
||||
"update": 0,
|
||||
"values": [Vector2(0, 1100), Vector2(0, 982), Vector2(0, 982), Vector2(0, 1100)]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("SouthWest:visible")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0, 2.4),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 1,
|
||||
"values": [true, false]
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_c3i4w"]
|
||||
_data = {
|
||||
"RESET": SubResource("Animation_3cn2c"),
|
||||
"hide": SubResource("Animation_dt1yq"),
|
||||
"show": SubResource("Animation_0maif")
|
||||
"hide": SubResource("Animation_yis4x"),
|
||||
"peek": SubResource("Animation_jugqx"),
|
||||
"show": SubResource("Animation_nicro")
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_8uxnp"]
|
||||
animation = &"hide"
|
||||
|
||||
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_v05eu"]
|
||||
animation = &"show"
|
||||
|
||||
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_28a4x"]
|
||||
advance_mode = 2
|
||||
|
||||
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_bj7v0"]
|
||||
switch_mode = 2
|
||||
|
||||
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_xpwgd"]
|
||||
switch_mode = 2
|
||||
|
||||
[sub_resource type="AnimationNodeStateMachine" id="AnimationNodeStateMachine_osrbp"]
|
||||
states/hidden/node = SubResource("AnimationNodeAnimation_8uxnp")
|
||||
states/hidden/position = Vector2(592, 100)
|
||||
states/visible/node = SubResource("AnimationNodeAnimation_v05eu")
|
||||
states/visible/position = Vector2(364, 100)
|
||||
transitions = ["Start", "visible", SubResource("AnimationNodeStateMachineTransition_28a4x"), "visible", "hidden", SubResource("AnimationNodeStateMachineTransition_bj7v0"), "hidden", "visible", SubResource("AnimationNodeStateMachineTransition_xpwgd")]
|
||||
graph_offset = Vector2(-309, -132)
|
||||
|
||||
[node name="ShotHUD" type="Control"]
|
||||
top_level = true
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 1
|
||||
mouse_filter = 2
|
||||
script = ExtResource("1_x5b4c")
|
||||
|
||||
[node name="WoahNiceFeedback" type="RichTextLabel" parent="."]
|
||||
|
@ -544,7 +644,7 @@ anchor_right = 0.6
|
|||
anchor_bottom = 0.85
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 1
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="PowerGauge" type="Control" parent="ShotGauges"]
|
||||
layout_mode = 1
|
||||
|
@ -650,16 +750,11 @@ grow_horizontal = 1
|
|||
grow_vertical = 1
|
||||
pivot_offset = Vector2(-400, 0)
|
||||
|
||||
[node name="HUDAnimation" type="AnimationPlayer" parent="."]
|
||||
libraries = {
|
||||
"": SubResource("AnimationLibrary_c3i4w")
|
||||
}
|
||||
|
||||
[node name="HUDStateMachine" type="AnimationTree" parent="."]
|
||||
[node name="ClubSelectorAnimation" type="AnimationPlayer" parent="ClubSelector"]
|
||||
unique_name_in_owner = true
|
||||
root_node = NodePath("%HUDStateMachine/..")
|
||||
tree_root = SubResource("AnimationNodeStateMachine_osrbp")
|
||||
anim_player = NodePath("../HUDAnimation")
|
||||
libraries = {
|
||||
"": SubResource("AnimationLibrary_5nauw")
|
||||
}
|
||||
|
||||
[node name="SouthWest" type="MarginContainer" parent="."]
|
||||
layout_mode = 1
|
||||
|
@ -667,8 +762,9 @@ anchors_preset = -1
|
|||
anchor_top = 1.0
|
||||
anchor_right = 0.333
|
||||
anchor_bottom = 1.0
|
||||
offset_top = -40.0
|
||||
offset_top = 20.0
|
||||
offset_right = 40.0
|
||||
offset_bottom = 118.0
|
||||
grow_vertical = 0
|
||||
theme_override_constants/margin_left = 16
|
||||
theme_override_constants/margin_bottom = 16
|
||||
|
@ -709,3 +805,10 @@ script = ExtResource("3_6groq")
|
|||
[node name="LifeBar" parent="SouthWest/VBoxContainer/MarginContainer/LifeBarRumbler" instance=ExtResource("9_w1fiw")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
|
||||
[node name="SWAnimation" type="AnimationPlayer" parent="SouthWest"]
|
||||
unique_name_in_owner = true
|
||||
root_node = NodePath("../..")
|
||||
libraries = {
|
||||
"": SubResource("AnimationLibrary_c3i4w")
|
||||
}
|
||||
|
|
|
@ -1,4 +1,45 @@
|
|||
class_name WorldUI extends Control
|
||||
## Container & accessor for the world UI.
|
||||
|
||||
@onready var shot_hud: ShotHUD = %ShotHUD
|
||||
const DEMO_CAMERA_GROUP := "DemoCamera"
|
||||
|
||||
@export var pause_scene := preload("res://src/ui/menus/pause_menu/pause_menu.tscn")
|
||||
|
||||
var _prev_camera: Camera3D
|
||||
|
||||
@onready var hud_container: Control = %HUDContainer
|
||||
@onready var pause_container: Control = %PauseContainer
|
||||
|
||||
|
||||
func _unhandled_key_input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("pause"):
|
||||
get_viewport().set_input_as_handled()
|
||||
pause()
|
||||
|
||||
|
||||
func add_player_hud(hud: ShotHUD) -> void:
|
||||
hud_container.add_child(hud)
|
||||
|
||||
|
||||
func pause() -> void:
|
||||
# Switch to demo cam, if there is one.
|
||||
var democams: Array[Node] = get_tree().get_nodes_in_group(DEMO_CAMERA_GROUP)
|
||||
if democams:
|
||||
_prev_camera = get_viewport().get_camera_3d()
|
||||
var democam: Camera3D = democams.pick_random()
|
||||
democam.make_current()
|
||||
|
||||
var menu := pause_scene.instantiate()
|
||||
pause_container.add_child(menu)
|
||||
menu.tree_exiting.connect(_unpause)
|
||||
hud_container.hide()
|
||||
get_tree().paused = true
|
||||
|
||||
|
||||
func _unpause() -> void:
|
||||
# Unset demo camera, if there is one.
|
||||
if is_instance_valid(_prev_camera):
|
||||
_prev_camera.make_current()
|
||||
_prev_camera = null
|
||||
hud_container.show()
|
||||
get_tree().paused = false
|
||||
|
|
|
@ -3,7 +3,6 @@ class_name RoundRobinManager extends PlayManager
|
|||
|
||||
|
||||
func on_initialization() -> void:
|
||||
print("IN ON_INITIALIZATION")
|
||||
# Set first player as active
|
||||
players[0].shot_setup.phase = ShotSetup.Phase.AIM
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
[gd_scene load_steps=9 format=3 uid="uid://cwnwcd8kushl3"]
|
||||
[gd_scene load_steps=8 format=3 uid="uid://cwnwcd8kushl3"]
|
||||
|
||||
[ext_resource type="Script" path="res://src/world/world.gd" id="1_ybjyx"]
|
||||
[ext_resource type="PackedScene" uid="uid://bm2o3mex10v11" path="res://levels/debug_level/debug_level.tscn" id="2_0xu5a"]
|
||||
[ext_resource type="PackedScene" uid="uid://c4ifdiohng830" path="res://src/ui/shot_hud/shot_hud.tscn" id="2_5b7qb"]
|
||||
[ext_resource type="Script" path="res://src/player/world_player.gd" id="2_e743i"]
|
||||
[ext_resource type="Script" path="res://src/ui/world_ui.gd" id="2_imewa"]
|
||||
[ext_resource type="Resource" uid="uid://crock3revdn73" path="res://src/player/debug_player.tres" id="3_pyw81"]
|
||||
|
@ -31,6 +30,21 @@ grow_vertical = 2
|
|||
mouse_filter = 1
|
||||
script = ExtResource("2_imewa")
|
||||
|
||||
[node name="ShotHUD" parent="UI" instance=ExtResource("2_5b7qb")]
|
||||
[node name="HUDContainer" type="Control" parent="UI"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="PauseContainer" type="Control" parent="UI"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 1
|
||||
|
|
Loading…
Reference in New Issue