@tool class_name MagicCircle extends Node2D @export var base_rad : float = 20; @export var layer_rad_inc : float = 1.1; @export var layers : int = 10 @export var vis_layers : float = 10.0 @export var main_color : Color = Color(1, 1, 1, 1) @export var fixed_seed : int = 1234; @export var squish : float = 0.7 @export var rot_speed : float = 0.1; @export var line_width : float = 0.6 var runes : Texture2D = load("res://assets/vfx/runes.png"); var rot = 0; var time = 0; func _process(_delta): queue_redraw() # absloute angle, NO rot func _draw_arc(radius, start_angle, end_angle, color, segments=10): var segment_size : float = (end_angle - start_angle) / segments var last_pos = Vector2(cos(start_angle), sin(start_angle)) * radius for i in range(segments+1): var angle = start_angle + (i * segment_size) var next_pos = Vector2(cos(angle), sin(angle)) * radius draw_line(last_pos, next_pos, color, line_width) last_pos = next_pos # yes rot func _draw_circle(radius, small_circles, small_radius, color, segments = 50): if (small_circles == 0): _draw_arc(radius, 0, 2*PI, color, segments) return var arc_segments = segments / small_circles var arc_size = (2*PI) / small_circles # arc_length = angle * radius # angle = arc_length / radius var small_circle_angle = (small_radius / radius) for i in range(small_circles): var small_angle = i * arc_size; var start_angle = i * arc_size + small_circle_angle var end_angle = (i + 1) * arc_size - small_circle_angle _draw_arc(radius, start_angle, end_angle, color, arc_segments) var circle_pos = Vector2(cos(small_angle), sin(small_angle)) * radius draw_arc(circle_pos, small_radius, 0, 2*PI, 10, color, line_width) _draw_rand_rune(circle_pos, color) func _draw_text_circle(radius, rune_num, color, segments = 50): _draw_circle(radius + 10, 0, 0, color, segments) _draw_circle(radius - 10, 0, 0, color, segments) var rune_diff = (2 * PI) / rune_num for i in range(rune_num): var angle = i * rune_diff var pos = Vector2(cos(angle), sin(angle)) * radius _draw_rand_rune(pos, color) # yes rot func _draw_polygon(radius, segments, skip, color): var segment_angle = (2*PI) / segments var last_pos = Vector2(1, 0) * radius for i in range(segments +1): var angle = (i * skip) * segment_angle var next_pos = Vector2(cos(angle), sin(angle)) * radius draw_line(last_pos, next_pos, color, line_width) last_pos = next_pos func _draw_rand_rune(draw_pos, color): var pos = draw_pos pos.x -= 5;# pos.y -= 5 draw_texture_rect_region(runes, Rect2(pos.x, pos.y, 10, 10), Rect2(rand_r(0, 4) * 10, 0, 10, 10), color) # inclusive func rand_r(min_v, max_v): return randi() % (max_v - min_v + 1) + min_v func _draw(): seed(fixed_seed) for i in range(1, layers): var layer_type = randf(); var layer_counter = float(i) / layers # 0 - 1 var layer_inv_counter = 1 - layer_counter # 1 - 0 var layer_dir = -1 if rand_r(0, 1) else 1; var layer_rot_mult = rand_r(1, 12) * rot_speed * layer_dir var layer_rot = Time.get_ticks_msec() * layer_inv_counter * layer_rot_mult * 0.001; var layer_radius = i * pow(base_rad, layer_rad_inc) var layer_color = main_color layer_color.a = clamp(vis_layers - i, 0, 1) draw_set_transform(Vector2.ZERO, layer_rot, Vector2.ONE) if layer_type < 0.2: var small_circles = rand_r(0, 5) var small_radius = layer_radius * 0.1 _draw_circle(layer_radius, small_circles, small_radius, layer_color) elif layer_type < 0.7: var vertices = rand_r(5, 8) var skip = rand_r(1, 2) _draw_polygon(layer_radius, vertices, skip, layer_color) elif layer_type <= 1: var rune_num = round(4 + layer_counter * 32) _draw_text_circle(layer_radius, rune_num, layer_color) scale.y = squish