diff --git a/.gitignore b/.gitignore index f648967..94bc59e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .DS_Store fruit_catcher/__pycache__ +result.json diff --git a/fruit_catcher/catcher.py b/fruit_catcher/catcher.py index 88f79d4..ed21c6d 100644 --- a/fruit_catcher/catcher.py +++ b/fruit_catcher/catcher.py @@ -3,6 +3,7 @@ from random import randint class CatcherPiece: character = "-" color = "white_on_indigo" + z = 1 def __init__(self, position): self.position = position @@ -24,13 +25,13 @@ class Catcher: x, y = self.position width, height = game.board_size if keystroke.name == "KEY_LEFT": - if 0 < x: - self.position = (x-1, y) - self.update_piece_positions() + new_x = max(0, x - 3) + self.position = (new_x, y) + self.update_piece_positions() if keystroke.name == "KEY_RIGHT": - if x + self.width < width: - self.position = (x+1, y) - self.update_piece_positions() + new_x = min(width - self.width, x + 3) + self.position = (new_x, y) + self.update_piece_positions() def create_pieces(self, game): x, y = self.position diff --git a/fruit_catcher/fruit.py b/fruit_catcher/fruit.py index 11d0173..8c3034f 100644 --- a/fruit_catcher/fruit.py +++ b/fruit_catcher/fruit.py @@ -1,49 +1,72 @@ -from random import randint +from random import randint, choice -SHAPE_DEFINITIONS = [ - [(0,0)], - [(0, 0), (1, 0), (0, 1), (1, 1)], +FRUIT_TYPES = [ + {'shape': [(0, 0)], 'color': 'green_on_indigo'}, + {'shape': [(0, 0), (1, 0)], 'color': 'yellow_on_indigo'}, + {'shape': [(0, 0), (1, 0), (2, 0)], 'color': 'red_on_indigo'}, + {'shape': [(0, 0), (0, 1)], 'color': 'cyan_on_indigo'}, + {'shape': [(0, 0), (1, 0), (0, 1), (1, 1)], 'color': 'magenta_on_indigo'}, + {'shape': [(0, 0), (1, 1), (2, 0)], 'color': 'white_on_indigo'}, ] class FruitPiece: character = "@" - color = "green_on_indigo" display = True - def __init__(self, position): + + def __init__(self, position, color, z): self.position = position + self.color = color + self.z = z class Fruit: - width = 2 - height = 1 display = False - pieces = [] - name = "fruit" character = "@" - color = "green_on_indigo" - def __init__(self, position, game, shape_offsets): + def __init__(self, position, game, shape_offsets, color, dx, speed, start_z): self.position = position self.pieces = {} - for offset in shape_offsets: - self.create_shape(game, offset) + self.color = color + self.dx = dx + self.speed = speed + self.alive = True + for i, offset in enumerate(shape_offsets): + self.create_shape(game, offset, start_z + i) def play_turn(self, game): - if game.turn_number % 3 == 0: - x, y = self.position - if y >= 29: - for piece in self.pieces.values(): - game.remove_agent(piece) - game.remove_agent(self) - game.end() - else: - self.position = (x, y + 1) - self.update_piece_positions() - self.check_catcher_collision(game) + if game.turn_number % self.speed == 0: + self.move(game) - def create_shape(self, game, offset): + def move(self, game): + x, y = self.position + width, height = game.board_size + offsets = list(self.pieces.keys()) + max_ox = max(ox for ox, oy in offsets) + min_ox = min(ox for ox, oy in offsets) + max_oy = max(oy for ox, oy in offsets) + + new_x = x + self.dx + if new_x + min_ox < 0 or new_x + max_ox >= width: + self.dx = -self.dx + new_x = x + self.dx + + new_y = y + 1 + if new_y + max_oy >= height: + for piece in self.pieces.values(): + game.remove_agent(piece) + game.remove_agent(self) + self.alive = False + game.state['Lives'] -= 1 + if game.state['Lives'] <= 0: + game.end() + else: + self.position = (new_x, new_y) + self.update_piece_positions() + self.check_catcher_collision(game) + + def create_shape(self, game, offset, z): x, y = self.position ox, oy = offset - piece = FruitPiece((x + ox, y + oy)) + piece = FruitPiece((x + ox, y + oy), self.color, z) self.pieces[offset] = piece game.add_agent(piece) @@ -62,4 +85,5 @@ class Fruit: for p in self.pieces.values(): game.remove_agent(p) game.remove_agent(self) - return \ No newline at end of file + self.alive = False + return diff --git a/fruit_catcher/game.py b/fruit_catcher/game.py index 9361fd6..3ecf159 100644 --- a/fruit_catcher/game.py +++ b/fruit_catcher/game.py @@ -12,6 +12,6 @@ def play(): Catcher((11, 29)), FruitManager(), ] - state = {'Score': 0} + state = {'Score': 0, 'Lives': 5} game = Game(agents, state, board_size=(WIDTH, HEIGHT), framerate=24, color="white_on_indigo", dump_state="result.json") game.play() diff --git a/fruit_catcher/manager.py b/fruit_catcher/manager.py index 4f9702a..277a4e5 100644 --- a/fruit_catcher/manager.py +++ b/fruit_catcher/manager.py @@ -1,18 +1,31 @@ -from .fruit import Fruit, SHAPE_DEFINITIONS +from .fruit import Fruit, FRUIT_TYPES from random import choice, randint -from retro.errors import AgentNotFoundByName class FruitManager: display = False + def __init__(self): + self.active_fruits = [] + self.last_spawn_turn = 0 + self.next_z = 0 + def play_turn(self, game): - try: - game.get_agent_by_name("fruit") - except AgentNotFoundByName: + self.active_fruits = [f for f in self.active_fruits if f.alive] + spawn_interval = max(12, 72 - game.turn_number // 10) + if game.turn_number - self.last_spawn_turn >= spawn_interval: self.create_piece(game) + self.last_spawn_turn = game.turn_number def create_piece(self, game): - x = randint(0, 25) - fruit = Fruit((x, 1), game, choice(SHAPE_DEFINITIONS)) + width, _ = game.board_size + fruit_type = choice(FRUIT_TYPES) + shape = fruit_type['shape'] + max_ox = max(ox for ox, oy in shape) + x = randint(0, width - 1 - max_ox) + dx = choice([-1, 0, 0, 1]) + speed = randint(2, 5) + fruit = Fruit((x, 1), game, shape, fruit_type['color'], dx, speed, self.next_z) + self.next_z += len(shape) game.add_agent(fruit) + self.active_fruits.append(fruit)