Add block placement preview to Voxel demo, improve debug display (#1190)

- Allow placing/breaking blocks when further away (up to 5 blocks instead of 4).
- Add a background to the debug display to improve readability on bright backgrounds.
- Simplify coordinate display using the `%v` placeholder available in 4.3 onwards.
This commit is contained in:
Hugo Locurcio
2025-04-15 16:53:12 +02:00
committed by GitHub
parent c05d05009b
commit a88ca219b8
4 changed files with 44 additions and 28 deletions

View File

@@ -8,31 +8,11 @@ func _process(_delta: float) -> void:
if Input.is_action_just_pressed(&"debug"):
visible = not visible
text = "Position: " + _vector_to_string_appropriate_digits(player.transform.origin)
text += "\nEffective render distance: " + str(voxel_world.effective_render_distance)
text += "\nLooking: " + _cardinal_string_from_radians(player.transform.basis.get_euler().y)
text += "\nMemory: " + "%3.0f" % (OS.get_static_memory_usage() / 1048576.0) + " MiB"
text += "\nFPS: " + String.num_uint64(Engine.get_frames_per_second())
# Avoids the problem of showing more digits than needed or available.
func _vector_to_string_appropriate_digits(vector: Vector3) -> String:
var factors: Array[int] = [1000, 1000, 1000]
for i in 3:
if abs(vector[i]) > 4096:
@warning_ignore("integer_division")
factors[i] = factors[i] / 10
if abs(vector[i]) > 65536:
@warning_ignore("integer_division")
factors[i] = factors[i] / 10
if abs(vector[i]) > 524288:
@warning_ignore("integer_division")
factors[i] = factors[i] / 10
return "(" + \
str(round(vector.x * factors[0]) / factors[0]) + ", " + \
str(round(vector.y * factors[1]) / factors[1]) + ", " + \
str(round(vector.z * factors[2]) / factors[2]) + ")"
text = "Position: %.1v" % player.transform.origin \
+ "\nEffective render distance: " + str(voxel_world.effective_render_distance) \
+ "\nLooking: " + _cardinal_string_from_radians(player.transform.basis.get_euler().y) \
+ "\nMemory: " + "%3.0f" % (OS.get_static_memory_usage() / 1048576.0) + " MiB" \
+ "\nFPS: %d" % Engine.get_frames_per_second()
# Expects a rotation where 0 is North, on the range -PI to PI.

View File

@@ -20,6 +20,7 @@ var _selected_block := 6
@onready var selected_block_texture: TextureRect = $SelectedBlock
@onready var voxel_world: Node = $"../VoxelWorld"
@onready var crosshair: CenterContainer = $"../PauseMenu/Crosshair"
@onready var aim_preview: MeshInstance3D = $AimPreview
func _ready() -> void:
@@ -54,6 +55,9 @@ func _process(_delta: float) -> void:
# Block breaking/placing.
if crosshair.visible and raycast.is_colliding():
aim_preview.visible = true
var ray_current_block_position := Vector3i((ray_position - ray_normal / 2).floor())
aim_preview.global_position = Vector3(ray_current_block_position) + Vector3(0.5, 0.5, 0.5)
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.
@@ -61,11 +65,14 @@ func _process(_delta: float) -> void:
return
if breaking:
var block_global_position := Vector3i((ray_position - ray_normal / 2).floor())
var block_global_position := ray_current_block_position
voxel_world.set_block_global_position(block_global_position, 0)
elif placing:
# Calculate the position of the block to be placed.
var block_global_position := Vector3i((ray_position + ray_normal / 2).floor())
voxel_world.set_block_global_position(block_global_position, _selected_block)
else:
aim_preview.visible = false
func _physics_process(delta: float) -> void:

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=6 format=3 uid="uid://1s4asqpay67m"]
[gd_scene load_steps=10 format=3 uid="uid://1s4asqpay67m"]
[ext_resource type="Script" uid="uid://rm45k07vw817" path="res://player/player.gd" id="1"]
[ext_resource type="Texture2D" uid="uid://d3f34krqfgdjd" path="res://world/textures/texture_sheet.png" id="2"]
@@ -13,6 +13,27 @@ radius = 0.375
atlas = ExtResource("2")
region = Rect2(0, 0, 64, 64)
[sub_resource type="Gradient" id="Gradient_rkbax"]
offsets = PackedFloat32Array(0.952381, 1)
colors = PackedColorArray(0, 0, 0, 0.0941176, 0, 0, 0, 1)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_g1dw6"]
gradient = SubResource("Gradient_rkbax")
width = 256
height = 256
fill = 2
fill_from = Vector2(0.5, 0.5)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_yw30f"]
transparency = 1
shading_mode = 0
albedo_texture = SubResource("GradientTexture2D_g1dw6")
uv1_scale = Vector3(3, 2, 1)
[sub_resource type="BoxMesh" id="BoxMesh_qjkh3"]
material = SubResource("StandardMaterial3D_yw30f")
size = Vector3(1.001, 1.001, 1.001)
[node name="Player" type="CharacterBody3D"]
collision_layer = 0
script = ExtResource("1")
@@ -31,7 +52,7 @@ near = 0.02
far = 1000.0
[node name="RayCast3D" type="RayCast3D" parent="Head"]
target_position = Vector3(0, 0, -4)
target_position = Vector3(0, 0, -5)
[node name="SelectedBlock" type="TextureRect" parent="."]
texture_filter = 1
@@ -48,3 +69,8 @@ grow_horizontal = 0
grow_vertical = 0
texture = SubResource("2")
expand_mode = 1
[node name="AimPreview" type="MeshInstance3D" parent="."]
top_level = true
visible = false
mesh = SubResource("BoxMesh_qjkh3")

View File

@@ -37,6 +37,9 @@ offset_bottom = -20.0
grow_horizontal = 2
grow_vertical = 2
theme = ExtResource("7")
theme_override_colors/font_shadow_color = Color(0, 0, 0, 0.501961)
theme_override_constants/shadow_offset_x = 2
theme_override_constants/shadow_offset_y = 2
theme_override_font_sizes/font_size = 48
script = ExtResource("6")