10 Commits

56 changed files with 33910 additions and 572 deletions

BIN
assets/spider/result.bin Normal file

Binary file not shown.

33434
assets/spider/result.gltf Normal file

File diff suppressed because it is too large Load Diff

View 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

Binary file not shown.

View File

@@ -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()

View File

@@ -30,8 +30,7 @@ config/icon="res://icon.svg"
[autoload]
MathUtils="*res://singeltons/MathUtils.gd"
DamageHandler="*res://singeltons/DamageHandler.gd"
DebugUi="*res://scenes/debug_ui/debug_ui.tscn"
[display]
@@ -79,6 +78,11 @@ turn_right={
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
show_debug_ui={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":80,"key_label":0,"unicode":112,"location":0,"echo":false,"script":null)
]
}
[physics]

View File

@@ -1,36 +0,0 @@
[gd_resource type="Resource" script_class="EntityStats" load_steps=12 format=3 uid="uid://qcjre5wwbrs3"]
[ext_resource type="Script" path="res://scripts/resources/Stats/ArmorStat.gd" id="1_c7135"]
[ext_resource type="Script" path="res://scripts/resources/Entity/EntityStats.gd" id="1_xti0a"]
[ext_resource type="Script" path="res://scripts/resources/Stats/HealthStat.gd" id="2_hsnpy"]
[ext_resource type="Script" path="res://scripts/resources/Stats/MaxHealthStat.gd" id="3_26tso"]
[ext_resource type="Script" path="res://scripts/resources/Stats/MovementSpeedStat.gd" id="4_goc2a"]
[ext_resource type="Script" path="res://scripts/resources/Stats/ShieldStat.gd" id="6_rncik"]
[sub_resource type="Resource" id="Resource_vbm44"]
script = ExtResource("1_c7135")
_value = 0
[sub_resource type="Resource" id="Resource_nyvlf"]
script = ExtResource("2_hsnpy")
_value = 0
[sub_resource type="Resource" id="Resource_pxuuc"]
script = ExtResource("3_26tso")
_value = 10
[sub_resource type="Resource" id="Resource_vs6ff"]
script = ExtResource("4_goc2a")
_value = 0
[sub_resource type="Resource" id="Resource_r5hb1"]
script = ExtResource("6_rncik")
_value = 0
[resource]
script = ExtResource("1_xti0a")
max_health = SubResource("Resource_pxuuc")
health = SubResource("Resource_nyvlf")
armor = SubResource("Resource_vbm44")
shield = SubResource("Resource_r5hb1")
movementSpeed = SubResource("Resource_vs6ff")

View File

@@ -9,14 +9,5 @@ shadow_enabled = true
[node name="CSGBox3D" type="CSGBox3D" parent="."]
transform = Transform3D(0.804543, 0.301369, -0.511748, -0.471444, 0.848123, -0.241718, 0.361179, 0.435734, 0.824431, 0, 0, 0)
[node name="CSGBox3D" type="CSGBox3D" parent="CSGBox3D"]
transform = Transform3D(0.804543, 0.301369, -0.511748, -0.471444, 0.848123, -0.241718, 0.361179, 0.435734, 0.824431, 0, 0, 0)
[node name="CSGBox3D" type="CSGBox3D" parent="CSGBox3D/CSGBox3D"]
transform = Transform3D(0.804543, 0.301369, -0.511748, -0.471444, 0.848123, -0.241718, 0.361179, 0.435734, 0.824431, 0, 0, 0)
[node name="CSGBox3D" type="CSGBox3D" parent="CSGBox3D/CSGBox3D/CSGBox3D"]
transform = Transform3D(0.804543, 0.301369, -0.511748, -0.471444, 0.848123, -0.241718, 0.361179, 0.435734, 0.824431, 0, 0, 0)
[node name="Camera3D" type="Camera3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 0.901077, 0.433659, 0, -0.433659, 0.901077, 0, 1.21776, 2.12747)

View File

@@ -0,0 +1,13 @@
extends Control
@export var show_debug_ui: bool = true
func _input(event: InputEvent) -> void:
if event.is_action_pressed("show_debug_ui"):
show_debug_ui = !show_debug_ui
func _process(delta: float) -> void:
if show_debug_ui:
DebugDraw2D.set_text("Frames drawn", Engine.get_frames_drawn())
DebugDraw2D.set_text("FPS", Engine.get_frames_per_second())
DebugDraw2D.set_text("delta", delta)

View File

@@ -0,0 +1,12 @@
[gd_scene load_steps=2 format=3 uid="uid://clcnavxmm7eae"]
[ext_resource type="Script" path="res://scenes/debug_ui/debug_ui.gd" id="1_24u3s"]
[node name="DebugUi" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_24u3s")

View File

@@ -1 +0,0 @@
class_name Enemie extends Entity

View File

@@ -1,70 +0,0 @@
class_name Entity extends Node3D
var stats: EntityStats
var equipments: Array[Equipment]
signal died_event(entity: Entity)
func init_entity(stats: EntityStats):
self.stats = stats;
func equip(newEquipment: Equipment)-> void:
equipments.append(newEquipment)
func unequip(equipmentToRemove: Equipment)-> void:
equipments.erase(equipmentToRemove)
func get_health()->int:
return stats.health.value
func get_shield()->int:
return stats.shield.value
func reduce_shield(damage: int):
stats.shield.value -= damage
if stats.shield.value <= 0:
stats.shield.value = 0
func increase_health(additional_health: int):
stats.health.value += additional_health
if stats.health.value > get_max_health():
stats.health.value = get_max_health()
func reduce_health(damage: int):
stats.health.value -= damage
if stats.health.value <= 0:
died()
func died():
died_event.emit(self)
func get_max_health()->int:
var max_health = stats.max_health
for equipment in equipments:
max_health += equipment.get_max_health()
return max_health
func get_armor()->int:
var armor = stats.armor
for equipment in equipments:
armor += equipment.get_armor()
return armor
func get_max_Shield()->int:
var shield = stats.shield
for equipment in equipments:
shield += equipment.get_max_shield()
return shield
func get_movement_speed()->int:
var movement_speed = stats.movement_speed
for equipment in equipments:
movement_speed += equipment.get_evement_speed()
return movement_speed
func get_damage()->int:
var damage = 0
for equipment in equipments:
damage += equipment.get_damage()
return damage

View File

@@ -1,19 +0,0 @@
class_name PlayerCharacter extends Entity
var mech: Mech
func init_player_character(stats: EntityStats, mech: Mech):
init_entity(stats)
self.mech = mech;
func get_max_health() -> int:
return super() + mech.get_max_health()
func get_armor() -> int:
return super() + mech.get_armor()
func get_max_Shield() -> int:
return super() + mech.get_shield()
func get_movement_speed() -> int:
return super() + mech.get_movement_speed()

View File

@@ -1,16 +0,0 @@
class_name Attachment extends Node3D
var stats: AttachmentStats
func init_attachment(stats: AttachmentStats):
self.stats = stats
func get_damage()->int:
return stats.damage.value
func get_fire_rate()->int:
return stats.fire_rate.value
func get_hit_effects()-> Array[Effect]:
return stats.hit_effects.value

View File

@@ -1,22 +0,0 @@
class_name Equipment extends Node3D
var stats: EquipmentStats
func init_equipment(stats: EquipmentStats):
self.stats = stats;
func get_armor()-> int:
return stats.armor.value
func get_max_health()-> int:
return stats.max_health.value
func get_max_shield()-> int:
return stats.max_shield.value
func get_evement_speed()-> int:
return stats.movementSpeed.value
func get_damage()-> int:
return stats.damage.value

View File

@@ -1 +0,0 @@
class_name Arms extends Equipment

View File

@@ -1 +0,0 @@
class_name Boots extends Equipment

View File

@@ -1 +0,0 @@
class_name Hydraulics extends Equipment

View File

@@ -1,28 +0,0 @@
extends Node3D
class_name Mech
var boots: Boots
var arms: Arms
var hydraulics: Hydraulics
func init_mech(boots: Boots, arms: Arms, hydraulics: Hydraulics):
self.boots = boots
self.arms = arms
self.hydraulics= hydraulics
func get_max_health()-> int:
return boots.get_max_health() +arms.get_max_health()+hydraulics.get_max_health()
func get_armor()-> int:
return boots.get_armor()+arms.get_armor()+hydraulics.get_armor()
func get_max_shield()-> int:
return boots.get_max_shield()+arms.get_max_shield()+hydraulics.get_max_shield()
func get_damage()-> int:
return boots.get_damage()+arms.get_damage()+hydraulics.get_damage()
func get_movement_speed()-> int:
return boots.get_evement_speed()+arms.get_evement_speed()+hydraulics.get_evement_speed()

View File

@@ -1,33 +0,0 @@
class_name Weapon extends Node3D
var stats: WeaponStats
var attachments: Array[Attachment]
func init_weapon(stats: WeaponStats):
self.stats = stats;
func attach(newAttachment: Attachment)-> void:
attachments.append(newAttachment)
func unattach(attachmentToRemove: Attachment)-> void:
attachments.erase(attachmentToRemove)
func get_damage()->int:
var damage = stats.damage
for attachment in attachments:
damage += attachment.get_damage()
return damage
func get_fire_rate()->int:
var fire_rate = stats.fire_rate
for attachment in attachments:
fire_rate += attachment.get_fire_rate()
return fire_rate
func get_hit_effects()-> Array[Effect]:
var hit_effects = []
hit_effects.append_array(stats.hit_effects.value)
for attachment in attachments:
hit_effects.append_array(attachment.get_hit_effects())
return hit_effects

View 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)

View File

@@ -1,6 +0,0 @@
extends Resource
class_name Effect
func apply_effect (orign_entity: Entity, target_entity: Entity)-> void:
assert(false)

View File

@@ -1,6 +0,0 @@
class_name HealEffect extends Effect
@export var heal_amount: int
func apply_effect (orign_entity: Entity, target_entity: Entity)-> void:
target_entity.increase_health(heal_amount)

View File

@@ -1,13 +0,0 @@
extends Resource
class_name EntityResource
@export var entity_stats: EntityStats
@export var entity_scene: PackedScene
func instantiate(parent: Node3D)->Entity:
var entity_instance = entity_scene.instantiate() as Entity
entity_instance.init_entity(entity_stats)
parent.add_child(entity_instance)
return entity_instance

View File

@@ -1,10 +0,0 @@
extends Resource
class_name EntityStats
@export var max_health: MaxHealthStat
@export var health: HealthStat
@export var armor: ArmorStat
@export var shield: ShieldStat
@export var max_shield: MaxShieldStat
@export var movementSpeed: MovementSpeedStat

View File

@@ -1,14 +0,0 @@
extends Resource
class_name EquipmentResource
@export var name: String
@export var equipment_stats: EquipmentStats
@export var equipment_scene: PackedScene
func instantiate(parent: Node3D)->Equipment:
var equipment_instance = equipment_scene.instantiate() as Equipment
equipment_instance.init_Equipment(equipment_stats)
parent.add_child(equipment_instance)
return equipment_instance

View File

@@ -1,9 +0,0 @@
extends Resource
class_name EquipmentStats
@export var max_health: MaxHealthStat
@export var armor: ArmorStat
@export var max_shield: MaxShieldStat
@export var movementSpeed: MovementSpeedStat
@export var damage: DamageStat

View File

@@ -1,3 +0,0 @@
extends MechPartResource
class_name ArmsResource

View File

@@ -1,3 +0,0 @@
extends MechPartResource
class_name BootsResource

View File

@@ -1,3 +0,0 @@
extends MechPartResource
class_name HydraulicsResource

View File

@@ -1,3 +0,0 @@
extends EquipmentResource
class_name MechPartResource

View File

@@ -1,13 +0,0 @@
extends Resource
class_name ArmorStat
signal value_changed_signal(currentArmor: int)
@export var _value: int
var value: int:
get:
return _value
set(new_value):
value = new_value;
value_changed_signal.emit(_value)

View File

@@ -1,13 +0,0 @@
extends Resource
class_name DamageStat
signal value_changed_signal(currentDamage: int)
@export var _value: int
var value: int:
get:
return _value
set(new_value):
value = new_value;
value_changed_signal.emit(_value)

View File

@@ -1,13 +0,0 @@
extends Resource
class_name HitEffectStat
signal value_changed_signal(effects: Array[Effect])
@export var _value: Array[Effect]
var value: Array[Effect]:
get:
return _value
set(new_value):
value = new_value;
value_changed_signal.emit(_value)

View File

@@ -1,13 +0,0 @@
extends Resource
class_name FireRateStat
signal value_changed_signal(currentFireRate: int)
@export var _value: int
var value: int:
get:
return _value
set(new_value):
value = new_value;
value_changed_signal.emit(_value)

View File

@@ -1,13 +0,0 @@
extends Resource
class_name HealthStat
signal value_changed_signal(currentHealth: int)
@export var _value: int
var value: int:
get:
return _value
set(new_value):
value = new_value;
value_changed_signal.emit(_value)

View File

@@ -1,13 +0,0 @@
extends Resource
class_name MaxHealthStat
signal value_changed_signal(currentMaxHealth: int)
@export var _value: int
var value: int:
get:
return _value
set(new_value):
value = new_value;
value_changed_signal.emit(_value)

View File

@@ -1,13 +0,0 @@
extends Resource
class_name MaxShieldStat
signal value_changed_signal(currentMaxShield: int)
@export var _value: int
var value: int:
get:
return _value
set(new_value):
value = new_value;
value_changed_signal.emit(_value)

View File

@@ -1,13 +0,0 @@
extends Resource
class_name MovementSpeedStat
signal value_changed_signal(currentMovementSpeed: int)
@export var _value: int
var value: int:
get:
return _value
set(new_value):
value = new_value;
value_changed_signal.emit(_value)

View File

@@ -1,13 +0,0 @@
extends Resource
class_name ShieldStat
signal value_changed_signal(currentShield: int)
@export var _value: int
var value: int:
get:
return _value
set(new_value):
value = new_value;
value_changed_signal.emit(_value)

View File

@@ -1,13 +0,0 @@
extends Resource
class_name AttachmentResource
@export var attachment_stats: AttachmentStats
@export var attachment_scene: PackedScene
func instantiate(parent: Node3D)->Attachment:
var attachment_instance = attachment_scene.instantiate() as Attachment
attachment_instance.init_Attachment(attachment_stats)
parent.add_child(attachment_instance)
return attachment_instance

View File

@@ -1,7 +0,0 @@
extends Resource
class_name AttachmentStats
@export var damage: DamageStat
@export var fire_rate: FireRateStat
@export var hit_effects: HitEffectStat

View File

@@ -1,13 +0,0 @@
extends Resource
class_name WeaponResource
@export var name: String
@export var weapon_stats: WeaponStats
@export var weapon_scene: PackedScene
func instantiate(parent: Node3D)->Weapon:
var weapon_instance = weapon_scene.instantiate() as Weapon
weapon_instance.init_weapon(weapon_stats)
parent.add_child(weapon_instance)
return weapon_instance

View File

@@ -1,8 +0,0 @@
extends Resource
class_name WeaponStats
@export var damage: DamageStat
@export var fire_rate: FireRateStat
@export var hit_effects: HitEffectStat

View File

@@ -1,20 +0,0 @@
extends Object
func apply_damage(damage_dealer: Entity, damage_receiver: Entity, weapon: Weapon ):
var damage = weapon.get_damage() + damage_dealer.get_damage()
var armor = damage_receiver.get_armor()
var damage_percent = 90*( pow(MathUtils.e, 0.03*armor))
var damage_after_armor = damage * damage_percent
if damage_after_armor < 1 :
damage_after_armor = 1
var shield = damage_receiver.get_shield()
if shield > 0:
damage_receiver.reduce_shield(damage_after_armor)
else:
damage_receiver.reduce_health(damage_after_armor)
for effect in weapon.get_hit_effects():
effect.apply_effect(damage_dealer,damage_receiver)

View File

@@ -1,3 +0,0 @@
extends Object
var e = 2.718281828459045235360287471352

View File

@@ -1 +0,0 @@

View File

@@ -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)

View 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;
}

View File

@@ -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]

View File

@@ -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()
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
#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()
#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()
if show_x_lines:
_draw_x_lines()
if show_z_lines:
_draw_z_lines()
return _cells.get(cell_pos, null)
if show_arrows:
_draw_arrows()
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)
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)
# 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
var space_state = get_world_3d().direct_space_state
var query = PhysicsRayQueryParameters3D.create(from, to)
var result = space_state.intersect_ray(query)
if result.has("position"):
var cell = get_cell_from_pos(result["position"])
if cell:
print("Zelle an", cell.position, ":", cell.flow_direction)
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)

View File

@@ -1,7 +0,0 @@
extends Node3D
func _process(delta: float) -> void:
DebugDraw2D.set_text("Frames drawn", Engine.get_frames_drawn())
DebugDraw2D.set_text("FPS", Engine.get_frames_per_second())
DebugDraw2D.set_text("delta", delta)

View File

@@ -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")

View 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)

View 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

View 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")