126 lines
4.2 KiB
GDScript
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)
|