fixed the path rebuilding lag
This commit is contained in:
@@ -8,12 +8,12 @@ extends Node3D
|
||||
|
||||
var enabled: bool = false
|
||||
var level: Level
|
||||
var point: FlowNode
|
||||
var point: FlowNodeData
|
||||
var obstacle_last_point: int = -1
|
||||
var valid_point: bool = false # a point is valid if the path would still be traversable overall if this point was made untraversable
|
||||
var ray_collider: Object
|
||||
var ray_point: Vector3
|
||||
var last_point: FlowNode
|
||||
var last_point: FlowNodeData
|
||||
var last_tower_base: TowerBase
|
||||
var interact_key_held: bool = false
|
||||
var interacted_once: bool = false
|
||||
@@ -78,7 +78,7 @@ func _process(delta: float) -> void:
|
||||
if !valid_point:
|
||||
wall_preview.set_visible(false)
|
||||
if point:
|
||||
wall_preview.global_position = point.global_position
|
||||
wall_preview.global_position = point.position
|
||||
wall_preview.global_rotation = Vector3.ZERO
|
||||
|
||||
|
||||
@@ -92,8 +92,8 @@ func reset() -> void:
|
||||
|
||||
|
||||
func process_looking_at_level() -> void:
|
||||
point = level.flow_field.get_closest_buildable_point(ray_point)
|
||||
if level.walls.has(point) or !point.buildable or hero.currency < Data.wall_cost:
|
||||
point = level.flow_field.get_closest_point(ray_point, false, true)
|
||||
if level.walls.has(point) or hero.currency < Data.wall_cost:
|
||||
wall_preview.set_visible(false)
|
||||
valid_point = false
|
||||
clear_previous_point()
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
[ext_resource type="Texture2D" uid="uid://chhmkmlfrobhu" path="res://Assets/Textures/bubble.png" id="15_q3yot"]
|
||||
[ext_resource type="Texture2D" uid="uid://cqnapc8cscl7i" path="res://Assets/Textures/border.png" id="16_x1xjr"]
|
||||
[ext_resource type="PackedScene" uid="uid://chnj376d3lcjd" path="res://UI/pickup_notification.tscn" id="17_oyeww"]
|
||||
[ext_resource type="PackedScene" uid="uid://d17c77pqsi8oy" path="res://UI/EnemyCard/enemy_card_ui.tscn" id="18_dfkac"]
|
||||
[ext_resource type="Script" uid="uid://b5wle8f6rv3e7" path="res://PCs/player_movement.gd" id="20_cfhw8"]
|
||||
[ext_resource type="Texture2D" uid="uid://deelc254ct7ae" path="res://Assets/Textures/place_icon.png" id="22_o55s8"]
|
||||
[ext_resource type="AudioStream" uid="uid://csu2hce4bfoki" path="res://Audio/cardPlace1.ogg" id="24_8ch4w"]
|
||||
@@ -433,7 +432,6 @@ pickup_notif_scene = ExtResource("17_oyeww")
|
||||
wave_start_label = NodePath("StartWaveLabel")
|
||||
place_text = NodePath("VBoxContainer2/HBoxContainer/RichTextLabel")
|
||||
swap_text = NodePath("VBoxContainer2/HBoxContainer2/RichTextLabel")
|
||||
enemy_card_scene = ExtResource("18_dfkac")
|
||||
energy_label = NodePath("Currencies/HBoxContainer/EnergyLabel")
|
||||
blank_cassette_label = NodePath("Currencies/BlankCassetteLabel")
|
||||
feature_preview = NodePath("FeaturePreview")
|
||||
|
||||
@@ -3,101 +3,38 @@ extends Node3D
|
||||
|
||||
signal path_updated()
|
||||
|
||||
@export var data_file: FlowFieldData
|
||||
@export var start_points: Array[Node3D]
|
||||
@export var goal_points: Array[Node3D]
|
||||
@export var nodes_visible: bool = false
|
||||
|
||||
var flow_node_scene: PackedScene = preload("res://Scenes/FlowField/flow_node.tscn")
|
||||
var nodes: Array[FlowNode] = []
|
||||
var start_nodes: Array[FlowNode] = []
|
||||
var goal_nodes: Array[FlowNode] = []
|
||||
var created_nodes: int = 0
|
||||
var start_nodes: Array[FlowNodeData]
|
||||
var goal_nodes: Array[FlowNodeData]
|
||||
var magic_node: FlowNodeData
|
||||
var data: FlowFieldData :
|
||||
get():
|
||||
return data
|
||||
set(value):
|
||||
data = value
|
||||
for node: FlowNodeData in data.nodes:
|
||||
if node.type == FlowNodeData.NodeType.START:
|
||||
start_nodes.append(node)
|
||||
if node.type == FlowNodeData.NodeType.GOAL:
|
||||
goal_nodes.append(node)
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if !nodes_visible:
|
||||
for node: FlowNode in nodes:
|
||||
node.visible = false
|
||||
|
||||
|
||||
func load_from_data(data: FlowFieldData = data_file) -> void:
|
||||
data_file = data
|
||||
for node: FlowNode in nodes:
|
||||
delete_node(node)
|
||||
nodes = []
|
||||
start_nodes = []
|
||||
goal_nodes = []
|
||||
var dict: Dictionary[FlowNodeData, FlowNode] = {}
|
||||
created_nodes = 0
|
||||
for node_data: FlowNodeData in data_file.nodes:
|
||||
var new_flow_node: FlowNode = create_node(node_data.position)
|
||||
new_flow_node.node_id = node_data.node_id
|
||||
new_flow_node.grid_id = node_data.grid_id
|
||||
new_flow_node.grid_x = node_data.grid_x
|
||||
new_flow_node.grid_y = node_data.grid_y
|
||||
new_flow_node.buildable = node_data.buildable
|
||||
dict[node_data] = new_flow_node
|
||||
if node_data.type == FlowNodeData.NodeType.START:
|
||||
start_nodes.append(new_flow_node)
|
||||
elif node_data.type == FlowNodeData.NodeType.GOAL:
|
||||
goal_nodes.append(new_flow_node)
|
||||
for node_data: FlowNodeData in dict.keys():
|
||||
for neighbor: FlowNodeData in node_data.connected_nodes:
|
||||
dict[node_data].add_connection(dict[neighbor])
|
||||
|
||||
|
||||
@warning_ignore("unused_parameter")
|
||||
func _process(delta: float) -> void:
|
||||
if !nodes_visible:
|
||||
return
|
||||
for node: FlowNode in nodes:
|
||||
if node.traversable and node.buildable:
|
||||
node.set_color(Color.WEB_GRAY)
|
||||
elif node.traversable and !node.buildable:
|
||||
node.set_color(Color.CORAL)
|
||||
else:
|
||||
node.set_color(Color.BLACK)
|
||||
if goal_nodes.has(node):
|
||||
node.set_color(Color.BLUE)
|
||||
if start_nodes.has(node):
|
||||
node.set_color(Color.PINK)
|
||||
if magic_node:
|
||||
magic_node.set_color(Color.DEEP_PINK)
|
||||
|
||||
|
||||
func get_closest_traversable_point(pos: Vector3) -> FlowNode:
|
||||
var closest_point: FlowNode = null
|
||||
func get_closest_point(pos: Vector3, traversable_required: bool = false, buildable_required: bool = false) -> FlowNodeData:
|
||||
var closest_point: FlowNodeData = null
|
||||
var closest_dist: float = 100000.0
|
||||
for node: FlowNode in nodes:
|
||||
if node.traversable and node.global_position.distance_to(pos) < closest_dist:
|
||||
closest_dist = node.global_position.distance_to(pos)
|
||||
closest_point = node
|
||||
return closest_point
|
||||
|
||||
|
||||
func get_closest_point_point(pos: Vector3) -> FlowNode:
|
||||
var closest_point: FlowNode = null
|
||||
var closest_dist: float = 100000.0
|
||||
for node: FlowNode in nodes:
|
||||
if node.global_position.distance_to(pos) < closest_dist:
|
||||
closest_dist = node.global_position.distance_to(pos)
|
||||
closest_point = node
|
||||
return closest_point
|
||||
|
||||
|
||||
func get_closest_buildable_point(pos: Vector3) -> FlowNode:
|
||||
var closest_point: FlowNode = null
|
||||
var closest_dist: float = 100000.0
|
||||
for node: FlowNode in nodes:
|
||||
if node.buildable and node.global_position.distance_to(pos) < closest_dist:
|
||||
closest_dist = node.global_position.distance_to(pos)
|
||||
for node: FlowNodeData in data.nodes:
|
||||
if node.position.distance_to(pos) < closest_dist:
|
||||
if !traversable_required or node.traversable:
|
||||
if !buildable_required or node.buildable:
|
||||
closest_dist = node.position.distance_to(pos)
|
||||
closest_point = node
|
||||
return closest_point
|
||||
|
||||
|
||||
func test_traversability() -> bool:
|
||||
for node: FlowNode in start_nodes:
|
||||
for node: FlowNodeData in start_nodes:
|
||||
while node.best_path != null:
|
||||
if node.best_path.traversable:
|
||||
node = node.best_path
|
||||
@@ -106,9 +43,9 @@ func test_traversability() -> bool:
|
||||
return true
|
||||
|
||||
|
||||
func iterate_search(search_frontier: Array[FlowNode], reached: Array[FlowNode]) -> void:
|
||||
var current: FlowNode = search_frontier.pop_front()
|
||||
for node: FlowNode in current.connections:
|
||||
func iterate_search(search_frontier: Array[FlowNodeData], reached: Array[FlowNodeData]) -> void:
|
||||
var current: FlowNodeData = search_frontier.pop_front()
|
||||
for node: FlowNodeData in current.connected_nodes:
|
||||
if !reached.has(node):
|
||||
reached.append(node)
|
||||
if node.traversable:
|
||||
@@ -117,9 +54,9 @@ func iterate_search(search_frontier: Array[FlowNode], reached: Array[FlowNode])
|
||||
|
||||
|
||||
func calculate() -> void:
|
||||
var reached: Array[FlowNode] = []
|
||||
var search_frontier: Array[FlowNode] = []
|
||||
for node: FlowNode in goal_nodes:
|
||||
var reached: Array[FlowNodeData] = []
|
||||
var search_frontier: Array[FlowNodeData] = []
|
||||
for node: FlowNodeData in goal_nodes:
|
||||
node.best_path = null
|
||||
reached.append(node)
|
||||
search_frontier.append(node)
|
||||
@@ -127,20 +64,19 @@ func calculate() -> void:
|
||||
iterate_search(search_frontier, reached)
|
||||
|
||||
|
||||
var magic_node: FlowNode = null
|
||||
func traversable_after_blocking_point(point: FlowNode) -> bool:
|
||||
func traversable_after_blocking_point(point: FlowNodeData) -> bool:
|
||||
magic_node = null
|
||||
var reached: Array[FlowNode] = [point]
|
||||
var search_frontier: Array[FlowNode] = []
|
||||
for node: FlowNode in point.connections:
|
||||
var reached: Array[FlowNodeData] = [point]
|
||||
var search_frontier: Array[FlowNodeData] = []
|
||||
for node: FlowNodeData in point.connected_nodes:
|
||||
if node.best_path == point and node.traversable:
|
||||
reached.append(node)
|
||||
search_frontier.append(node)
|
||||
if search_frontier.size() == 0: # if no neighbors rely on this node, then we're all good
|
||||
return true
|
||||
while search_frontier.size() > 0:
|
||||
var current: FlowNode = search_frontier.pop_front()
|
||||
for node: FlowNode in current.connections:
|
||||
var current: FlowNodeData = search_frontier.pop_front()
|
||||
for node: FlowNodeData in current.connected_nodes:
|
||||
if !reached.has(node):
|
||||
if node.traversable and node.best_path != node and !reached.has(node.best_path):
|
||||
#if we havent already seen the node this neighbor goes to,
|
||||
@@ -154,33 +90,23 @@ func traversable_after_blocking_point(point: FlowNode) -> bool:
|
||||
return false
|
||||
|
||||
|
||||
## Connects many nodes to a single single node, if any connections already
|
||||
## exist, this function disconnects them instead
|
||||
func connect_many_nodes(common_node: FlowNode, child_nodes: Array[FlowNode]) -> void:
|
||||
for node: FlowNode in child_nodes:
|
||||
if common_node.connections.has(node):
|
||||
disconnect_nodes(common_node, node)
|
||||
else:
|
||||
connect_nodes(common_node, node)
|
||||
|
||||
|
||||
func toggle_goal(nodes_to_toggle: Array[FlowNode]) -> void:
|
||||
for node: FlowNode in nodes_to_toggle:
|
||||
func toggle_goal(nodes_to_toggle: Array[FlowNodeData]) -> void:
|
||||
for node: FlowNodeData in nodes_to_toggle:
|
||||
if goal_nodes.has(node):
|
||||
goal_nodes.erase(node)
|
||||
else:
|
||||
goal_nodes.append(node)
|
||||
|
||||
|
||||
func toggle_start(nodes_to_toggle: Array[FlowNode]) -> void:
|
||||
for node: FlowNode in nodes_to_toggle:
|
||||
func toggle_start(nodes_to_toggle: Array[FlowNodeData]) -> void:
|
||||
for node: FlowNodeData in nodes_to_toggle:
|
||||
if start_nodes.has(node):
|
||||
start_nodes.erase(node)
|
||||
else:
|
||||
start_nodes.append(node)
|
||||
|
||||
|
||||
func toggle_traversable(node: FlowNode) -> bool:
|
||||
func toggle_traversable(node: FlowNodeData) -> bool:
|
||||
node.traversable = !node.traversable
|
||||
calculate()
|
||||
#TODO: technically the path only changed if the new path IS traversable
|
||||
@@ -188,64 +114,5 @@ func toggle_traversable(node: FlowNode) -> bool:
|
||||
return test_traversability()
|
||||
|
||||
|
||||
func toggle_buildable(node: FlowNode) -> void:
|
||||
func toggle_buildable(node: FlowNodeData) -> void:
|
||||
node.buildable = !node.buildable
|
||||
|
||||
|
||||
func create_node(pos: Vector3 = Vector3.ZERO, grid_id: int = -1, grid_x: int = 0, grid_y: int = 0) -> FlowNode:
|
||||
var node: FlowNode = flow_node_scene.instantiate()
|
||||
node.node_id = created_nodes
|
||||
node.grid_id = grid_id
|
||||
node.grid_x = grid_x
|
||||
node.grid_y = grid_y
|
||||
node.position = pos
|
||||
node.set_color(Color.WEB_GRAY)
|
||||
nodes.append(node)
|
||||
add_child(node)
|
||||
node.owner = self
|
||||
created_nodes += 1
|
||||
return node
|
||||
|
||||
|
||||
func delete_node(node: FlowNode) -> void:
|
||||
for neighbor: FlowNode in node.connections:
|
||||
node.remove_connection(neighbor)
|
||||
nodes.erase(node)
|
||||
node.queue_free()
|
||||
|
||||
|
||||
func connect_nodes(node1: FlowNode, node2: FlowNode) -> void:
|
||||
if node1 != node2:
|
||||
node1.add_connection(node2)
|
||||
node2.add_connection(node1)
|
||||
|
||||
|
||||
func disconnect_nodes(node1: FlowNode, node2: FlowNode) -> void:
|
||||
if node1 != node2:
|
||||
node1.remove_connection(node2)
|
||||
node2.remove_connection(node1)
|
||||
|
||||
|
||||
func create_grid(x_size: int, y_size: int, gap: float) -> void:
|
||||
data_file.grids += 1
|
||||
var grid_id: int = data_file.grids
|
||||
var grid: Array[Array] = []
|
||||
for x: int in x_size:
|
||||
var row: Array[FlowNode] = []
|
||||
for y: int in y_size:
|
||||
#var start_pos: Vector3 = Vector3.ZERO - (Vector3(gap * x_size, 0, gap * y_size) / 2.0)
|
||||
var point_position: Vector3 = Vector3((x - floori(x_size / 2.0)) * gap, 0, (y - floori(y_size / 2.0)) * gap)
|
||||
#point_position += global_position
|
||||
#row.append(create_node(start_pos + Vector3(gap * x, 0, gap * y)))
|
||||
row.append(create_node(point_position, grid_id, x, y))
|
||||
grid.append(row)
|
||||
for x: int in grid.size():
|
||||
for y: int in grid[x].size():
|
||||
if y > 0:
|
||||
connect_nodes(grid[x][y], grid[x][y - 1])
|
||||
if x > 0:
|
||||
connect_nodes(grid[x][y], grid[x - 1][y])
|
||||
if y < grid[x].size() - 1:
|
||||
connect_nodes(grid[x][y], grid[x][y + 1])
|
||||
if x < grid.size() - 1:
|
||||
connect_nodes(grid[x][y], grid[x + 1][y])
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
class_name FlowFieldData
|
||||
extends Resource
|
||||
extends RefCounted
|
||||
|
||||
@export var nodes: Array[FlowNodeData]
|
||||
@export var grids: int = 0
|
||||
var nodes: Array[FlowNodeData]
|
||||
var grids: int = 0
|
||||
|
||||
|
||||
func to_dict() -> Dictionary:
|
||||
|
||||
@@ -4,10 +4,62 @@ extends Node
|
||||
@export var flow_field: FlowField
|
||||
|
||||
|
||||
func create_grid(x: int, y: int, gap: int) -> Array[FlowNode]:
|
||||
#return flow_field.create_grid(x, y, gap)
|
||||
return []
|
||||
func create_grid(x_size: int, y_size: int, gap: float) -> Array[FlowNodeData]:
|
||||
flow_field.data.grids += 1
|
||||
var grid_id: int = flow_field.data.grids
|
||||
var grid: Array[Array] = []
|
||||
var created_nodes: Array[FlowNodeData] = []
|
||||
|
||||
for x: int in x_size:
|
||||
var row: Array[FlowNodeData] = []
|
||||
for y: int in y_size:
|
||||
var point_position: Vector3 = Vector3((x - floori(x_size / 2.0)) * gap, 0, (y - floori(y_size / 2.0)) * gap)
|
||||
var created_node: FlowNodeData = create_node(point_position, grid_id, x, y)
|
||||
created_nodes.append(created_node)
|
||||
row.append(created_node)
|
||||
grid.append(row)
|
||||
|
||||
for x: int in grid.size():
|
||||
for y: int in grid[x].size():
|
||||
if y > 0:
|
||||
connect_nodes(grid[x][y], grid[x][y - 1])
|
||||
if x > 0:
|
||||
connect_nodes(grid[x][y], grid[x - 1][y])
|
||||
if y < grid[x].size() - 1:
|
||||
connect_nodes(grid[x][y], grid[x][y + 1])
|
||||
if x < grid.size() - 1:
|
||||
connect_nodes(grid[x][y], grid[x + 1][y])
|
||||
return created_nodes
|
||||
|
||||
|
||||
func create_node(pos: Vector3 = Vector3.ZERO, grid_id: int = -1, grid_x: int = 0, grid_y: int = 0) -> FlowNode:
|
||||
return flow_field.create_node(pos, grid_id, grid_x, grid_y)
|
||||
func create_node(pos: Vector3 = Vector3.ZERO, grid_id: int = -1, grid_x: int = 0, grid_y: int = 0) -> FlowNodeData:
|
||||
var node: FlowNodeData = FlowNodeData.new()
|
||||
node.node_id = flow_field.data.nodes.size()
|
||||
node.grid_id = grid_id
|
||||
node.grid_x = grid_x
|
||||
node.grid_y = grid_y
|
||||
node.position = pos
|
||||
flow_field.data.nodes.append(node)
|
||||
return node
|
||||
|
||||
|
||||
func delete_node(node: FlowNodeData) -> void:
|
||||
for neighbor: FlowNodeData in node.connections:
|
||||
disconnect_nodes(node, neighbor)
|
||||
flow_field.data.nodes.erase(node)
|
||||
|
||||
|
||||
func connect_nodes(a: FlowNodeData, b: FlowNodeData) -> void:
|
||||
if a != b:
|
||||
if a.connected_nodes.has(b):
|
||||
a.connected_nodes.append(b)
|
||||
if b.connected_nodes.has(a):
|
||||
b.add_connection(a)
|
||||
|
||||
|
||||
func disconnect_nodes(a: FlowNodeData, b: FlowNodeData) -> void:
|
||||
if a != b:
|
||||
if a.connected_nodes.has(b):
|
||||
a.connected_nodes.erase(b)
|
||||
if b.connected_nodes.has(a):
|
||||
b.connected_nodes.erase(a)
|
||||
|
||||
@@ -4,14 +4,17 @@ extends Node
|
||||
@export_group("Basic Function")
|
||||
@export var zone_list: Array[PackedScene]
|
||||
@export var zone_holder: Node3D
|
||||
@export var visualiser_scene: PackedScene
|
||||
|
||||
@export_group("Flow Field Editor")
|
||||
@export var flow_field: FlowField
|
||||
@export var raycast: RayCast3D
|
||||
@export var project_raycast: RayCast3D
|
||||
@export var camera: Camera3D
|
||||
@export var camera_pivot: Node3D
|
||||
@export var position_field: HBoxContainer
|
||||
@export var position_x: LineEdit
|
||||
@export var position_y: LineEdit
|
||||
@export var position_z: LineEdit
|
||||
@export var x_field: LineEdit
|
||||
@export var y_field: LineEdit
|
||||
@export var z_field: LineEdit
|
||||
@@ -20,8 +23,10 @@ extends Node
|
||||
@export var gap_field: LineEdit
|
||||
@export var save_path: LineEdit
|
||||
|
||||
var hover: FlowNode = null
|
||||
var selected: Array[FlowNode] = []
|
||||
var flow_field: FlowField
|
||||
var visualisers: Dictionary[FlowNodeData, FlowNodeVisualiser]
|
||||
var hover: FlowNodeVisualiser = null
|
||||
var selected: Array[FlowNodeVisualiser] = []
|
||||
var vector_dirty: bool = false
|
||||
var editing: bool = false
|
||||
var selected_zone: int = -1
|
||||
@@ -29,10 +34,13 @@ var level: Level
|
||||
var radius: float = 0
|
||||
var up_angle: float = 0
|
||||
var rotate_held: bool = false
|
||||
var flow_field_data: FlowFieldData
|
||||
var flow_field_editor: FlowFieldEditor
|
||||
var path_vfx: PathVFX
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
flow_field_editor = FlowFieldEditor.new()
|
||||
add_child(flow_field_editor)
|
||||
var i: int = 0
|
||||
for zone: PackedScene in zone_list:
|
||||
i += 1
|
||||
@@ -40,6 +48,36 @@ func _ready() -> void:
|
||||
$VBoxContainer2/OptionButton.select(0)
|
||||
$VBoxContainer2/OptionButton.item_selected.connect(select_zone)
|
||||
_on_trash_button_pressed()
|
||||
path_vfx = PathVFX.new()
|
||||
path_vfx.line_width = 0.4
|
||||
path_vfx.material = load("res://path_material.tres")
|
||||
add_child(path_vfx)
|
||||
|
||||
|
||||
func setup_visualisers_from_flow_field_data(data: FlowFieldData) -> void:
|
||||
for visualiser: FlowNodeVisualiser in visualisers.keys():
|
||||
visualiser.queue_free()
|
||||
visualisers = {}
|
||||
for node: FlowNodeData in data.nodes:
|
||||
add_visual(node)
|
||||
for node: FlowNodeData in visualisers.keys():
|
||||
add_visual_connections(node)
|
||||
|
||||
|
||||
func add_visual(data: FlowNodeData) -> void:
|
||||
var visual: FlowNodeVisualiser = visualiser_scene.instantiate() as FlowNodeVisualiser
|
||||
visual.data = data
|
||||
visual.position = data.position
|
||||
add_child(visual)
|
||||
visualisers[data] = visual
|
||||
|
||||
|
||||
func add_visual_connections(data: FlowNodeData) -> void:
|
||||
var connections: Array[FlowNodeVisualiser] = []
|
||||
for node: FlowNodeData in data.connected_nodes:
|
||||
connections.append(visualisers[node])
|
||||
visualisers[data].connections = connections
|
||||
visualisers[data].setup_connection_visualisers()
|
||||
|
||||
|
||||
func select_zone(zone_index: int) -> void:
|
||||
@@ -86,24 +124,23 @@ func _process(delta: float) -> void:
|
||||
var y: float = Input.get_axis("Move Forward", "Move Backward")
|
||||
var x: float = Input.get_axis("Move Left", "Move Right")
|
||||
var input_vector: Vector2 = Input.get_vector("Move Left", "Move Right", "Move Forward", "Move Backward")
|
||||
#camera_pivot.position += Vector3(x, 0, y) * delta * 30
|
||||
#set_cam_position()
|
||||
|
||||
var movement: Vector3 = ((camera_pivot.transform.basis.z * input_vector.y) + (camera_pivot.transform.basis.x * input_vector.x))
|
||||
var vec2: Vector2 = Vector2(movement.x, movement.z).normalized()
|
||||
camera_pivot.position += Vector3(vec2.x, 0.0, vec2.y) * delta * 30.0
|
||||
|
||||
|
||||
func set_node_colors() -> void:
|
||||
for node: FlowNode in flow_field.nodes:
|
||||
if node.traversable and node.buildable:
|
||||
for node: FlowNodeVisualiser in visualisers.values():
|
||||
if node.data.traversable and node.data.buildable:
|
||||
node.set_color(Color.WEB_GRAY)
|
||||
elif node.traversable and !node.buildable:
|
||||
elif node.data.traversable and !node.data.buildable:
|
||||
node.set_color(Color.CORAL)
|
||||
else:
|
||||
node.set_color(Color.BLACK)
|
||||
if flow_field.goal_nodes.has(node):
|
||||
if flow_field.goal_nodes.has(node.data):
|
||||
node.set_color(Color.BLUE)
|
||||
if flow_field.start_nodes.has(node):
|
||||
if flow_field.start_nodes.has(node.data):
|
||||
node.set_color(Color.PINK)
|
||||
if selected.has(node):
|
||||
node.set_color(Color.GREEN)
|
||||
@@ -157,24 +194,39 @@ func _on_z_field_changed(text: String) -> void:
|
||||
selected[0].global_position.z = float(text)
|
||||
|
||||
|
||||
## Connects many nodes to a single single node, if any connections already
|
||||
## exist, this function disconnects them instead
|
||||
func connect_many_nodes(common_node: FlowNodeData, child_nodes: Array[FlowNodeData]) -> void:
|
||||
for node: FlowNodeData in child_nodes:
|
||||
if common_node.connections.has(node):
|
||||
flow_field_editor.disconnect_nodes(common_node, node)
|
||||
else:
|
||||
flow_field_editor.connect_nodes(common_node, node)
|
||||
|
||||
|
||||
func set_position() -> void:
|
||||
for node: FlowNode in selected:
|
||||
node.global_position = Vector3(float($Position/x.text), float($Position/y.text), float($Position/z.text))
|
||||
for node: FlowNodeVisualiser in selected:
|
||||
var vector: Vector3 = Vector3(float(position_x.text), float(position_y.text), float(position_z.text))
|
||||
node.data.position = vector
|
||||
node.global_position = vector
|
||||
|
||||
|
||||
func offset_position() -> void:
|
||||
for node: FlowNode in selected:
|
||||
node.global_position += Vector3(float($Position/x.text), float($Position/y.text), float($Position/z.text))
|
||||
for node: FlowNodeVisualiser in selected:
|
||||
var vector: Vector3 = Vector3(float(position_x.text), float(position_y.text), float(position_z.text))
|
||||
node.data.position += vector
|
||||
node.global_position += vector
|
||||
|
||||
|
||||
func _on_create_button_pressed() -> void:
|
||||
flow_field.create_node()
|
||||
add_visual(flow_field_editor.create_node())
|
||||
|
||||
|
||||
func _on_generate_grid_button_pressed() -> void:
|
||||
flow_field.create_grid(int(x_size_field.text), int(y_size_field.text), float(gap_field.text))
|
||||
selected.append_array(flow_field.nodes)
|
||||
create_grid_select_button(flow_field.data_file.grids)
|
||||
for node: FlowNodeData in flow_field_editor.create_grid(int(x_size_field.text), int(y_size_field.text), float(gap_field.text)):
|
||||
add_visual(node)
|
||||
selected.append(node)
|
||||
create_grid_select_button(flow_field.data.grids)
|
||||
|
||||
|
||||
func create_grid_select_button(grid: int) -> void:
|
||||
@@ -186,6 +238,13 @@ func create_grid_select_button(grid: int) -> void:
|
||||
|
||||
func _on_calculate_button_pressed() -> void:
|
||||
flow_field.calculate()
|
||||
var points: Array[Vector3] = []
|
||||
var node: FlowNodeData = flow_field.get_closest_point(flow_field.start_nodes[0].position, true, false)
|
||||
points.append(node.position + Vector3(0, 0.1, 0))
|
||||
while node.best_path:
|
||||
node = node.best_path
|
||||
points.append(node.position + Vector3(0, 0.1, 0))
|
||||
path_vfx.path(points)
|
||||
|
||||
|
||||
func _on_connect_button_pressed() -> void:
|
||||
@@ -193,20 +252,24 @@ func _on_connect_button_pressed() -> void:
|
||||
|
||||
|
||||
func _on_mark_goal_button_pressed() -> void:
|
||||
flow_field.toggle_goal(selected)
|
||||
for node: FlowNodeVisualiser in selected:
|
||||
flow_field.toggle_goal([node.data])
|
||||
selected = []
|
||||
vector_dirty = true
|
||||
|
||||
|
||||
func _on_mark_start_button_pressed() -> void:
|
||||
flow_field.toggle_start(selected)
|
||||
for node: FlowNodeVisualiser in selected:
|
||||
flow_field.toggle_start([node.data])
|
||||
selected = []
|
||||
vector_dirty = true
|
||||
|
||||
|
||||
func _on_extrude_button_pressed() -> void:
|
||||
if selected.size() == 1:
|
||||
var node: FlowNode = flow_field.create_node(selected[0].position)
|
||||
var node: FlowNodeVisualiser = visualiser_scene.instantiate() as FlowNodeVisualiser
|
||||
add_child(node)
|
||||
node.data = flow_field.create_node(selected[0].position)
|
||||
node.add_connection(selected[0])
|
||||
selected[0].add_connection(node)
|
||||
selected[0].set_color(Color.WEB_GRAY)
|
||||
@@ -216,61 +279,35 @@ func _on_extrude_button_pressed() -> void:
|
||||
|
||||
|
||||
func _on_toggle_traversable_button_pressed() -> void:
|
||||
for node: FlowNode in selected:
|
||||
if !flow_field.toggle_traversable(node):
|
||||
flow_field.toggle_traversable(node)
|
||||
for node: FlowNodeVisualiser in selected:
|
||||
if !flow_field.toggle_traversable(node.data):
|
||||
flow_field.toggle_traversable(node.data)
|
||||
selected = []
|
||||
return
|
||||
selected = []
|
||||
|
||||
|
||||
func _on_toggle_buildable_button_pressed() -> void:
|
||||
for node: FlowNode in selected:
|
||||
flow_field.toggle_buildable(node)
|
||||
for node: FlowNodeVisualiser in selected:
|
||||
flow_field.toggle_buildable(node.data)
|
||||
|
||||
|
||||
#TODO: This doesnt work as you'd expect because of physics frames
|
||||
func _on_project_downwards_button_pressed() -> void:
|
||||
for node: FlowNode in selected:
|
||||
project_raycast.global_position = node.global_position + Vector3.UP
|
||||
for node: FlowNodeVisualiser in selected:
|
||||
project_raycast.position = node.position + Vector3.UP
|
||||
project_raycast.target_position = Vector3.DOWN * 100.0
|
||||
await get_tree().physics_frame
|
||||
await get_tree().physics_frame
|
||||
await get_tree().physics_frame
|
||||
await get_tree().physics_frame
|
||||
if project_raycast.is_colliding():
|
||||
node.global_position = project_raycast.get_collision_point()
|
||||
node.position = project_raycast.get_collision_point()
|
||||
node.data.position = node.position
|
||||
|
||||
|
||||
func _on_save_button_pressed() -> void:
|
||||
var new_flow_field_data: FlowFieldData = FlowFieldData.new()
|
||||
var dict: Dictionary[FlowNode, FlowNodeData] = {}
|
||||
var grid_num: int = -1
|
||||
for node: FlowNode in flow_field.nodes:
|
||||
var new_flow_node_data: FlowNodeData = FlowNodeData.new()
|
||||
new_flow_node_data.node_id = node.node_id
|
||||
new_flow_node_data.grid_id = node.grid_id
|
||||
if node.grid_id > grid_num:
|
||||
grid_num += 1
|
||||
new_flow_node_data.grid_x = node.grid_x
|
||||
new_flow_node_data.grid_y = node.grid_y
|
||||
new_flow_node_data.position = node.global_position
|
||||
new_flow_node_data.buildable = node.buildable
|
||||
if flow_field.start_nodes.has(node):
|
||||
new_flow_node_data.type = FlowNodeData.NodeType.START
|
||||
elif flow_field.goal_nodes.has(node):
|
||||
new_flow_node_data.type = FlowNodeData.NodeType.GOAL
|
||||
else:
|
||||
new_flow_node_data.type = FlowNodeData.NodeType.STANDARD
|
||||
dict[node] = new_flow_node_data
|
||||
for node: FlowNode in flow_field.nodes:
|
||||
var flow_node_data: FlowNodeData = dict[node]
|
||||
for neighbor: FlowNode in node.connections:
|
||||
flow_node_data.connected_nodes.append(dict[neighbor])
|
||||
new_flow_field_data.nodes.append(flow_node_data)
|
||||
new_flow_field_data.grids = grid_num
|
||||
|
||||
var string: String = JSON.stringify(new_flow_field_data.to_dict())
|
||||
var string: String = JSON.stringify(flow_field.data.to_dict())
|
||||
var path: String = save_path.text + ".json"
|
||||
var dir: DirAccess = DirAccess.open("user://")
|
||||
if !dir.dir_exists("pathing_graphs"):
|
||||
@@ -302,48 +339,41 @@ func _on_load_button_pressed() -> void:
|
||||
if parse_result == OK:
|
||||
var dict: Dictionary = json.data
|
||||
var flow_field_data: FlowFieldData = FlowFieldData.from_dict(dict)
|
||||
flow_field.load_from_data(flow_field_data)
|
||||
flow_field.data = flow_field_data
|
||||
for grid: int in flow_field_data.grids:
|
||||
create_grid_select_button(grid + 1)
|
||||
|
||||
|
||||
#func _on_load_button_pressed() -> void:
|
||||
#if ResourceLoader.exists(save_path.text + ".res"):
|
||||
#print("file exists")
|
||||
#var resource: Resource = ResourceLoader.load(save_path.text + ".res", "", ResourceLoader.CACHE_MODE_IGNORE)
|
||||
#if resource is FlowFieldData:
|
||||
#flow_field.load_from_data(resource)
|
||||
#print("loaded some data")
|
||||
#else:
|
||||
#print("some error loading!")
|
||||
setup_visualisers_from_flow_field_data(flow_field_data)
|
||||
|
||||
|
||||
func _on_trash_button_pressed() -> void:
|
||||
if flow_field:
|
||||
flow_field.queue_free()
|
||||
for visualiser: FlowNodeVisualiser in visualisers.values():
|
||||
visualiser.queue_free()
|
||||
visualisers = {}
|
||||
for child: Node in $VBoxContainer3.get_children():
|
||||
child.queue_free()
|
||||
flow_field = FlowField.new()
|
||||
flow_field_data = FlowFieldData.new()
|
||||
flow_field.data_file = flow_field_data
|
||||
flow_field.data = FlowFieldData.new()
|
||||
add_child(flow_field)
|
||||
flow_field_editor.flow_field = flow_field
|
||||
if level:
|
||||
level.flow_field = flow_field
|
||||
|
||||
|
||||
func _on_select_all_pressed() -> void:
|
||||
selected = []
|
||||
for node: FlowNode in flow_field.nodes:
|
||||
for node: FlowNodeVisualiser in flow_field.nodes:
|
||||
selected.append(node)
|
||||
|
||||
|
||||
func select_in_grid(grid: int) -> void:
|
||||
selected = []
|
||||
for node: FlowNode in flow_field.nodes:
|
||||
if node.grid_id == grid:
|
||||
for node: FlowNodeVisualiser in flow_field.nodes:
|
||||
if node.data.grid_id == grid:
|
||||
selected.append(node)
|
||||
|
||||
|
||||
func _on_print_ids_pressed() -> void:
|
||||
for node: FlowNode in selected:
|
||||
print(node.node_id)
|
||||
for node: FlowNodeVisualiser in selected:
|
||||
print(node.data.node_id)
|
||||
|
||||
@@ -3,20 +3,25 @@
|
||||
[ext_resource type="Script" uid="uid://05c5q1v2nv8p" path="res://Scenes/FlowField/flow_field_tool.gd" id="1_e7pmn"]
|
||||
[ext_resource type="PackedScene" uid="uid://y1qa1g3ic8sp" path="res://Zones/Moat/scn_moat.tscn" id="2_030xf"]
|
||||
[ext_resource type="PackedScene" uid="uid://csq7if8wojp4g" path="res://Zones/Cave/scn_cave.tscn" id="3_xar7e"]
|
||||
[ext_resource type="PackedScene" uid="uid://bssfvyxv5uo1f" path="res://Scenes/FlowField/flow_node.tscn" id="4_50p2d"]
|
||||
|
||||
[sub_resource type="Environment" id="Environment_e7pmn"]
|
||||
ambient_light_source = 2
|
||||
ambient_light_color = Color(0.728822, 0.728822, 0.728822, 1)
|
||||
|
||||
[node name="FlowFieldTool" type="Node" unique_id=897052359 node_paths=PackedStringArray("zone_holder", "raycast", "project_raycast", "camera", "camera_pivot", "position_field", "x_field", "y_field", "z_field", "x_size_field", "y_size_field", "gap_field", "save_path")]
|
||||
[node name="FlowFieldTool" type="Node" unique_id=897052359 node_paths=PackedStringArray("zone_holder", "raycast", "project_raycast", "camera", "camera_pivot", "position_field", "position_x", "position_y", "position_z", "x_field", "y_field", "z_field", "x_size_field", "y_size_field", "gap_field", "save_path")]
|
||||
script = ExtResource("1_e7pmn")
|
||||
zone_list = Array[PackedScene]([ExtResource("2_030xf"), ExtResource("3_xar7e")])
|
||||
zone_holder = NodePath("ZoneHolder")
|
||||
visualiser_scene = ExtResource("4_50p2d")
|
||||
raycast = NodePath("CameraFocus/Camera3D/RayCast3D")
|
||||
project_raycast = NodePath("RayCast3D")
|
||||
camera = NodePath("CameraFocus/Camera3D")
|
||||
camera_pivot = NodePath("CameraFocus")
|
||||
position_field = NodePath("Position")
|
||||
position_x = NodePath("Position/x")
|
||||
position_y = NodePath("Position/y")
|
||||
position_z = NodePath("Position/z")
|
||||
x_field = NodePath("Position/x")
|
||||
y_field = NodePath("Position/y")
|
||||
z_field = NodePath("Position/z")
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
class_name FlowNode
|
||||
class_name FlowNodeVisualiser
|
||||
extends StaticBody3D
|
||||
|
||||
@export var connections: Array[FlowNode]
|
||||
@export var visualisers: Array[Node3D]
|
||||
@export var traversable: bool = true
|
||||
@export var buildable: bool = true
|
||||
|
||||
var data: FlowNodeData
|
||||
var connections: Array[FlowNodeVisualiser]
|
||||
var visualisers: Array[Node3D]
|
||||
var visual_scene: PackedScene = preload("res://Scenes/FlowField/cube2.tscn")
|
||||
var node_id: int = 0
|
||||
var grid_id: int = -1
|
||||
var grid_x: int = 0
|
||||
var grid_y: int = 0
|
||||
var best_path: FlowNode :
|
||||
var best_path: FlowNodeVisualiser :
|
||||
get():
|
||||
return best_path
|
||||
set(value):
|
||||
@@ -20,9 +14,9 @@ var best_path: FlowNode :
|
||||
set_connector_color(best_path, Color.DARK_GREEN)
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
func setup_connection_visualisers() -> void:
|
||||
visualisers = []
|
||||
for node: FlowNode in connections:
|
||||
for node: FlowNodeVisualiser in connections:
|
||||
var visual: Node3D = visual_scene.instantiate()
|
||||
add_child(visual)
|
||||
visual.owner = self
|
||||
@@ -45,13 +39,13 @@ func set_color(new_color: Color) -> void:
|
||||
$flow_node/Sphere.material_override.albedo_color = new_color
|
||||
|
||||
|
||||
func set_connector_color(node: FlowNode, new_color: Color) -> void:
|
||||
func set_connector_color(node: FlowNodeVisualiser, new_color: Color) -> void:
|
||||
if visible:
|
||||
var i: int = connections.find(node)
|
||||
visualisers[i].get_child(0).material_override.albedo_color = new_color
|
||||
|
||||
|
||||
func add_connection(node: FlowNode) -> void:
|
||||
func add_connection(node: FlowNodeVisualiser) -> void:
|
||||
if !connections.has(node):
|
||||
var visual: Node3D = visual_scene.instantiate()
|
||||
add_child(visual)
|
||||
@@ -61,7 +55,7 @@ func add_connection(node: FlowNode) -> void:
|
||||
set_connector_color(node, Color.WEB_GRAY)
|
||||
|
||||
|
||||
func remove_connection(node: FlowNode) -> void:
|
||||
func remove_connection(node: FlowNodeVisualiser) -> void:
|
||||
if connections.has(node):
|
||||
var i: int = connections.find(node)
|
||||
visualisers.pop_at(i).queue_free()
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
class_name FlowNodeData
|
||||
extends Resource
|
||||
extends RefCounted
|
||||
|
||||
enum NodeType {
|
||||
STANDARD = 0,
|
||||
START = 1,
|
||||
GOAL = 2,
|
||||
OBSTACLE = 3,
|
||||
}
|
||||
|
||||
@export var node_id: int = -1
|
||||
@export var position: Vector3 = Vector3.ZERO
|
||||
@export var type: NodeType = NodeType.STANDARD
|
||||
@export var buildable: bool = true
|
||||
@export var connected_nodes: Array[FlowNodeData]
|
||||
@export var in_grid: bool = false
|
||||
@export var grid_id: int = -1
|
||||
@export var grid_x: int = 0
|
||||
@export var grid_y: int = 0
|
||||
|
||||
var node_id: int = -1
|
||||
var position: Vector3 = Vector3.ZERO
|
||||
var type: NodeType = NodeType.STANDARD
|
||||
var buildable: bool = true
|
||||
var traversable: bool = true
|
||||
var connected_nodes: Array[FlowNodeData]
|
||||
var best_path: FlowNodeData
|
||||
var in_grid: bool = false
|
||||
var grid_id: int = -1
|
||||
var grid_x: int = 0
|
||||
var grid_y: int = 0
|
||||
|
||||
|
||||
#This function cannot fill in the connection information until a complete set
|
||||
@@ -32,6 +36,10 @@ static func from_dict(dict: Dictionary) -> FlowNodeData:
|
||||
data.grid_id = dict["grid_id"]
|
||||
data.grid_x = dict["grid_x"]
|
||||
data.grid_y = dict["grid_y"]
|
||||
|
||||
if data.type == NodeType.OBSTACLE:
|
||||
data.buildable = false
|
||||
data.traversable = false
|
||||
return data
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ class_name TowerBase extends StaticBody3D
|
||||
|
||||
var game_manager: GameManager
|
||||
var owner_id: int
|
||||
var point: FlowNode
|
||||
var point: FlowNodeData
|
||||
var tower: Tower = null
|
||||
var has_card: bool :
|
||||
set(_value):
|
||||
|
||||
@@ -138,7 +138,7 @@ func _physics_process(delta: float) -> void:
|
||||
|
||||
|
||||
func consider_leap(direction: Vector3) -> void:
|
||||
var node: FlowNode = check_jump(character.global_position + (direction * jump_distance))
|
||||
var node: FlowNodeData = check_jump(character.global_position + (direction * jump_distance))
|
||||
if node:
|
||||
var expected_distance_remaining: float = calculate_distance_to_goal(node)
|
||||
expected_distance_remaining += (character.global_position + (direction * jump_distance)).distance_to(node.global_position)
|
||||
@@ -153,8 +153,8 @@ func finish_jump() -> void:
|
||||
jumping = false
|
||||
|
||||
|
||||
func check_jump(destination: Vector3) -> FlowNode:
|
||||
var closest_point: FlowNode = flow_field.get_closest_traversable_point(destination)
|
||||
func check_jump(destination: Vector3) -> FlowNodeData:
|
||||
var closest_point: FlowNodeData = flow_field.get_closest_point(destination, true, false)
|
||||
if !closest_point.best_path or closest_point.global_position.distance_to(destination) > 1.2:
|
||||
return null
|
||||
return closest_point.best_path
|
||||
|
||||
@@ -4,7 +4,7 @@ extends EnemyMovement
|
||||
#var path: Curve3D
|
||||
#var path_progress: float = 0.0
|
||||
var flow_field: FlowField
|
||||
var next_node: FlowNode :
|
||||
var next_node: FlowNodeData :
|
||||
get():
|
||||
return next_node
|
||||
set(value):
|
||||
@@ -16,16 +16,16 @@ var next_node: FlowNode :
|
||||
#TODO: make deterministic random
|
||||
var x: float = randf_range(-1, 1)
|
||||
var y: float = randf_range(-1, 1)
|
||||
if Vector3(next_node.global_position.x + x, next_node.global_position.y, next_node.global_position.z + y).distance_to(next_node.global_position) <= 1.0:
|
||||
if Vector3(next_node.position.x + x, next_node.position.y, next_node.position.z + y).distance_to(next_node.position) <= 1.0:
|
||||
found_point = true
|
||||
next_pos = Vector3(next_node.global_position.x + x, next_node.global_position.y, next_node.global_position.z + y)
|
||||
next_pos = Vector3(next_node.position.x + x, next_node.position.y, next_node.position.z + y)
|
||||
var next_pos: Vector3
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
super._ready()
|
||||
if flow_field:
|
||||
next_node = flow_field.get_closest_traversable_point(character.global_position)
|
||||
next_node = flow_field.get_closest_point(character.global_position, true, false)
|
||||
#We skip one node so the "start" nodes placed near
|
||||
#spawners are just usefull for "catching" enemies that are looking
|
||||
#for a way into the pathfinding graph
|
||||
@@ -33,14 +33,14 @@ func _ready() -> void:
|
||||
distance_remaining += calculate_distance_to_goal(next_node)
|
||||
|
||||
|
||||
func calculate_distance_to_goal(node: FlowNode) -> float:
|
||||
func calculate_distance_to_goal(node: FlowNodeData) -> float:
|
||||
var distance: float = 0.0
|
||||
distance += character.global_position.distance_to(node.global_position)
|
||||
distance += character.global_position.distance_to(node.position)
|
||||
if node.best_path:
|
||||
var then_next_node: FlowNode = node.best_path
|
||||
distance += node.global_position.distance_to(then_next_node.global_position)
|
||||
var then_next_node: FlowNodeData = node.best_path
|
||||
distance += node.position.distance_to(then_next_node.position)
|
||||
while then_next_node.best_path:
|
||||
distance += then_next_node.global_position.distance_to(then_next_node.best_path.global_position)
|
||||
distance += then_next_node.position.distance_to(then_next_node.best_path.position)
|
||||
then_next_node = then_next_node.best_path
|
||||
return distance
|
||||
|
||||
|
||||
@@ -21,9 +21,8 @@ var enemies_spawned: Dictionary = {}
|
||||
var enemies_to_spawn: int = 0
|
||||
var done_spawning: bool = true
|
||||
var enemy_id: int = 0
|
||||
var path: Path3D
|
||||
var path_polygon: PackedScene = preload("res://path_polygon.tscn")
|
||||
var game_manager: GameManager
|
||||
var path_vfx: PathVFX
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
@@ -84,27 +83,27 @@ func networked_spawn_land_enemy(enemy_num: int, id1: int, id2: int) -> void:
|
||||
func create_path() -> void:
|
||||
if type != Data.EnemyType.LAND:
|
||||
return
|
||||
path = Path3D.new()
|
||||
path.curve = Curve3D.new()
|
||||
add_child(path)
|
||||
var polygon: CSGPolygon3D = path_polygon.instantiate()
|
||||
path.add_child(polygon)
|
||||
polygon.mode = CSGPolygon3D.MODE_PATH
|
||||
polygon.path_node = path.get_path()
|
||||
path.global_position = Vector3.ZERO
|
||||
if path_vfx:
|
||||
path_vfx.queue_free()
|
||||
path_vfx = PathVFX.new()
|
||||
path_vfx.line_width = 0.2
|
||||
path_vfx.material = load("res://path_material.tres")
|
||||
add_child(path_vfx)
|
||||
path_vfx.global_position = Vector3.ZERO
|
||||
update_path()
|
||||
|
||||
|
||||
|
||||
func update_path() -> void:
|
||||
if type != Data.EnemyType.LAND or !flow_field.nodes:
|
||||
if type != Data.EnemyType.LAND or !flow_field.data.nodes:
|
||||
return
|
||||
path.curve = Curve3D.new()
|
||||
var node: FlowNode = flow_field.get_closest_traversable_point(global_position)
|
||||
path.curve.add_point(node.global_position + Vector3(0, 0.5, 0))
|
||||
var points: Array[Vector3] = []
|
||||
var node: FlowNodeData = flow_field.get_closest_point(flow_field.start_nodes[0].position, true, false)
|
||||
points.append(node.position + Vector3(0, 0.15, 0))
|
||||
while node.best_path:
|
||||
node = node.best_path
|
||||
path.curve.add_point(node.global_position + Vector3(0, 0.5, 0))
|
||||
points.append(node.position + Vector3(0, 0.15, 0))
|
||||
path_vfx.path(points)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ func spawn_level(scene: PackedScene) -> void:
|
||||
var flow_field: FlowField = FlowField.new()
|
||||
level.flow_field = flow_field
|
||||
level.add_child(flow_field)
|
||||
flow_field.load_from_data(FlowFieldTool.load_flow_field_from_disc(level_config.zone.flow_field_data_path))
|
||||
flow_field.data = FlowFieldTool.load_flow_field_from_disc(level_config.zone.flow_field_data_path)
|
||||
level.load_flow_field()
|
||||
level.game_manager = self
|
||||
for x: EnemySpawner in level.enemy_spawns:
|
||||
@@ -121,7 +121,7 @@ func spawn_level(scene: PackedScene) -> void:
|
||||
root_scene.add_child(level)
|
||||
for spawner: EnemySpawner in level.enemy_spawns:
|
||||
spawner.create_path()
|
||||
level.generate_obstacle(level_config.points_blocked)
|
||||
level.generate_obstacles(level_config.points_blocked)
|
||||
|
||||
|
||||
func spawn_players() -> void:
|
||||
@@ -214,7 +214,9 @@ func temp_set_upcoming_wave(new_wave: WaveConfig, coins: int) -> void:
|
||||
pot = coins
|
||||
var dict: Dictionary[String, int] = {}
|
||||
for enemy_group: EnemyGroup in new_wave.enemy_groups.keys():
|
||||
dict[enemy_group.enemy.title] = enemy_group.count
|
||||
if !dict.has(enemy_group.enemy.title):
|
||||
dict[enemy_group.enemy.title] = 0
|
||||
dict[enemy_group.enemy.title] += enemy_group.count
|
||||
connected_players_nodes[multiplayer.get_unique_id()].hud.set_upcoming_wave(dict)
|
||||
|
||||
|
||||
@@ -351,7 +353,6 @@ func start() -> void:
|
||||
set_upcoming_wave()
|
||||
level.flow_field.calculate()
|
||||
level.enemy_spawns[0].update_path()
|
||||
level.generate_obstacles()
|
||||
|
||||
#Start game
|
||||
game_active = true
|
||||
|
||||
@@ -11,22 +11,22 @@ extends Node3D
|
||||
@export var printer: CardPrinter
|
||||
@export var shop: ShopStand
|
||||
@export var obstacles: Array[PackedScene]
|
||||
var walls: Dictionary[FlowNode, TowerBase] = {}
|
||||
|
||||
var walls: Dictionary[FlowNodeData, TowerBase] = {}
|
||||
var wall_id: int = 0
|
||||
var tower_base_scene: PackedScene = load("res://Scenes/TowerBase/tower_base.tscn")
|
||||
var tower_frame_scene: PackedScene = load("res://Scenes/tower_frame.tscn")
|
||||
var tower_frames: Dictionary[FlowNode, Node3D] = {}
|
||||
var tower_frames: Dictionary[FlowNodeData, Node3D] = {}
|
||||
var game_manager: GameManager
|
||||
var flow_field: FlowField
|
||||
|
||||
|
||||
func load_flow_field() -> void:
|
||||
var x: int = 0
|
||||
for spawn: EnemySpawner in enemy_spawns:
|
||||
flow_field.path_updated.connect(spawn.update_path)
|
||||
for node: FlowNode in flow_field.nodes:
|
||||
|
||||
for node: FlowNodeData in flow_field.data.nodes:
|
||||
if node.buildable:
|
||||
x += 1
|
||||
var frame: Node3D = tower_frame_scene.instantiate()
|
||||
tower_frames[node] = frame
|
||||
add_child(frame)
|
||||
@@ -34,23 +34,23 @@ func load_flow_field() -> void:
|
||||
|
||||
|
||||
func disable_all_tower_frames() -> void:
|
||||
for node: FlowNode in tower_frames:
|
||||
for node: FlowNodeData in tower_frames:
|
||||
tower_frames[node].visible = false
|
||||
|
||||
|
||||
func enable_non_path_tower_frames() -> void:
|
||||
for node: FlowNode in tower_frames:
|
||||
for node: FlowNodeData in tower_frames:
|
||||
tower_frames[node].visible = true
|
||||
disable_path_tower_frames()
|
||||
|
||||
|
||||
func disable_path_tower_frames() -> void:
|
||||
for node: FlowNode in tower_frames:
|
||||
for node: FlowNodeData in tower_frames:
|
||||
if node.traversable and !flow_field.traversable_after_blocking_point(node):
|
||||
tower_frames[node].visible = false
|
||||
|
||||
|
||||
func set_wall(point: FlowNode, caller_id: int) -> void:
|
||||
func set_wall(point: FlowNodeData, caller_id: int) -> void:
|
||||
point.traversable = false
|
||||
flow_field.calculate()
|
||||
flow_field.path_updated.emit()
|
||||
@@ -59,7 +59,7 @@ func set_wall(point: FlowNode, caller_id: int) -> void:
|
||||
wall_id += 1
|
||||
|
||||
|
||||
func remove_wall(point: FlowNode) -> void:
|
||||
func remove_wall(point: FlowNodeData) -> void:
|
||||
var wall: TowerBase = walls[point]
|
||||
#game_manager.connected_players_nodes[wall.owner_id].currency += Data.wall_cost
|
||||
game_manager.connected_players_nodes[wall.owner_id].unready_self()
|
||||
@@ -71,10 +71,10 @@ func remove_wall(point: FlowNode) -> void:
|
||||
enable_non_path_tower_frames()
|
||||
|
||||
|
||||
func spawn_wall(point: FlowNode, name_id: int, caller_id: int) -> void:
|
||||
func spawn_wall(point: FlowNodeData, name_id: int, caller_id: int) -> void:
|
||||
var base: TowerBase = tower_base_scene.instantiate() as TowerBase
|
||||
base.game_manager = game_manager
|
||||
base.position = point.global_position
|
||||
base.position = point.position
|
||||
base.name = "Wall" + str(name_id)
|
||||
base.owner_id = caller_id
|
||||
base.point = point
|
||||
@@ -83,59 +83,15 @@ func spawn_wall(point: FlowNode, name_id: int, caller_id: int) -> void:
|
||||
disable_path_tower_frames()
|
||||
|
||||
|
||||
func generate_obstacle(ids: Array[int]) -> void:
|
||||
var points: Array[FlowNode] = []
|
||||
for node: FlowNode in flow_field.nodes:
|
||||
func generate_obstacles(ids: Array[int]) -> void:
|
||||
var points: Array[FlowNodeData] = []
|
||||
for node: FlowNodeData in flow_field.data.nodes:
|
||||
if ids.has(node.node_id):
|
||||
points.append(node)
|
||||
for node: FlowNode in points:
|
||||
for node: FlowNodeData in points:
|
||||
var obstacle: Node3D = obstacles[0].instantiate()
|
||||
obstacle.position = node.position
|
||||
flow_field.toggle_buildable(node)
|
||||
if node.traversable:
|
||||
flow_field.toggle_traversable(node)
|
||||
add_child(obstacle)
|
||||
|
||||
|
||||
func generate_obstacles() -> void:
|
||||
pass
|
||||
#print(str(multiplayer.get_unique_id()) + " spawning obstacles with seed: " + str(Game.rng.seed))
|
||||
#var obstacle_count: int = NoiseRandom.randi_in_range(1, 0, 5)
|
||||
#obstacle_count = 0
|
||||
# for index: int in obstacle_count:
|
||||
# #var x: int = Game.randi_in_range(10 * index, 1 - a_star_graph_3d.grid_size.x, a_star_graph_3d.grid_size.x - 1)
|
||||
#var y: int = Game.randi_in_range(32 * index, 1 - a_star_graph_3d.grid_size.y, a_star_graph_3d.grid_size.y - 1)
|
||||
# var chosen_obstacle: int = Game.randi_in_range(4 * index, 0, obstacle_scenes.size() - 1)
|
||||
# var obstacle: GridMap = obstacle_scenes[chosen_obstacle].instantiate() as GridMap
|
||||
# var orientations: Array[int] = [0, 90, 180, 270]
|
||||
# var chosen_orientation: int = Game.randi_in_range(15 * index, 0, orientations.size() - 1)
|
||||
# #obstacle.position = Vector3(x, 0, y)
|
||||
# obstacle.set_rotation_degrees(Vector3(0, chosen_orientation, 0))
|
||||
# add_child(obstacle)
|
||||
# for cell: Vector3i in obstacle.get_used_cells():
|
||||
# var cell_coord: Vector3 = obstacle.to_global(obstacle.map_to_local(cell))
|
||||
# remove_world_tile(round(cell_coord.x), round(cell_coord.z))
|
||||
# obstacle.queue_free()
|
||||
|
||||
|
||||
#func cell_coord_to_astar_point(x: int, y: int) -> int:
|
||||
# var center_point_x: int = floori(a_star_graph_3d.grid_size.x / 2.0) * a_star_graph_3d.grid_size.y
|
||||
# var center_point_y: int = floori(a_star_graph_3d.grid_size.y / 2.0)
|
||||
# return (center_point_x + (int(x / 2.0) * a_star_graph_3d.grid_size.y)) + (center_point_y + int(y / 2.0))
|
||||
|
||||
|
||||
#func remove_world_tile(x: int, y: int) -> void:
|
||||
# if get_cell_item(Vector3i(x, 0, y)) != 1 or abs(x) >= a_star_graph_3d.grid_size.x or abs(y) >= a_star_graph_3d.grid_size.y:
|
||||
# return
|
||||
# set_cell_item(Vector3i(x, 0, y), INVALID_CELL_ITEM)
|
||||
# var point: int = cell_coord_to_astar_point(x, y)
|
||||
# var north_point: int = cell_coord_to_astar_point(x - 1, y)
|
||||
# var south_point: int = cell_coord_to_astar_point(x + 1, y)
|
||||
# var east_point: int = cell_coord_to_astar_point(x, y + 1)
|
||||
# var west_point: int = cell_coord_to_astar_point(x, y - 1)
|
||||
# if x % 2 == 0 and y % 2 == 0: #If the tile is on a point on the pathfinding grid
|
||||
# a_star_graph_3d.astar.set_point_disabled(point)
|
||||
# if x % 2 == 1 and y % 2 == 0: #If the cell breaks a north-south link
|
||||
# a_star_graph_3d.astar.disconnect_points(north_point, south_point)
|
||||
# if x % 2 == 0 and y % 2 == 1: #If the cell breaks a east-west link
|
||||
# a_star_graph_3d.astar.disconnect_points(east_point, west_point)
|
||||
|
||||
@@ -52,7 +52,8 @@ static func generate_wave(spawn_power: int, spawn_pool: Array[Enemy], spawners:
|
||||
var first_enemy_id: int = -1
|
||||
while !enemy_chosen:
|
||||
#Next, determine what is the most groups we can afford
|
||||
most_enemies_afforded = int(spawn_power / enemy.spawn_power)
|
||||
@warning_ignore("integer_division")
|
||||
most_enemies_afforded = spawn_power / enemy.spawn_power
|
||||
if most_enemies_afforded > 0:
|
||||
enemy_chosen = true
|
||||
else:
|
||||
|
||||
BIN
Sprite-0001.png
Normal file
BIN
Sprite-0001.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 549 B |
40
Sprite-0001.png.import
Normal file
40
Sprite-0001.png.import
Normal file
@@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c4ens2cmrmfxq"
|
||||
path="res://.godot/imported/Sprite-0001.png-7647bf9f8b536d839277d4b64aee9852.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Sprite-0001.png"
|
||||
dest_files=["res://.godot/imported/Sprite-0001.png-7647bf9f8b536d839277d4b64aee9852.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
BIN
Sprite-0002.png
Normal file
BIN
Sprite-0002.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 272 B |
41
Sprite-0002.png.import
Normal file
41
Sprite-0002.png.import
Normal file
@@ -0,0 +1,41 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://vegv8grg30ka"
|
||||
path.s3tc="res://.godot/imported/Sprite-0002.png-be2d0c11222c1eca468919d34832f25a.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Sprite-0002.png"
|
||||
dest_files=["res://.godot/imported/Sprite-0002.png-be2d0c11222c1eca468919d34832f25a.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
12
path_material.tres
Normal file
12
path_material.tres
Normal file
@@ -0,0 +1,12 @@
|
||||
[gd_resource type="ShaderMaterial" format=3 uid="uid://bqn48u5unlnmj"]
|
||||
|
||||
[ext_resource type="Shader" uid="uid://dq04j2s5foo2f" path="res://Shaders/mightyduke_ps1.gdshader" id="1_txk5a"]
|
||||
[ext_resource type="Texture2D" uid="uid://c23wkr8t41qmw" path="res://red.png" id="2_txk5a"]
|
||||
|
||||
[resource]
|
||||
render_priority = 0
|
||||
shader = ExtResource("1_txk5a")
|
||||
shader_parameter/albedo = ExtResource("2_txk5a")
|
||||
shader_parameter/jitter_z_coordinate = true
|
||||
shader_parameter/jitter_depth_independent = true
|
||||
shader_parameter/alpha_scissor = 1.0
|
||||
163
path_vfx.gd
Normal file
163
path_vfx.gd
Normal file
@@ -0,0 +1,163 @@
|
||||
class_name PathVFX
|
||||
extends MeshInstance3D
|
||||
|
||||
@export var line_width: float
|
||||
@export var material: Material
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
var test_points: Array[Vector3] = []
|
||||
test_points.append(Vector3(5, 1, 1))
|
||||
test_points.append(Vector3(1, 1, 1))
|
||||
test_points.append(Vector3(1, 1, 5))
|
||||
path(test_points)
|
||||
|
||||
|
||||
func path(path_points: Array[Vector3]) -> void:
|
||||
if path_points.size() < 2:
|
||||
return
|
||||
#Add vertices
|
||||
var vertices: PackedVector3Array = PackedVector3Array()
|
||||
|
||||
for x: int in path_points.size() - 1:
|
||||
if x > 0:
|
||||
if path_points.size() > x + 2:
|
||||
vertices.append_array(get_quad(path_points[x], path_points[x + 1], path_points[x - 1], path_points[x + 2]))
|
||||
else:
|
||||
vertices.append_array(get_quad(path_points[x], path_points[x + 1], path_points[x - 1], Vector3.ZERO))
|
||||
if x == 0:
|
||||
if path_points.size() > 2:
|
||||
vertices.append_array(get_quad(path_points[x], path_points[x + 1], Vector3.ZERO, path_points[x + 2]))
|
||||
else:
|
||||
print("go1")
|
||||
vertices.append_array(get_quad(path_points[x], path_points[x + 1], Vector3.ZERO, Vector3.ZERO))
|
||||
|
||||
#Add UVs
|
||||
var uvs: PackedVector2Array = PackedVector2Array()
|
||||
|
||||
for i: int in path_points.size() - 1:
|
||||
uvs.append(Vector2(1, float(i) / (path_points.size() - 1)))
|
||||
uvs.append(Vector2(0, float(i + 1) / (path_points.size() - 1)))
|
||||
uvs.append(Vector2(1, float(i + 1) / (path_points.size() - 1)))
|
||||
|
||||
uvs.append(Vector2(0, float(i + 1) / path_points.size() - 1))
|
||||
uvs.append(Vector2(1, float(i) / path_points.size() - 1))
|
||||
uvs.append(Vector2(0, float(i) / path_points.size() - 1))
|
||||
#print(float(i) / path_points.size() - 1)
|
||||
|
||||
#var prev_distance: float = 0
|
||||
#var scaler: float = 0.4
|
||||
#
|
||||
#for i: int in path_points.size() - 1:
|
||||
#var distance: float = path_points[i].distance_to(path_points[i + 1])
|
||||
#var next_distance: float = prev_distance + distance
|
||||
#uvs.append(Vector2(1, prev_distance * scaler))
|
||||
#uvs.append(Vector2(0, next_distance * scaler))
|
||||
#uvs.append(Vector2(1, next_distance * scaler))
|
||||
#
|
||||
#uvs.append(Vector2(0, next_distance * scaler))
|
||||
#uvs.append(Vector2(1, prev_distance * scaler))
|
||||
#uvs.append(Vector2(0, prev_distance * scaler))
|
||||
##print(float(i) / path_points.size() - 1)
|
||||
#prev_distance = distance
|
||||
|
||||
#Initialize the ArrayMesh
|
||||
var arr_mesh: ArrayMesh = ArrayMesh.new()
|
||||
var arrays: Array = []
|
||||
arrays.resize(Mesh.ARRAY_MAX)
|
||||
arrays[Mesh.ARRAY_VERTEX] = vertices
|
||||
arrays[Mesh.ARRAY_TEX_UV] = uvs
|
||||
|
||||
#Create the Mesh
|
||||
arr_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays)
|
||||
arr_mesh.surface_set_material(arr_mesh.get_surface_count() - 1, material)
|
||||
mesh = arr_mesh
|
||||
|
||||
|
||||
func get_edge(pos: Vector3, direction1: Vector2, direction2: Vector2) -> Array[Vector3]:
|
||||
var verts: Array[Vector3] = []
|
||||
|
||||
var ortho1: Vector2 = Vector2(-direction1.y, direction1.x).normalized()
|
||||
var ortho2: Vector2 = Vector2(direction2.y, -direction2.x).normalized()
|
||||
|
||||
var top_sample1: Vector3 = pos - (Vector3(ortho1.x, 0.0, ortho1.y) * line_width)
|
||||
var top_sample2: Vector3 = pos - (Vector3(ortho2.x, 0.0, ortho2.y) * line_width)
|
||||
|
||||
var bottom_sample1: Vector3 = pos + (Vector3(ortho1.x, 0.0, ortho1.y) * line_width)
|
||||
var bottom_sample2: Vector3 = pos + (Vector3(ortho2.x, 0.0, ortho2.y) * line_width)
|
||||
|
||||
var top: Vector3 = top_sample1 + ((top_sample2 - top_sample1) * 0.5)
|
||||
var bottom: Vector3 = bottom_sample1 + ((bottom_sample2 - bottom_sample1) * 0.5)
|
||||
|
||||
var top_dir: Vector3 = (pos - top).normalized()
|
||||
var bottom_dir: Vector3 = (pos - bottom).normalized()
|
||||
|
||||
verts.append(pos + (top_dir * line_width))
|
||||
verts.append(pos + (bottom_dir * line_width))
|
||||
|
||||
#verts.append(top)
|
||||
#verts.append(bottom)
|
||||
|
||||
return verts
|
||||
|
||||
|
||||
func get_quad(start_point: Vector3, end_point: Vector3, head_point: Vector3, tail_point: Vector3) -> Array[Vector3]:
|
||||
var verts: Array[Vector3] = []
|
||||
|
||||
var head_to_start: Vector2
|
||||
if head_point != Vector3.ZERO:
|
||||
head_to_start = Vector2(start_point.x, start_point.z) - Vector2(head_point.x, head_point.z)
|
||||
var start_to_end: Vector2 = Vector2(end_point.x, end_point.z) - Vector2(start_point.x, start_point.z)
|
||||
var end_to_start: Vector2 = Vector2(start_point.x, start_point.z) - Vector2(end_point.x, end_point.z)
|
||||
var end_to_tail: Vector2
|
||||
if tail_point != Vector3.ZERO:
|
||||
end_to_tail = Vector2(tail_point.x, tail_point.z) - Vector2(end_point.x, end_point.z)
|
||||
|
||||
var first_edge: Array[Vector3] = []
|
||||
if head_point != Vector3.ZERO:
|
||||
first_edge.append_array(get_edge(start_point, -head_to_start, start_to_end))
|
||||
else:
|
||||
first_edge.append_array(get_edge(start_point, Vector2.ZERO, start_to_end))
|
||||
|
||||
var second_edge: Array[Vector3] = []
|
||||
if tail_point != Vector3.ZERO:
|
||||
second_edge.append_array(get_edge(end_point, start_to_end, -end_to_tail))
|
||||
else:
|
||||
second_edge.append_array(get_edge(end_point, start_to_end, Vector2.ZERO))
|
||||
|
||||
|
||||
verts.append(first_edge[1])
|
||||
verts.append(second_edge[1])
|
||||
verts.append(second_edge[0])
|
||||
|
||||
verts.append(second_edge[1])
|
||||
verts.append(first_edge[1])
|
||||
verts.append(first_edge[0])
|
||||
|
||||
#verts.append(first_edge[0])
|
||||
#verts.append(first_edge[1])
|
||||
#verts.append(second_edge[0])
|
||||
|
||||
#verts.append(first_edge[0])
|
||||
#verts.append(second_edge[1])
|
||||
#verts.append(first_edge[1])
|
||||
|
||||
#verts.append(first_edge[0])
|
||||
#verts.append(second_edge[0])
|
||||
#verts.append(second_edge[1])
|
||||
|
||||
#var top_left: Vector3 = start_point - (orthovec3 * line_width)
|
||||
#var bottom_left: Vector3 = start_point + (orthovec3 * line_width)
|
||||
#var top_right: Vector3 = end_point - (orthovec3 * line_width)
|
||||
#var bottom_right: Vector3 = end_point + (orthovec3 * line_width)
|
||||
|
||||
|
||||
#verts.append(top_left)
|
||||
#verts.append(bottom_right)
|
||||
#verts.append(bottom_left)
|
||||
#verts.append(top_left)
|
||||
#verts.append(top_right)
|
||||
#verts.append(bottom_right)
|
||||
|
||||
#print(verts)
|
||||
return verts
|
||||
1
path_vfx.gd.uid
Normal file
1
path_vfx.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ca8u5ji004qkp
|
||||
35
path_vfx.tscn
Normal file
35
path_vfx.tscn
Normal file
@@ -0,0 +1,35 @@
|
||||
[gd_scene format=3 uid="uid://dywi5lu2c7y0f"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://ca8u5ji004qkp" path="res://path_vfx.gd" id="1_npwh2"]
|
||||
[ext_resource type="Material" uid="uid://bqn48u5unlnmj" path="res://path_material.tres" id="2_avv77"]
|
||||
|
||||
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_avv77"]
|
||||
sky_horizon_color = Color(0.66224277, 0.6717428, 0.6867428, 1)
|
||||
ground_horizon_color = Color(0.66224277, 0.6717428, 0.6867428, 1)
|
||||
|
||||
[sub_resource type="Sky" id="Sky_a4eki"]
|
||||
sky_material = SubResource("ProceduralSkyMaterial_avv77")
|
||||
|
||||
[sub_resource type="Environment" id="Environment_2hybw"]
|
||||
background_mode = 2
|
||||
sky = SubResource("Sky_a4eki")
|
||||
tonemap_mode = 2
|
||||
glow_enabled = true
|
||||
|
||||
[node name="Node3D" type="MeshInstance3D" unique_id=401062502]
|
||||
script = ExtResource("1_npwh2")
|
||||
line_width = 0.4
|
||||
material = ExtResource("2_avv77")
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=336386562]
|
||||
environment = SubResource("Environment_2hybw")
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="." unique_id=365896800]
|
||||
transform = Transform3D(-0.8660254, -0.43301278, 0.25, 0, 0.49999997, 0.86602545, -0.50000006, 0.75, -0.43301266, 0, 0, 0)
|
||||
shadow_enabled = true
|
||||
directional_shadow_max_distance = 1.0
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="." unique_id=2114620631]
|
||||
transform = Transform3D(1, 0, 0, 0, -4.371139e-08, 1, 0, -1, -4.371139e-08, 1.4980783, 1.4475169, 1.9058113)
|
||||
projection = 1
|
||||
size = 8.752
|
||||
41
red.png.import
Normal file
41
red.png.import
Normal file
@@ -0,0 +1,41 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c23wkr8t41qmw"
|
||||
path.s3tc="res://.godot/imported/red.png-13f6abb0e0c70056504666ed9c349d99.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://red.png"
|
||||
dest_files=["res://.godot/imported/red.png-13f6abb0e0c70056504666ed9c349d99.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
Reference in New Issue
Block a user