diff --git a/game/file_manager.py b/game/file_manager.py index dc60282..f6b3b3f 100644 --- a/game/file_manager.py +++ b/game/file_manager.py @@ -6,10 +6,11 @@ from utils.preload import button_texture, button_hovered_texture from arcade.gui.experimental.scroll_area import UIScrollArea, UIScrollBar class FileManager(arcade.gui.UIAnchorLayout): - def __init__(self, width, allowed_extensions): - super().__init__(size_hint=(0.95, 0.875), vertical=False) + def __init__(self, width, height, size_hint, allowed_extensions): + super().__init__(size_hint=size_hint, vertical=False) self.filemanager_width = width + self.filemanager_height = height self.current_directory = os.path.expanduser("~") self.allowed_extensions = allowed_extensions @@ -36,9 +37,9 @@ class FileManager(arcade.gui.UIAnchorLayout): self.bottom_box = self.add(arcade.gui.UIBoxLayout(space_between=5), anchor_x="center", anchor_y="bottom", align_y=5) self.filename_label = self.bottom_box.add(arcade.gui.UILabel(text="Filename:", font_name="Roboto", font_size=17)) - self.filename_input = self.bottom_box.add(arcade.gui.UIInputText(width=self.filemanager_width * 0.35, height=self.filemanager_width * 0.02).with_border(color=arcade.color.WHITE)) + self.filename_input = self.bottom_box.add(arcade.gui.UIInputText(width=self.filemanager_width * 0.35, height=self.filemanager_height * 0.05).with_border(color=arcade.color.WHITE)) - self.submit_button = self.bottom_box.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text="Submit", style=button_style, width=self.filemanager_width * 0.5, height=self.filemanager_width * 0.025)) + self.submit_button = self.bottom_box.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text="Submit", style=button_style, width=self.filemanager_width * 0.5, height=self.filemanager_height * 0.05)) self.submit_button.on_click = lambda event: self.submit(self.current_directory) self.submit_button.visible = False @@ -55,9 +56,7 @@ class FileManager(arcade.gui.UIAnchorLayout): def submit(self, content): self.submitted_content = content if self.mode == "import" else f"{content}/{self.filename_input.text}" - - self.disable() - + def get_content(self, directory): if not directory in self.content_cache or time.perf_counter() - self.content_cache[directory][-1] >= 30: try: @@ -109,19 +108,16 @@ class FileManager(arcade.gui.UIAnchorLayout): self.current_directory_label.text = self.current_directory - self.file_buttons.append(self.files_box.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text="Go up", style=button_style, width=self.filemanager_width / 1.5))) + self.file_buttons.append(self.files_box.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text="Go up", style=button_style, width=self.filemanager_width / 1.5, height=self.filemanager_height * 0.05,))) self.file_buttons[-1].on_click = lambda event, directory=self.current_directory: self.change_directory(os.path.dirname(directory)) for file in self.get_content(self.current_directory): - self.file_buttons.append(self.files_box.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text=file, style=button_style, width=self.filemanager_width / 1.5))) + self.file_buttons.append(self.files_box.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text=file, style=button_style, width=self.filemanager_width / 1.5, height=self.filemanager_height * 0.05,))) if os.path.isdir(f"{self.current_directory}/{file}"): self.file_buttons[-1].on_click = lambda event, directory=f"{self.current_directory}/{file}": self.change_directory(directory) else: self.file_buttons[-1].on_click = lambda event, file=f"{self.current_directory}/{file}": self.submit(file) - def disable(self): - self.parent.parent.disable() # The FileManager UIManager. self.parent is the FileManager UIAnchorLayout - def change_directory(self, directory): if directory.startswith("//"): # Fix / paths directory = directory[1:] diff --git a/game/play.py b/game/play.py index b977314..d0f648f 100644 --- a/game/play.py +++ b/game/play.py @@ -3,10 +3,10 @@ import arcade, arcade.gui, pyglet, random, json from dataclasses import asdict from utils.preload import SPRITE_TEXTURES, button_texture, button_hovered_texture -from utils.constants import button_style, DO_RULES, IF_RULES, SHAPES, ALLOWED_INPUT +from utils.constants import button_style, DO_RULES, IF_RULES, SPRITES, ALLOWED_INPUT from game.rules import RuleUI, Block, VarBlock -from game.sprites import BaseShape, Rectangle, Circle, Triangle +from game.sprites import BaseShape, Rectangle, Circle, Triangle, TexturedRectangle from game.file_manager import FileManager class Game(arcade.gui.UIView): @@ -23,7 +23,7 @@ class Game(arcade.gui.UIView): self.rules_box = RuleUI(self.window) - self.file_manager = FileManager(self.window.width * 0.95, [".json"]).with_border() + self.file_manager = FileManager(self.window.width * 0.95, self.window.height * 0.875, (0.95, 0.875), [".json"]).with_border() self.ui_selector_box = self.anchor.add(arcade.gui.UIBoxLayout(vertical=False, space_between=self.window.width / 100), anchor_x="left", anchor_y="bottom", align_y=5, align_x=self.window.width / 100) self.add_ui_selector("Simulation", lambda event: self.simulation()) @@ -39,8 +39,18 @@ class Game(arcade.gui.UIView): self.rulesets = self.rules_box.rulesets - self.sprites_box = arcade.gui.UIAnchorLayout(size_hint=(0.95, 0.9)) - self.sprite_types = SHAPES + self.sprite_add_filemanager = FileManager(self.window.width * 0.9, self.window.height * 0.75, (0.9, 0.75), [".png", ".jpg", ".jpeg", ".bmp", ".gif"]) + self.sprite_add_ui = arcade.gui.UIBoxLayout(size_hint=(0.95, 0.9), space_between=10) + self.sprite_add_ui.add(arcade.gui.UILabel(text="Add Sprite", font_size=24, text_color=arcade.color.WHITE)) + + self.sprite_add_ui.add(arcade.gui.UILabel(text="Sprite Name:", font_size=18, text_color=arcade.color.WHITE)) + self.sprite_name_input = self.sprite_add_ui.add(arcade.gui.UIInputText(width=self.window.width * 0.4, height=self.window.height * 0.05).with_border(color=arcade.color.WHITE)) + + self.sprite_add_ui.add(arcade.gui.UILabel(text="Select a texture for the sprite:", font_size=18, text_color=arcade.color.WHITE)) + self.sprite_add_ui.add(self.sprite_add_filemanager, anchor_x="center", anchor_y="bottom", align_y=25) + + self.sprites_ui = arcade.gui.UIAnchorLayout(size_hint=(0.95, 0.9)) + self.sprite_types = SPRITES self.shapes = [] self.shape_batch = pyglet.graphics.Batch() @@ -52,6 +62,7 @@ class Game(arcade.gui.UIView): button.on_click = on_click def move_x(self, a, shape): + a = float(a) if isinstance(shape, Triangle): shape.x += a shape.x2 += a @@ -60,6 +71,7 @@ class Game(arcade.gui.UIView): shape.x += a def move_y(self, a, shape): + a = float(a) if isinstance(shape, Triangle): shape.y += a shape.y2 += a @@ -68,6 +80,7 @@ class Game(arcade.gui.UIView): shape.y += a def change_x(self, a, shape): + a = float(a) if isinstance(shape, Triangle): offset_x2 = shape.x2 - shape.x offset_x3 = shape.x3 - shape.x @@ -79,6 +92,7 @@ class Game(arcade.gui.UIView): shape.x = a def change_y(self, a, shape): + a = float(a) if isinstance(shape, Triangle): offset_y2 = shape.y2 - shape.y offset_y3 = shape.y3 - shape.y @@ -90,18 +104,22 @@ class Game(arcade.gui.UIView): shape.y = a def change_x_velocity(self, a, shape): + a = float(a) 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.shape_color}]) def change_y_velocity(self, a, shape): + a = float(a) 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.shape_color}]) def change_x_gravity(self, a): + a = float(a) self.x_gravity = a self.triggered_events.append(["x_gravity_change", {}]) def change_y_gravity(self, a): + a = float(a) self.y_gravity = a self.triggered_events.append(["y_gravity_change", {}]) @@ -116,6 +134,7 @@ class Game(arcade.gui.UIView): shape.delete() def change_size(self, a, shape): + a = float(a) if isinstance(shape, Circle): shape.radius = a elif isinstance(shape, Rectangle): @@ -146,38 +165,56 @@ class Game(arcade.gui.UIView): 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)) + + else: + self.shapes.append(TexturedRectangle(shape_type, img=SPRITE_TEXTURES.get(shape_type, SPRITE_TEXTURES["rectangle"]), x=x, y=y, batch=self.shape_batch)) shape = self.shapes[-1] self.triggered_events.append(["spawn", {"event_shape_type": shape.shape_type, "shape_size": shape.shape_size, "shape_x": shape.x, "shape_y": shape.y, "shape": shape, "shape_color": shape.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) + def add_sprite(self): + self.disable_previous() - 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)) + self.mode = "sprite_add" - 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)) + self.anchor.add(self.sprite_add_ui, anchor_x="center", anchor_y="center") + + def check_selection(delta_time): + if self.sprite_add_filemanager.submitted_content: + texture = arcade.load_texture(self.sprite_add_filemanager.submitted_content) + + SPRITE_TEXTURES[self.sprite_name_input.text] = texture + SPRITES[self.sprite_name_input.text] = self.sprite_add_filemanager.submitted_content + + self.sprites_grid.clear() + + for n, shape in enumerate(SPRITES): + row, col = n % 8, n // 8 + box = self.sprites_grid.add(arcade.gui.UIBoxLayout(), row=row, column=col) + box.add(arcade.gui.UILabel(text=shape, font_size=16, text_color=arcade.color.WHITE)) + box.add(arcade.gui.UIImage(texture=SPRITE_TEXTURES[shape], width=self.window.width / 15, height=self.window.width / 15)) + + self.anchor.remove(self.sprite_add_ui) + arcade.unschedule(check_selection) + + arcade.schedule(check_selection, 0.1) def on_show_view(self): super().on_show_view() - self.sprites_box.add(arcade.gui.UILabel(text="Sprites", font_size=24, text_color=arcade.color.WHITE), anchor_x="center", anchor_y="top") + self.sprites_ui.add(arcade.gui.UILabel(text="Sprites", font_size=24, text_color=arcade.color.WHITE), anchor_x="center", anchor_y="top") - self.sprites_grid = self.sprites_box.add(arcade.gui.UIGridLayout(columns=8, row_count=8, align="left", vertical_spacing=10, horizontal_spacing=10, size_hint=(0.95, 0.85)), anchor_x="center", anchor_y="center").with_border() + self.sprites_grid = self.sprites_ui.add(arcade.gui.UIGridLayout(columns=8, row_count=8, align="left", vertical_spacing=10, horizontal_spacing=10, size_hint=(0.95, 0.85), width=self.window.width * 0.95, height=self.window.height * 0.85), anchor_x="center", anchor_y="center") - for n, shape in enumerate(SHAPES): + for n, shape in enumerate(SPRITES): row, col = n % 8, n // 8 box = self.sprites_grid.add(arcade.gui.UIBoxLayout(), row=row, column=col) box.add(arcade.gui.UILabel(text=shape, font_size=16, text_color=arcade.color.WHITE)) box.add(arcade.gui.UIImage(texture=SPRITE_TEXTURES[shape], width=self.window.width / 15, height=self.window.width / 15)) - self.sprites_box.add(arcade.gui.UITextureButton(text="Add Sprite", width=self.window.width / 2, height=self.window.height / 10, texture=button_texture, texture_hovered=button_hovered_texture, style=button_style)) + add_sprite_button = self.sprites_ui.add(arcade.gui.UITextureButton(text="Add Sprite", width=self.window.width / 2, height=self.window.height / 10, texture=button_texture, texture_hovered=button_hovered_texture, style=button_style), anchor_x="center", anchor_y="bottom", align_y=10) + add_sprite_button.on_click = lambda event: self.add_sprite() self.triggered_events.append(["start", {}]) @@ -205,8 +242,7 @@ class Game(arcade.gui.UIView): "change_y_velocity": self.change_y_velocity, "change_color": self.change_color, "change_size": self.change_size, - "destroy": self.destroy, - "morph": self.morph + "destroy": self.destroy } } @@ -254,17 +290,23 @@ class Game(arcade.gui.UIView): data = json.load(file) self.triggered_events = [] + self.rulesets = {} if not data: self.add_widget(arcade.gui.UIMessageBox(message_text="Invalid file. Could not import rules.", width=self.window.width * 0.5, height=self.window.height * 0.25)) return - for rule_num, ruleset in data.items(): + for rule_num, ruleset in data["rulesets"].items(): kwargs = ruleset kwargs["children"] = [Block(**child) for child in ruleset["children"]] kwargs["vars"] = [VarBlock(**var) for var in ruleset["vars"]] block = Block(**kwargs) self.rulesets[rule_num] = block + + self.sprite_types = data.get("sprites", SPRITES) + for sprite_name, sprite_path in self.sprite_types.items(): + if not sprite_name in SPRITE_TEXTURES: + SPRITE_TEXTURES[sprite_name] = arcade.load_texture(sprite_path) self.rules_box.rulesets = self.rulesets self.rules_box.current_rule_num = self.get_max_rule_num() + 1 @@ -272,9 +314,19 @@ class Game(arcade.gui.UIView): self.rules() - if self.mode == "export" and self.file_manager.submitted_content: + if self.mode == "export" and self.file_manager.submitted_content: with open(self.file_manager.submitted_content, "w") as file: - file.write(json.dumps({rule_num: asdict(block) for rule_num, block in self.rulesets.items()}, indent=4)) + file.write(json.dumps( + { + "rules": { + rule_num: asdict(block) for rule_num, block in self.rulesets.items() + }, + "sprites": self.sprite_types + + }, + indent=4)) + + self.add_widget(arcade.gui.UIMessageBox(message_text="Rules and Sprites exported successfully!", width=self.window.width * 0.5, height=self.window.height * 0.25)) if not self.mode == "simulation": return @@ -307,7 +359,7 @@ class Game(arcade.gui.UIView): def on_key_press(self, symbol, modifiers): if symbol == arcade.key.ESCAPE: self.main_exit() - elif self.mode == "simulation" and symbol in [ord(key) for key in ALLOWED_INPUT]: + elif self.mode == "simulation" and symbol in [ord(key) if len(key) == 1 else getattr(arcade.key, key.upper()) for key in ALLOWED_INPUT]: self.triggered_events.append(["on_input", {"event_key": chr(symbol)}]) def on_mouse_press(self, x, y, button, modifiers): @@ -339,7 +391,9 @@ class Game(arcade.gui.UIView): elif self.mode == "rules": self.anchor.remove(self.rules_box) elif self.mode == "sprites": - self.anchor.remove(self.sprites_box) + self.anchor.remove(self.sprites_ui) + elif self.mode == "sprite_add": + self.anchor.remove(self.sprite_add_ui) self.anchor.trigger_full_render() @@ -371,7 +425,7 @@ class Game(arcade.gui.UIView): self.mode = "sprites" - self.anchor.add(self.sprites_box, anchor_x="center", anchor_y="top") + self.anchor.add(self.sprites_ui, anchor_x="center", anchor_y="top") def simulation(self): self.disable_previous() diff --git a/game/rules.py b/game/rules.py index a4164f8..2b2bd23 100644 --- a/game/rules.py +++ b/game/rules.py @@ -124,10 +124,10 @@ class BlockRenderer: def _build_block_with_vars(self, b: Block, x: int, y: int) -> None: lx, ly = x, y - 42 - current_x = lx + 10 + current_x = lx + 14 current_y = ly + 28 - pattern = r' ([a-z]) ' + pattern = r'(?:^| )([a-z])(?= |$)' parts = re.split(pattern, b.label) var_index = 0 @@ -145,19 +145,19 @@ class BlockRenderer: self.text_objects.append(text_obj) self.text_by_rule_num[b.rule_num].append(text_obj) - current_x += len(part) * 10 + current_x += len(part) * 12 else: if var_index < len(b.vars): var = b.vars[var_index] var_width, var_height = self._build_var_ui( var, current_x, current_y, b.rule_num ) - current_x += var_width + 7 + current_x += var_width + 10 var_index += 1 def _build_block(self, b: Block, x: int, y: int) -> int: is_wrap = b.rule_type != "do" - h, w = 42, 280 + h, w = 42, 380 if b.rule_type == "if": color = IF_COLOR @@ -467,7 +467,7 @@ class RuleUI(arcade.gui.UIAnchorLayout): if block == self.dragged_rule_ui or (self.dragged_rule_ui.rule in NEEDS_SHAPE and block.rule not in PROVIDES_SHAPE): continue - if arcade.LBWH(block.x, block.y - 44, 280, 44).intersection(arcade.LBWH(self.dragged_rule_ui.x, self.dragged_rule_ui.y - 44, 280, 44)): + if arcade.LBWH(block.x, block.y - 44, 380, 44).intersection(arcade.LBWH(self.dragged_rule_ui.x, self.dragged_rule_ui.y - 44, 380, 44)): block.children.append(self.dragged_rule_ui) del self.rulesets[self.dragged_rule_ui.rule_num] self.block_renderer.refresh() @@ -491,7 +491,7 @@ class RuleUI(arcade.gui.UIAnchorLayout): continue projected_vec = self.camera.unproject((event.x, event.y)) - if arcade.LBWH(block.x, block.y - 44, 280, 44).point_in_rect((projected_vec.x, projected_vec.y)): + if arcade.LBWH(block.x, block.y - 44, 380, 44).point_in_rect((projected_vec.x, projected_vec.y)): if block not in list(self.rulesets.values()): # its children self.remove_from_parent(block, list(self.rulesets.values())) self.block_renderer.refresh() @@ -526,9 +526,22 @@ class RuleUI(arcade.gui.UIAnchorLayout): elif isinstance(event, arcade.gui.UIMouseReleaseEvent): if self.dragged_rule_ui: - block_vec = self.camera.unproject((self.dragged_rule_ui.x, self.dragged_rule_ui.y)) - if self.trash_sprite.rect.intersection(arcade.LBWH(block_vec.x, block_vec.y, 280, 44)) and not self.trash_sprite._current_keyframe_index == self.trash_sprite.animation.num_frames - 1: - del self.rulesets[self.dragged_rule_ui.rule_num] + block_screen_pos = self.camera.project((self.dragged_rule_ui.x, self.dragged_rule_ui.y)) + + block_rect = arcade.LBWH(block_screen_pos[0], block_screen_pos[1], 380, 44) + trash_rect = arcade.LBWH( + self.trash_sprite.center_x - self.trash_sprite.width / 2, + self.trash_sprite.center_y - self.trash_sprite.height / 2, + self.trash_sprite.width, + self.trash_sprite.height + ) + + if block_rect.intersection(trash_rect): + self.remove_from_parent(self.dragged_rule_ui, list(self.rulesets.values())) + + if self.dragged_rule_ui.rule_num in self.rulesets: + del self.rulesets[self.dragged_rule_ui.rule_num] + self.dragged_rule_ui = None self.block_renderer.refresh() return @@ -556,8 +569,8 @@ class RuleUI(arcade.gui.UIAnchorLayout): def on_update(self, dt): if self.dragged_rule_ui: - block_vec = self.camera.unproject((self.dragged_rule_ui.x, self.dragged_rule_ui.y)) - if self.trash_sprite.rect.intersection(arcade.LBWH(block_vec.x, block_vec.y, 280, 44)) and not self.trash_sprite._current_keyframe_index == self.trash_sprite.animation.num_frames - 1: + block_screen_pos = self.camera.project((self.dragged_rule_ui.x, self.dragged_rule_ui.y)) + if self.trash_sprite.rect.intersection(arcade.LBWH(block_screen_pos[0], block_screen_pos[1], 380, 44)) and not self.trash_sprite._current_keyframe_index == self.trash_sprite.animation.num_frames - 1: self.trash_sprite.update_animation() else: self.trash_sprite.time = 0 diff --git a/game/sprites.py b/game/sprites.py index b41ed3c..a8a4faa 100644 --- a/game/sprites.py +++ b/game/sprites.py @@ -106,12 +106,11 @@ class Circle(pyglet.shapes.Circle, BaseShape): return not (has_neg and has_pos) -class Rectangle(pyglet.shapes.Rectangle, BaseShape): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - BaseShape.__init__(self) - self.shape_type = "rectangle" - + +class BaseRectangle(BaseShape): + def __init__(self): + super().__init__() + @property def shape_size(self): return self.width @@ -181,6 +180,18 @@ class Rectangle(pyglet.shapes.Rectangle, BaseShape): return (ccw(x1, y1, x3, y3, x4, y4) != ccw(x2, y2, x3, y3, x4, y4) and ccw(x1, y1, x2, y2, x3, y3) != ccw(x1, y1, x2, y2, x4, y4)) +class Rectangle(pyglet.shapes.Rectangle, BaseRectangle): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + BaseRectangle.__init__(self) + self.shape_type = "rectangle" + +class TexturedRectangle(pyglet.sprite.Sprite, BaseRectangle): + def __init__(self, shape_type, *args, **kwargs): + super().__init__(*args, **kwargs) + BaseRectangle.__init__(self) + self.shape_type = shape_type + class Triangle(pyglet.shapes.Triangle, BaseShape): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/utils/constants.py b/utils/constants.py index 52f5561..130b1fe 100644 --- a/utils/constants.py +++ b/utils/constants.py @@ -1,12 +1,21 @@ +import os import arcade.color, operator from arcade.types import Color from arcade.gui.widgets.buttons import UITextureButtonStyle, UIFlatButtonStyle from arcade.gui.widgets.slider import UISliderStyle -SHAPES = ["rectangle", "circle", "triangle"] +# Get the directory where this module is located +_module_dir = os.path.dirname(os.path.abspath(__file__)) +_assets_dir = os.path.join(os.path.dirname(_module_dir), 'assets') + +SPRITES = { + os.path.splitext(file_name)[0]: os.path.join(_assets_dir, 'graphics', 'sprites', file_name) + for file_name in os.listdir(os.path.join(_assets_dir, 'graphics', 'sprites')) + } + VAR_NAMES = ["a", "b", "c", "d", "e", "f", "g"] -ALLOWED_INPUT = ["a", "b", "c", "d", "e", "q", "w", "s", "t"] +ALLOWED_INPUT = ["a", "b", "c", "d", "e", "q", "w", "s", "t", "space", "left", "right", "up", "down"] TRIGGER_COLOR = (255, 204, 102) DO_COLOR = (102, 178, 255) @@ -39,8 +48,8 @@ OPS = { } VAR_DEFAULT = { - "shape_type": SHAPES[0], - "target_type": SHAPES[1], + "shape_type": "rectangle", + "target_type": "circle", "variable": 0, "color": "WHITE", "size": 10, @@ -49,8 +58,8 @@ VAR_DEFAULT = { } VAR_OPTIONS = { - "shape_type": SHAPES, - "target_type": SHAPES, + "shape_type": SPRITES, + "target_type": SPRITES, "variable": (-700, 700), "color": COLORS, "size": (1, 200), @@ -118,13 +127,6 @@ TRIGGER_RULES = { "vars": ["shape_type", "event_shape_type"], "func": lambda *v: v[0] == v[1] }, - "morphs": { - "key": "morphs", - "description": "IF {a} shape morphs into {b}", - "user_vars": ["shape_type", "target_type"], - "vars": ["shape_type", "target_type", "event_a_type", "event_b_type"], - "func": lambda *v: (v[0] == v[2]) and (v[3] == v[1]) - }, "collides": { "key": "collides", "description": "IF {a} shape collides with {b}", @@ -289,14 +291,6 @@ DO_RULES = { "vars": ["shape"] }, - "morph_into": { - "key": "morph_into", - "description": "Morph this into {a}", - "action": {"type": "shape_action", "name": "morph"}, - "user_vars": ["shape_type"], - "vars": ["shape", "shape_type"] - }, - "change_x_gravity": { "key": "change_x_gravity", "description": "Change X gravity to {a}", @@ -327,7 +321,6 @@ PROVIDES_SHAPE = [ "spawns", "color_changes", "size_changes", - "morphs", "collides", # IFs, technically, these need and provide a shape to the next rule @@ -362,7 +355,6 @@ NEEDS_SHAPE = [ "change_y_velocity", "change_size", "destroy", - "morph_into" ] RULE_DEFAULTS = {