Godot Version
3
Highscore
extends Node2D
# High score variable
var high_score := 0
# Reference to the label node
onready var high_score_label = get_node("/root/Game/Control/Highscore")
func _ready():
# Initialize the label with the current high score
_update_high_score_label()
func _update_high_score_label():
# Update the label text
high_score_label.text = "High Score: %d" % high_score
func _on_player_score_increased(new_score: int):
# Check if the new score is higher than the current high score
if new_score > high_score:
high_score = new_score
_update_high_score_label()
Line2d
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/Control/Star") # Center point of the circle
onready var animation_player = get_node("/root/Game/Control/AnimationPlayer") # Animation player
onready var blackhole = get_node("/root/Game/Control/Blackhole")
onready var explosion = get_node("/root/Game/Control/Explosion")
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
var error_change_direction = false # Error check state
var is_animation_playing = false # Track if animation is currently playing
func _ready():
self.width = line_thickness # Set the initial line thickness
self.default_color = Color(1, 1, 1) # Set the line color to white
if animation_player:
animation_player.connect("animation_finished", self, "_on_animation_finished")
else:
print("Error: AnimationPlayer node is not assigned")
# Initialize the score label
score_label.text = "Score: 0"
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
if is_animation_playing:
_reset_animation() # Reset the animation if it is playing
score_label.text = "Score: 0" # Reset the score label
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()
_on_draw_in_progress()
func _draw():
if custom_points.size() > 1:
draw_polyline(custom_points, self.default_color, line_thickness) # Always draw the line white
func _on_draw_in_progress():
var perfection_score = calculate_perfection()
score_label.text = "%0.1f" % perfection_score # Update score label with the current score
var current_angle = get_angle()
var angle_diff1 = fmod(current_angle + 360.0, 360.0) - fmod(last_angle + 360.0, 360.0)
var angle_diff2 = fmod(current_angle + 540.0, 360.0) - fmod(last_angle + 540.0, 360.0)
var sign_diff = 0
if abs(angle_diff1) <= abs(angle_diff2):
sign_diff = sign(angle_diff1)
else:
sign_diff = sign(angle_diff2)
total_sign += sign_diff
if abs(total_sign) < custom_points.size() * 0.75 and custom_points.size() > 3:
error_change_direction = true
drawing = false
_on_draw_finished()
var angle_diff = min(abs(angle_diff1), abs(angle_diff2))
angle_covered += sign_diff * angle_diff
last_angle = current_angle
if abs(angle_covered) >= 360.0:
drawing = false
_on_draw_finished()
func _on_draw_finished():
if error_change_direction or abs(angle_covered) < 340.0:
score_label.text = "It's not a circle"
custom_points = []
return
var perfection_score = calculate_perfection()
if perfection_score >= 50:
_play_explosion_animation() # Play explosion animation when score is 50 or more
explosion.visible = true
if is_near_complete_circle():
print("Completed a circle!")
custom_points = []
func is_near_complete_circle():
if custom_points.size() < min_circle_points:
return false
var center = Vector2()
for point in custom_points:
center += point
center /= custom_points.size()
var total_distance = 0.0
for point in custom_points:
total_distance += center.distance_to(point)
var average_radius = total_distance / custom_points.size()
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))
return max_deviation < 15
func calculate_perfection():
if custom_points.size() < 3:
return 0
var center = Vector2()
for point in custom_points:
center += point
center /= custom_points.size()
var total_distance = 0.0
for point in custom_points:
total_distance += center.distance_to(point)
var average_distance = total_distance / custom_points.size()
var deviation = 0.0
for point in custom_points:
deviation += abs(center.distance_to(point) - average_distance)
var average_deviation = deviation / custom_points.size()
return max(0, min(100, 100 - average_deviation))
func get_angle():
if not center_point:
print("Error: center_point is null")
return 0
var center_position = center_point.global_position
return center_position.angle_to_point(get_global_mouse_position()) * 180.0 / PI
func _play_explosion_animation():
if animation_player:
animation_player.play("Explosion")
is_animation_playing = true # Mark animation as playing
else:
print("Error: AnimationPlayer node is not assigned")
func _reset_animation():
if animation_player:
animation_player.stop() # Stop the current animation
is_animation_playing = false # Mark animation as stopped
blackhole.visible = false # Hide the blackhole
explosion.visible = false # Hide the explosion
center_point.visible = true # Show the center point
print("Animation reset.") # Debug print to verify reset
else:
print("Error: AnimationPlayer node is not assigned")
func _on_animation_finished(anim_name):
print("Animation finished: " + anim_name)
if anim_name == "Explosion":
blackhole.visible = true
explosion.visible = false
center_point.visible = false
animation_player.play("Blackhole")
elif anim_name == "Blackhole":
is_animation_playing = false # Reset animation playing state
blackhole.visible = true # Ensure blackhole is visible after animation ends
center_point.visible = false # Hide the center point
print("Blackhole animation finished.")
And i am using an plugin Igbgui
extends Node
#Instant Games Bridge by Mewton Games, GUI Node by Repin Develop v1.11
#Добавьте данную сцену как дочернюю там где вам необходим функционал IGB.
#Отключение звука при сворачивании, показе interstitial и rewarded происходит автоматически.
#platform
export var game_ready = false #поставте галочу, чтобы отправить сигнал ready в нужной сцене
var vk_only = false #vk games, работает только на платформе vk
var vk_direct_only = false #vk direct only, работает только на мобильной платформе vk direct
var vk_play_only = false #vk play, работает только на vk play
var yandex_only = false #yandex games, работает только на yandex играх
var no_social = false #html5 платформа без интеграции с плагином
#device
var desktop = false #работает только на ПК
var mobile = false #работает только на телефонах
signal app_visible #сигнал при возвращении видимости игры после сворачивания
signal app_hidden #сигнал при сворачивании игры
#advertisement
export var show_banner = false #показать баннер
export var show_interstitial = false #поставьте галочу для показа interstitial, либо вызывайте ее при помощи AnimationPlayer
export var show_rewarded = false #поставьте галочу для показа rewarded, либо вызывайте ее при помощи AnimationPlayer
signal get_reward #используйте сигнал "get_reward" для получения награды
signal ad_open #сигнал при открытии interstitial и rewarded рекламы.
signal ad_close #сигнал при закрытии interstitial и rewarded рекламы.
#social
export var share_app = false #поставте галочу в сцене, где необходимо поделится приложением vk.
export(String) var game_link = "" #ссылка на игру, пример: https://vk.com/app123
export var join_community = false #приглашение в сообщество vk
export(String) var community_id = "" #id вашего сообщества vk, состоит только из цифр, пример: 123
export var vk_donut_check = false #включение проверки подписки на сообщество vk donut через переменную vk_donut_subscriber, так же требуется указать community_id
var vk_donut_subscriber = false #проверка подписки на ваше сообщество через vk donut, true - когда есть подписка и false при ее отсутствии.
export var invite_friends = false #пригласить друга из vk
export var create_post = false #сделать пост на стене vk
export(String) var post_message = "" #текст вашего поста
export(String) var post_attachments = "" #ссылка или номер вложения к посту, например: photo-123 or video-123 etc.
export var add_to_favorites = false #добавить в избранное vk
export var rate = false #оценить приложение в yandex
export var open_catalog = false #открыть каталог игр в yandex
export(String) var catalog_link = "" #ссылка на страницу разработчика, пример: /games/developer?name= Не работает на iOS!
#leaderboard
export var vk_direct_leaderboard = false #доступно только в vk direct, показывает только ваш результат
var vk_direct_result = 0.0 #ваш результат который отобразится в окне vk direct
export var yandex_leaderboard = false #активация доски лидеров yandex
var yandex_result = 0.0 #результат который отобразится на странице игры в yandex играх
export(String) var yandex_leaderboard_name = "" #техническое название лидерборда в который будет осуществляться запись
#storage
export(Array) var data_key #выберете String для создания названия ключа
export(Array) var data_value #выберете любое значение для вашего ключа. ВНИМАНИЕ! Размер массива "data_key", должен совпадать с размером "data_value"
export var save_data = false #сохранение значений
export var load_data = false #загрузка значений
signal data_loaded #проверка загрузки значений
export var delete_data = false #удаление значений
func _ready():
#game ready
if game_ready:
Bridge.platform.send_message(Bridge.PlatformMessage.GAME_READY)
#connect states
Bridge.advertisement.connect("banner_state_changed",self,"_banner_state")
Bridge.advertisement.connect("interstitial_state_changed",self,"_interstitial_state")
Bridge.advertisement.connect("rewarded_state_changed",self,"_rewarded_state")
Bridge.game.connect("visibility_state_changed",self,"_visibility_state")
#get current device
print("current device: " + str(Bridge.device.type))
#get current platform
print("current platform: " + str(Bridge.platform.id))
#get current language
print("current language: " + str(Bridge.platform.language))
#get player authorized
print("player authorized:" + str(Bridge.player.is_authorized))
#set language
if OS.get_name() == "HTML5":
TranslationServer.set_locale(Bridge.platform.language)
#set platform visibility
if Bridge.platform.id == "vk":
vk_only = true
if Bridge.platform.id == "vk" and Bridge.device.type == "mobile":
vk_direct_only = true
if Bridge.platform.id == "yandex":
yandex_only = true
if Bridge.platform.id == "vk_play":
vk_play_only = true
if Bridge.platform.id == "mock":
no_social = true
#set device visibility
if Bridge.device.type == "desktop":
desktop = true
if Bridge.device.type == "mobile":
mobile = true
#vk donut check
if Bridge.platform.id == "vk":
if vk_donut_check:
JavaScript.eval("""
let url = new URL(window.location.href)
let accessToken = url.searchParams.get('access_token')
bridge.platform.sdk.send('VKWebAppCallAPIMethod', {
method: 'donut.isDon',
params: {
owner_id: '-"""+str(community_id)+"""',
v: '5.131',
access_token: accessToken
}})
.then((data) => {
if (data.response) {
console
window.vk_donut_subscriber = true
}
else {
window.vk_donut_subscriber = false
}
})
.catch((error) => {
console.log(error)
})""")
yield(get_tree().create_timer(5), "timeout")
if JavaScript.get_interface("window").vk_donut_subscriber == true:
vk_donut_subscriber = true
if JavaScript.get_interface("window").vk_donut_subscriber == false:
vk_donut_subscriber = false
if vk_donut_subscriber:
print("vk donut subscription: true")
else:
print("vk donut subscription: false")
func _process(_delta):
#advertisement
if show_banner:
$anim.play("show_banner")
if show_interstitial:
$anim.play("interstitial")
if show_rewarded:
$anim.play("rewarded")
#vk social
if vk_only:
if share_app:
$anim.play("share_app")
if join_community:
$anim.play("join_community")
if invite_friends:
$anim.play("invite_friends")
if create_post:
$anim.play("create_post")
if add_to_favorites:
$anim.play("add_to_favorites")
#vk direct leaderboard
if vk_direct_only:
if vk_direct_leaderboard:
$anim.play("vk_direct_leaderboard")
#yandex social
if yandex_only:
if rate:
$anim.play("rate")
if open_catalog:
$anim.play("open_catalog")
#yandexleaderboard
if yandex_leaderboard:
$anim.play("yandex_leaderboard")
#storage
if load_data:
$anim.play("load_data")
if save_data:
$anim.play("save_data")
if delete_data:
$anim.play("delete_data")
func _finished(anim_name):
#advertisement
if anim_name == "show_banner":
Bridge.advertisement.show_banner()
show_banner = false
if anim_name == "interstitial":
Bridge.advertisement.show_interstitial()
show_interstitial = false
if anim_name == "rewarded":
Bridge.advertisement.show_rewarded()
show_rewarded = false
#vk social
if vk_only:
if anim_name == "share_app":
Bridge.social.share(Bridge.ShareVkOptions.new(game_link))
share_app = false
if anim_name == "join_community":
Bridge.social.join_community(Bridge.JoinCommunityVkOptions.new(community_id))
join_community = false
if anim_name == "invite_friends":
Bridge.social.invite_friends()
invite_friends = false
if anim_name == "create_post":
Bridge.social.create_post(Bridge.CreatePostVkOptions.new(post_message,post_attachments))
create_post = false
if anim_name == "add_to_favorites":
Bridge.social.add_to_favorites()
add_to_favorites = false
#vk direct leaderboard
if vk_direct_only:
if anim_name == "vk_direct_leaderboard":
Bridge.leaderboard.show_native_popup(Bridge.ShowNativePopupVkOptions.new(vk_direct_result,true))
vk_direct_leaderboard = false
#yandex social
if yandex_only:
if anim_name == "rate":
Bridge.social.rate()
rate = false
if anim_name == "open_catalog":
JavaScript.eval("window.open('https://yandex."+str(Bridge.platform.tld)+str(catalog_link)+"')")
open_catalog = false
#yandex_leaderboard
if anim_name == "yandex_leaderboard":
Bridge.leaderboard.set_score(Bridge.SetScoreYandexOptions.new(yandex_result,yandex_leaderboard_name))
print("leaderboard " + str(yandex_leaderboard_name))
yandex_leaderboard = false
#storage
if anim_name == "load_data":
load_data()
load_data = false
if anim_name == "save_data":
save_data()
save_data = false
if anim_name == "delete_data":
delete_data()
delete_data = false
#ad state and audio mute in advertisement
func _banner_state(state:String):
print("banner ",state)
func _interstitial_state(state:String):
if state == "opened":
AudioServer.set_bus_mute(0, true)
emit_signal("ad_open")
print("interstitial opened")
if state == "closed":
emit_signal("ad_close")
AudioServer.set_bus_mute(0, false)
print("interstitial closed")
if state == "failed":
emit_signal("ad_close")
AudioServer.set_bus_mute(0, false)
print("interstitial failed and closed")
func _rewarded_state(state:String):
if state == "opened":
emit_signal("ad_open")
AudioServer.set_bus_mute(0, true)
print("rewarded opened")
if state == "rewarded":
emit_signal("get_reward")
print("get reward")
if state == "closed":
emit_signal("ad_close")
AudioServer.set_bus_mute(0, false)
print("rewarded closed")
if state == "failed":
emit_signal("ad_close")
AudioServer.set_bus_mute(0, false)
print("rewarded failed and closed")
#audio mute in minimizing
func _visibility_state(state:String):
if state == "visible":
AudioServer.set_bus_volume_db(0,0)
emit_signal("app_visible")
print("game visible")
if state == "hidden":
AudioServer.set_bus_volume_db(0,-80)
emit_signal("app_hidden")
print("game hidden")
#audio mute in mouse focus out
func _notification(what):
match what:
MainLoop.NOTIFICATION_WM_MOUSE_ENTER:
if OS.get_name() == "HTML5":
AudioServer.set_bus_volume_db(0,0)
print("mouse in")
MainLoop.NOTIFICATION_WM_MOUSE_EXIT:
if OS.get_name() == "HTML5":
AudioServer.set_bus_volume_db(0,-80)
print("mouse out")
#storage func and status
func load_data():
Bridge.storage.get(data_key,funcref(self,"_load_data_completed"))
func save_data():
Bridge.storage.set(data_key, data_value, funcref(self,"_save_data_completed"))
func delete_data():
Bridge.storage.delete(data_key)
func _load_data_completed(success ,data):
print("data loaded: " + str(success))
if success:
print(data)
data_value = data
emit_signal("data_loaded")
else:
print("empty")
func _save_data_completed(success):
print("data saved: " + str(success))
and there was this