123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- extends CharacterBody3D
- const EYE_HEIGHT_STAND = 1.6
- const EYE_HEIGHT_CROUCH = 1.4
- const MOVEMENT_SPEED_GROUND = 0.6
- const MOVEMENT_SPEED_AIR = 0.11
- const MOVEMENT_SPEED_CROUCH_MODIFIER = 0.5
- const MOVEMENT_FRICTION_GROUND = 0.9
- const MOVEMENT_FRICTION_AIR = 0.98
- var _mouse_motion = Vector2()
- var _selected_block = 6
- @onready var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
- @onready var head = $Head
- @onready var raycast = $Head/RayCast3D
- @onready var camera_attributes = $Head/Camera3D.attributes
- @onready var selected_block_texture = $SelectedBlock
- @onready var voxel_world = $"../VoxelWorld"
- @onready var crosshair = $"../PauseMenu/Crosshair"
- func _ready():
- Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
- func _process(_delta):
- # Mouse movement.
- _mouse_motion.y = clamp(_mouse_motion.y, -1560, 1560)
- transform.basis = Basis.from_euler(Vector3(0, _mouse_motion.x * -0.001, 0))
- head.transform.basis = Basis.from_euler(Vector3(_mouse_motion.y * -0.001, 0, 0))
- # Block selection.
- var ray_position = raycast.get_collision_point()
- var ray_normal = raycast.get_collision_normal()
- if Input.is_action_just_pressed(&"pick_block"):
- # Block picking.
- var block_global_position = Vector3i((ray_position - ray_normal / 2).floor())
- _selected_block = voxel_world.get_block_global_position(block_global_position)
- else:
- # Block prev/next keys.
- if Input.is_action_just_pressed(&"prev_block"):
- _selected_block -= 1
- if Input.is_action_just_pressed(&"next_block"):
- _selected_block += 1
- _selected_block = wrapi(_selected_block, 1, 30)
- # Set the appropriate texture.
- var uv = Chunk.calculate_block_uvs(_selected_block)
- selected_block_texture.texture.region = Rect2(uv[0] * 512, Vector2.ONE * 64)
- # Block breaking/placing.
- if crosshair.visible and raycast.is_colliding():
- var breaking = Input.is_action_just_pressed(&"break")
- var placing = Input.is_action_just_pressed(&"place")
- # Either both buttons were pressed or neither are, so stop.
- if breaking == placing:
- return
- if breaking:
- var block_global_position = Vector3i((ray_position - ray_normal / 2).floor())
- voxel_world.set_block_global_position(block_global_position, 0)
- elif placing:
- var block_global_position = Vector3i((ray_position + ray_normal / 2).floor())
- voxel_world.set_block_global_position(block_global_position, _selected_block)
- func _physics_process(delta):
- camera_attributes.dof_blur_far_enabled = Settings.fog_enabled
- camera_attributes.dof_blur_far_distance = Settings.fog_distance * 1.5
- camera_attributes.dof_blur_far_transition = Settings.fog_distance * 0.125
- # Crouching.
- var crouching = Input.is_action_pressed(&"crouch")
- head.transform.origin.y = lerpf(head.transform.origin.y, EYE_HEIGHT_CROUCH if crouching else EYE_HEIGHT_STAND, 16 * delta)
- # Keyboard movement.
- var movement_vec2 = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
- var movement = transform.basis * (Vector3(movement_vec2.x, 0, movement_vec2.y))
- if is_on_floor():
- movement *= MOVEMENT_SPEED_GROUND
- else:
- movement *= MOVEMENT_SPEED_AIR
- if crouching:
- movement *= MOVEMENT_SPEED_CROUCH_MODIFIER
- # Gravity.
- velocity.y -= gravity * delta
- velocity += Vector3(movement.x, 0, movement.z)
- # Apply horizontal friction.
- velocity.x *= MOVEMENT_FRICTION_GROUND if is_on_floor() else MOVEMENT_FRICTION_AIR
- velocity.z *= MOVEMENT_FRICTION_GROUND if is_on_floor() else MOVEMENT_FRICTION_AIR
- move_and_slide()
- # Jumping, applied next frame.
- if is_on_floor() and Input.is_action_pressed(&"jump"):
- velocity.y = 7.5
- func _input(event):
- if event is InputEventMouseMotion:
- if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
- _mouse_motion += event.relative
- func chunk_pos():
- return Vector3i((transform.origin / Chunk.CHUNK_SIZE).floor())
|