Added the pathfinding module

This commit is contained in:
douwe
2025-09-01 20:22:54 +02:00
parent a232425980
commit a58cfe74a1
23 changed files with 183 additions and 63 deletions

View File

@@ -5,17 +5,25 @@ signal cpu_tick
var cobor_vm := CoborVirtualMachine.new()
var running := false
var register_size := 8
var register_size := 16
var modules : Array[Module]
func _ready() -> void:
func _init() -> void:
cobor_vm.set_registers(register_size,[])
func _ready() -> void:
var register_index := 1
for child in get_children():
if child is Module:
var module := child as Module
modules.push_back(module)
register_size += module.set_registers(register_index)
module.set_reserved_registers(register_index)
register_index += module.get_register_reservation_size()
if $ProgrammingUI != null:
$ProgrammingUI.memory_setup()
func show_ui(show:bool)->void:
$ProgrammingUI.visible = show
func run_step() -> void:
if not running:

View File

@@ -1,10 +1,13 @@
[gd_scene load_steps=2 format=3 uid="uid://crtis0eyywl61"]
[gd_scene load_steps=3 format=3 uid="uid://crtis0eyywl61"]
[ext_resource type="Script" uid="uid://b87ksbp5mjn2a" path="res://nodes/robots/coding/cpu.gd" id="1_mh3k1"]
[ext_resource type="PackedScene" uid="uid://c2es6v8lb8tug" path="res://nodes/robots/coding/programming_ui.tscn" id="2_pm1m8"]
[node name="CPU" type="Node"]
script = ExtResource("1_mh3k1")
[node name="CPUClock" type="Timer" parent="."]
[node name="ProgrammingUI" parent="." instance=ExtResource("2_pm1m8")]
[connection signal="timeout" from="CPUClock" to="." method="_tick"]

View File

@@ -15,6 +15,6 @@ allow_lesser = true
alignment = 1
editable = false
[node name="name" type="Label" parent="."]
[node name="type" type="Label" parent="."]
layout_mode = 2
text = "[X] Click"

View File

@@ -4,20 +4,26 @@ extends PanelContainer
@onready var memory := $%Memory as VBoxContainer
@onready var memory_entry := load("uid://dqwi5rekytyds") as PackedScene
@export var cpu : CPU
@onready var cpu := get_parent() as CPU
func _ready() -> void:
func memory_setup() -> void:
var register_types : Dictionary[int, String]
for module in cpu.modules:
register_types.assign(module.get_register_types())
for i in range(cpu.register_size):
var entry := memory_entry.instantiate() as Control
(entry.get_node("address") as Label).text = "[/" + str(i) + "]"
(entry.get_node("address") as Label).text = "[ /" + str(i).pad_zeros(2) + " ]"
(entry.get_node("value") as SpinBox).value = 0
(entry.get_node("type") as Label).text = register_types[i] if register_types.has(i) else "Free"
memory.add_child(entry)
func _process(_delta: float) -> void:
# Set execution indicator
for line in code_editor.get_executing_lines():
code_editor.set_line_as_executing(line, false)
code_editor.set_line_as_executing(cpu.cobor_vm.get_program_counter(), true)
if cpu.cobor_vm.get_program_size() < cpu.cobor_vm.get_program_counter():
code_editor.set_line_as_executing(cpu.cobor_vm.get_program_counter(), true)
# Show register values
var registers := cpu.cobor_vm.get_registers()
for i in range(registers.size()):

View File

@@ -41,7 +41,12 @@ gutters_draw_line_numbers = true
gutters_zero_pad_line_numbers = true
indent_automatic = true
[node name="Memory" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"]
[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
horizontal_scroll_mode = 0
[node name="Memory" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/ScrollContainer"]
unique_name_in_owner = true
layout_mode = 2

View File

@@ -2,11 +2,14 @@ class_name Module extends Node
@onready var cpu := get_parent() as CPU
func set_registers(index:int)->int:
func get_register_reservation_size()->int:
return 0
func early_tick()->void:
func set_reserved_registers(index:int)->void:
pass
func get_register_types()->Dictionary[int, String]:
return {}
func late_tick()->void:
pass

View File

@@ -0,0 +1,75 @@
extends Module
var enabled := true
var pos_x_register_index:int
var pos_y_register_index:int
var pos_z_register_index:int
var index_register_index:int
var prev_index := 0
var target := Vector3i.ZERO
var path : Array[Vector3i]
func _ready() -> void:
if Terrain.instance == null:
print("No terrain to plan path on")
if cpu.get_parent() is not Robot:
print("Module not part of Robot")
func get_register_reservation_size()->int:
return 4
func set_reserved_registers(index:int)->void:
pos_x_register_index = index
pos_y_register_index = index+1
pos_z_register_index = index+2
index_register_index = index+3
func get_register_types()->Dictionary[int, String]:
return {
pos_x_register_index: "[X] Path",
pos_y_register_index: "[Y] Path",
pos_z_register_index: "[Z] Path",
index_register_index: "Idx Path"
}
func early_tick()->void:
var registers := cpu.cobor_vm.get_registers()
prev_index = registers[index_register_index]
func late_tick()->void:
var registers := cpu.cobor_vm.get_registers()
var index := registers[index_register_index]
if index < 0:
target = Vector3i(
registers[pos_x_register_index],
registers[pos_y_register_index],
registers[pos_z_register_index]
)
print("Target set: ", target)
else:
if index == prev_index:
print("index stays same")
return
if prev_index < 0:
var path_finder := VoxelAStarGrid3D.new()
path_finder.set_terrain(Terrain.instance)
path_finder.set_region(AABB(cpu.get_parent().global_position + Vector3.ONE * -100, Vector3.ONE * 200))
path = path_finder.find_path(cpu.get_parent().global_position, target)
if not path.is_empty():
path.append(target)
print("Recalculating path of size:", path.size(), " towards: ", target)
if index >= path.size():
index = path.size()-1
var step:Vector3i
if path.size() == 0:
step = Vector3i.ZERO
else:
step = path[index]
print("next step: ", step)
registers[pos_x_register_index] = step.x
registers[pos_y_register_index] = step.y
registers[pos_z_register_index] = step.z
registers[index_register_index] = index
cpu.cobor_vm.set_registers(cpu.register_size, registers)

View File

@@ -0,0 +1 @@
uid://wsrudejqfo5e

View File

@@ -1,21 +1,31 @@
extends Module
var enabled := true
var pos_x_register_index:int
var pos_y_register_index:int
var pos_z_register_index:int
var pos := Vector3i.ZERO
func _ready() -> void:
if Terrain.instance == null:
print("No terrain to get clicks from")
func set_registers(index:int)->int:
func get_register_reservation_size()->int:
return 3
func set_reserved_registers(index:int)->void:
pos_x_register_index = index
pos_y_register_index = index+1
pos_z_register_index = index+2
return 3
func get_register_types()->Dictionary[int, String]:
return {
pos_x_register_index: "[X] Click",
pos_y_register_index: "[Y] Click",
pos_z_register_index: "[Z] Click"
}
func _unhandled_input(event: InputEvent) -> void:
if not enabled: return
@@ -32,8 +42,11 @@ func set_click_registers()->void:
var origin := current_camera.project_ray_origin(mouse_pos_2d)
var dir := current_camera.project_ray_normal(mouse_pos_2d)
var res := Terrain.instance.get_voxel_tool().raycast(origin, dir, 100)
pos = res.previous_position
func early_tick()->void:
var registers := cpu.cobor_vm.get_registers()
registers[pos_x_register_index] = res.previous_position.x
registers[pos_y_register_index] = res.previous_position.y
registers[pos_z_register_index] = res.previous_position.z
registers[pos_x_register_index] = pos.x
registers[pos_y_register_index] = pos.y
registers[pos_z_register_index] = pos.z
cpu.cobor_vm.set_registers(cpu.register_size, registers)

View File

@@ -1,6 +0,0 @@
[gd_scene load_steps=2 format=3 uid="uid://d22umiybuk0xf"]
[ext_resource type="Script" uid="uid://dii2n2xcatyuh" path="res://nodes/robots/modules/player_click_module.gd" id="1_few5k"]
[node name="PlayerClickModule" type="Node"]
script = ExtResource("1_few5k")

View File

@@ -1,4 +1,4 @@
extends CharacterBody3D
class_name Robot extends CharacterBody3D
@onready var terrain := get_node("../VoxelTerrain") as VoxelTerrain
@@ -9,20 +9,20 @@ func _on_input_event(camera: Node, event: InputEvent, event_position: Vector3, n
if event is InputEventMouseButton and event.is_pressed():
var button_event = event as InputEventMouseButton
if button_event.button_index == MOUSE_BUTTON_LEFT:
$ProgrammingUI.visible = true
$CPU.show_ui(true)
selected = true
elif button_event.button_index == MOUSE_BUTTON_RIGHT:
$ProgrammingUI.visible = false
$CPU.show_ui(false)
selected = false
func _unhandled_input(event: InputEvent) -> void:
if selected:
if event is InputEventMouseButton and event.is_pressed():
var button_event = event as InputEventMouseButton
if button_event.button_index == MOUSE_BUTTON_LEFT:
move_to_mouse_click()
elif button_event.button_index == MOUSE_BUTTON_RIGHT:
pass
#func _unhandled_input(event: InputEvent) -> void:
#if selected:
#if event is InputEventMouseButton and event.is_pressed():
#var button_event = event as InputEventMouseButton
#if button_event.button_index == MOUSE_BUTTON_LEFT:
#move_to_mouse_click()
#elif button_event.button_index == MOUSE_BUTTON_RIGHT:
#pass
func move_to_mouse_click():
var mouse_pos_2d := get_viewport().get_mouse_position()

View File

@@ -1,8 +1,8 @@
[gd_scene load_steps=10 format=3 uid="uid://chem70rrdwjpg"]
[ext_resource type="Script" uid="uid://bnw0h8cuyf3g5" path="res://nodes/robots/robot.gd" id="1_suikl"]
[ext_resource type="PackedScene" uid="uid://c2es6v8lb8tug" path="res://nodes/robots/coding/programming_ui.tscn" id="3_tmdoi"]
[ext_resource type="PackedScene" uid="uid://d22umiybuk0xf" path="res://nodes/robots/modules/player_click_module.tscn" id="4_hm8dm"]
[ext_resource type="Script" uid="uid://dii2n2xcatyuh" path="res://nodes/robots/modules/player_click_module.gd" id="3_tmdoi"]
[ext_resource type="Script" uid="uid://wsrudejqfo5e" path="res://nodes/robots/modules/path_finder_module.gd" id="4_hm8dm"]
[ext_resource type="PackedScene" uid="uid://crtis0eyywl61" path="res://nodes/robots/coding/cpu.tscn" id="5_r4wpy"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_hm8dm"]
@@ -26,23 +26,23 @@ height = 0.8
[node name="Robot" type="CharacterBody3D"]
script = ExtResource("1_suikl")
[node name="CPU" parent="." instance=ExtResource("5_r4wpy")]
[node name="PlayerClickModule" type="Node" parent="CPU"]
script = ExtResource("3_tmdoi")
[node name="PathFinderModule" type="Node" parent="CPU"]
script = ExtResource("4_hm8dm")
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.1, 0)
mesh = SubResource("BoxMesh_hm8dm")
[node name="MeshInstance3D2" type="MeshInstance3D" parent="MeshInstance3D"]
transform = Transform3D(1.91069e-15, -1, -4.37114e-08, -4.37114e-08, -4.37114e-08, 1, -1, 0, -4.37114e-08, 0, 0.5, 0)
transform = Transform3D(1, -1.31134e-07, 4.37114e-08, -4.37114e-08, -4.37114e-08, 1, -1.31134e-07, -1, -4.37114e-08, 0, 0.5, 0)
mesh = SubResource("PrismMesh_hm8dm")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("CapsuleShape3D_llm6e")
[node name="ProgrammingUI" parent="." node_paths=PackedStringArray("cpu") instance=ExtResource("3_tmdoi")]
cpu = NodePath("../CPU")
[node name="CPU" parent="." instance=ExtResource("5_r4wpy")]
[node name="PlayerClickModule" parent="CPU" instance=ExtResource("4_hm8dm")]
[connection signal="input_event" from="." to="." method="_on_input_event"]
[connection signal="cpu_tick" from="CPU" to="ProgrammingUI" method="_on_cpu_tick"]