119 lines
3.8 KiB
GDScript
119 lines
3.8 KiB
GDScript
@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;
|
|
|
|
# Called when the node enters the scene tree for the first time.
|
|
func _ready():
|
|
pass # Replace with function body.
|
|
|
|
|
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
|
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(1, squish))
|
|
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)
|