The_Dark_Side_of_Earth/vines_petals/vine.gd

147 lines
5.3 KiB
GDScript

class_name Vine extends Node2D
@export var petal_location : Vector2
@export var petal_offset : Vector2
@export var vine_locations : Array[Vector2]
@export var bud_resource : PackedScene
var img_path_inactive = "res://vines_petals/vine_inactive.png"
@export var img_path_active : String
const status_data = [
{
"name": "Slow",
"params" : {},
"img_path": "res://vines_petals/vine_active_green.png"
},
{
"name": "Vulnerable",
"params" : {},
"img_path": "res://vines_petals/vine_active_purple.png"
},]
var status_name : String
var status_params : Dictionary = {}
var active_depth = -1
var fully_active = false
var vine_data = []
var max_depth = 150
var vine_end_data = []
func _ready() -> void:
var data : Dictionary = status_data.pick_random()
status_name = data.name
status_params = data.params if data.has("params") else {}
img_path_active = data.img_path
func draw_vine(pos1 : Vector2, pos2 : Vector2, depth : int):
var sprite = Sprite2D.new()
get_tree().get_root().get_node("main").add_child(sprite)
if active_depth >= depth:
sprite.texture = ResourceLoader.load(img_path_active)
else:
sprite.texture = ResourceLoader.load(img_path_inactive)
while depth + 1 > vine_data.size():
vine_data.append([])
vine_data[depth].append(sprite)
sprite.position = (pos1 + pos2)/2.0
sprite.rotation = (pos1 - pos2).angle() + PI/2
sprite.scale *= (pos1 - pos2).length() * 1 / sprite.texture.get_width()
sprite.scale.x = 3
sprite.z_index = -1
func grow_vine_sequence(location1 : Vector2, offset1 : Vector2, location2: Vector2, offset2 : Vector2, num_segments: int, depth: int, grow_bud = false, quick_spawn = false):
depth = min(depth, max_depth)
var pos1 = Grid.get_world_position(location1, offset1)
var pos2 = Grid.get_world_position(location2, offset2)
var positions = []
positions.append(pos1)
var segment_length = (pos1 - pos2).length() / num_segments
var offsets = generate_random_offsets(num_segments, 0.6 * segment_length)
for i in range(num_segments - 1):
var t = (i + 1) * 1.0/num_segments
var center = t * pos2 + (1 - t) * pos1
var offset = offsets[i + 1] * (pos2 - pos1).normalized().rotated(PI/2)
positions.append(center + offset)
positions.append(pos2)
for i in range(num_segments):
draw_vine(positions[i], positions[i+1], depth + i + 1)
if not quick_spawn:
await get_tree().create_timer(0.2).timeout
if active_depth >= depth + num_segments:
if grow_bud and location2.y > 0 and location2.y <= Grid.max_bud_height:
spawn_bud(location2, offset2, depth + num_segments)
else:
if location2.y > 0 and location2.y <= Grid.max_bud_height:
for i in range(vine_end_data.size()):
if vine_end_data[i].location == location1:
vine_end_data.remove_at(i)
break
vine_end_data.append({"location": location2, "offset": offset2, "depth": depth+num_segments})
Grid.vines_per_node[location2.x][location2.y].append(self)
vine_locations.append(Global.vec_mod(location2, Grid.num_collumns))
func generate_random_offsets(segment_count, max_second_derivative):
var differences = []
var last_diff = 0
for i in range(segment_count):
var new_diff = last_diff + randf_range(-max_second_derivative, max_second_derivative)
differences.append(new_diff)
last_diff = new_diff
var sum = 0.0
for i in range(segment_count):
sum += differences[i]
var correction = - sum / segment_count
for i in range(segment_count):
differences[i] += correction
var ret = []
var next_val = 0
for i in range(segment_count):
ret.append(next_val)
next_val += differences[i]
return ret
func spawn_bud(location, offset, depth):
var bud = bud_resource.instantiate()
bud.location = location
bud.offset = offset
bud.vine = self
bud.depth = depth
get_tree().get_root().get_node("main").add_child(bud)
func activate():
update_active_depth()
func update_active_depth():
if active_depth < max_depth:
await get_tree().create_timer(0.15).timeout
active_depth += 1
if vine_data.size() > active_depth:
for sprite in vine_data[active_depth]:
sprite.texture = ResourceLoader.load(img_path_active)
for data in vine_end_data:
if data.depth == active_depth:
spawn_bud(data.location, data.offset, data.depth)
update_active_depth()
func init_random():
Grid.vines_per_node[petal_location.x][petal_location.y].append(self)
vine_locations.append(petal_location)
vine_end_data.append({"location": petal_location, "offset": petal_offset, "depth": 0})
for i in range(randi_range(2,2)):
var end = vine_end_data.pick_random()
var branches_count = 0
for branch in range(ceil(randf() * 4)):
var dir = [Vector2.UP, Vector2.DOWN, Vector2.RIGHT, Vector2.LEFT].pick_random()
var target = Global.vec_mod(end.location + dir, Grid.num_collumns)
if target.y <= Grid.max_bud_height + 1 and Grid.vines_per_node[target.x][target.y].is_empty():
if not (target.y <= 0 or target.y > Grid.max_bud_height):
branches_count += 1
var target_offset = random_offset()
var pos1 = Grid.get_world_position(end.location, end.offset)
var pos2 = Grid.get_world_position(target, target_offset)
var num_seg = floor((pos1-pos2).length() / 96)
grow_vine_sequence(end.location, end.offset, target, target_offset, num_seg, end.depth, true, true)
if i==0 and branches_count == 1:
vine_end_data.append({"location": petal_location, "offset": petal_offset, "depth": 0})
func random_offset():
return Vector2(randf_range(60, 240), randf_range(90, 270))