From d5de17f8e052893096d0c65f98a30032a55dce97 Mon Sep 17 00:00:00 2001 From: csd4ni3l Date: Sun, 23 Nov 2025 22:40:17 +0100 Subject: [PATCH] Add sprites sidebar, x and y gravity instead of gravity, fix a bunch of bugs, so now rules work, add input, mouse move and mouse click events, fix color changes, fix very slow loading times, go from is rules to greater, less and between rules --- README.md | 4 +- assets/graphics/sprites/circle.png | Bin 0 -> 1174 bytes assets/graphics/sprites/rectangle.png | Bin 0 -> 487 bytes assets/graphics/sprites/triangle.png | Bin 0 -> 1022 bytes game/play.py | 249 ++++++++++++++++----- game/sprites.py | 19 +- utils/constants.py | 309 +++++++++++++++++--------- utils/preload.py | 8 +- utils/utils.py | 30 +-- 9 files changed, 420 insertions(+), 199 deletions(-) create mode 100644 assets/graphics/sprites/circle.png create mode 100644 assets/graphics/sprites/rectangle.png create mode 100644 assets/graphics/sprites/triangle.png diff --git a/README.md b/README.md index 6b56e55..e3fb572 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ Chaos Protocol is a simulation game where you have a rule engine and objects, which you can apply rules to! By default, the game launches with random rules. -Basically a framework of sorts, which can even be random! \ No newline at end of file +Basically a framework of sorts, which can even be random! + +The project is a huge WIP! You can't do much yet, but you have basic rules and simulation. \ No newline at end of file diff --git a/assets/graphics/sprites/circle.png b/assets/graphics/sprites/circle.png new file mode 100644 index 0000000000000000000000000000000000000000..86c678ea68c66c9f1f52884ebeab94da8aebeaa7 GIT binary patch literal 1174 zcmeAS@N?(olHy`uVBq!ia0vp^(?FPm4M^HB7CvHNV2Sl~aSW-L^Y(6F-fa&7*Nc}D zzAe3W%4hwWl~XhAn9@XCw`oNAe_d6{e}Ut{pOTK%X|3CqI=jR$Rcx%^WZqyXD5k=} zE!4uwd8mmc(XnZRf@8!41sx9oDhdBPd#_>gwOjA)`;R}qyT7|*#&b(0rE||e%g0CW z>+5iS^TXC7I(xtJF23jL&no*q|MbcDsJ-UynrpX~ey^*Xo;mB%|FfRjwam_JrTQD@ zx=!22_;S`VP166@8(9l`~SMS^;*=g(tEp3)pThEA7Htjtb$?b}j@@QAsVmpDtS&6iZ&(qgArbzI zts`rx*WsF(5C3jzPOR-c{BXkF)=)2=_m@pl^AEZ$&7N47Q@4Ew>%X;!bT9rpvg_~7 zVwaklnw0#+sb6;OkD3z}U;ICQ(bo@ki3$HF{SL0Y9i6yT(e&^qX}5JbhYuy6+dS>< z+6lKGSS`PN^3!*5U4Nat=GQytMNLx|TYj}zX8y6;b0f|%uhc%C?H0jYuqUl7@#B)e zm3`OGbw>ea^hp$hi>`?V%BU_TeqLYYrVM%hUG)r4HUlzlv*RB3hr86>gXt z8j)Abv~4pN_wAi~HP*^aaQiT!M0*c8 zH+3bPtD1JZMl`V^$+co1Q*3QrU0VJ_z0<<0e@Q>zKlyQ{XktxLVV3Q)swmePZK4lr zFMgQubZx=K>gUI&?tfS%-D6<4QORch`5h|?7A@a@_+5GSm-8xj79C`g!)#{iU}eCe-Dui>=w}4xr-=eM7Ux@0y7A4bv ze0ptl#=Pei^Uv@8FS;$Zy)>IMcVi99>95!Gk|ULNeJ`(ei^nR+=DTPg5| ZeOl(pcb^(oIswZY22WQ%mvv4FO#m`>EK2|Y literal 0 HcmV?d00001 diff --git a/assets/graphics/sprites/rectangle.png b/assets/graphics/sprites/rectangle.png new file mode 100644 index 0000000000000000000000000000000000000000..af2800edafdb0a0da7462325b5365343c7d478fb GIT binary patch literal 487 zcmeAS@N?(olHy`uVBq!ia0vp^(?FPm4M^HB7CvHNU|i?v;uumf=j|OsuEP!jEC+2L z|F8c!Me=D_vBIi21INt|*Uh}i%>R3i+yQIO?v@Q69MmL^eE-t0dvER9KgXk9e`%2y zr>5D|b}O;w9ho(=wu}Y0X@#;<50~z%J$0b~xCE7`1H{fqu*e^JNGaFdM{ciLVf7#B3mM*$|c> zP=%>*c%N90Kq;oeU0E?+0 z$P=d#pfME)?L-v<6sE%=MWhi>VLA-5L=ysbOou{_IEBD8rX|ouEJc9FbO@{>HX_i6 z>0oFe_9LLjbPyaN&LGf$=|H%&p(p!OLnCu}Jag?$3bSCUgS{DAXi+9N5A073$!pVc z`5&8i>J`J^^cK$jj0ESWPhyqClO5fg!%98NQI;2r%<6c?*MsQQhH8bm#-j}tC&Ydk zyJ&b&(f`$wSs(d6S8EL$JK=|2Z70hPd3#F!lX5tDpREWmb}43re=P#>vba|1xf_20 DsmQXX literal 0 HcmV?d00001 diff --git a/game/play.py b/game/play.py index dd2bbcb..3783fd0 100644 --- a/game/play.py +++ b/game/play.py @@ -1,11 +1,12 @@ import arcade, arcade.gui, pyglet, random -from utils.constants import slider_style, dropdown_style, VAR_NAMES, VAR_DEFAULT, DEFAULT_GRAVITY, VAR_OPTIONS, DO_RULES, IF_RULES +from utils.preload import SPRITE_TEXTURES +from utils.constants import slider_style, dropdown_style, VAR_NAMES, VAR_DEFAULT, DEFAULT_X_GRAVITY, DEFAULT_Y_GRAVITY, VAR_OPTIONS, DO_RULES, IF_RULES, SHAPES, ALLOWED_INPUT from arcade.gui.experimental.scroll_area import UIScrollArea, UIScrollBar from game.rules import generate_rule -from game.sprites import * +from game.sprites import BaseShape, Rectangle, Circle, Triangle class Game(arcade.gui.UIView): def __init__(self, pypresence_client): @@ -18,16 +19,19 @@ class Game(arcade.gui.UIView): self.scroll_area = UIScrollArea(size_hint=(0.25, 1)) # center on screen self.scroll_area.scroll_speed = -75 - self.anchor.add(self.scroll_area, anchor_x="right", anchor_y="center", align_x=-self.window.width * 0.02) + self.anchor.add(self.scroll_area, anchor_x="right", anchor_y="bottom", align_x=-self.window.width * 0.02) self.scrollbar = UIScrollBar(self.scroll_area) self.scrollbar.size_hint = (0.02, 1) self.anchor.add(self.scrollbar, anchor_x="right", anchor_y="center") - self.rules_box = arcade.gui.UIBoxLayout(align="left", size_hint=(0.25, 1)).with_background(color=arcade.color.DARK_GRAY) + self.rules_box = arcade.gui.UIBoxLayout(align="center", size_hint=(0.25, 1)).with_background(color=arcade.color.DARK_GRAY) self.scroll_area.add(self.rules_box) - self.gravity = DEFAULT_GRAVITY + self.sprites_box = self.anchor.add(arcade.gui.UIBoxLayout(size_hint=(0.15, 1), align="center", space_between=10).with_background(color=arcade.color.DARK_GRAY), anchor_x="left", anchor_y="bottom") + + self.x_gravity = DEFAULT_X_GRAVITY + self.y_gravity = DEFAULT_Y_GRAVITY self.current_ruleset_num = 0 self.rulesets = {} @@ -40,39 +44,119 @@ class Game(arcade.gui.UIView): self.shapes = [] self.shape_batch = pyglet.graphics.Batch() - def move_x(self, shape, a): - shape.x += a + def move_x(self, a, shape): + if isinstance(shape, Triangle): + shape.x += a + shape.x2 += a + shape.x3 += a + else: + shape.x += a - def move_y(self, shape, a): - shape.y += a + def move_y(self, a, shape): + if isinstance(shape, Triangle): + shape.y += a + shape.y2 += a + shape.y3 += a + else: + shape.y += a - def change_x(self, shape, a): - shape.x = a + def change_x(self, a, shape): + if isinstance(shape, Triangle): + offset_x2 = shape.x2 - shape.x + offset_x3 = shape.x3 - shape.x + + shape.x = a + shape.x2 = a + offset_x2 + shape.x3 = a + offset_x3 + else: + shape.x = a + + def change_y(self, a, shape): + if isinstance(shape, Triangle): + offset_y2 = shape.y2 - shape.y + offset_y3 = shape.y3 - shape.y + + shape.y = a + shape.y2 = a + offset_y2 + shape.y3 = a + offset_y3 + else: + shape.y = a - def change_y(self, shape, a): - shape.y = a - - def change_x_velocity(self, shape, a): + def change_x_velocity(self, a, shape): shape.x_velocity = a + self.triggered_events.append(["x_velocity_change", {"event_shape_type": shape.shape_type, "shape_size": shape.shape_size, "shape_x": shape.x, "shape_y": shape.y, "shape": shape, "shape_color": shape.color}]) - def change_y_velocity(self, shape, a): + def change_y_velocity(self, a, shape): shape.y_velocity = a + self.triggered_events.append(["y_velocity_change", {"event_shape_type": shape.shape_type, "shape_size": shape.shape_size, "shape_x": shape.x, "shape_y": shape.y, "shape": shape, "shape_color": shape.color}]) - def change_gravity(self, a): - self.gravity = a + def change_x_gravity(self, a): + self.x_gravity = a + self.triggered_events.append(["x_gravity_change", {}]) - def spawn(self, shape): - x, y = random.randint(100, self.window.width - 100), random.randint(100, self.window.height - 100) + def change_y_gravity(self, a): + self.y_gravity = a + self.triggered_events.append(["y_gravity_change", {}]) - if shape == "circle": + def change_color(self, a, shape): + shape.color = getattr(arcade.color, a) + self.triggered_events.append(["color_change", {"event_shape_type": shape.shape_type, "shape_size": shape.shape_size, "shape_x": shape.x, "shape_y": shape.y, "shape": shape, "shape_color": shape.color}]) + + def destroy(self, shape: BaseShape): + self.triggered_events.append(["destroyed", {"event_shape_type": shape.shape_type}]) + if shape in self.shapes: + self.shapes.remove(shape) + shape.delete() + + def change_size(self, a, shape): + if isinstance(shape, Circle): + shape.radius = a + elif isinstance(shape, Rectangle): + shape.width = a + shape.height = a + elif isinstance(shape, Triangle): + size = a - shape.shape_size + + shape.x += size + shape.y += size + + shape.x2 += size + shape.y2 += size + + shape.x3 += size + shape.y3 += size + + self.triggered_events.append(["size_change", {"event_shape_type": shape.shape_type, "shape_size": shape.shape_size, "shape_x": shape.x, "shape_y": shape.y, "shape": shape, "shape_color": shape.color}]) + + def spawn(self, shape_type): + x, y = random.randint(self.window.width * 0.15 + 50, self.window.width * 0.75 - 50), random.randint(100, self.window.height - 100) + + if shape_type == "circle": self.shapes.append(Circle(x, y, 10, color=arcade.color.WHITE, batch=self.shape_batch)) - elif shape == "rectangle": + elif shape_type == "rectangle": self.shapes.append(Rectangle(x, y, width=10, height=10, color=arcade.color.WHITE, batch=self.shape_batch)) - elif shape == "triangle": + elif shape_type == "triangle": self.shapes.append(Triangle(x, y, x + 10, y, x + 5, y + 10, color=arcade.color.WHITE, batch=self.shape_batch)) + shape = self.shapes[-1] + + self.triggered_events.append(["spawns", {"event_shape_type": shape.shape_type, "shape_size": shape.shape_size, "shape_x": shape.x, "shape_y": shape.y, "shape": shape, "shape_color": shape.color}]) + + def morph(self, a, shape): + old_shape_x, old_shape_y, old_shape_size, old_shape_color = shape.x, shape.y, shape.shape_size, shape.shape_color + self.destroy(shape) + + if a == "circle": + self.shapes.append(Circle(old_shape_x, old_shape_y, old_shape_size, color=getattr(arcade.color, old_shape_color), batch=self.shape_batch)) + + elif a == "rectangle": + self.shapes.append(Rectangle(old_shape_x, old_shape_y, width=old_shape_size, height=old_shape_size, color=getattr(arcade.color, old_shape_color), batch=self.shape_batch)) + + elif a == "triangle": + self.shapes.append(Triangle(old_shape_x, old_shape_y, old_shape_x + old_shape_size, old_shape_y, old_shape_x + int(old_shape_size / 2), old_shape_y + old_shape_size, color=getattr(arcade.color, old_shape_color), batch=self.shape_batch)) + def create_rule_ui(self, rule_box: arcade.gui.UIBoxLayout, rule, rule_type, rule_num=1): rule_dict = IF_RULES[rule] if rule_type == "if" else DO_RULES[rule] @@ -81,7 +165,7 @@ class Game(arcade.gui.UIView): default_values = {VAR_NAMES[n]: VAR_DEFAULT[variable] for n, variable in enumerate(rule_dict["user_vars"])} description = rule_dict["description"].format_map(default_values) - desc_label = rule_box.add(arcade.gui.UILabel(description if rule_type == "if" else f"THEN {description}", font_size=13, width=self.window.width * 0.25)) + desc_label = rule_box.add(arcade.gui.UILabel(description, font_size=13, width=self.window.width * 0.225)) self.rule_labels[f"{self.current_ruleset_num}_{rule_num}_desc"] = desc_label for n, variable_type in enumerate(rule_dict["user_vars"]): @@ -89,16 +173,17 @@ class Game(arcade.gui.UIView): self.rule_values[key] = default_values[VAR_NAMES[n]] - label = rule_box.add(arcade.gui.UILabel(f'{VAR_NAMES[n]}: {default_values[VAR_NAMES[n]]}', font_size=11, width=self.window.width * 0.25, height=self.window.height / 25)) + label = rule_box.add(arcade.gui.UILabel(f'{VAR_NAMES[n]}: {default_values[VAR_NAMES[n]]}', font_size=11, width=self.window.width * 0.225, height=self.window.height / 25)) self.rule_labels[key] = label if variable_type in ["variable", "size"]: - slider = rule_box.add(arcade.gui.UISlider(value=default_values[VAR_NAMES[n]], min_value=VAR_OPTIONS[variable_type][0], max_value=VAR_OPTIONS[variable_type][1], step=1, style=slider_style, width=self.window.width * 0.25, height=self.window.height / 25)) + slider = rule_box.add(arcade.gui.UISlider(value=default_values[VAR_NAMES[n]], min_value=VAR_OPTIONS[variable_type][0], max_value=VAR_OPTIONS[variable_type][1], step=1, style=slider_style, width=self.window.width * 0.225, height=self.window.height / 25)) slider._render_steps = lambda surface: None slider.on_change = lambda event, variable_type=variable_type, rule=rule, rule_type=rule_type, ruleset_num=ruleset_num, rule_num=rule_num, n=n: self.change_rule_value(ruleset_num, rule_num, rule, rule_type, variable_type, n, event.new_value) self.rule_var_changers[key] = slider + elif variable_type in ["shape_type", "target_type", "color"]: - dropdown = rule_box.add(arcade.gui.UIDropdown(default=default_values[VAR_NAMES[n]], options=VAR_OPTIONS[variable_type], active_style=dropdown_style, primary_style=dropdown_style, dropdown_style=dropdown_style, width=self.window.width * 0.25, height=self.window.height / 25)) + dropdown = rule_box.add(arcade.gui.UIDropdown(default=default_values[VAR_NAMES[n]], options=VAR_OPTIONS[variable_type], active_style=dropdown_style, primary_style=dropdown_style, dropdown_style=dropdown_style, width=self.window.width * 0.225, height=self.window.height / 25)) dropdown.on_change = lambda event, variable_type=variable_type, rule=rule, rule_type=rule_type, ruleset_num=ruleset_num, rule_num=rule_num, n=n: self.change_rule_value(ruleset_num, rule_num, rule, rule_type, variable_type, n, event.new_value) self.rule_var_changers[key] = dropdown @@ -109,7 +194,7 @@ class Game(arcade.gui.UIView): self.rulesets[self.current_ruleset_num] = ruleset self.create_rule_ui(rule_box, ruleset[0], "if") - self.create_rule_ui(rule_box, ruleset[1], "do") + self.create_rule_ui(rule_box, ruleset[1], "do", 2) else: self.rulesets[self.current_ruleset_num] = ruleset @@ -124,25 +209,35 @@ class Game(arcade.gui.UIView): def on_show_view(self): super().on_show_view() - add_rule_button = self.rules_box.add(arcade.gui.UIFlatButton(text="Add rule", width=self.window.width * 0.25, height=self.window.height / 15, style=dropdown_style)) + self.rules_box.add(arcade.gui.UILabel(text="Rules", font_size=24, text_color=arcade.color.BLACK)) + self.rules_box.add(arcade.gui.UISpace(height=self.window.height / 50, width=self.window.width * 0.25)) # have to add a width of 0.25 so it doesnt resize to 0.225 + + add_rule_button = self.rules_box.add(arcade.gui.UIFlatButton(text="Add rule", width=self.window.width * 0.225, height=self.window.height / 15, style=dropdown_style)) add_rule_button.on_click = lambda event: self.add_rule() self.rules_box.add(arcade.gui.UISpace(height=self.window.height / 50)) - for _ in range(8): - self.add_rule() + self.add_rule(["on_left_click", "spawn"]) + self.add_rule(["size_greater", "morph_into"]) + + self.sprites_box.add(arcade.gui.UILabel(text="Sprites", font_size=24, text_color=arcade.color.BLACK)) + self.sprites_box.add(arcade.gui.UISpace(height=self.window.height / 50)) + + for shape in SHAPES: + self.sprites_box.add(arcade.gui.UILabel(text=shape, font_size=16)) + self.sprites_box.add(arcade.gui.UIImage(texture=SPRITE_TEXTURES[shape], width=self.window.width / 15, height=self.window.width / 15)) self.triggered_events.append(["game_launch", {}]) - def add_rule(self): - self.rulesets[self.current_ruleset_num] = generate_rule() + def add_rule(self, force=None): + self.rulesets[self.current_ruleset_num] = generate_rule() if not force else force self.add_ruleset(self.rulesets[self.current_ruleset_num]) self.current_ruleset_num += 1 def get_rule_values(self, ruleset_num, rule_num, rule_dict, event_args): args = [self.rule_values[f"{ruleset_num}_{rule_num}_{user_var}_{n}"] for n, user_var in enumerate(rule_dict["user_vars"])] - return args + [event_args[var] for var in rule_dict.get("vars", []) if var in rule_dict["user_vars"]] + return args + [event_args[var] for var in rule_dict.get("vars", []) if not var in rule_dict["user_vars"]] def check_rule(self, ruleset_num, rule_num, rule_dict, event_args): return rule_dict["func"](*self.get_rule_values(ruleset_num, rule_num, rule_dict, event_args)) @@ -151,7 +246,8 @@ class Game(arcade.gui.UIView): ACTION_FUNCTION_DICT = { "global_action": { "spawn": self.spawn, - "change_gravity": self.change_gravity + "change_x_gravity": self.change_x_gravity, + "change_y_gravity": self.change_y_gravity }, "shape_action": { "move_x": self.move_x, @@ -159,7 +255,11 @@ class Game(arcade.gui.UIView): "change_x": self.change_x, "change_y": self.change_y, "change_x_velocity": self.change_x_velocity, - "change_y_velocity": self.change_y_velocity + "change_y_velocity": self.change_y_velocity, + "change_color": self.change_color, + "change_size": self.change_size, + "destroy": self.destroy, + "morph": self.morph } } @@ -173,7 +273,6 @@ class Game(arcade.gui.UIView): while len(self.triggered_events) > 0: trigger, trigger_args = self.triggered_events.pop(0) - for key, ruleset in self.rulesets.items(): if len(ruleset) == 2: if_rule_dict = IF_RULES[ruleset[0]] @@ -182,20 +281,19 @@ class Game(arcade.gui.UIView): if not if_rule_dict["trigger"] == trigger: continue - if if_rule_dict["trigger"] in ["every_update"]: - for shape in self.shapes: - event_args = trigger_args - + if do_rule_dict["action"]["type"] == "shape_action": + for shape in self.shapes: + event_args = trigger_args.copy() if not "event_shape_type" in trigger_args: - event_args.update({"event_shape_type": shape.shape_type, "shape_size": shape.size}) + event_args.update({"event_shape_type": shape.shape_type, "shape_size": shape.shape_size, "shape_x": shape.x, "shape_y": shape.y, "shape": shape, "shape_color": shape.color}) - if self.check_rule(key, 0, if_rule_dict, event_args): - self.run_do_rule(key, 1, do_rule_dict, event_args) + if self.check_rule(key, 1, if_rule_dict, event_args): + self.run_do_rule(key, 2, do_rule_dict, event_args) else: - event_args = trigger_args - if self.check_rule(key, 0, if_rule_dict, event_args): - self.run_do_rule(key, 1, do_rule_dict, event_args) - + event_args = trigger_args.copy() + if self.check_rule(key, 1, if_rule_dict, event_args): + self.run_do_rule(key, 2, do_rule_dict, event_args) + else: if_rule_dicts = IF_RULES[ruleset[0]], IF_RULES[ruleset[2]] do_rule_dict = DO_RULES[ruleset[3]] @@ -203,21 +301,35 @@ class Game(arcade.gui.UIView): if not (if_rule_dicts[0]["trigger"] == trigger and if_rule_dicts[0]["trigger"] == trigger): continue - for shape in self.shapes if not "event_shape_type" in trigger_args else [shape]: - event_args = trigger_args - if not "event_shape_type" in trigger_args: - event_args.update({"event_shape_type": shape.shape_type, "shape_size": shape.size}) + if do_rule_dict["action"]["type"] == "shape_action": + for shape in self.shapes: + event_args = trigger_args + + if not "event_shape_type" in trigger_args: + event_args.update({"event_shape_type": shape.shape_type, "shape_size": shape.shape_size, "shape_x": shape.x, "shape_y": shape.y, "shape": shape, "shape_color": shape.color}) + if ruleset[1] == "and": + if self.check_rule(key, 1, if_rule_dicts[0], event_args) and self.check_rule(key, 2, if_rule_dicts[1], event_args): + self.run_do_rule(key, 3, do_rule_dict, event_args) + + elif ruleset[1] == "or": + if self.check_rule(key, 1, if_rule_dicts[0], event_args) or self.check_rule(key, 2, if_rule_dicts[1], event_args): + self.run_do_rule(key, 3, do_rule_dict, event_args) + else: + event_args = trigger_args if ruleset[1] == "and": - if self.check_rule(key, 0, if_rule_dicts[0], event_args) and self.check_rule(key, 2, if_rule_dicts[1], event_args): + if self.check_rule(key, 1, if_rule_dicts[0], event_args) and self.check_rule(key, 2, if_rule_dicts[1], event_args): self.run_do_rule(key, 3, do_rule_dict, event_args) elif ruleset[1] == "or": - if self.check_rule(key, 0, if_rule_dicts[0], event_args) or self.check_rule(key, 2, if_rule_dicts[1], event_args): + if self.check_rule(key, 1, if_rule_dicts[0], event_args) or self.check_rule(key, 2, if_rule_dicts[1], event_args): self.run_do_rule(key, 3, do_rule_dict, event_args) for shape in self.shapes: - shape.update(self.gravity) + shape.update(self.x_gravity, self.y_gravity) + + if shape.x < 0 or shape.x > self.window.width or shape.y < 0 or shape.y > self.window.height: + self.destroy(shape) def change_rule_value(self, ruleset_num, rule_num, rule, rule_type, variable_type, n, value): rule_dict = IF_RULES[rule] if rule_type == "if" else DO_RULES[rule] @@ -232,10 +344,29 @@ class Game(arcade.gui.UIView): description = rule_dict["description"].format_map(values) - self.rule_labels[f"{ruleset_num}_{rule_num}_desc"].text = description if rule_type == "if" else f"THEN {description}" + self.rule_labels[f"{ruleset_num}_{rule_num}_desc"].text = description self.rule_labels[key].text = f'{VAR_NAMES[n]}: {value}' - def on_draw(self): - super().on_draw() + def on_key_press(self, symbol, modifiers): + if symbol == arcade.key.ESCAPE: + self.main_exit() + elif symbol in ALLOWED_INPUT: + self.triggered_events.append(["on_input", {"event_key": chr(symbol)}]) - self.shape_batch.draw() \ No newline at end of file + def on_mouse_press(self, x, y, button, modifiers): + if button == arcade.MOUSE_BUTTON_LEFT: + self.triggered_events.append(["on_left_click", {}]) + elif button == arcade.MOUSE_BUTTON_RIGHT: + self.triggered_events.append(["on_right_click", {}]) + + def on_mouse_move(self, x, y, button, modifiers): + self.triggered_events.append(["on_mouse_move", {}]) + + def main_exit(self): + from menus.main import Main + self.window.show_view(Main(self.pypresence_client)) + + def on_draw(self): + self.window.clear() + self.shape_batch.draw() + self.ui.draw() \ No newline at end of file diff --git a/game/sprites.py b/game/sprites.py index 0e57c96..696be3f 100644 --- a/game/sprites.py +++ b/game/sprites.py @@ -1,4 +1,4 @@ -import pyglet +import pyglet, arcade.color from utils.constants import DEFAULT_X_VELOCITY, DEFAULT_Y_VELOCITY @@ -7,11 +7,22 @@ class BaseShape(): self.shape_type = "" self.x_velocity = DEFAULT_X_VELOCITY self.y_velocity = DEFAULT_Y_VELOCITY + self._shape_color = "WHITE" - def update(self, gravity): + def update(self, x_gravity, y_gravity): self.x += self.x_velocity self.y += self.y_velocity - self.y -= gravity + self.x -= x_gravity + self.y -= y_gravity + + @property + def shape_color(self): + return self._shape_color + + @shape_color.setter + def shape_color(self, color): + self._shape_color = color + self.color = getattr(arcade.color, color) class Circle(pyglet.shapes.Circle, BaseShape): def __init__(self, *args, **kwargs): @@ -41,4 +52,4 @@ class Triangle(pyglet.shapes.Triangle, BaseShape): @property def shape_size(self): - return self.x2 - self.x \ No newline at end of file + return max(self.x, self.x2, self.x3) - min(self.x, self.x2, self.x3) \ No newline at end of file diff --git a/utils/constants.py b/utils/constants.py index e802a41..f931dae 100644 --- a/utils/constants.py +++ b/utils/constants.py @@ -7,11 +7,27 @@ LOGICAL_OPERATORS = ["and", "or"] SHAPES = ["rectangle", "circle", "triangle"] VAR_NAMES = ["a", "b", "c", "d", "e", "f", "g"] -DEFAULT_GRAVITY = 2 +DEFAULT_X_GRAVITY = 0 +DEFAULT_Y_GRAVITY = 2 + DEFAULT_X_VELOCITY = 0 DEFAULT_Y_VELOCITY = 0 -COLORS = [key for key, value in arcade.color.__dict__.items() if isinstance(value, Color)] +ALLOWED_INPUT = [ord(key) for key in ["a", "b", "c", "d", "e", "q", "w", "s", "t"]] + +COLORS = [ + "BLACK", "WHITE", "GRAY", "DARK_GRAY", "CYAN", + "AMBER", "AQUA", "GREEN", "LIGHT_GREEN", + "RED", "LIGHT_RED", "DARK_RED", + "BLUE", "LIGHT_BLUE", "DARK_BLUE", + "YELLOW", "LIGHT_YELLOW", "DARK_YELLOW", + "MAGENTA", "PURPLE", "VIOLET", "INDIGO", + "ORANGE", "BROWN", + "GOLD", "SILVER", "BRONZE", + "TEAL", "AZURE", + "PINK", "HOT_PINK", + "MINT_GREEN", "CHARTREUSE" +] VAR_DEFAULT = { "shape_type": SHAPES[0], @@ -19,49 +35,94 @@ VAR_DEFAULT = { "variable": 0, "color": "WHITE", "size": 10, + "key_input": ALLOWED_INPUT[0] } VAR_OPTIONS = { "shape_type": SHAPES, "target_type": SHAPES, - "variable": (0, 2500), + "variable": (-700, 700), "color": COLORS, - "size": (1, 200), + "size": (1, 200), + "key_input": ALLOWED_INPUT } IF_RULES = { - "x_position": { - "key": "x_position", - "description": "IF X for {a} shape is {b}", + "x_position_greater": { + "key": "x_position_greater", + "description": "IF X for {a} shape is greater than {b}", "trigger": "every_update", "user_vars": ["shape_type", "variable"], "vars": ["shape_type", "variable", "event_shape_type", "shape_x"], - "func": lambda *v: (v[0] == v[2]) and (v[3] == v[1]) + "func": lambda *v: (v[0] == v[2]) and (v[3] > v[1]) }, - "y_position": { - "key": "y_position", - "description": "IF Y for {a} shape is {b}", + "x_position_less": { + "key": "x_position_less", + "description": "IF X for {a} shape is less than {b}", + "trigger": "every_update", + "user_vars": ["shape_type", "variable"], + "vars": ["shape_type", "variable", "event_shape_type", "shape_x"], + "func": lambda *v: (v[0] == v[2]) and (v[3] < v[1]) + }, + "x_position_between": { + "key": "x_position_between", + "description": "IF X for {a} shape is between {b} and {c}", + "trigger": "every_update", + "user_vars": ["shape_type", "variable", "variable"], + "vars": ["shape_type", "variable", "variable", "event_shape_type", "shape_x"], + "func": lambda *v: (v[0] == v[3]) and (min(v[1], v[2]) <= v[4] <= max(v[1], v[2])) + }, + + "y_position_greater": { + "key": "y_position_greater", + "description": "IF Y for {a} shape is greater than {b}", "trigger": "every_update", "user_vars": ["shape_type", "variable"], "vars": ["shape_type", "variable", "event_shape_type", "shape_y"], - "func": lambda *v: (v[0] == v[2]) and (v[3] == v[1]) + "func": lambda *v: (v[0] == v[2]) and (v[3] > v[1]) }, - "color_is": { - "key": "color_is", - "description": "IF {a} shape color is {b}", + "y_position_less": { + "key": "y_position_less", + "description": "IF Y for {a} shape is less than {b}", "trigger": "every_update", - "user_vars": ["shape_type", "color"], - "vars": ["shape_type", "color", "event_shape_type", "shape_color"], - "func": lambda *v: (v[0] == v[2]) and (v[3] == v[1]) + "user_vars": ["shape_type", "variable"], + "vars": ["shape_type", "variable", "event_shape_type", "shape_y"], + "func": lambda *v: (v[0] == v[2]) and (v[3] < v[1]) }, - "size_is": { - "key": "size_is", - "description": "IF {a} shape size is {b}", + "y_position_between": { + "key": "y_position_between", + "description": "IF Y for {a} shape is between {b} and {c}", "trigger": "every_update", - "user_vars": ["shape_type", "size"], - "vars": ["shape_type", "size", "event_shape_type", "shape_size"], - "func": lambda *v: (v[0] == v[2]) and (v[3] == v[1]) + "user_vars": ["shape_type", "variable", "variable"], + "vars": ["shape_type", "variable", "variable", "event_shape_type", "shape_y"], + "func": lambda *v: (v[0] == v[3]) and (min(v[1], v[2]) <= v[4] <= max(v[1], v[2])) }, + + "size_greater": { + "key": "size_greater", + "description": "IF {a} shape size is greater than {b}", + "trigger": "every_update", + "user_vars": ["shape_type", "variable"], + "vars": ["shape_type", "variable", "event_shape_type", "shape_size"], + "func": lambda *v: (v[0] == v[2]) and (v[3] > v[1]) + }, + "size_less": { + "key": "size_less", + "description": "IF {a} shape size is less than {b}", + "trigger": "every_update", + "user_vars": ["shape_type", "variable"], + "vars": ["shape_type", "variable", "event_shape_type", "shape_size"], + "func": lambda *v: (v[0] == v[2]) and (v[3] < v[1]) + }, + "size_between": { + "key": "size_between", + "description": "IF {a} shape size is between {b} and {c}", + "trigger": "every_update", + "user_vars": ["shape_type", "variable", "variable"], + "vars": ["shape_type", "variable", "variable", "event_shape_type", "shape_size"], + "func": lambda *v: (v[0] == v[3]) and (min(v[1], v[2]) <= v[4] <= max(v[1], v[2])) + }, + "spawns": { "key": "spawns", "description": "IF {a} shape spawns", @@ -81,7 +142,7 @@ IF_RULES = { "x_velocity_changes": { "key": "x_velocity_changes", "description": "IF {a} shape X velocity changes", - "trigger": "x_change", + "trigger": "x_velocity_change", "user_vars": ["shape_type"], "vars": ["shape_type", "event_shape_type"], "func": lambda *v: v[0] == v[1] @@ -89,7 +150,7 @@ IF_RULES = { "y_velocity_changes": { "key": "y_velocity_changes", "description": "IF {a} shape Y velocity changes", - "trigger": "y_change", + "trigger": "y_velocity_change", "user_vars": ["shape_type"], "vars": ["shape_type", "event_shape_type"], "func": lambda *v: v[0] == v[1] @@ -110,14 +171,6 @@ IF_RULES = { "vars": ["shape_type", "event_shape_type"], "func": lambda *v: v[0] == v[1] }, - "gravity_changes": { - "key": "gravity_changes", - "description": "IF gravity changes", - "user_vars": [], - "trigger": "gravity_change", - "vars": [], - "func": lambda *v: True - }, "color_changes": { "key": "color_changes", "description": "IF {a} shape color changes", @@ -150,6 +203,38 @@ IF_RULES = { "vars": ["shape_type", "target_type", "event_a_type", "event_b_type"], "func": lambda *v: (v[0] == v[2]) and (v[3] == v[1]) }, + "on_left_click": { + "key": "on_left_click", + "description": "IF you left click", + "trigger": "on_left_click", + "user_vars": [], + "vars": [], + "func": lambda *v: True + }, + "on_right_click": { + "key": "on_right_click", + "description": "IF you right click", + "trigger": "on_right_click", + "user_vars": [], + "vars": [], + "func": lambda *v: True + }, + "on_mouse_move": { + "key": "on_mouse_move", + "description": "IF mouse moves", + "trigger": "on_mouse_move", + "user_vars": [], + "vars": [], + "func": lambda *v: True + }, + "on_input": { + "key": "on_input", + "description": "IF {a} key is pressed", + "trigger": "on_input", + "user_vars": ["key_input"], + "vars": ["key_input", "event_key"], + "func": lambda *v: v[0] == v[1] + }, "game_launch": { "key": "game_launch", "description": "IF game launches", @@ -176,39 +261,29 @@ NON_COMPATIBLE_WHEN = [ ("spawns", "y_velocity_changes"), ("spawns", "x_gravity_changes"), ("spawns", "y_gravity_changes"), - ("spawns", "gravity_changes"), ("spawns", "color_changes"), ("spawns", "size_changes"), - + ("destroyed", "morphs"), ("destroyed", "collides"), ("destroyed", "x_velocity_changes"), ("destroyed", "y_velocity_changes"), ("destroyed", "x_gravity_changes"), ("destroyed", "y_gravity_changes"), - ("destroyed", "gravity_changes"), ("destroyed", "color_changes"), ("destroyed", "size_changes"), - + ("morphs", "collides"), ("morphs", "x_velocity_changes"), ("morphs", "y_velocity_changes"), ("morphs", "x_gravity_changes"), ("morphs", "y_gravity_changes"), - ("morphs", "gravity_changes"), ("morphs", "color_changes"), ("morphs", "size_changes"), - + ("collides", "destroyed"), ("collides", "morphs"), - ("collides", "gravity_changes"), - - ("x_gravity_changes", "gravity_changes"), - ("y_gravity_changes", "gravity_changes"), - - ("color_changes", "gravity_changes"), - ("size_changes", "gravity_changes"), - + ("every_update", "spawns"), ("every_update", "destroyed"), ("every_update", "morphs"), @@ -217,22 +292,20 @@ NON_COMPATIBLE_WHEN = [ ("every_update", "y_velocity_changes"), ("every_update", "x_gravity_changes"), ("every_update", "y_gravity_changes"), - ("every_update", "gravity_changes"), ("every_update", "color_changes"), ("every_update", "size_changes"), - ("every_update", "launch"), - - ("launch", "spawns"), - ("launch", "destroyed"), - ("launch", "morphs"), - ("launch", "collides"), - ("launch", "x_velocity_changes"), - ("launch", "y_velocity_changes"), - ("launch", "x_gravity_changes"), - ("launch", "y_gravity_changes"), - ("launch", "gravity_changes"), - ("launch", "color_changes"), - ("launch", "size_changes"), + ("every_update", "game_launch"), + + ("game_launch", "spawns"), + ("game_launch", "destroyed"), + ("game_launch", "morphs"), + ("game_launch", "collides"), + ("game_launch", "x_velocity_changes"), + ("game_launch", "y_velocity_changes"), + ("game_launch", "x_gravity_changes"), + ("game_launch", "y_gravity_changes"), + ("game_launch", "color_changes"), + ("game_launch", "size_changes"), ] NON_COMPATIBLE_DO_WHEN = [ @@ -242,43 +315,45 @@ NON_COMPATIBLE_DO_WHEN = [ ("destroyed", "move_y"), ("destroyed", "change_x_velocity"), ("destroyed", "change_y_velocity"), - ("destroyed", "change_gravity"), + ("destroyed", "change_x_gravity"), + ("destroyed", "change_y_gravity"), ("destroyed", "change_color"), ("destroyed", "change_size"), ("destroyed", "morph_into"), ("destroyed", "destroy"), - + ("morphs", "morph_into"), - - ("gravity_changes", "change_x"), - ("gravity_changes", "change_y"), - ("gravity_changes", "move_x"), - ("gravity_changes", "move_y"), - ("gravity_changes", "change_x_velocity"), - ("gravity_changes", "change_y_velocity"), - ("gravity_changes", "change_gravity"), - ("gravity_changes", "change_color"), - ("gravity_changes", "change_size"), - ("gravity_changes", "morph_into"), - ("gravity_changes", "destroy"), - + ("x_velocity_changes", "change_x_velocity"), ("y_velocity_changes", "change_y_velocity"), ("color_changes", "change_color"), + ("size_changes", "change_size"), - - ("launch", "change_x"), - ("launch", "change_y"), - ("launch", "move_x"), - ("launch", "move_y"), - ("launch", "change_x_velocity"), - ("launch", "change_y_velocity"), - ("launch", "change_gravity"), - ("launch", "change_color"), - ("launch", "change_size"), - ("launch", "destroy"), - ("launch", "morph_into") + + ("every_update", "change_x"), + ("every_update", "change_y"), + ("every_update", "move_x"), + ("every_update", "move_y"), + ("every_update", "change_x_velocity"), + ("every_update", "change_y_velocity"), + ("every_update", "change_color"), + ("every_update", "change_size"), + ("every_update", "destroy"), + ("every_update", "morph_into"), + + ("game_launch", "change_x"), + ("game_launch", "change_y"), + ("game_launch", "move_x"), + ("game_launch", "move_y"), + ("game_launch", "change_x_velocity"), + ("game_launch", "change_y_velocity"), + ("game_launch", "change_x_gravity"), + ("game_launch", "change_y_gravity"), + ("game_launch", "change_color"), + ("game_launch", "change_size"), + ("game_launch", "destroy"), + ("game_launch", "morph_into") ] DO_RULES = { @@ -286,84 +361,104 @@ DO_RULES = { "key": "change_x", "description": "Change this shape's X to {a}", "action": {"type": "shape_action", "name": "change_x"}, - "user_vars": ["shape", "variable"] + "user_vars": ["variable"], + "vars": ["shape", "variable"] }, "change_y": { "key": "change_y", "description": "Change this shape's Y to {a}", "action": {"type": "shape_action", "name": "change_y"}, - "user_vars": ["shape", "variable"] + "user_vars": ["variable"], + "vars": ["shape", "variable"] }, "move_x": { "key": "move_x", "description": "Move this shape's X by {a}", "action": {"type": "shape_action", "name": "move_x"}, - "user_vars": ["shape", "variable"] + "user_vars": ["variable"], + "vars": ["shape", "variable"] }, "move_y": { "key": "move_y", "description": "Move this shape's Y by {a}", "action": {"type": "shape_action", "name": "move_y"}, - "user_vars": ["shape", "variable"] + "user_vars": ["variable"], + "vars": ["shape", "variable"] }, "change_x_velocity": { "key": "change_x_velocity", "description": "Change X velocity of this to {a}", - "action": {"type": "shape_action", "name": "change_x_vel"}, - "user_vars": ["shape", "variable"] + "action": {"type": "shape_action", "name": "change_x_velocity"}, + "user_vars": ["variable"], + "vars": ["shape", "variable"] }, "change_y_velocity": { "key": "change_y_velocity", "description": "Change Y velocity of this to {a}", - "action": {"type": "shape_action", "name": "change_y_vel"}, - "user_vars": ["shape", "variable"] + "action": {"type": "shape_action", "name": "change_y_velocity"}, + "user_vars": ["variable"], + "vars": ["shape", "variable"] }, "change_color": { "key": "change_color", "description": "Change this shape's color to {a}", "action": {"type": "shape_action", "name": "change_color"}, - "user_vars": ["shape", "color"] + "user_vars": ["color"], + "vars": ["shape", "color"] }, "change_size": { "key": "change_size", "description": "Change this shape's size to {a}", "action": {"type": "shape_action", "name": "change_size"}, - "user_vars": ["shape", "size"] + "user_vars": ["size"], + "vars": ["shape", "size"] }, "destroy": { "key": "destroy", "description": "Destroy this", "action": {"type": "shape_action", "name": "destroy"}, - "user_vars": ["shape"] + "user_vars": [], + "vars": ["shape"] }, "morph_into": { "key": "morph_into", "description": "Morph this into {a}", "action": {"type": "shape_action", "name": "morph"}, - "user_vars": ["shape", "shape_type"] + "user_vars": ["shape_type"], + "vars": ["shape", "shape_type"] }, - "change_gravity": { - "key": "change_gravity", - "description": "Change gravity to {a}", - "action": {"type": "global_action", "name": "change_gravity"}, - "user_vars": ["shape", "variable"] + "change_x_gravity": { + "key": "change_x_gravity", + "description": "Change X gravity to {a}", + "action": {"type": "global_action", "name": "change_x_gravity"}, + "user_vars": ["variable"], + "vars": ["variable"] + }, + + "change_y_gravity": { + "key": "change_y_gravity", + "description": "Change Y gravity to {a}", + "action": {"type": "global_action", "name": "change_y_gravity"}, + "user_vars": ["variable"], + "vars": ["variable"] }, "spawn": { "key": "spawn", "description": "Spawn {a}", "action": {"type": "global_action", "name": "spawn"}, - "user_vars": ["shape_type"] + "user_vars": ["shape_type"], + "vars": ["shape_type"] } } diff --git a/utils/preload.py b/utils/preload.py index fcd2cf3..616c84d 100644 --- a/utils/preload.py +++ b/utils/preload.py @@ -5,4 +5,10 @@ _module_dir = os.path.dirname(os.path.abspath(__file__)) _assets_dir = os.path.join(os.path.dirname(_module_dir), 'assets') button_texture = arcade.gui.NinePatchTexture(64 // 4, 64 // 4, 64 // 4, 64 // 4, arcade.load_texture(os.path.join(_assets_dir, 'graphics', 'button.png'))) -button_hovered_texture = arcade.gui.NinePatchTexture(64 // 4, 64 // 4, 64 // 4, 64 // 4, arcade.load_texture(os.path.join(_assets_dir, 'graphics', 'button_hovered.png'))) \ No newline at end of file +button_hovered_texture = arcade.gui.NinePatchTexture(64 // 4, 64 // 4, 64 // 4, 64 // 4, arcade.load_texture(os.path.join(_assets_dir, 'graphics', 'button_hovered.png'))) + +SPRITE_TEXTURES = { + "circle": arcade.load_texture(os.path.join(_assets_dir, 'graphics', 'sprites', 'circle.png')), + "rectangle": arcade.load_texture(os.path.join(_assets_dir, 'graphics', 'sprites', 'rectangle.png')), + "triangle": arcade.load_texture(os.path.join(_assets_dir, 'graphics', 'sprites', 'triangle.png')), +} diff --git a/utils/utils.py b/utils/utils.py index 470037e..746040f 100644 --- a/utils/utils.py +++ b/utils/utils.py @@ -1,9 +1,7 @@ -import logging, arcade, arcade.gui, sys, traceback +import logging, arcade, arcade.gui, sys, traceback, pyglet.display from utils.constants import menu_background_color -import pyglet.info, pyglet.event - def dump_platform(): import platform logging.debug(f'Platform: {platform.platform()}') @@ -16,6 +14,7 @@ def dump_gl(context=None): info = context.get_info() else: from pyglet.gl import gl_info as info + logging.debug(f'gl_info.get_version(): {info.get_version()}') logging.debug(f'gl_info.get_vendor(): {info.get_vendor()}') logging.debug(f'gl_info.get_renderer(): {info.get_renderer()}') @@ -37,30 +36,7 @@ def print_debug_info(): logging.debug('') logging.debug('########################## DEBUG INFO ##########################') logging.debug('') - -class ErrorView(arcade.gui.UIView): - def __init__(self, message, title): - super().__init__() - - self.message = message - self.title = title - - def exit(self): - logging.fatal('Exited with error code 1.') - sys.exit(1) - - def on_show_view(self): - super().on_show_view() - - self.window.set_caption('Chaos Protocol - Error') - self.window.set_mouse_visible(True) - self.window.set_exclusive_mouse(False) - arcade.set_background_color(menu_background_color) - - msgbox = arcade.gui.UIMessageBox(width=self.window.width / 2, height=self.window.height / 2, message_text=self.message, title=self.title) - msgbox.on_action = lambda _: self.exit() - self.add_widget(msgbox) - + def on_exception(*exc_info): logging.error(f"Unhandled exception:\n{''.join(traceback.format_exception(exc_info[1], limit=None))}")