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)