#!/usr/bin/python3 import random import os import json from engine import maze, sdl2 as engine, controls, graphics, unit_manager, scoring class MiceMaze( controls.KeyBindings, unit_manager.UnitManager, graphics.Graphics, scoring.Scoring ): # ==================== INITIALIZATION ==================== def __init__(self, maze_file): self.map = maze.Map(maze_file) self.audio = True self.cell_size = 40 self.full_screen = False self.render_engine = engine.GameWindow(self.map.width, self.map.height, self.cell_size, "Mice!", key_callback=self.trigger) self.load_assets() self.render_engine.window.show() self.pointer = (random.randint(1, self.map.width-2), random.randint(1, self.map.height-2)) self.scroll_cursor() self.points = 0 self.units = {} self.unit_positions = {} self.unit_positions_before = {} self.scrolling_direction = None self.game_status = "start_menu" self.game_end = (False, None) self.scrolling = False self.sounds = {} self.start_game() self.background_texture = None self.configs = self.get_config() def get_config(self): configs = {} for file in os.listdir("conf"): if file.endswith(".json"): with open(os.path.join("conf", file)) as f: configs[file[:-5]] = json.load(f) return configs def start_game(self): self.ammo = { "bomb": { "count": 2, "max": 5 }, "nuclear": { "count": 1, "max": 1 }, "mine": { "count": 5, "max": 5 } } self.blood_stains = {} self.background_texture = None for _ in range(5): self.spawn_rat() def reset_game(self): self.pause = False self.game_status = "game" self.game_end = (False, None) self.units.clear() self.points = 0 self.start_game() # ==================== GAME LOGIC ==================== def refill_ammo(self): for ammo_type, data in self.ammo.items(): if ammo_type == "bomb": if random.random() < 0.01: data["count"] = min(data["count"] + 1, data["max"]) elif ammo_type == "mine": if random.random() < 0.05: data["count"] = min(data["count"] + 1, data["max"]) def update_maze(self): if self.game_over(): return if self.game_status == "paused": self.render_engine.dialog("Pause") return if self.game_status == "start_menu": self.render_engine.dialog("Welcome to the Mice!", subtitle="A game by Matteo because he was bored",image=self.assets["BMP_WEWIN"]) return self.render_engine.delete_tag("unit") self.render_engine.delete_tag("effect") self.render_engine.draw_pointer(self.pointer[0] * self.cell_size, self.pointer[1] * self.cell_size) self.unit_positions.clear() self.unit_positions_before.clear() for unit in self.units.values(): self.unit_positions.setdefault(unit.position, []).append(unit) self.unit_positions_before.setdefault(unit.position_before, []).append(unit) for unit in self.units.copy().values(): unit.move() unit.collisions() unit.draw() self.render_engine.update_status(f"Mice: {self.count_rats()} - Points: {self.points}") self.refill_ammo() self.render_engine.update_ammo(self.ammo, self.assets) self.scroll() self.render_engine.new_cycle(50, self.update_maze) def run(self): self.render_engine.mainloop(update=self.update_maze, bg_update=self.draw_maze) # ==================== GAME OVER LOGIC ==================== def game_over(self): if self.game_end[0]: if not self.game_end[1]: self.render_engine.dialog("Game Over: Mice are too many!", image=self.assets["BMP_WEWIN"]) else: self.render_engine.dialog(f"You Win! Points: {self.points}", image=self.assets["BMP_WEWIN"], scores=self.read_score()) return True count_rats = self.count_rats() if count_rats > 200: self.render_engine.stop_sound() self.render_engine.play_sound("WEWIN.WAV") self.game_end = (True, False) self.game_status = "paused" return True if not count_rats: self.render_engine.stop_sound() self.render_engine.play_sound("VICTORY.WAV") self.render_engine.play_sound("WELLDONE.WAV", tag="effects") self.game_end = (True, True) self.game_status = "paused" self.save_score() return True if __name__ == "__main__": print("Game starting...") solver = MiceMaze('maze.json') solver.run()