netmasked/scripts/magic_circle.gd

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