Boat/boat/boat.gd
2025-03-22 00:03:08 +01:00

126 lines
4.2 KiB
GDScript

extends RigidBody3D
@export_group("Buyancy")
@export var float_force := 40
@export var water_drag:= 0.05
@export var water_angular_drag := 0.05
@export var WaterNode:MeshInstance3D
@export var ripple_texture: Texture2D
@export var upforce_max := 500.0
@export_group("Inputs")
@export var acceleration := 10 # Forward force
@export var turn_speed := 2.0 # Rotation speed
@export var max_speed := 60.0 # Limit speed
## Slow down naturally
@export var water_resistance := 0.98
@onready var gravity:float = ProjectSettings.get_setting("physics/3d/default_gravity")
###### Buyancy ########
var cells_scale: Vector2 = Vector2(1.0, 1.0) # Same as `CellsScale`
var max_ripple_height: float = 1.0 # Same as `MaxRippleHeight`
var Wantedheight: float = 1.0 # Same as `MaxRippleHeight`
var ripple: Vector2 # Same as `MaxRippleHeight`
var noise: FastNoiseLite
var InputForce:Vector3
var water_height :=0.0
var inWater := false
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
var material
if WaterNode != null:
material = WaterNode.mesh.surface_get_material(0)
noise = load("res://mat/wavenoise.tres").noise
if material != null:
cells_scale = material.get_shader_parameter("CellsScale")
ripple = material.get_shader_parameter("RippleTimeScale")
max_ripple_height = material.get_shader_parameter("MaxRippleHeight")
ripple_texture = load("res://mat/wavenoise.tres")
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
# Get input directions
var forward_input = Input.get_action_strength("move_forward") - Input.get_action_strength("move_backward")
var turn_input = Input.get_action_strength("turn_right") - Input.get_action_strength("turn_left")
# Apply forward force in the boat's local forward direction
var forward_vector = global_transform.basis.x # Local forward direction
var direction = forward_vector * forward_input * acceleration
InputForce = direction
print (InputForce)
apply_central_force(InputForce)
func _physics_process(_delta: float) -> void:
water_height = get_water_height(global_position)
var currentDepth = water_height - global_position.y
if currentDepth > 0:
inWater = true
var force_to_apply:Vector3 = Vector3.UP * clamp(float_force * gravity * currentDepth,0.0,upforce_max)
apply_central_force(force_to_apply)
var water_tilt = get_water_normal()
# Get current rotation
var current_rotation = $untitled.rotation
# Smoothly interpolate rotation to match water tilt
current_rotation.x = lerp_angle(current_rotation.x, water_tilt.x, 0.25) # Smooth pitch
current_rotation.z = lerp_angle(current_rotation.z, water_tilt.z, 0.25) # Smooth roll
$untitled.rotation = current_rotation # Apply the new rotation
else:
inWater = false
func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
# Change comportement based on if in water or not
if inWater:
state.linear_velocity *= 1 - water_drag
state.angular_velocity *= 1 - water_angular_drag
func get_water_height(_position:Vector3) -> float:
var wave_speed = 15.0
# Step 1: Compute noise-based wave height
var uv = Vector2(_position.x, _position.z) * cells_scale # Matches shader scaling
# Step 2: Apply time-based animation for moving waves
var time_offset = Time.get_ticks_msec() * 0.001 * wave_speed
var noise_value = noise.get_noise_2d(uv.x + time_offset, uv.y + time_offset) # Noise-based wave
# Step 3: Scale and return final water height
return 0.15 + (noise_value * max_ripple_height)
func get_water_normal() -> Vector3:
var offset = 1.0 # Distance for sampling points (adjust as needed)
# Sample water height at three nearby points
var p1 = global_position + Vector3(offset, 0, 0) # Right side
var p2 = global_position + Vector3(0, 0, offset) # Forward side
var h1 = get_water_height(p1) # Height at right side
var h2 = get_water_height(p2) # Height at forward side
var h_center = get_water_height(global_position) # Center height
# Calculate tilt angles
var pitch = atan2(h2 - h_center, offset) # Forward/backward tilt (X-axis)
var roll = atan2(h1 - h_center, offset) # Left/right tilt (Z-axis)
return Vector3(pitch, 0, roll) # Euler angles (X: pitch, Y: unused, Z: roll)