Remove bloat, add level selector and some basic levels that just create input and outputs currently, no checking, make tool box invisible during screenshot

This commit is contained in:
csd4ni3l
2025-10-13 21:24:30 +02:00
parent 00fdbf7fe6
commit f4054fafa8
5 changed files with 99 additions and 14 deletions

View File

@@ -1,19 +1,19 @@
import arcade, arcade.gui, random, datetime import arcade, arcade.gui, random, datetime
from utils.utils import cubic_bezier_points, get_gate_port_position from utils.utils import cubic_bezier_points, get_gate_port_position, generate_task_text
from utils.constants import dropdown_style, LOGICAL_GATES from utils.constants import dropdown_style, LOGICAL_GATES, LEVELS
from datetime import datetime from datetime import datetime
class LogicalGate(arcade.gui.UIBoxLayout): class LogicalGate(arcade.gui.UIBoxLayout):
def __init__(self, id, x, y, gate_type): def __init__(self, id, x, y, gate_type, value):
super().__init__(x=x, y=y, space_between=2, vertical=False) super().__init__(x=x, y=y, space_between=2, vertical=False)
self.id = id self.id = id
self.gate_type = gate_type self.gate_type = gate_type
if gate_type == "INPUT": if gate_type == "INPUT":
self.value = 1 self.value = value
else: else:
self.value = 0 self.value = 0
@@ -41,12 +41,14 @@ class LogicalGate(arcade.gui.UIBoxLayout):
return f"{self.gate_type}: {self.value}" return f"{self.gate_type}: {self.value}"
class Game(arcade.gui.UIView): class Game(arcade.gui.UIView):
def __init__(self, pypresence_client): def __init__(self, pypresence_client, level_num):
super().__init__() super().__init__()
self.pypresence_client = pypresence_client self.pypresence_client = pypresence_client
self.pypresence_client.update(state="In game") self.pypresence_client.update(state="In game")
self.level_num = level_num
self.gates: list[LogicalGate] = [] self.gates: list[LogicalGate] = []
self.connections = [] self.connections = []
self.default_gate_type = "AND" self.default_gate_type = "AND"
@@ -60,9 +62,19 @@ class Game(arcade.gui.UIView):
self.anchor = self.add_widget(arcade.gui.UIAnchorLayout(size_hint=(1, 1))) self.anchor = self.add_widget(arcade.gui.UIAnchorLayout(size_hint=(1, 1)))
self.tools_box = self.anchor.add(arcade.gui.UIBoxLayout(space_between=5), anchor_x="right", anchor_y="bottom", align_x=-5, align_y=20) self.tools_box = self.anchor.add(arcade.gui.UIBoxLayout(space_between=5), anchor_x="right", anchor_y="bottom", align_x=-5, align_y=20)
self.task_label = self.anchor.add(arcade.gui.UILabel(text=generate_task_text(LEVELS[level_num]), font_size=24), anchor_x="center", anchor_y="top")
for gate in LOGICAL_GATES.keys(): for gate in LOGICAL_GATES.keys():
button = self.tools_box.add(arcade.gui.UIFlatButton(width=self.window.width * 0.1, height=self.window.height * 0.075, text=f"Create {gate} gate", style=dropdown_style)) button = self.tools_box.add(arcade.gui.UIFlatButton(width=self.window.width * 0.1, height=self.window.height * 0.075, text=f"Create {gate} gate", style=dropdown_style))
button.on_click = lambda event, gate=gate: self.add_gate(random.randint(0, self.window.width - 100), random.randint(200, self.window.height - 100), gate) button.on_click = lambda event, gate=gate: self.add_gate(random.randint(0, self.window.width - 300), random.randint(200, self.window.height - 100), gate)
for requirement in LEVELS[level_num]:
if requirement[1] == "INPUT":
for _ in range(requirement[0]):
self.add_gate(random.randint(0, self.window.width - 300), random.randint(200, self.window.height - 100), "INPUT", requirement[2])
elif requirement[1] == "OUTPUT":
for _ in range(requirement[0]):
self.add_gate(random.randint(0, self.window.width - 300), random.randint(200, self.window.height - 100), "OUTPUT")
evaluate_button = self.tools_box.add(arcade.gui.UIFlatButton(width=self.window.width * 0.1, height=self.window.height * 0.075, text="Evaluate", style=dropdown_style)) evaluate_button = self.tools_box.add(arcade.gui.UIFlatButton(width=self.window.width * 0.1, height=self.window.height * 0.075, text="Evaluate", style=dropdown_style))
evaluate_button.on_click = lambda event: self.run_logic() evaluate_button.on_click = lambda event: self.run_logic()
@@ -74,11 +86,17 @@ class Game(arcade.gui.UIView):
hide_button.on_click = lambda event: self.hide_show_panel() hide_button.on_click = lambda event: self.hide_show_panel()
def screenshot(self): def screenshot(self):
self.tools_box.visible = False
self.tools_box._requires_render = True
self.on_draw()
image = arcade.get_image() image = arcade.get_image()
now = datetime.now() now = datetime.now()
timestamp = now.strftime("%Y-%m-%d_%H-%M-%S") timestamp = now.strftime("%Y-%m-%d_%H-%M-%S")
image.save(f"{timestamp}.png") image.save(f"{timestamp}.png")
self.tools_box.visible = True
self.add_widget(arcade.gui.UIMessageBox( self.add_widget(arcade.gui.UIMessageBox(
width=self.window.width / 2, width=self.window.width / 2,
height=self.window.height / 2, height=self.window.height / 2,
@@ -132,8 +150,8 @@ class Game(arcade.gui.UIView):
self.selected_output = None self.selected_output = None
self.selected_input = None self.selected_input = None
def add_gate(self, x, y, gate_type): def add_gate(self, x, y, gate_type, value=None):
self.gates.append(self.add_widget(LogicalGate(len(self.gates), x, y, gate_type))) self.gates.append(self.add_widget(LogicalGate(len(self.gates), x, y, gate_type, value)))
self.gates[-1].input_add_button.on_click = lambda e, gate_id=len(self.gates) - 1: self.select_input(gate_id) self.gates[-1].input_add_button.on_click = lambda e, gate_id=len(self.gates) - 1: self.select_input(gate_id)
self.gates[-1].output_add_button.on_click = lambda e, gate_id=len(self.gates) - 1: self.select_output(gate_id) self.gates[-1].output_add_button.on_click = lambda e, gate_id=len(self.gates) - 1: self.select_output(gate_id)

44
menus/level_selector.py Normal file
View File

@@ -0,0 +1,44 @@
import arcade, arcade.gui
from math import ceil
from utils.constants import button_style, LEVELS
from utils.preload import button_texture, button_hovered_texture
class LevelSelector(arcade.gui.UIView):
def __init__(self, pypresence_client):
super().__init__()
self.pypresence_client = pypresence_client
self.pypresence_client.update(state="In Menus", details="Level Selector")
self.anchor = self.add_widget(arcade.gui.UIAnchorLayout(size_hint=(1, 1)))
self.grid = self.anchor.add(arcade.gui.UIGridLayout(width=self.window.width / 2, height=self.window.height / 2, vertical_spacing=10, horizontal_spacing=10, column_count=5, row_count=ceil(len(LEVELS) / 5)), anchor_x="center", anchor_y="top", align_y=-self.window.height / 8)
def on_show_view(self):
super().on_show_view()
self.back_button = arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text='<--', style=button_style, width=100, height=50)
self.back_button.on_click = lambda event: self.main_exit()
self.anchor.add(self.back_button, anchor_x="left", anchor_y="top", align_x=5, align_y=-5)
self.anchor.add(arcade.gui.UILabel(text="Level Selector", font_size=40), anchor_x="center", anchor_y="top")
for n in range(len(LEVELS)):
row, col = n // 5, n % 5
level_button = self.grid.add(arcade.gui.UITextureButton(width=self.window.width / 8, height=self.window.height / 8, text=f"Level {n + 1}", texture=button_texture, texture_hovered=button_hovered_texture, style=button_style), row=row, column=col)
level_button.on_click = lambda event, n=n: self.play(n)
self.grid._trigger_size_hint_update()
def main_exit(self):
from menus.main import Main
self.window.show_view(Main(self.pypresence_client))
def play(self, n):
from game.play import Game
self.window.show_view(Game(self.pypresence_client, n))
def on_key_press(self, symbol, modifiers):
if symbol == arcade.key.ESCAPE:
self.main_exit()

View File

@@ -59,8 +59,8 @@ class Main(arcade.gui.UIView):
self.settings_button.on_click = lambda event: self.settings() self.settings_button.on_click = lambda event: self.settings()
def play(self): def play(self):
from game.play import Game from menus.level_selector import LevelSelector
self.window.show_view(Game(self.pypresence_client)) self.window.show_view(LevelSelector(self.pypresence_client))
def settings(self): def settings(self):
from menus.settings import Settings from menus.settings import Settings

View File

@@ -8,16 +8,34 @@ log_dir = 'logs'
discord_presence_id = 1427213145667276840 discord_presence_id = 1427213145667276840
LOGICAL_GATES = { LOGICAL_GATES = {
"INPUT": lambda a: a,
"AND": lambda a, b: a and b, "AND": lambda a, b: a and b,
"OR": lambda a, b: a or b, "OR": lambda a, b: a or b,
"NAND": lambda a, b: not (a and b), "NAND": lambda a, b: not (a and b),
"NOR": lambda a, b: not (a or b), "NOR": lambda a, b: not (a or b),
"XOR": lambda a, b: a != b, "XOR": lambda a, b: a != b,
"XNOR": lambda a, b: a == b, "XNOR": lambda a, b: a == b,
"OUTPUT": lambda a: a
} }
LEVELS = [
[
[2, "INPUT", 1],
[1, "AND"],
[1, "OUTPUT", 1]
],
[
[1, "INPUT", 1],
[1, "INPUT", 0],
[1, "AND"],
[1, "OUTPUT", 0]
],
[
[1, "INPUT", 0],
[1, "INPUT", 1],
[1, "OR"],
[1, "OUTPUT", 1]
]
]
button_style = {'normal': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK), 'hover': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK), button_style = {'normal': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK), 'hover': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK),
'press': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK), 'disabled': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK)} 'press': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK), 'disabled': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK)}
big_button_style = {'normal': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK, font_size=26), 'hover': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK, font_size=26), big_button_style = {'normal': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK, font_size=26), 'hover': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK, font_size=26),

View File

@@ -4,8 +4,13 @@ from utils.constants import menu_background_color
import pyglet.display import pyglet.display
def lerp(a, b, t): def generate_task_text(level):
return a + (b - a) * t text = "Task: You need to use "
text += f"{', '.join([f'{requirement[0]} {requirement[1]} gate(s)' for requirement in level if not requirement[1] in ['INPUT', 'OUTPUT']])}"
text += f" to result in {', '.join([f'{requirement[0]} OUTPUT gate(s) with value {requirement[2]}' for requirement in level if requirement[1] == 'OUTPUT'])}"
return text
def cubic_bezier_point(p0, p1, p2, p3, t): def cubic_bezier_point(p0, p1, p2, p3, t):
u = 1 - t u = 1 - t