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
RESOLUTION=1920x1080

4
engine/controls.py

@ -13,7 +13,7 @@ class KeyBindings:
self.new_rat()
elif key == "D":
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":
self.audio = not self.audio
elif key == "F":
@ -32,6 +32,8 @@ class KeyBindings:
self.spawn_bomb(self.pointer)
elif key == "UpRelease" or key == "DownRelease" or key == "LeftRelease" or key == "RightRelease":
self.stop_scrolling()
elif key == "P":
self.pause = not self.pause
# elif key == "mouse":
# adjusted_coords = (coords[0]//self.cell_size*2, coords[1]//self.cell_size*2)
# self.pointer = adjusted_coords

28
engine/sdl2.py

@ -1,6 +1,8 @@
import os
import sdl2
import sdl2.ext
from sdl2.ext.compat import byteify
from PIL import Image
class GameWindow:
@ -9,8 +11,8 @@ class GameWindow:
self.cell_size = cell_size
self.width = width * cell_size
self.height = height * cell_size
self.actual_screen_size = (640, 480)
if self.width > self.actual_screen_size[0] or self.height > self.actual_screen_size[1]:
self.actual_screen_size = os.environ.get("RESOLUTION", "640x480").split("x")
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
else:
self.target_size = (self.width, self.height)
@ -22,6 +24,8 @@ class GameWindow:
self.max_h_offset = self.target_size[1] - self.height
print(f"Screen size: {self.width}x{self.height}")
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.delay = 30
self.load_joystick()
@ -63,7 +67,7 @@ class GameWindow:
def draw_text(self, text, font, position, color):
sprite = self.factory.from_text(text, color=color, fontmanager=font)
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:
sprite.position = position
self.renderer.copy(sprite, dstrect=sprite.position)
@ -75,8 +79,6 @@ class GameWindow:
self.renderer.copy(sprite, dstrect=sprite.position)
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
if filling:
self.renderer.fill((x, y, width, height), sdl2.ext.Color(*filling))
@ -92,6 +94,21 @@ class GameWindow:
def delete_tag(self, tag):
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):
return image.size
@ -174,6 +191,7 @@ class GameWindow:
self.h_offset = y
def play_sound(self, sound_file):
return
sample = sdl2.sdlmixer.Mix_LoadWAV(byteify(sound_file, "utf-8"))
if sample is None:

57
rats.py

@ -1,12 +1,12 @@
#!/usr/bin/python3
import cProfile
import pstats
import random
from units import rat, bomb
import uuid
import subprocess
from engine import maze, sdl2 as engine, controls
import os
import datetime
import subprocess
class MiceMaze(controls.KeyBindings):
def __init__(self, maze_file):
@ -23,7 +23,10 @@ class MiceMaze(controls.KeyBindings):
self.unit_positions = {}
self.unit_positions_before = {}
self.scrolling_direction = None
self.pause = False
self.game_end = (False, None)
self.scrolling = False
self.sounds = {}
for _ in range(5):
self.new_rat()
@ -55,8 +58,41 @@ class MiceMaze(controls.KeyBindings):
variant = x*y % 4
tile = self.grasses[variant] if cell else self.tunnel
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):
if self.pause:
self.engine.pause_screen("Paused")
return
if self.game_over():
return
self.engine.delete_tag("unit")
self.engine.delete_tag("effect")
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)
def play_sound(self, sound_file):
def play_sound(self, sound_file,tag="main"):
if self.audio:
subprocess.Popen(["aplay", f"sound/{sound_file}"])
#self.engine.play_sound(f"sound/{sound_file}")
if len(self.sounds) > 5:
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):
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)
if __name__ == "__main__":
profiler = cProfile.Profile()
profiler.enable()
solver = MiceMaze('maze.json')
solver.run()

1
requirements.txt

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

2
units/points.py

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

4
units/rat.py

@ -96,11 +96,11 @@ class Rat(Unit):
if "fuck" in dir(self):
self.fuck(unit)
def die(self, unit=None):
def die(self, unit=None, score=10):
if not unit:
unit = self
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):
direction = self.calculate_rat_direction()

Loading…
Cancel
Save