Compare commits

...

3 Commits

10 changed files with 49 additions and 70 deletions

View File

@ -14,6 +14,9 @@ enum Type {
@export var type: Club.Type @export var type: Club.Type
@export var _model: PackedScene @export var _model: PackedScene
@export_range(-360, 360, 0.001, "radians") var angle := 0.0
@export var power := 1.0
## Global typesafe accessor for club catalog ## Global typesafe accessor for club catalog
static var catalog: ClubCatalogType: static var catalog: ClubCatalogType:
get: get:

View File

@ -8,3 +8,5 @@ script = ExtResource("1_7mcyu")
name = "DEBUG Driver" name = "DEBUG Driver"
type = 1 type = 1
_model = ExtResource("1_ug675") _model = ExtResource("1_ug675")
angle = 0.785398
power = 1.0

View File

@ -8,3 +8,5 @@ script = ExtResource("1_6ksva")
name = "DEBUG Iron" name = "DEBUG Iron"
type = 2 type = 2
_model = ExtResource("1_5wgil") _model = ExtResource("1_5wgil")
angle = 0.785398
power = 0.6

View File

@ -8,3 +8,5 @@ script = ExtResource("1_qlirk")
name = "DEBUG Putter" name = "DEBUG Putter"
type = 4 type = 4
_model = ExtResource("1_ghpah") _model = ExtResource("1_ghpah")
angle = 0.0
power = 0.8

View File

@ -8,3 +8,5 @@ script = ExtResource("1_gy3nk")
name = "DEBUG Wedge" name = "DEBUG Wedge"
type = 3 type = 3
_model = ExtResource("1_voves") _model = ExtResource("1_voves")
angle = 1.39626
power = 0.8

View File

@ -36,7 +36,10 @@ const BIG_POWER_THRESHOLD := 0.7
const WATER_DAMAGE := 10.0 const WATER_DAMAGE := 10.0
## Angle of influence that shot curve has, in radians ## Angle of influence that shot curve has, in radians
const CURVE_INFLUENCE := PI / 8 const CURVE_INFLUENCE := PI / 16
## Impulse offset multiplier due to curve, in meters
const CURVE_FACTOR := 0.002
## Maximum absolute curve for the "nice shot" animation to play ## Maximum absolute curve for the "nice shot" animation to play
const NICE_THRESHOLD := 0.2 const NICE_THRESHOLD := 0.2
@ -48,7 +51,7 @@ const EXPLOSIVE_FORCE_FACTOR := 0.12
@export var driving_range := false @export var driving_range := false
## Initially-selected club ## Initially-selected club
@export var initial_club: Club.Type = Club.Type.DRIVER @export var initial_club_type: Club.Type = Club.Type.DRIVER
## Initially-selected ball type ## Initially-selected ball type
@export var initial_ball: GameBall.Type = GameBall.Type.BASIC @export var initial_ball: GameBall.Type = GameBall.Type.BASIC
@ -92,11 +95,15 @@ var phase: Phase = Phase.FINISHED:
var hud: ShotHUD var hud: ShotHUD
var club: Club.Type: var club_type: Club.Type:
set(value): set(value):
if value != club: if value != club_type:
_on_club_change(value) _on_club_change(value)
club = value club_type = value
var club: Club:
get:
return player.get_club(club_type) if player else null
var ball_type: GameBall.Type: var ball_type: GameBall.Type:
set(value): set(value):
@ -105,8 +112,6 @@ var ball_type: GameBall.Type:
ball_point.spawn_ball(value) ball_point.spawn_ball(value)
ball_type = value ball_type = value
var shot_ref: Node3D
var shot_power: float: var shot_power: float:
set(value): set(value):
hud.power_bar.value = value hud.power_bar.value = value
@ -149,13 +154,9 @@ var _tracking_camera: OrbitalCamera
@onready var ball_point: BallPoint = %BallPoint @onready var ball_point: BallPoint = %BallPoint
@onready var drive_ref: RayCast3D = %DriveRef
@onready var drive_arrow: Node3D = %DriveArrow @onready var drive_arrow: Node3D = %DriveArrow
@onready var wedge_ref: RayCast3D = %WedgeRef
@onready var wedge_arrow: Node3D = %WedgeArrow @onready var wedge_arrow: Node3D = %WedgeArrow
@onready var iron_ref: RayCast3D = %IronRef
@onready var iron_arrow: Node3D = %IronArrow @onready var iron_arrow: Node3D = %IronArrow
@onready var putt_ref: RayCast3D = %PuttRef
@onready var putt_arrow: Node3D = %PuttArrow @onready var putt_arrow: Node3D = %PuttArrow
@onready var downswing_timer: Timer = %DownswingTimer @onready var downswing_timer: Timer = %DownswingTimer
@ -180,7 +181,7 @@ func _ready() -> void:
hud = ShotHUD.create(player) hud = ShotHUD.create(player)
world.ui.add_player_hud(hud) world.ui.add_player_hud(hud)
ball_type = initial_ball ball_type = initial_ball
club = initial_club club_type = initial_club_type
character.set_color(player.color) character.set_color(player.color)
# Set up player 3D label # Set up player 3D label
@ -240,21 +241,22 @@ func finish_downswing() -> void:
func get_shot_impulse(meter_pct: float) -> Vector3: func get_shot_impulse(meter_pct: float) -> Vector3:
return -shot_ref.global_basis.z * base_power * meter_pct # Basic direction of the shot
var shot_vec := -direction.global_basis.rotated(direction.global_basis.x, club.angle).z
# Curve rotates shot direction around the Y-axis
var curved_shot := shot_vec.rotated(Vector3.UP, shot_curve * CURVE_INFLUENCE * shot_power)
# Various factors attenuate shot power
return curved_shot * club.power * base_power * meter_pct
func take_shot() -> void: func take_shot() -> void:
# Impact screenshake & hitlag # Impact screenshake
if game: if game:
if shot_power > BIG_POWER_THRESHOLD: if shot_power > BIG_POWER_THRESHOLD:
#game.viewport.hit_lag_big()
var shake_intensity: float = ( var shake_intensity: float = (
10.0 * (shot_power - BIG_POWER_THRESHOLD) / (1.0 - BIG_POWER_THRESHOLD) 10.0 * (shot_power - BIG_POWER_THRESHOLD) / (1.0 - BIG_POWER_THRESHOLD)
) )
game.viewport.screen_shake(shake_intensity, 1.0) game.viewport.screen_shake(shake_intensity, 1.0)
else:
pass
#game.viewport.hit_lag_small()
print_debug("WHACK!\nPower: ", shot_power, "\nCurve: ", shot_curve) print_debug("WHACK!\nPower: ", shot_power, "\nCurve: ", shot_curve)
@ -263,21 +265,19 @@ func take_shot() -> void:
print_debug("Shot impulse: ", impulse, "; ", impulse.length(), " N*s") print_debug("Shot impulse: ", impulse, "; ", impulse.length(), " N*s")
# Curve the curve # Curve the curve
var curve := shot_ref.global_basis.x.normalized() * shot_curve var curve := direction.global_basis.x.normalized() * shot_curve * absf(shot_curve)
# Position where the ball is hit (imparts spin) # Position where the ball is hit (imparts spin)
var offset := curve * 0.001 var offset := -curve * CURVE_FACTOR
print_debug("Shot offset: ", offset, "; ", offset.length(), " m") print_debug("Shot offset: ", offset, "; ", offset.length(), " m")
# Rotate impulse
impulse = impulse.rotated(Vector3.UP, -shot_curve * CURVE_INFLUENCE * shot_power)
if game_ball: if game_ball:
game_ball.iron_ball = club == Club.Type.IRON game_ball.iron_ball = club_type == Club.Type.IRON
game_ball.freeze = false game_ball.freeze = false
game_ball.apply_impulse(impulse, offset) game_ball.apply_impulse(impulse, offset)
# Play SFX # Play SFX
shot_sfx.play_shot_sfx(club, is_shot_good(), shot_power) shot_sfx.play_shot_sfx(club_type, is_shot_good(), shot_power)
# Use a ball if a limited type is selected # Use a ball if a limited type is selected
if player.get_balls(ball_type) > 0: if player.get_balls(ball_type) > 0:
@ -289,9 +289,9 @@ func _show_shot_projection() -> void:
if not game_ball: if not game_ball:
return return
shot_projection.putt_projection = club == Club.Type.PUTTER shot_projection.putt_projection = club_type == Club.Type.PUTTER
shot_projection.initial_speed = 1 shot_projection.initial_speed = 1
shot_projection.basis = shot_ref.basis.orthonormalized() shot_projection.basis = Basis.from_euler(Vector3(club.angle, 0, 0))
var shot_speed := get_shot_impulse(1.0).length() / game_ball.mass var shot_speed := get_shot_impulse(1.0).length() / game_ball.mass
var tween := get_tree().create_tween() var tween := get_tree().create_tween()
tween.tween_property(shot_projection, "initial_speed", shot_speed, CAMERA_SNAP_TIME).set_trans( tween.tween_property(shot_projection, "initial_speed", shot_speed, CAMERA_SNAP_TIME).set_trans(
@ -401,20 +401,16 @@ func _on_club_change(new_club_type: Club.Type) -> void:
character.hold_right(new_club.get_model()) character.hold_right(new_club.get_model())
match new_club_type: match new_club_type:
Club.Type.DRIVER: Club.Type.DRIVER:
shot_ref = drive_ref
drive_arrow.show() drive_arrow.show()
Club.Type.PUTTER: Club.Type.PUTTER:
shot_ref = putt_ref
putt_arrow.show() putt_arrow.show()
Club.Type.WEDGE: Club.Type.WEDGE:
shot_ref = wedge_ref
wedge_arrow.show() wedge_arrow.show()
Club.Type.IRON: Club.Type.IRON:
shot_ref = iron_ref
iron_arrow.show() iron_arrow.show()
Club.Type.SPECIAL: Club.Type.SPECIAL:
# TODO figure this out # TODO figure this out
shot_ref = drive_ref pass
_: _:
print_debug("Not sure how to equip club type: ", new_club) print_debug("Not sure how to equip club type: ", new_club)
@ -522,15 +518,15 @@ func _process(delta: float) -> void:
# Club select # Club select
if Input.is_action_just_pressed("select_driver"): if Input.is_action_just_pressed("select_driver"):
club = Club.Type.DRIVER club_type = Club.Type.DRIVER
if Input.is_action_just_pressed("select_iron"): if Input.is_action_just_pressed("select_iron"):
club = Club.Type.IRON club_type = Club.Type.IRON
if Input.is_action_just_pressed("select_wedge"): if Input.is_action_just_pressed("select_wedge"):
club = Club.Type.WEDGE club_type = Club.Type.WEDGE
if Input.is_action_just_pressed("select_special"): if Input.is_action_just_pressed("select_special"):
club = Club.Type.SPECIAL club_type = Club.Type.SPECIAL
if Input.is_action_just_pressed("select_putter"): if Input.is_action_just_pressed("select_putter"):
club = Club.Type.PUTTER club_type = Club.Type.PUTTER
# Ball select # Ball select
if Input.is_action_just_pressed("ball_next"): if Input.is_action_just_pressed("ball_next"):

View File

@ -348,36 +348,8 @@ transform = Transform3D(-0.311543, -0.0687373, 0.947743, 0, 0.99738, 0.0723374,
[node name="Direction" type="Node3D" parent="."] [node name="Direction" type="Node3D" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
[node name="DriveRef" type="RayCast3D" parent="Direction"] [node name="ShotRef" type="RayCast3D" parent="Direction"]
unique_name_in_owner = true transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.08, 0)
transform = Transform3D(1, 0, 0, 0, 0.707107, -0.707107, 0, 0.707107, 0.707107, 0, 0.08, 0)
enabled = false
target_position = Vector3(0, 0, -1)
collision_mask = 0
collide_with_bodies = false
debug_shape_thickness = 4
[node name="WedgeRef" type="RayCast3D" parent="Direction"]
unique_name_in_owner = true
transform = Transform3D(0.7, 0, 0, 0, 0.181173, -0.676148, 0, 0.676148, 0.181173, 0, 0.08, 0)
enabled = false
target_position = Vector3(0, 0, -1)
collision_mask = 0
collide_with_bodies = false
debug_shape_thickness = 4
[node name="IronRef" type="RayCast3D" parent="Direction"]
unique_name_in_owner = true
transform = Transform3D(0.7, 0, 0, 0, 0.449952, -0.536231, 0, 0.536231, 0.449952, 0, 0.08, 0)
enabled = false
target_position = Vector3(0, 0, -1)
collision_mask = 0
collide_with_bodies = false
debug_shape_thickness = 4
[node name="PuttRef" type="RayCast3D" parent="Direction"]
unique_name_in_owner = true
transform = Transform3D(0.8, 0, 0, 0, 0.8, 0, 0, 0, 0.8, 0, 0.08, 0)
enabled = false enabled = false
target_position = Vector3(0, 0, -1) target_position = Vector3(0, 0, -1)
collision_mask = 0 collision_mask = 0

View File

@ -13,9 +13,9 @@ func _attenuate_volume(power: float) -> float:
return lerpf(BASE_VOLUME, MAX_VOLUME, power) return lerpf(BASE_VOLUME, MAX_VOLUME, power)
func play_shot_sfx(club: Club.Type, good: bool, power: float) -> void: func play_shot_sfx(club_type: Club.Type, good: bool, power: float) -> void:
var player: AudioStreamPlayer3D var player: AudioStreamPlayer3D
match club: match club_type:
Club.Type.PUTTER: Club.Type.PUTTER:
player = putt_sfx_player player = putt_sfx_player
_: _:

View File

@ -35,7 +35,7 @@ func set_state_for_player(player: WorldPlayer) -> void:
special_label.set_enabled(player.special != null) special_label.set_enabled(player.special != null)
putter_label.set_enabled(player.putter != null) putter_label.set_enabled(player.putter != null)
if player.shot_setup: if player.shot_setup:
value = player.shot_setup.club value = player.shot_setup.club_type
func _get_club_label(club: Club.Type) -> Label: func _get_club_label(club: Club.Type) -> Label:

View File

@ -625,7 +625,7 @@ libraries = {
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="WoahNiceFeedback"] [node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="WoahNiceFeedback"]
stream = ExtResource("2_5f3rs") stream = ExtResource("2_5f3rs")
volume_db = -3.0 volume_db = -16.0
bus = &"SFX" bus = &"SFX"
[node name="WastedFeedback" type="RichTextLabel" parent="."] [node name="WastedFeedback" type="RichTextLabel" parent="."]