Compare commits
9 Commits
develop
...
swarm_engi
| Author | SHA1 | Date | |
|---|---|---|---|
| 5301cfa598 | |||
| 19cc3a1888 | |||
| 3965b3603a | |||
| 4b53993237 | |||
| dbd4f668aa | |||
| 641b069cb0 | |||
| 6fecc5632c | |||
| 44280e9202 | |||
| b9c94eeed6 |
BIN
assets/spider/result.bin
Normal file
BIN
assets/spider/result.bin
Normal file
Binary file not shown.
33434
assets/spider/result.gltf
Normal file
33434
assets/spider/result.gltf
Normal file
File diff suppressed because it is too large
Load Diff
53
assets/spider/result.gltf.import
Normal file
53
assets/spider/result.gltf.import
Normal file
@ -0,0 +1,53 @@
|
||||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://bcsjr6kydgdqy"
|
||||
path="res://.godot/imported/result.gltf-fa6e7d401ecc486ebc1efbad267cda09.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/spider/result.gltf"
|
||||
dest_files=["res://.godot/imported/result.gltf-fa6e7d401ecc486ebc1efbad267cda09.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
_subresources={
|
||||
"meshes": {
|
||||
"result_Cube": {
|
||||
"generate/lightmap_uv": 0,
|
||||
"generate/lods": 0,
|
||||
"generate/shadow_meshes": 1,
|
||||
"lods/normal_merge_angle": 60.0,
|
||||
"lods/normal_split_angle": 25.0,
|
||||
"save_to_file/enabled": true,
|
||||
"save_to_file/path": "res://assets/spider/spider_mesh.res"
|
||||
}
|
||||
},
|
||||
"nodes": {
|
||||
"PATH:RootNode/SpiderArmature/Skeleton3D": {
|
||||
"rest_pose/external_animation_library": null
|
||||
}
|
||||
}
|
||||
}
|
||||
gltf/naming_version=1
|
||||
gltf/embedded_image_handling=1
|
||||
BIN
assets/spider/spider_mesh.res
Normal file
BIN
assets/spider/spider_mesh.res
Normal file
Binary file not shown.
@ -17,6 +17,9 @@ var not_dead := true
|
||||
@export_multiline var death_message : Array[String]
|
||||
#@onready var color_rect: ColorRect = $CanvasLayer/ColorRect
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
DebugDraw3D.draw_sphere(position, .5)
|
||||
|
||||
func handle_dying():
|
||||
not_dead = false
|
||||
#weapon_slot_2.queue_free()
|
||||
|
||||
7
scripts/helper/color_helper.gd
Normal file
7
scripts/helper/color_helper.gd
Normal file
@ -0,0 +1,7 @@
|
||||
extends Resource
|
||||
class_name ColorHelper
|
||||
|
||||
static func get_direction_color(direction: Vector3) -> Color:
|
||||
var angle = atan2(direction.z, direction.x)
|
||||
var hue = (angle / (2.0 * PI)) + 0.5
|
||||
return Color.from_hsv(hue, 1.0, 1.0)
|
||||
@ -1 +0,0 @@
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
extends Resource
|
||||
class_name FlowFieldCell
|
||||
|
||||
var position:Vector3 = Vector3(0.0, 0.0, 0.0)
|
||||
var flow_direction:Vector3 = Vector3(randf(), 0.0, randf())
|
||||
|
||||
func debug_process() -> void:
|
||||
if flow_direction.length() > 0.0:
|
||||
DebugDraw3D.draw_arrow(position, position + flow_direction, Color(1,1,1,1), 0.1)
|
||||
else:
|
||||
DebugDraw3D.draw_sphere(position, .05)
|
||||
34
swarm_engine/flow_field_navigation/flow_field_compute.glsl
Normal file
34
swarm_engine/flow_field_navigation/flow_field_compute.glsl
Normal file
@ -0,0 +1,34 @@
|
||||
#[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
// Speicher für FlowField-Daten
|
||||
layout(std430, set = 0, binding = 0) buffer FlowFieldBuffer {
|
||||
vec2 flow_field[];
|
||||
};
|
||||
|
||||
// Zielposition und Grid-Daten
|
||||
layout(push_constant) uniform Params {
|
||||
vec2 target_pos;
|
||||
float cell_size;
|
||||
int grid_size_x;
|
||||
int grid_size_z;
|
||||
};
|
||||
|
||||
void main(){
|
||||
uint x = gl_GlobalInvocationID.x;
|
||||
uint z = gl_GlobalInvocationID.y;
|
||||
|
||||
if (x >= grid_size_x || z >= grid_size_z) return;
|
||||
|
||||
int index = int(z * grid_size_x + x);
|
||||
|
||||
// Zellzentrum berechnen
|
||||
vec2 cell_center = vec2(x, z) * cell_size + vec2(cell_size * 0.5);
|
||||
|
||||
// Richtung zum Ziel berechnen
|
||||
vec2 direction = normalize(target_pos - cell_center);
|
||||
|
||||
// Ergebnis in FlowField speichern
|
||||
flow_field[index] = direction;
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
[remap]
|
||||
|
||||
importer="glsl"
|
||||
type="RDShaderFile"
|
||||
uid="uid://bf4mkjohkqpox"
|
||||
path="res://.godot/imported/flow_field_compute.glsl-51e5023d4249c63dbf26c3aa62523e13.res"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://swarm_engine/flow_field_navigation/flow_field_compute.glsl"
|
||||
dest_files=["res://.godot/imported/flow_field_compute.glsl-51e5023d4249c63dbf26c3aa62523e13.res"]
|
||||
|
||||
[params]
|
||||
|
||||
@ -1,71 +1,234 @@
|
||||
extends Node3D
|
||||
class_name FlowFieldNav
|
||||
|
||||
@export_group("Debug")
|
||||
@export var debugVisu: bool = true
|
||||
@export var line_color: Color = Color(1, 1, 1, 1)
|
||||
# https://docs.godotengine.org/cs/4.x/tutorials/shaders/compute_shaders.html#create-a-local-renderingdevice
|
||||
# Das Updaten der flow richtung kann auf der grafikkarte gemacht werden mit compute shader
|
||||
|
||||
@export_group("Grid")
|
||||
@export var grid_size: int = 10
|
||||
@export_category("Debug Visualization")
|
||||
@export_group("Grid Center")
|
||||
@export var show_grid_center: bool = false
|
||||
@export_color_no_alpha var grid_center_color: Color = Color(1, 1, 1, 1)
|
||||
@export var grid_center_size: float = 0.5
|
||||
@export_group("Border")
|
||||
@export var show_border: bool = false
|
||||
@export_color_no_alpha var border_color: Color = Color(1, 1, 1, 1)
|
||||
@export_group("Cells")
|
||||
@export_subgroup("X Lines")
|
||||
@export var show_x_lines: bool = false
|
||||
@export_color_no_alpha var x_lines_color: Color = Color(1, 1, 1)
|
||||
@export_subgroup("Z Lines")
|
||||
@export var show_z_lines: bool = false
|
||||
@export_color_no_alpha var z_lines_color: Color = Color(1, 1, 1)
|
||||
@export_group("Arrows")
|
||||
@export var show_arrows: bool = false
|
||||
@export var arrows_size: float = 0.1
|
||||
@export_color_no_alpha var cell_center_color: Color = Color(1, 1, 1)
|
||||
@export var cell_center_size: float = 0.2
|
||||
|
||||
@export_category("Grid")
|
||||
@export var cell_size: float = 1.0
|
||||
@export_group("Grid Size", "grid_size_")
|
||||
@export var grid_size_x: int = 2
|
||||
@export var grid_size_z: int = 5
|
||||
|
||||
var _cells: Dictionary
|
||||
var grid_offset: Vector3
|
||||
|
||||
@export var target: Node3D = null
|
||||
var flow_direction_list: Array[Vector2] = []
|
||||
|
||||
|
||||
var half_size_x: float
|
||||
var half_size_z: float
|
||||
|
||||
var rd: RenderingDevice
|
||||
var shader: RID
|
||||
var pipeline: RID
|
||||
var flow_field_buffer: RID
|
||||
var flow_field_data: PackedVector2Array
|
||||
|
||||
func _ready() -> void:
|
||||
var half_size = (grid_size * cell_size) * 0.5
|
||||
grid_offset = Vector3(-half_size + (cell_size * 0.5), 0, -half_size + (cell_size * 0.5))
|
||||
create_grid()
|
||||
#var rendering_device := RenderingServer.create_local_rendering_device()
|
||||
#var shader_file := load("res://swarm_engine/flow_field_navigation/flow_field_compute.glsl")
|
||||
#var shader_spirv: RDShaderSPIRV = shader_file.get_spirv()
|
||||
#var shader_RID := rendering_device.shader_create_from_spirv(shader_spirv)
|
||||
#
|
||||
#var center_array: PackedVector3Array
|
||||
#for x in range(grid_size_x):
|
||||
#for z in range(grid_size_z):
|
||||
#center_array.append(_get_cell_center_with_coordinates(x,z))
|
||||
#
|
||||
#var center_byte_array = center_array.to_byte_array()
|
||||
#var storage_buffer_RID = rendering_device.storage_buffer_create(center_byte_array.size(), center_byte_array)
|
||||
#
|
||||
#var uniform := RDUniform.new()
|
||||
#uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER
|
||||
#uniform.binding = 0
|
||||
#uniform.add_id(storage_buffer_RID)
|
||||
#var uniform_set_RID := rendering_device.uniform_set_create([uniform], shader_RID, 0)
|
||||
#
|
||||
#var pipeline_RID := rendering_device.compute_pipeline_create(shader_RID)
|
||||
#var compute_list_id := rendering_device.compute_list_begin()
|
||||
#
|
||||
#rendering_device.compute_list_bind_compute_pipeline(compute_list_id, pipeline_RID)
|
||||
#rendering_device.compute_list_bind_uniform_set(compute_list_id, uniform_set_RID, 0)
|
||||
#rendering_device.compute_list_dispatch(compute_list_id, 1, 1, 1)
|
||||
#rendering_device.compute_list_end()
|
||||
#rendering_device.submit()
|
||||
|
||||
func create_grid() -> void:
|
||||
_cells.clear()
|
||||
for x in range(grid_size):
|
||||
for z in range(grid_size):
|
||||
var cell = FlowFieldCell.new()
|
||||
var world_x = x * cell_size + grid_offset.x
|
||||
var world_z = z * cell_size + grid_offset.z
|
||||
cell.position = Vector3(world_x, 0, world_z)
|
||||
_cells[Vector3(x, 0, z)] = cell # Dictionary mit Grid-Koordinaten als Key
|
||||
#rd = RenderingServer.get_rendering_device()
|
||||
#
|
||||
## Compute Shader laden
|
||||
#var shader_file = load("res://swarm_engine/flow_field_navigation/flow_field_compute.glsl")
|
||||
#shader = rd.shader_create_from_spirv(shader_file.get_spirv())
|
||||
#pipeline = rd.compute_pipeline_create(shader)
|
||||
#
|
||||
## Speicher für FlowField erstellen
|
||||
#var buffer_size = grid_size_x * grid_size_z * 8 # Vector2 -> 2 floats = 8 Bytes pro Eintrag
|
||||
#flow_field_buffer = rd.storage_buffer_create(buffer_size)
|
||||
#flow_field_data.resize(grid_size_x * grid_size_z)
|
||||
#
|
||||
|
||||
for x in range(grid_size_x):
|
||||
for z in range(grid_size_z):
|
||||
flow_direction_list.append(Vector2(0.0, 0.0))
|
||||
half_size_x = (grid_size_x * cell_size) * 0.5
|
||||
half_size_z = (grid_size_z * cell_size) * 0.5
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if debugVisu:
|
||||
_debug_draw_grid()
|
||||
for cell in _cells.values():
|
||||
cell.debug_process()
|
||||
|
||||
func _debug_draw_grid() -> void:
|
||||
for x in range(grid_size + 1):
|
||||
var pos_x = x * cell_size + grid_offset.x - (cell_size * 0.5)
|
||||
DebugDraw3D.draw_line(Vector3(pos_x, 0, grid_offset.z - (cell_size * 0.5)), Vector3(pos_x, 0, grid_offset.z + grid_size * cell_size - (cell_size * 0.5)), line_color)
|
||||
#_update_gpu_flow_field()
|
||||
_update_flow_field()
|
||||
_draw_debug()
|
||||
|
||||
for z in range(grid_size + 1):
|
||||
var pos_z = z * cell_size + grid_offset.z - (cell_size * 0.5)
|
||||
DebugDraw3D.draw_line(Vector3(grid_offset.x - (cell_size * 0.5), 0, pos_z), Vector3(grid_offset.x + grid_size * cell_size - (cell_size * 0.5), 0, pos_z), line_color)
|
||||
func _update_gpu_flow_field():
|
||||
if not target:
|
||||
return
|
||||
|
||||
# Push-Constants für Shader setzen
|
||||
var push_constants = PackedByteArray()
|
||||
push_constants.append_array(PackedByteArray([
|
||||
target.position.x,
|
||||
target.position.z,
|
||||
cell_size,
|
||||
float(grid_size_x),
|
||||
float(grid_size_z)
|
||||
]))
|
||||
|
||||
# GPU Command erstellen
|
||||
var compute_list = rd.compute_list_begin()
|
||||
rd.compute_list_bind_compute_pipeline(compute_list, pipeline)
|
||||
rd.compute_list_bind_storage_buffer(compute_list, flow_field_buffer, 0, 0)
|
||||
rd.compute_list_set_push_constant(compute_list, push_constants, 0)
|
||||
rd.compute_list_dispatch(compute_list, grid_size_x, grid_size_z, 1)
|
||||
rd.compute_list_end()
|
||||
|
||||
# GPU Berechnung starten
|
||||
rd.submit()
|
||||
rd.sync()
|
||||
|
||||
# Daten von der GPU zurückholen
|
||||
var buffer_data = rd.buffer_get_data(flow_field_buffer)
|
||||
var output = buffer_data.to_float32_array()
|
||||
|
||||
# 2D-Array für FlowField initialisieren
|
||||
flow_direction_list = []
|
||||
for x in range(grid_size_x):
|
||||
flow_direction_list.append([]) # Erstellt leere Arrays für jede X-Spalte
|
||||
|
||||
# Konvertiere die 1D-GPU-Daten in ein 2D-Array
|
||||
for z in range(grid_size_z):
|
||||
for x in range(grid_size_x):
|
||||
var index = (z * grid_size_x + x) * 2 # 2 Floats pro Vector2
|
||||
var flow_vector = Vector2(output[index], output[index + 1])
|
||||
flow_direction_list[index] = flow_vector
|
||||
|
||||
func _update_flow_field():
|
||||
if target != null:
|
||||
for x in range(grid_size_x):
|
||||
for z in range(grid_size_z):
|
||||
var index = z * grid_size_x + x
|
||||
var flow_direction = (target.position - _get_cell_center_with_coordinates(x,z)).normalized() * (cell_size/2)
|
||||
flow_direction_list[index] = Vector2(flow_direction.x, flow_direction.z)
|
||||
var target_index = _get_index_from_position(target.position)
|
||||
flow_direction_list[target_index] = Vector2(0, 0)
|
||||
|
||||
|
||||
# Gibt die Zelle basierend auf einer Weltposition zurück
|
||||
func get_cell_from_pos(world_pos: Vector3) -> FlowFieldCell:
|
||||
var grid_x = int((world_pos.x - grid_offset.x) / cell_size)
|
||||
var grid_z = int((world_pos.z - grid_offset.z) / cell_size)
|
||||
var cell_pos = Vector3(grid_x, 0, grid_z)
|
||||
func _draw_debug():
|
||||
if show_grid_center:
|
||||
DebugDraw3D.draw_sphere(position, grid_center_size, grid_center_color)
|
||||
if show_border:
|
||||
_draw_border()
|
||||
|
||||
return _cells.get(cell_pos, null)
|
||||
if show_x_lines:
|
||||
_draw_x_lines()
|
||||
|
||||
if show_z_lines:
|
||||
_draw_z_lines()
|
||||
|
||||
# Raycast zur Bestimmung der Zelle unter dem Mauszeiger
|
||||
func _input(event):
|
||||
if event is InputEventMouseButton and event.pressed:
|
||||
var camera = get_viewport().get_camera_3d()
|
||||
var from = camera.project_ray_origin(get_viewport().get_mouse_position())
|
||||
var to = from + camera.project_ray_normal(get_viewport().get_mouse_position()) * 1000
|
||||
if show_arrows:
|
||||
_draw_arrows()
|
||||
|
||||
var space_state = get_world_3d().direct_space_state
|
||||
var query = PhysicsRayQueryParameters3D.create(from, to)
|
||||
var result = space_state.intersect_ray(query)
|
||||
func _draw_border():
|
||||
var top_left = position - Vector3(half_size_x, 0 , half_size_z)
|
||||
var top_right = position + Vector3(half_size_x, 0, -half_size_z)
|
||||
var bottom_left = position - Vector3(half_size_x, 0, -half_size_z)
|
||||
var bottom_right = position + Vector3(half_size_x, 0, half_size_z)
|
||||
|
||||
if result.has("position"):
|
||||
var cell = get_cell_from_pos(result["position"])
|
||||
if cell:
|
||||
print("Zelle an", cell.position, ":", cell.flow_direction)
|
||||
var lines: PackedVector3Array
|
||||
lines.append_array(PackedVector3Array([top_left, top_right]))
|
||||
lines.append_array(PackedVector3Array([top_right, bottom_right]))
|
||||
lines.append_array(PackedVector3Array([bottom_right, bottom_left]))
|
||||
lines.append_array(PackedVector3Array([bottom_left, top_left]))
|
||||
DebugDraw3D.draw_lines(lines, border_color)
|
||||
|
||||
func _draw_x_lines():
|
||||
var lines: PackedVector3Array
|
||||
for x in range(grid_size_x - 1):
|
||||
var start = position - Vector3(half_size_x - ((x + 1) * cell_size), 0, half_size_z)
|
||||
var end = position - Vector3(half_size_x - ((x + 1) * cell_size), 0, -half_size_z)
|
||||
lines.append_array(PackedVector3Array([start, end]))
|
||||
DebugDraw3D.draw_lines(lines, x_lines_color)
|
||||
|
||||
func _draw_z_lines():
|
||||
var lines: PackedVector3Array
|
||||
for z in range(grid_size_z - 1):
|
||||
var start = position - Vector3(half_size_x, 0, half_size_z - ((z + 1) * cell_size))
|
||||
var end = position - Vector3(-half_size_x, 0, half_size_z - ((z + 1) * cell_size))
|
||||
lines.append_array(PackedVector3Array([start, end]))
|
||||
DebugDraw3D.draw_lines(lines, z_lines_color)
|
||||
|
||||
func _draw_arrows():
|
||||
var points: PackedVector3Array
|
||||
for x in range(grid_size_x):
|
||||
for z in range(grid_size_z):
|
||||
var cell_center = _get_cell_center_with_coordinates(x,z)
|
||||
var index = z * grid_size_x + x
|
||||
if flow_direction_list[index].length() > 0.0:
|
||||
var direction = Vector3(flow_direction_list[index].x, 0, flow_direction_list[index].y).normalized()
|
||||
var arrow_end = cell_center + direction * (cell_size * 0.4)
|
||||
DebugDraw3D.draw_arrow(cell_center, arrow_end, ColorHelper.get_direction_color(direction), arrows_size)
|
||||
else:
|
||||
print("Keine Zelle gefunden!")
|
||||
points.append(cell_center)
|
||||
DebugDraw3D.draw_points(points, DebugDraw3D.POINT_TYPE_SQUARE, cell_center_size, cell_center_color)
|
||||
|
||||
func _get_cell_center_with_coordinates(x:int, z:int) -> Vector3:
|
||||
return position + Vector3(
|
||||
(-half_size_x + (x * cell_size) + (cell_size * 0.5)),
|
||||
0,
|
||||
(-half_size_z + (z * cell_size) + (cell_size * 0.5)))
|
||||
|
||||
func _get_coordinates_from_position(pos: Vector3) -> Vector2i:
|
||||
return Vector2i(int((pos.x - position.x + half_size_x) / cell_size),
|
||||
int((pos.z - position.z + half_size_z) / cell_size))
|
||||
|
||||
func _get_index_from_position(pos: Vector3) -> int:
|
||||
var pos_coord = _get_coordinates_from_position(pos)
|
||||
if _is_coordinate_valid(pos_coord):
|
||||
return -1
|
||||
return pos_coord.y * grid_size_x + pos_coord.x
|
||||
|
||||
func _is_coordinate_valid(coord: Vector2i) -> bool:
|
||||
return coord.x < 0 or coord.x >= grid_size_x or coord.y < 0 or coord.y >= grid_size_z
|
||||
|
||||
func get_direction_from_position(position: Vector3) -> Vector3:
|
||||
var index = _get_index_from_position(position)
|
||||
return Vector3(flow_direction_list[index].x, 0, flow_direction_list[index].y)
|
||||
|
||||
@ -1 +0,0 @@
|
||||
extends Node3D
|
||||
@ -1,20 +1,71 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://bwo12me8h21q5"]
|
||||
[gd_scene load_steps=6 format=3 uid="uid://bwo12me8h21q5"]
|
||||
|
||||
[ext_resource type="Script" path="res://swarm_engine/swarm_engine_debug_level.gd" id="1_f0ttr"]
|
||||
[ext_resource type="PackedScene" uid="uid://cn2xvs2g7box5" path="res://swarm_engine/flow_field_navigation/flow_field_navigation.tscn" id="1_xwcpn"]
|
||||
[ext_resource type="PackedScene" uid="uid://cdau7qryen3uq" path="res://swarm_engine/swarm_unit/swarm_unit.tscn" id="3_6kohq"]
|
||||
[ext_resource type="PackedScene" uid="uid://dycbdcrwsm6wu" path="res://experimente/felox/player.tscn" id="6_wayso"]
|
||||
|
||||
[sub_resource type="PlaneMesh" id="PlaneMesh_3dwe5"]
|
||||
size = Vector2(400, 400)
|
||||
|
||||
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_vtddf"]
|
||||
points = PackedVector3Array(-200, 0, -200, -200, 0, 200, 200, 0, -200, 200, 0, 200)
|
||||
|
||||
[node name="World" type="Node3D"]
|
||||
script = ExtResource("1_f0ttr")
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(-0.866023, -0.433016, 0.250001, 0, 0.499998, 0.866027, -0.500003, 0.749999, -0.43301, 0, 0, 0)
|
||||
shadow_enabled = true
|
||||
|
||||
[node name="FlowFieldNavigation" parent="." instance=ExtResource("1_xwcpn")]
|
||||
grid_size = 100
|
||||
cell_size = 2.0
|
||||
[node name="FlowFieldNavigation" parent="." node_paths=PackedStringArray("target") instance=ExtResource("1_xwcpn")]
|
||||
unique_name_in_owner = true
|
||||
show_grid_center = true
|
||||
grid_center_color = Color(0, 0.0833333, 1, 1)
|
||||
show_border = true
|
||||
show_x_lines = true
|
||||
x_lines_color = Color(1, 0.45, 0, 1)
|
||||
show_z_lines = true
|
||||
z_lines_color = Color(1, 0, 0.0166664, 1)
|
||||
show_arrows = true
|
||||
cell_center_color = Color(0.702375, 0.0507974, 0.96251, 1)
|
||||
cell_size = 4.0
|
||||
grid_size_x = 50
|
||||
grid_size_z = 50
|
||||
target = NodePath("../player")
|
||||
|
||||
[node name="CSGSphere3D" type="CSGSphere3D" parent="FlowFieldNavigation"]
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
||||
mesh = SubResource("PlaneMesh_3dwe5")
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.331371, 0.943501, 0, -0.943501, 0.331371, 0, 13.203, 5.65752)
|
||||
[node name="StaticBody3D" type="StaticBody3D" parent="MeshInstance3D"]
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="MeshInstance3D/StaticBody3D"]
|
||||
shape = SubResource("ConvexPolygonShape3D_vtddf")
|
||||
|
||||
[node name="player" parent="." instance=ExtResource("6_wayso")]
|
||||
unique_name_in_owner = true
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 3.50529)
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="player"]
|
||||
unique_name_in_owner = true
|
||||
transform = Transform3D(1, 0, 0, 0, 0.707107, 0.707107, 0, -0.707107, 0.707107, 0, 10, 8)
|
||||
|
||||
[node name="Node3D" type="Node3D" parent="."]
|
||||
|
||||
[node name="SwarmUnit" parent="Node3D" node_paths=PackedStringArray("flow_field_navigation") instance=ExtResource("3_6kohq")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0338392, 0, -41.7085)
|
||||
move_speed = 4
|
||||
flow_field_navigation = NodePath("../../FlowFieldNavigation")
|
||||
|
||||
[node name="SwarmUnit2" parent="Node3D" node_paths=PackedStringArray("flow_field_navigation") instance=ExtResource("3_6kohq")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -17.4426, 0, -41.7085)
|
||||
move_speed = 4
|
||||
flow_field_navigation = NodePath("../../FlowFieldNavigation")
|
||||
|
||||
[node name="SwarmUnit3" parent="Node3D" node_paths=PackedStringArray("flow_field_navigation") instance=ExtResource("3_6kohq")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0338392, 0, -58.7671)
|
||||
move_speed = 4
|
||||
flow_field_navigation = NodePath("../../FlowFieldNavigation")
|
||||
|
||||
[node name="SwarmUnit4" parent="Node3D" node_paths=PackedStringArray("flow_field_navigation") instance=ExtResource("3_6kohq")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -17.4426, 0, -58.7671)
|
||||
move_speed = 4
|
||||
flow_field_navigation = NodePath("../../FlowFieldNavigation")
|
||||
|
||||
36
swarm_engine/swarm_unit/multi_mesh_instance_3d.gd
Normal file
36
swarm_engine/swarm_unit/multi_mesh_instance_3d.gd
Normal file
@ -0,0 +1,36 @@
|
||||
extends MultiMeshInstance3D
|
||||
|
||||
@export var move_speed = 2
|
||||
@export var number: int = 100
|
||||
@export var stretch: int = 2
|
||||
|
||||
|
||||
@onready var flow_field_navigation: FlowFieldNav = %FlowFieldNavigation
|
||||
@onready var player: Player = %player
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
for x in range(number):
|
||||
for z in range(number):
|
||||
var index = z * number + x
|
||||
self.multimesh.set_instance_transform(index, Transform3D(Basis(), Vector3(x * stretch, 0.0, -z * stretch)))
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
for x in range(number):
|
||||
for z in range(number):
|
||||
var index = z * number + x
|
||||
var current_trans = self.multimesh.get_instance_transform(index)
|
||||
|
||||
var cell = flow_field_navigation.get_cell_from_pos(current_trans.origin)
|
||||
if cell != null and cell.flow_direction.length() > 0.0:
|
||||
var movement = cell.flow_direction.normalized() * move_speed * delta
|
||||
current_trans.origin += movement
|
||||
|
||||
var direction_to_player = (player.position - current_trans.origin).normalized()
|
||||
var target_rotation_y = Quaternion(Vector3.UP, atan2(-direction_to_player.x, -direction_to_player.z))
|
||||
var fix_rotation_x = Quaternion(Vector3.RIGHT, deg_to_rad(-90))
|
||||
var fix_rotation_y_180 = Quaternion(Vector3.UP, deg_to_rad(180))
|
||||
var final_rotation = fix_rotation_y_180 * target_rotation_y * fix_rotation_x
|
||||
current_trans.basis = Basis(final_rotation)
|
||||
|
||||
self.multimesh.set_instance_transform(index, current_trans)
|
||||
10
swarm_engine/swarm_unit/swarm_unit.gd
Normal file
10
swarm_engine/swarm_unit/swarm_unit.gd
Normal file
@ -0,0 +1,10 @@
|
||||
extends CharacterBody3D
|
||||
|
||||
@export var move_speed = 2
|
||||
@export var flow_field_navigation: FlowFieldNav
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
var flow_direction = flow_field_navigation.get_direction_from_position(position)
|
||||
if flow_direction.length() > 0.0:
|
||||
var movement = flow_direction.normalized() * move_speed * delta
|
||||
position += movement
|
||||
11
swarm_engine/swarm_unit/swarm_unit.tscn
Normal file
11
swarm_engine/swarm_unit/swarm_unit.tscn
Normal file
@ -0,0 +1,11 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://cdau7qryen3uq"]
|
||||
|
||||
[ext_resource type="Script" path="res://swarm_engine/swarm_unit/swarm_unit.gd" id="1_eynce"]
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_o8sb1"]
|
||||
|
||||
[node name="SwarmUnit" type="CharacterBody3D"]
|
||||
script = ExtResource("1_eynce")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
shape = SubResource("CapsuleShape3D_o8sb1")
|
||||
Loading…
Reference in New Issue
Block a user