/
evggal
/
math_game
Обзор
Документация
Войти
/
evggal
/
math_game
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
scripts/graph_cell.gd
348 строк
12 KB
kitkikat
Добавлен вход в мини-игру, изменено отображение графиков, исправлены баги, доработаны алгоритмы поиска пересечения графов
23 дек 2024, 01:40
23 дек 2024, 01:40
43a9047
Код
Авторство
О чём код?
extends Control # Параметры сетки и ячеек var grid_size: Vector2 = Vector2(2, 2) var cell_size: Vector2 = Vector2(400, 400) # Смещения графиков var offset_sin: Vector2 = Vector2(0, 0) var offset_exp: Vector2 = Vector2(0, 0) var offset_log: Vector2 = Vector2(0, 0) var offset_poly: Vector2 = Vector2(0, 0) # Коэффициенты графиков var a: float = 50.0 var b: float = 1.0 var c: float = 0.0 # Точки A и B var point_a: Vector2 = Vector2(300, 300) var point_b: Vector2 = Vector2(600, 300) # UI элементы @onready var line_edit_x: LineEdit = $Ui/GraphField2/line_edit_x @onready var line_edit_y: LineEdit = $Ui/GraphField2/line_edit_y @onready var h_slider_x: HSlider = $Ui/GraphField2/HSliderX @onready var h_slider_y: HSlider = $Ui/GraphField2/HSliderY @onready var selected_graph_label: Label = $Result # Выбранная ячейка var selected_cell: Vector2 = Vector2(-1, -1) # Радиус попадания точки var point_radius: float = 10.0 # Граф точек пересечения var intersection_graph: Dictionary = {} func _ready(): update_graphs() func _input(event): if event is InputEventMouseButton and event.pressed: var new_selected_cell = get_cell_under_mouse(event.position) if new_selected_cell != selected_cell: selected_cell = new_selected_cell update_selected_graph_label() update_graphs() func get_cell_under_mouse(mouse_pos: Vector2) -> Vector2: var cell_x = int(mouse_pos.x / cell_size.x) var cell_y = int(mouse_pos.y / cell_size.y) if cell_x < grid_size.x and cell_y < grid_size.y: return Vector2(cell_x, cell_y) return Vector2(-1, -1) func update_selected_graph_label(): match selected_cell: Vector2(0, 0): selected_graph_label.text = "Выбранный график - Синус" Vector2(1, 0): selected_graph_label.text = "Выбранный график - Экспонента" Vector2(0, 1): selected_graph_label.text = "Выбранный график - Логарифм" Vector2(1, 1): selected_graph_label.text = "Выбранный график - Полином" _: selected_graph_label.text = "Не выбрано" func _on_line_edit_x_text_changed(new_text: String): if selected_cell != Vector2(-1, -1): var new_offset_x = new_text.to_float() if is_valid_offset(new_offset_x): set_graph_offset_x(selected_cell, new_offset_x) else: line_edit_x.text = str(get_graph_offset_x(selected_cell)) func _on_line_edit_y_text_changed(new_text: String): if selected_cell != Vector2(-1, -1): var new_offset_y = new_text.to_float() if is_valid_offset(new_offset_y): set_graph_offset_y(selected_cell, new_offset_y) else: line_edit_y.text = str(get_graph_offset_y(selected_cell)) func _on_h_slider_x_value_changed(value: float): if selected_cell != Vector2(-1, -1): set_graph_offset_x(selected_cell, value) func _on_h_slider_y_value_changed(value: float): if selected_cell != Vector2(-1, -1): set_graph_offset_y(selected_cell, value) func is_valid_offset(offset: float) -> bool: # Проверка на корректность значения смещения return not is_nan(offset) and not is_inf(offset) and offset >= -1000 and offset <= 1000 func set_graph_offset_x(cell: Vector2, new_offset_x: float): match cell: Vector2(0, 0): offset_sin.x = new_offset_x Vector2(1, 0): offset_exp.x = new_offset_x Vector2(0, 1): offset_log.x = new_offset_x Vector2(1, 1): offset_poly.x = new_offset_x update_graphs() func set_graph_offset_y(cell: Vector2, new_offset_y: float): match cell: Vector2(0, 0): offset_sin.y = new_offset_y Vector2(1, 0): offset_exp.y = new_offset_y Vector2(0, 1): offset_log.y = new_offset_y Vector2(1, 1): offset_poly.y = new_offset_y update_graphs() func get_graph_offset_x(cell: Vector2) -> float: match cell: Vector2(0, 0): return offset_sin.x Vector2(1, 0): return offset_exp.x Vector2(0, 1): return offset_log.x Vector2(1, 1): return offset_poly.x return 0.0 func get_graph_offset_y(cell: Vector2) -> float: match cell: Vector2(0, 0): return offset_sin.y Vector2(1, 0): return offset_exp.y Vector2(0, 1): return offset_log.y Vector2(1, 1): return offset_poly.y return 0.0 func update_graphs(): queue_redraw() func _draw(): draw_grid() draw_graphs() draw_points() draw_global_coordinate_frame() draw_intersection_nodes() func draw_global_coordinate_frame(): var total_width = grid_size.x * cell_size.x var total_height = grid_size.y * cell_size.y draw_rect(Rect2(Vector2(0, 0), Vector2(total_width, total_height)), Color(1, 1, 1), false, 13) func draw_grid(): var total_width = grid_size.x * cell_size.x var total_height = grid_size.y * cell_size.y for i in range(int(grid_size.x) + 1): var x = i * cell_size.x draw_line(Vector2(x, 0), Vector2(x, total_height), Color(0.4, 0.4, 0.4), 2) for i in range(int(grid_size.y) + 1): var y = i * cell_size.y draw_line(Vector2(0, y), Vector2(total_width, y), Color(0.4, 0.4, 0.4), 2) func draw_graphs(): draw_graph("sin", offset_sin, Vector2(cell_size.x / 2, cell_size.y / 2), Color(1, 0, 0), 6) draw_graph("exp", offset_exp, Vector2(cell_size.x * 1.5, cell_size.y / 2), Color(0, 1, 0), 6) draw_graph("log", offset_log, Vector2(cell_size.x / 2, cell_size.y * 1.5), Color(0, 0, 1), 6) draw_poly_graph(offset_poly, Vector2(cell_size.x * 1.5, cell_size.y * 1.5), Color(1, 1, 0), 12) func draw_graph(graph_type: String, offset: Vector2, cell_center: Vector2, color: Color, thickness: float): for x in range(-int(cell_size.x * grid_size.x), int(cell_size.x * grid_size.x), 2): var y = 0 match graph_type: "sin": y = a * sin(b * x * 0.02) + c "exp": y = a * exp(b * x * 0.01) + c "log": y = a * log(b * x) + c if x > 0 else -1e10 _: continue if y == -1e10: continue var point = Vector2(x + cell_center.x + offset.x, -y + cell_center.y - offset.y) point = clamp_point_to_global_bounds(point) draw_line(point, point + Vector2(2, 0), color, thickness) func draw_poly_graph(offset: Vector2, cell_center: Vector2, color: Color, thickness: float): for x in range(-int(cell_size.x * grid_size.x), int(cell_size.x * grid_size.x), 2): var y = a * pow(x, 2) * 0.001 + b * x + c var point = Vector2(x + cell_center.x + offset.x, -y + cell_center.y - offset.y) point = clamp_point_to_global_bounds(point) draw_line(point, point + Vector2(2, 0), color, thickness) func draw_points(): draw_circle(point_a, 5, Color(225, 228, 178)) draw_circle(point_b, 5, Color(139, 0, 255)) func draw_intersection_nodes(): for point in intersection_graph.keys(): draw_circle(point, 5, Color(0, 0, 0)) func clamp_point_to_global_bounds(point: Vector2) -> Vector2: point.x = clamp(point.x, 0, grid_size.x * cell_size.x) point.y = clamp(point.y, 0, grid_size.y * cell_size.y) return point func find_intersections(): intersection_graph = {} var graphs = [ {"type": "sin", "offset": offset_sin}, {"type": "exp", "offset": offset_exp}, {"type": "log", "offset": offset_log}, {"type": "poly", "offset": offset_poly}] for i in range(len(graphs)): for j in range(i + 1, len(graphs)): var intersections = find_pair_graph_intersections(graphs[i], graphs[j]) for point in intersections: if not intersection_graph.has(point): intersection_graph[point] = [] intersection_graph[point].append(graphs[i]["type"]) intersection_graph[point].append(graphs[j]["type"]) print("Intersection found at:", point, "between", graphs[i]["type"], "and", graphs[j]["type"]) func find_pair_graph_intersections(graph1: Dictionary, graph2: Dictionary) -> Array: var step = 1.0 var tolerance = 10.0 var intersections = [] for x in range(-int(cell_size.x * grid_size.x), int(cell_size.x * grid_size.x), step): var y1 = evaluate_graph(graph1["type"], x - graph1["offset"].x, graph1["offset"]) var y2 = evaluate_graph(graph2["type"], x - graph2["offset"].x, graph2["offset"]) if abs(y1 - y2) <= tolerance: var point = Vector2(x + graph1["offset"].x, y1) intersections.append(point) return intersections func evaluate_graph(graph_type: String, x: float, offset: Vector2) -> float: match graph_type: "sin": return a * sin(b * x * 0.02) + c + offset.y "exp": return a * exp(b * x * 0.01) + c + offset.y "log": return a * log(b * x) + c + offset.y if x > 0 else -1e10 "poly": return a * pow(x, 2) * 0.001 + b * x + c + offset.y _: return -1e10 func check_success_condition(): var point_a_graph = get_point_graph(point_a) var point_b_graph = get_point_graph(point_b) if point_a_graph != null and point_b_graph != null: if do_graphs_intersect(point_a_graph, point_b_graph) or (do_graphs_intersect(point_a_graph, "sin") and do_graphs_intersect(point_b_graph, "sin")) or (do_graphs_intersect(point_a_graph, "exp") and do_graphs_intersect(point_b_graph, "exp")) or (do_graphs_intersect(point_a_graph, "log") and do_graphs_intersect(point_b_graph, "log")) or (do_graphs_intersect(point_a_graph, "poly") and do_graphs_intersect(point_b_graph, "poly")): print("Success condition met!") emit_signal("mini_game_completed") on_mini_game_completed() else: print("Points A or B are not on intersecting graphs.") else: print("Points A or B are not on any graph.") func get_point_graph(point: Vector2) -> String: var graphs = [ {"type": "sin", "offset": offset_sin}, {"type": "exp", "offset": offset_exp}, {"type": "log", "offset": offset_log}, {"type": "poly", "offset": offset_poly} ] var tolerance = 10.0 for graph in graphs: var x_adjusted = point.x - graph["offset"].x var y_graph = evaluate_graph(graph["type"], x_adjusted, graph["offset"]) var y_adjusted = y_graph + graph["offset"].y print("Checking point:", point, "on graph:", graph["type"], "with adjusted y:", y_adjusted) if abs(point.y - y_adjusted) <= (point_radius + tolerance): print("Point", point, "is near/on graph:", graph["type"]) return graph["type"] return '' func do_graphs_intersect(graph_type1: String, graph_type2: String) -> bool: for point in intersection_graph.keys(): if graph_type1 in intersection_graph[point] and graph_type2 in intersection_graph[point]: return true return false func on_mini_game_completed(): selected_graph_label.visible = true # Создаем таймер var timer := Timer.new() timer.wait_time = 10.0 # Устанавливаем задержку timer.one_shot = true # Таймер одноразовый add_child(timer) # Добавляем таймер в сцену timer.start() # Запускаем таймер # Ждем завершения таймера await timer.timeout var main_scenes = load("res://scenes/world_1.tscn") get_tree().change_scene_to_packed(main_scenes) # Алгоритм A* для поиска пути func a_star_search(start: Vector2, goal: Vector2) -> Array: var open_set = [start] var came_from = {} var g_score = {start: 0} var f_score = {start: heuristic_cost_estimate(start, goal)} while open_set.size() > 0: var current = get_lowest_f_score(open_set, f_score) if current == goal: return reconstruct_path(came_from, current) open_set.erase(current) var neighbors = get_neighbors(current) for neighbor in neighbors: var tentative_g_score = g_score[current] + dist_between(current, neighbor) if neighbor not in g_score or tentative_g_score < g_score[neighbor]: came_from[neighbor] = current g_score[neighbor] = tentative_g_score f_score[neighbor] = tentative_g_score + heuristic_cost_estimate(neighbor, goal) if neighbor not in open_set: open_set.append(neighbor) return [] func heuristic_cost_estimate(a: Vector2, b: Vector2) -> float: return a.distance_to(b) func get_lowest_f_score(open_set: Array, f_score: Dictionary) -> Vector2: var lowest = open_set[0] for node in open_set: if f_score[node] < f_score[lowest]: lowest = node return lowest func reconstruct_path(came_from: Dictionary, current: Vector2) -> Array: var total_path = [current] while current in came_from: current = came_from[current] total_path.append(current) total_path.reverse() return total_path func get_neighbors(node: Vector2) -> Array: var neighbors = [] var directions = [Vector2(1, 0), Vector2(-1, 0), Vector2(0, 1), Vector2(0, -1)] for direction in directions: var neighbor = node + direction if is_valid_node(neighbor): neighbors.append(neighbor) return neighbors func is_valid_node(node: Vector2) -> bool: return node.x >= 0 and node.x < grid_size.x * cell_size.x and node.y >= 0 and node.y < grid_size.y * cell_size.y func dist_between(a: Vector2, b: Vector2) -> float: return a.distance_to(b)