Browse Source

Aggiungi supporto per la risoluzione personalizzata e gestione della pausa nel gioco

master
Matteo Benedetto 1 year ago
parent
commit
97038023d5
  1. 1
      .env
  2. 4
      engine/controls.py
  3. 28
      engine/sdl2.py
  4. 57
      rats.py
  5. 1
      requirements.txt
  6. 3
      scores.txt
  7. BIN
      units/__pycache__/rat.cpython-313.pyc
  8. 11
      units/bomb.py
  9. 2
      units/points.py
  10. 4
      units/rat.py

1
.env

@ -1 +1,2 @@
SDL_VIDEODRIVER=x11 SDL_VIDEODRIVER=x11
RESOLUTION=1920x1080

4
engine/controls.py

@ -13,7 +13,7 @@ class KeyBindings:
self.new_rat() self.new_rat()
elif key == "D": elif key == "D":
if self.units: if self.units:
self.units[random.choice(list(self.units.keys()))].die() self.units[random.choice(list(self.units.keys()))].die(score=5)
elif key == "M": elif key == "M":
self.audio = not self.audio self.audio = not self.audio
elif key == "F": elif key == "F":
@ -32,6 +32,8 @@ class KeyBindings:
self.spawn_bomb(self.pointer) self.spawn_bomb(self.pointer)
elif key == "UpRelease" or key == "DownRelease" or key == "LeftRelease" or key == "RightRelease": elif key == "UpRelease" or key == "DownRelease" or key == "LeftRelease" or key == "RightRelease":
self.stop_scrolling() self.stop_scrolling()
elif key == "P":
self.pause = not self.pause
# elif key == "mouse": # elif key == "mouse":
# adjusted_coords = (coords[0]//self.cell_size*2, coords[1]//self.cell_size*2) # adjusted_coords = (coords[0]//self.cell_size*2, coords[1]//self.cell_size*2)
# self.pointer = adjusted_coords # self.pointer = adjusted_coords

28
engine/sdl2.py

@ -1,6 +1,8 @@
import os import os
import sdl2 import sdl2
import sdl2.ext import sdl2.ext
from sdl2.ext.compat import byteify
from PIL import Image from PIL import Image
class GameWindow: class GameWindow:
@ -9,8 +11,8 @@ class GameWindow:
self.cell_size = cell_size self.cell_size = cell_size
self.width = width * cell_size self.width = width * cell_size
self.height = height * cell_size self.height = height * cell_size
self.actual_screen_size = (640, 480) self.actual_screen_size = os.environ.get("RESOLUTION", "640x480").split("x")
if self.width > self.actual_screen_size[0] or self.height > self.actual_screen_size[1]: if self.width > int(self.actual_screen_size[0]) or self.height > int(self.actual_screen_size[1]):
self.target_size = self.actual_screen_size self.target_size = self.actual_screen_size
else: else:
self.target_size = (self.width, self.height) self.target_size = (self.width, self.height)
@ -22,6 +24,8 @@ class GameWindow:
self.max_h_offset = self.target_size[1] - self.height self.max_h_offset = self.target_size[1] - self.height
print(f"Screen size: {self.width}x{self.height}") print(f"Screen size: {self.width}x{self.height}")
sdl2.ext.init(joystick=True) sdl2.ext.init(joystick=True)
sdl2.SDL_Init(sdl2.SDL_INIT_AUDIO)
self.window = sdl2.ext.Window(title=title, size=self.target_size,)# flags=sdl2.SDL_WINDOW_FULLSCREEN) self.window = sdl2.ext.Window(title=title, size=self.target_size,)# flags=sdl2.SDL_WINDOW_FULLSCREEN)
self.delay = 30 self.delay = 30
self.load_joystick() self.load_joystick()
@ -63,7 +67,7 @@ class GameWindow:
def draw_text(self, text, font, position, color): def draw_text(self, text, font, position, color):
sprite = self.factory.from_text(text, color=color, fontmanager=font) sprite = self.factory.from_text(text, color=color, fontmanager=font)
if position == "center": if position == "center":
sprite.position = (self.size[0] // 2 - sprite.size[0] // 2, self.size[1] // 2 - sprite.size[1] // 2) sprite.position = (self.target_size[0] // 2 - sprite.size[0] // 2, self.target_size[1] // 2 - sprite.size[1] // 2)
else: else:
sprite.position = position sprite.position = position
self.renderer.copy(sprite, dstrect=sprite.position) self.renderer.copy(sprite, dstrect=sprite.position)
@ -75,8 +79,6 @@ class GameWindow:
self.renderer.copy(sprite, dstrect=sprite.position) self.renderer.copy(sprite, dstrect=sprite.position)
def draw_rectangle(self, x, y, width, height, tag, outline="red", filling=None): def draw_rectangle(self, x, y, width, height, tag, outline="red", filling=None):
if not self.is_in_visible_area(x, y):
return
x, y = x + self.w_offset, y + self.h_offset x, y = x + self.w_offset, y + self.h_offset
if filling: if filling:
self.renderer.fill((x, y, width, height), sdl2.ext.Color(*filling)) self.renderer.fill((x, y, width, height), sdl2.ext.Color(*filling))
@ -92,6 +94,21 @@ class GameWindow:
def delete_tag(self, tag): def delete_tag(self, tag):
pass pass
def win_screen(self, text, image=None):
self.draw_rectangle(50 - self.w_offset, 50 - self.h_offset,
self.target_size[0] - 100, self.target_size[1] - 100, "win", filling=(255, 255, 255))
self.draw_text(text, self.fonts[50], "center", sdl2.ext.Color(0, 0, 0))
if image:
image_size = self.get_image_size(image)
self.draw_image(self.target_size[0] // 2 - image_size[0] // 2,
self.target_size[1] // 2 - image_size[1] // 2-150, image, "win")
def pause_screen(self, text):
self.draw_rectangle(50 - self.w_offset, 50 - self.h_offset,
self.target_size[0] - 100, self.target_size[1] - 100, "pause", filling=(255, 255, 255))
self.draw_text(text, self.fonts[50], "center", sdl2.ext.Color(0, 0, 0))
def get_image_size(self, image): def get_image_size(self, image):
return image.size return image.size
@ -174,6 +191,7 @@ class GameWindow:
self.h_offset = y self.h_offset = y
def play_sound(self, sound_file): def play_sound(self, sound_file):
return return
sample = sdl2.sdlmixer.Mix_LoadWAV(byteify(sound_file, "utf-8")) sample = sdl2.sdlmixer.Mix_LoadWAV(byteify(sound_file, "utf-8"))
if sample is None: if sample is None:

57
rats.py

@ -1,12 +1,12 @@
#!/usr/bin/python3 #!/usr/bin/python3
import cProfile
import pstats
import random import random
from units import rat, bomb from units import rat, bomb
import uuid import uuid
import subprocess
from engine import maze, sdl2 as engine, controls from engine import maze, sdl2 as engine, controls
import os import os
import datetime
import subprocess
class MiceMaze(controls.KeyBindings): class MiceMaze(controls.KeyBindings):
def __init__(self, maze_file): def __init__(self, maze_file):
@ -23,7 +23,10 @@ class MiceMaze(controls.KeyBindings):
self.unit_positions = {} self.unit_positions = {}
self.unit_positions_before = {} self.unit_positions_before = {}
self.scrolling_direction = None self.scrolling_direction = None
self.pause = False
self.game_end = (False, None)
self.scrolling = False self.scrolling = False
self.sounds = {}
for _ in range(5): for _ in range(5):
self.new_rat() self.new_rat()
@ -55,8 +58,41 @@ class MiceMaze(controls.KeyBindings):
variant = x*y % 4 variant = x*y % 4
tile = self.grasses[variant] if cell else self.tunnel tile = self.grasses[variant] if cell else self.tunnel
self.engine.draw_image(x * self.cell_size, y * self.cell_size, tile, tag="maze") self.engine.draw_image(x * self.cell_size, y * self.cell_size, tile, tag="maze")
def game_over(self):
if self.game_end[0]:
if not self.game_end[1]:
self.engine.win_screen("Game Over: Mice are too many!", image=self.assets["BMP_WEWIN"])
else:
self.engine.win_screen(f"You Win! Points: {self.points}", image=self.assets["BMP_WEWIN"])
return True
if len(self.units) >= 150:
self.stop_sound()
self.play_sound("WEWIN.WAV")
self.game_end = (True, False)
return True
if not len(self.units):
self.stop_sound()
self.play_sound("VICTORY.WAV")
self.game_end = (True, True)
self.save_score()
return True
def save_score(self):
with open("scores.txt", "a") as f:
f.write(f"{datetime.datetime.now()} - {self.points}\n")
def read_score(self):
with open("scores.txt") as f:
return f.read().splitlines()
def update_maze(self): def update_maze(self):
if self.pause:
self.engine.pause_screen("Paused")
return
if self.game_over():
return
self.engine.delete_tag("unit") self.engine.delete_tag("unit")
self.engine.delete_tag("effect") self.engine.delete_tag("effect")
self.engine.draw_pointer(self.pointer[0] * self.cell_size, self.pointer[1] * self.cell_size) self.engine.draw_pointer(self.pointer[0] * self.cell_size, self.pointer[1] * self.cell_size)
@ -87,10 +123,17 @@ class MiceMaze(controls.KeyBindings):
) )
self.engine.scroll_view(self.pointer) self.engine.scroll_view(self.pointer)
def play_sound(self, sound_file): def play_sound(self, sound_file,tag="main"):
if self.audio: if self.audio:
subprocess.Popen(["aplay", f"sound/{sound_file}"]) if len(self.sounds) > 5:
#self.engine.play_sound(f"sound/{sound_file}") self.sounds.pop(next(iter(self.sounds))).kill()
self.sounds[f"{tag}_{random.random()}"] = subprocess.Popen(["aplay", f"sound/{sound_file}"])
def stop_sound(self, tag=None):
for key, value in self.sounds.copy().items():
if tag is None or tag in key:
value.kill()
del self.sounds[key]
def graphics_load(self): def graphics_load(self):
self.tunnel = self.engine.load_image("Rat/BMP_TUNNEL.png") self.tunnel = self.engine.load_image("Rat/BMP_TUNNEL.png")
@ -131,8 +174,6 @@ class MiceMaze(controls.KeyBindings):
self.engine.new_cycle(100, self.scroll) self.engine.new_cycle(100, self.scroll)
if __name__ == "__main__": if __name__ == "__main__":
profiler = cProfile.Profile()
profiler.enable()
solver = MiceMaze('maze.json') solver = MiceMaze('maze.json')
solver.run() solver.run()

1
requirements.txt

@ -1,2 +1 @@
pysdl2 pysdl2
pysdl2-dll

3
scores.txt

@ -0,0 +1,3 @@
2024-12-23 00:31:05.911787 - 25
2024-12-23 00:34:28.819938 - 50
2024-12-23 00:56:30.216347 - 25

BIN
units/__pycache__/rat.cpython-313.pyc

Binary file not shown.

11
units/bomb.py

@ -53,7 +53,8 @@ class Timer(Bomb):
if self.age == AGE_THRESHOLD: if self.age == AGE_THRESHOLD:
self.die() self.die()
def die(self, unit=None): def die(self, unit=None, score=None):
score = 10
print("BOOM") print("BOOM")
if not unit: if not unit:
unit = self unit = self
@ -68,11 +69,15 @@ class Timer(Bomb):
for victim in self.game.unit_positions.get((x, y), []): for victim in self.game.unit_positions.get((x, y), []):
if victim.id in self.game.units: if victim.id in self.game.units:
if victim.partial_move >= 0.5: if victim.partial_move >= 0.5:
victim.die() victim.die(score=score)
if score < 160:
score *= 2
for victim in self.game.unit_positions_before.get((x, y), []): for victim in self.game.unit_positions_before.get((x, y), []):
if victim.id in self.game.units: if victim.id in self.game.units:
if victim.partial_move < 0.5: if victim.partial_move < 0.5:
victim.die() victim.die(score=score)
if score < 160:
score *= 2
else: else:
break break
if direction == "N": if direction == "N":

2
units/points.py

@ -30,7 +30,7 @@ class Point(Unit):
def collisions(self): def collisions(self):
pass pass
def die(self, unit=None): def die(self, unit=None, score=None):
if not unit: if not unit:
unit = self unit = self
self.game.units.pop(unit.id) self.game.units.pop(unit.id)

4
units/rat.py

@ -96,11 +96,11 @@ class Rat(Unit):
if "fuck" in dir(self): if "fuck" in dir(self):
self.fuck(unit) self.fuck(unit)
def die(self, unit=None): def die(self, unit=None, score=10):
if not unit: if not unit:
unit = self unit = self
self.game.units.pop(unit.id) self.game.units.pop(unit.id)
self.game.spawn_unit(Point, unit.position_before) self.game.spawn_unit(Point, unit.position_before, value=score)
def draw(self): def draw(self):
direction = self.calculate_rat_direction() direction = self.calculate_rat_direction()

Loading…
Cancel
Save