How to recreate this game in godot.I will be happy for every ideas

Godot Version

3

I want to recreate this game https://neal.fun/perfect-circle/. Any ideas how to make it?
I made smth like this


but i want to stop it when it reaching the start point(where i start to draw or just want to be 1 circle).

Hi,
For the scoring, just save the closest and furthest point from the center of the circle and score the difference of distance.
To stop your circle to draw, save the start angle from the mouse to the center and check the current angle of the mouse. You stop when 360° is made. You can check every 10° to know if the player change direction.

Thanks good idea! I will try now

extends Line2D

var drawing = false
var custom_points = []
onready var score_label = get_node("/root/Game/Control/Score")  # Score label

var min_circle_points = 10  # Minimum number of points to consider a circle
var line_thickness = 10  # Initial line thickness
var start_angle = 0.0  # Start angle for circle drawing
var angle_covered = 0.0  # Total angle covered during drawing
var last_angle = 0.0  # Last angle position

func _ready():
	self.width = line_thickness  # Set the initial line thickness
	self.default_color = Color(1, 1, 1)  # Initial color for the drawing

func _input(event):
	if event is InputEventMouseButton:
		if event.button_index == BUTTON_LEFT and event.pressed:
			drawing = true
			custom_points = []  # Clear previous points
			start_angle = get_angle(event.position)  # Save the start angle
			angle_covered = 0.0  # Reset angle coverage
			last_angle = start_angle  # Initialize last angle
		elif event.button_index == BUTTON_LEFT and not event.pressed:
			drawing = false
			_on_draw_finished()

	if event is InputEventMouseMotion and drawing:
		custom_points.append(event.position)
		update()  # Request redraw
		_on_draw_in_progress()

func _draw():
	if custom_points.size() > 1:
		draw_polyline(custom_points, self.default_color, line_thickness)

func _on_draw_in_progress():
	# Update score dynamically during drawing
	var perfection_score = calculate_perfection()
	print("Circle Perfection Score: ", perfection_score)

	# Update score label with the perfection score
	score_label.text = str(perfection_score)

	# Change line color based on the perfection score
	self.default_color = calculate_color(perfection_score)

	# Check for angle coverage
	var current_angle = get_angle(get_global_mouse_position())
	var angle_diff = fmod(current_angle - last_angle + 360.0, 360.0)  # Difference from the last angle
	angle_covered += angle_diff
	last_angle = current_angle  # Update last angle for the next segment

	# Stop drawing if a full circle is covered
	if angle_covered >= 360.0:
		drawing = false
		_on_draw_finished()

func _on_draw_finished():
	if is_near_complete_circle():
		print("Completed a circle!")
		# Optional: You can reset the drawing state or disable further drawing
		custom_points = []  # Clear points or keep them based on your needs

func is_near_complete_circle():
	if custom_points.size() < min_circle_points:
		return false  # Not enough points to determine a complete circle

	# Calculate the center of the points
	var center = Vector2()
	for point in custom_points:
		center += point
	center /= custom_points.size()

	# Calculate the average radius (distance from center)
	var total_distance = 0.0
	for point in custom_points:
		total_distance += center.distance_to(point)
	var average_radius = total_distance / custom_points.size()

	# Calculate the deviation of each point from the average radius
	var max_deviation = 0.0
	for point in custom_points:
		var distance = center.distance_to(point)
		max_deviation = max(max_deviation, abs(distance - average_radius))

	# Check if the maximum deviation is within an acceptable range
	return max_deviation < 15  # Increase tolerance to better accommodate varying circle sizes

func calculate_perfection():
	if custom_points.size() < 3:
		return 0  # Not enough points to calculate perfection

	# Calculate the center of the drawn points
	var center = Vector2()
	for point in custom_points:
		center += point
	center /= custom_points.size()  # Average position becomes the center

	# Calculate the average radius (distance from center)
	var total_distance = 0.0
	for point in custom_points:
		total_distance += center.distance_to(point)
	var average_distance = total_distance / custom_points.size()

	# Calculate deviation from the average radius
	var deviation = 0.0
	for point in custom_points:
		deviation += abs(center.distance_to(point) - average_distance)
	var average_deviation = deviation / custom_points.size()

	# Calculate perfection score based on deviation (lower deviation is better)
	var perfection_score = max(0, min(100, 100 - average_deviation))  # Ensure the score is within 0-100 range
	return perfection_score

func calculate_color(perfection_score):
	# Interpolate between red and green based on perfection score
	var red = Color(1, 0, 0)  # Red color
	var green = Color(0, 1, 0)  # Green color

	# Interpolate based on perfection_score (0 = red, 100 = green)
	return red.linear_interpolate(green, perfection_score / 100.0)

func get_angle(position):
	# Calculate the angle between the center (0,0) and the given position
	return atan2(position.y, position.x) * 180 / PI  # Convert radians to degrees

i made this but now i cant draw normally


.

In your angle calculation, if you make a left-right while drawing, the angle_diff can be very hight (near 360). You need to keep the actual sign of the difference to apply this sign in the angle_diff. Something like this I suppose :

	var delta = current_angle - last_angle
	var angle_diff = fmod(delta + 360.0, 360.0)  # Difference from the last angle
	angle_covered += sign(delta) * angle_diff

Also you can check for the absolute value of the angle :
if abs(angle_covered) >= 360.0

1 Like

I will try now.Sadly the same

I made without 360 degrees but with start point and it worked but now there is another problem


At first you can see how its working but that problem is that if i start drawing like not circle shaped things and then go to the start point its looking like shit and i cant understand how to fix to not draw lines.

extends Line2D

var drawing = false
var custom_points = []
var start_point = Vector2()  # The point where the player starts drawing
var min_distance_to_close = 10.0  # Minimum distance to close the loop
var min_points_to_stop = 30  # Minimum points before considering to stop
var max_deviation_threshold = 15.0  # Maximum allowed deviation from the average radius
onready var score_label = get_node("/root/Game/Control/Score")  # Score label

var line_thickness = 10  # Initial line thickness

func _ready():
	self.width = line_thickness  # Set the initial line thickness
	self.default_color = Color(1, 1, 1)  # Initial color for the drawing

func _input(event):
	if event is InputEventMouseButton:
		if event.button_index == BUTTON_LEFT and event.pressed:
			drawing = true
			custom_points = []  # Clear previous points
			start_point = event.position  # Save the starting point
			custom_points.append(start_point)  # Add the starting point to the list
		elif event.button_index == BUTTON_LEFT and not event.pressed:
			drawing = false
			_on_draw_finished()

	if event is InputEventMouseMotion and drawing:
		custom_points.append(event.position)
		
		# Check if we are near the start point and if enough points have been drawn
		if custom_points.size() > min_points_to_stop and is_near_start_point(event.position):
			drawing = false
			_on_draw_finished()
		else:
			update()  # Request redraw
			_on_draw_in_progress()

func _draw():
	if custom_points.size() > 1:
		draw_polyline(custom_points, self.default_color, line_thickness)

func _on_draw_in_progress():
	# Update score dynamically during drawing
	var perfection_score = calculate_perfection()
	score_label.text = str(perfection_score)

	# Change line color based on the perfection score
	self.default_color = calculate_color(perfection_score)

func _on_draw_finished():
	if is_near_complete_circle():
		print("Completed a circle!")
	else:
		print("Not a circle!")
	
	custom_points = []  # Clear points after finishing the drawing

func is_near_complete_circle():
	if custom_points.size() < min_points_to_stop:
		return false  # Not enough points to determine a complete circle

	# Calculate the center of the points
	var center = Vector2()
	for point in custom_points:
		center += point
	center /= custom_points.size()

	# Calculate the average radius (distance from center)
	var total_distance = 0.0
	for point in custom_points:
		total_distance += center.distance_to(point)
	var average_radius = total_distance / custom_points.size()

	# Calculate the deviation of each point from the average radius
	var total_deviation = 0.0
	for point in custom_points:
		var distance = center.distance_to(point)
		total_deviation += abs(distance - average_radius)

	var average_deviation = total_deviation / custom_points.size()

	# Check if the average deviation is within the acceptable range
	return average_deviation <= max_deviation_threshold

func calculate_perfection():
	if custom_points.size() < 3:
		return 0  # Not enough points to calculate perfection

	# Calculate the center of the drawn points
	var center = Vector2()
	for point in custom_points:
		center += point
	center /= custom_points.size()  # Average position becomes the center

	# Calculate the average radius (distance from center)
	var total_distance = 0.0
	for point in custom_points:
		total_distance += center.distance_to(point)
	var average_distance = total_distance / custom_points.size()

	# Calculate deviation from the average radius
	var deviation = 0.0
	for point in custom_points:
		deviation += abs(center.distance_to(point) - average_distance)
	var average_deviation = deviation / custom_points.size()

	# Calculate perfection score based on deviation (lower deviation is better)
	var perfection_score = max(0, min(100, 100 - average_deviation))  # Ensure the score is within 0-100 range
	return perfection_score

func calculate_color(perfection_score):
	# Interpolate between red and green based on perfection score
	var red = Color(1, 0, 0)  # Red color
	var green = Color(0, 1, 0)  # Green color

	# Interpolate based on perfection_score (0 = red, 100 = green)
	return red.linear_interpolate(green, perfection_score / 100.0)

func is_near_start_point(current_position):
	# Check if the current position is close to the start point
	return start_point.distance_to(current_position) < min_distance_to_close

I made change in the previous code you give and achieve to stop when circle is full as adding a direction change check.
You surely need to change the path to your center point node at the beginning of the script.

Line2D.gd
extends Line2D

var drawing = false
var custom_points = []
onready var score_label = get_node("/root/Game/Control/Score")  # Score label
onready var center_point = get_node("/root/Game/Center")  # Center Node

var min_circle_points = 10  # Minimum number of points to consider a circle
var line_thickness = 10  # Initial line thickness
var start_angle = 0.0  # Start angle for circle drawing
var angle_covered = 0.0  # Total angle covered during drawing
var last_angle = 0.0  # Last angle position
var total_sign = 0.0

func _ready():
	self.width = line_thickness  # Set the initial line thickness
	self.default_color = Color(1, 1, 1)  # Initial color for the drawing

func _input(event):
	if event is InputEventMouseButton:
		if event.button_index == BUTTON_LEFT and event.pressed:
			drawing = true
			custom_points = []  # Clear previous points
			start_angle = get_angle()  # Save the start angle
			angle_covered = 0.0  # Reset angle coverage
			total_sign = 0.0 # Reset sign count
			last_angle = start_angle  # Initialize last angle
		elif event.button_index == BUTTON_LEFT and not event.pressed:
			drawing = false
			_on_draw_finished()

	if event is InputEventMouseMotion and drawing:
		custom_points.append(event.position)
		queue_redraw()  # Request redraw
		_on_draw_in_progress()

func _draw():
	if custom_points.size() > 1:
		draw_polyline(custom_points, self.default_color, line_thickness)

func _on_draw_in_progress():
	# Update score dynamically during drawing
	var perfection_score = calculate_perfection()
	# print("Circle Perfection Score: ", perfection_score)

	# Update score label with the perfection score
	score_label.text = str(perfection_score)

	# Change line color based on the perfection score
	self.default_color = calculate_color(perfection_score)

	# Check for angle coverage
	var current_angle = get_angle()

	# save current drawing direction
	var sign_diff = sign(current_angle - last_angle);
	# calculate total of sign
	total_sign += sign_diff

	# If less than 75% of all sign is in the same direction, the player change drawing sens
	if (abs(total_sign) < custom_points.size() * 0.75 and custom_points.size() > 3):
		# Handle direction change error here
		prints("error change direction in drawing")

	# Difference from the last angle
	# normal difference
	var angle_diff1 = abs(fmod(current_angle + 360.0, 360.0) - fmod(last_angle + 360.0, 360.0))
	# rotate by 180.0 degres difference (to remove the jump between 0 and 360 degres)
	var angle_diff2 = abs(fmod(current_angle + 540.0, 360.0) - fmod(last_angle + 540.0, 360.0))
	# get the minimal difference (with no jump)
	var angle_diff = min(angle_diff1, angle_diff2)
	angle_covered += sign_diff * angle_diff
	last_angle = current_angle  # Update last angle for the next segment

	# Stop drawing if a full circle is covered
	if abs(angle_covered) >= 360.0:
		drawing = false
		_on_draw_finished()

func _on_draw_finished():
	if is_near_complete_circle():
		print("Completed a circle!")
		# Optional: You can reset the drawing state or disable further drawing
		custom_points = []  # Clear points or keep them based on your needs

func is_near_complete_circle():
	if custom_points.size() < min_circle_points:
		return false  # Not enough points to determine a complete circle

	# Calculate the center of the points
	var center = Vector2()
	for point in custom_points:
		center += point
	center /= custom_points.size()

	# Calculate the average radius (distance from center)
	var total_distance = 0.0
	for point in custom_points:
		total_distance += center.distance_to(point)
	var average_radius = total_distance / custom_points.size()

	# Calculate the deviation of each point from the average radius
	var max_deviation = 0.0
	for point in custom_points:
		var distance = center.distance_to(point)
		max_deviation = max(max_deviation, abs(distance - average_radius))

	# Check if the maximum deviation is within an acceptable range
	return max_deviation < 15  # Increase tolerance to better accommodate varying circle sizes

func calculate_perfection():
	if custom_points.size() < 3:
		return 0  # Not enough points to calculate perfection

	# Calculate the center of the drawn points
	var center = Vector2()
	for point in custom_points:
		center += point
	center /= custom_points.size()  # Average position becomes the center

	# Calculate the average radius (distance from center)
	var total_distance = 0.0
	for point in custom_points:
		total_distance += center.distance_to(point)
	var average_distance = total_distance / custom_points.size()

	# Calculate deviation from the average radius
	var deviation = 0.0
	for point in custom_points:
		deviation += abs(center.distance_to(point) - average_distance)
	var average_deviation = deviation / custom_points.size()

	# Calculate perfection score based on deviation (lower deviation is better)
	var perfection_score = max(0, min(100, 100 - average_deviation))  # Ensure the score is within 0-100 range
	return perfection_score

func calculate_color(perfection_score):
	# Interpolate between red and green based on perfection score
	var red = Color(1, 0, 0)  # Red color
	var green = Color(0, 1, 0)  # Green color

	# Interpolate based on perfection_score (0 = red, 100 = green)
	return red.linear_interpolation(green, perfection_score / 100.0)

func get_angle():
	# Calculate the angle between the center (0,0) and the given position
	return center_point.global_position.angle_to_point(get_global_mouse_position()) * 180.0 / PI

I change it in Godot 4 and readapte it for godot 3 but not sure I haven’t forgot something.

Thanks for that! I will try soon

I tried this but there was some problems with global position cuz i am using animated sprite as an center and it does not have global position and its just an texture not the center.My center is created by code

extends Node2D

func _draw():
	var center = get_viewport().size / 2
	var radius = 10  
	draw_circle(center, radius, Color(1, 0, 0)) 


I just put the star on it.
Thats what i got when i change little bit your code.

extends Line2D

var drawing = false
var custom_points = []
onready var score_label = get_node("/root/Game/Control/Score")  # Score label
onready var center_point = get_node("/root/Game/Star")  # Center Node

var min_circle_points = 10  # Minimum number of points to consider a circle
var line_thickness = 10  # Initial line thickness
var start_angle = 0.0  # Start angle for circle drawing
var angle_covered = 0.0  # Total angle covered during drawing
var last_angle = 0.0  # Last angle position
var total_sign = 0.0

func _ready():
	self.width = line_thickness  # Set the initial line thickness
	self.default_color = Color(1, 1, 1)  # Initial color for the drawing

func _input(event):
	if event is InputEventMouseButton:
		if event.button_index == BUTTON_LEFT and event.pressed:
			drawing = true
			custom_points = []  # Clear previous points
			start_angle = get_angle()  # Save the start angle
			angle_covered = 0.0  # Reset angle coverage
			total_sign = 0.0 # Reset sign count
			last_angle = start_angle  # Initialize last angle
		elif event.button_index == BUTTON_LEFT and not event.pressed:
			drawing = false
			_on_draw_finished()

	if event is InputEventMouseMotion and drawing:
		custom_points.append(event.position)
		update() # Request redraw
		_on_draw_in_progress()

func _draw():
	if custom_points.size() > 1:
		draw_polyline(custom_points, self.default_color, line_thickness)

func _on_draw_in_progress():
	# Update score dynamically during drawing
	var perfection_score = calculate_perfection()
	# print("Circle Perfection Score: ", perfection_score)

	# Update score label with the perfection score
	score_label.text = str(perfection_score)

	# Change line color based on the perfection score
	self.default_color = calculate_color(perfection_score)

	# Check for angle coverage
	var current_angle = get_angle()

	# save current drawing direction
	var sign_diff = sign(current_angle - last_angle);
	# calculate total of sign
	total_sign += sign_diff

	# If less than 75% of all sign is in the same direction, the player change drawing sens
	if (abs(total_sign) < custom_points.size() * 0.75 and custom_points.size() > 3):
		# Handle direction change error here
		prints("error change direction in drawing")

	# Difference from the last angle
	# normal difference
	var angle_diff1 = abs(fmod(current_angle + 360.0, 360.0) - fmod(last_angle + 360.0, 360.0))
	# rotate by 180.0 degres difference (to remove the jump between 0 and 360 degres)
	var angle_diff2 = abs(fmod(current_angle + 540.0, 360.0) - fmod(last_angle + 540.0, 360.0))
	# get the minimal difference (with no jump)
	var angle_diff = min(angle_diff1, angle_diff2)
	angle_covered += sign_diff * angle_diff
	last_angle = current_angle  # Update last angle for the next segment

	# Stop drawing if a full circle is covered
	if abs(angle_covered) >= 360.0:
		drawing = false
		_on_draw_finished()

func _on_draw_finished():
	if is_near_complete_circle():
		print("Completed a circle!")
		# Optional: You can reset the drawing state or disable further drawing
		custom_points = []  # Clear points or keep them based on your needs

func is_near_complete_circle():
	if custom_points.size() < min_circle_points:
		return false  # Not enough points to determine a complete circle

	# Calculate the center of the points
	var center = Vector2()
	for point in custom_points:
		center += point
	center /= custom_points.size()

	# Calculate the average radius (distance from center)
	var total_distance = 0.0
	for point in custom_points:
		total_distance += center.distance_to(point)
	var average_radius = total_distance / custom_points.size()

	# Calculate the deviation of each point from the average radius
	var max_deviation = 0.0
	for point in custom_points:
		var distance = center.distance_to(point)
		max_deviation = max(max_deviation, abs(distance - average_radius))

	# Check if the maximum deviation is within an acceptable range
	return max_deviation < 15  # Increase tolerance to better accommodate varying circle sizes

func calculate_perfection():
	if custom_points.size() < 3:
		return 0  # Not enough points to calculate perfection

	# Calculate the center of the drawn points
	var center = Vector2()
	for point in custom_points:
		center += point
	center /= custom_points.size()  # Average position becomes the center

	# Calculate the average radius (distance from center)
	var total_distance = 0.0
	for point in custom_points:
		total_distance += center.distance_to(point)
	var average_distance = total_distance / custom_points.size()

	# Calculate deviation from the average radius
	var deviation = 0.0
	for point in custom_points:
		deviation += abs(center.distance_to(point) - average_distance)
	var average_deviation = deviation / custom_points.size()

	# Calculate perfection score based on deviation (lower deviation is better)
	var perfection_score = max(0, min(100, 100 - average_deviation))  # Ensure the score is within 0-100 range
	return perfection_score

func calculate_color(perfection_score):
	# Interpolate between red and green based on perfection score
	var red = Color(1, 0, 0)  # Red color
	var green = Color(0, 1, 0)  # Green color

	# Interpolate based on perfection_score (0 = red, 100 = green)
	return red.linear_interpolate(green, perfection_score / 100.0)

func get_angle():
	if not center_point:
		print("Error: center_point is null")
		return 0  # Prevent crash, return 0 if null
	
	# Get the global position of the parent (assuming it's Node2D or a similar type)
	var center_position = center_point.get_parent().global_position

	print("Center Point Parent Position: ", center_position)
	print("Mouse Position: ", get_global_mouse_position())

	return center_position.angle_to_point(get_global_mouse_position()) * 180.0 / PI

also there is this error


and thats my console

— Debugging process started —
Godot Engine v3.5.3.stable.official.6c814135b - https://godotengine.org
OpenGL ES 3.0 Renderer: GeForce GTX 550 Ti/PCIe/SSE2
Async. shader compilation: OFF

Error: center_point is null
Error: center_point is null
Error: center_point is null
Error: center_point is null
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point is null
error change direction in drawing
Error: center_point […]
[output overflow, print less text!]
— Debugging process stopped —
And now its not stopping :frowning:

It worked there were some more problems, thank you very much for helping me, i appreciate it!!! :+1: :+1: :+1:but still i can draw what i want :joy:

You need to create a stop or print an error here, I left it as just a print in the consol but you can set a variable and stop the drawing process before show an error ingame.

i fixed the errors now only if you can help me with this problem in the video

Added the stop when error occur. Also I made mistake in the sign calculation (angle can be very rought to work with). Hope I don’t make error converting back to godot 3.

Line2D.gd
extends Line2D

var drawing = false
var custom_points = []
onready var score_label = get_node("/root/Game/Control/Score")  # Score label
onready var center_point = get_node("/root/Game/Center")  # Score label

var min_circle_points = 10  # Minimum number of points to consider a circle
var line_thickness = 10  # Initial line thickness
var start_angle = 0.0  # Start angle for circle drawing
var angle_covered = 0.0  # Total angle covered during drawing
var last_angle = 0.0  # Last angle position
var total_sign = 0.0 # Total movement direction (must be close to total point count overwise draw is not continuously in the same direction)
var error_change_direction = false # Error check state

func _ready():
	self.width = line_thickness  # Set the initial line thickness
	self.default_color = Color(1, 1, 1)  # Initial color for the drawing

func _input(event):
	if event is InputEventMouseButton:
		if event.button_index == BUTTON_LEFT and event.pressed:
			drawing = true
			error_change_direction = false # Reset error check
			custom_points = []  # Clear previous points
			start_angle = get_angle()  # Save the start angle
			angle_covered = 0.0  # Reset angle coverage
			total_sign = 0.0 # Reset sign count
			last_angle = start_angle  # Initialize last angle
		elif event.button_index == BUTTON_LEFT and not event.pressed:
			drawing = false
			_on_draw_finished()

	if event is InputEventMouseMotion and drawing:
		custom_points.append(event.position)
		queue_redraw()  # Request redraw
		_on_draw_in_progress()

func _draw():
	if custom_points.size() > 1:
		draw_polyline(custom_points, self.default_color, line_thickness)

func _on_draw_in_progress():
	# Update score dynamically during drawing
	var perfection_score = calculate_perfection()
	# print("Circle Perfection Score: ", perfection_score)

	# Update score label with the perfection score
	score_label.text = str(perfection_score)

	# Change line color based on the perfection score
	self.default_color = calculate_color(perfection_score)

	# Check for angle coverage
	var current_angle = get_angle()


	# Difference from the last angle
	# normal difference
	var angle_diff1 = fmod(current_angle + 360.0, 360.0) - fmod(last_angle + 360.0, 360.0)
	# rotate by 180.0 degres difference (to remove the jump between 0 and 360 degres)
	var angle_diff2 = fmod(current_angle + 540.0, 360.0) - fmod(last_angle + 540.0, 360.0)

	var sign_diff = 0;
	# Save current drawing direction
	if (abs(angle_diff1) <= abs(angle_diff2)):
		sign_diff = sign(angle_diff1);
	else:
		sign_diff = sign(angle_diff2);
	
	# Calculate total of sign
	total_sign += sign_diff

	# If less than 75% of all sign is in the same direction, the player change drawing sens
	if (abs(total_sign) < custom_points.size() * 0.75 and custom_points.size() > 3):
		error_change_direction = true # Set error
		# stop drawing
		drawing = false
		_on_draw_finished()

	# Get the minimal difference (with no jump)
	var angle_diff = min(abs(angle_diff1), abs(angle_diff2))
	angle_covered += sign_diff * angle_diff
	last_angle = current_angle  # Update last angle for the next segment

	# Stop drawing if a full circle is covered
	if abs(angle_covered) >= 360.0:
		drawing = false
		_on_draw_finished()

func _on_draw_finished():
	if (error_change_direction):
		# Update score label with an error message
		score_label.text = "It's not a circle"
		custom_points = []  # Clear points or keep them based on your needs
		return

	if is_near_complete_circle():
		print("Completed a circle!")
		# Optional: You can reset the drawing state or disable further drawing
		custom_points = []  # Clear points or keep them based on your needs

func is_near_complete_circle():
	if custom_points.size() < min_circle_points:
		return false  # Not enough points to determine a complete circle

	# Calculate the center of the points
	var center = Vector2()
	for point in custom_points:
		center += point
	center /= custom_points.size()

	# Calculate the average radius (distance from center)
	var total_distance = 0.0
	for point in custom_points:
		total_distance += center.distance_to(point)
	var average_radius = total_distance / custom_points.size()

	# Calculate the deviation of each point from the average radius
	var max_deviation = 0.0
	for point in custom_points:
		var distance = center.distance_to(point)
		max_deviation = max(max_deviation, abs(distance - average_radius))

	# Check if the maximum deviation is within an acceptable range
	return max_deviation < 15  # Increase tolerance to better accommodate varying circle sizes

func calculate_perfection():
	if custom_points.size() < 3:
		return 0  # Not enough points to calculate perfection

	# Calculate the center of the drawn points
	var center = Vector2()
	for point in custom_points:
		center += point
	center /= custom_points.size()  # Average position becomes the center

	# Calculate the average radius (distance from center)
	var total_distance = 0.0
	for point in custom_points:
		total_distance += center.distance_to(point)
	var average_distance = total_distance / custom_points.size()

	# Calculate deviation from the average radius
	var deviation = 0.0
	for point in custom_points:
		deviation += abs(center.distance_to(point) - average_distance)
	var average_deviation = deviation / custom_points.size()

	# Calculate perfection score based on deviation (lower deviation is better)
	var perfection_score = max(0, min(100, 100 - average_deviation))  # Ensure the score is within 0-100 range
	return perfection_score

func calculate_color(perfection_score):
	# Interpolate between red and green based on perfection score
	var red = Color(1, 0, 0)  # Red color
	var green = Color(0, 1, 0)  # Green color

	# Interpolate based on perfection_score (0 = red, 100 = green)
	return red.linear_interpolate(green, perfection_score / 100.0)

func get_angle():
	if not center_point:
		print("Error: center_point is null")
		return 0  # Prevent crash, return 0 if null
	
	# Get the global position of the parent (assuming it's Node2D or a similar type)
	var center_position = center_point.get_parent().global_position

	print("Center Point Parent Position: ", center_position)
	print("Mouse Position: ", get_global_mouse_position())

	return center_position.angle_to_point(get_global_mouse_position()) * 180.0 / PI
1 Like

okay but now i cant just draw


every time this

Okay i forgot that i need to change the code little bit and now yes i cant draw what i want only circle but sadly with lines its works too

You can just change the check for error in the draw_finish function

func _on_draw_finished():
	if (error_change_direction or abs(angle_covered) < 340.0):
		# Update score label with error message
		score_label.text = "It's not a circle"
		custom_points = []  # Clear points or keep them based on your needs
		return

	if is_near_complete_circle():
		print("Completed a circle!")
		# Optional: You can reset the drawing state or disable further drawing
		custom_points = []  # Clear points or keep them based on your needs

I allow an unfinished circle with only 340° draw but you can just change the value

okay,then Thank you very much for helping me i am very grateful and i appreciate it :+1: :+1: :+1:

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.