Browse Source

Refactor keybindings configuration and remove obsolete JSON files

master
Matteo Benedetto 4 months ago
parent
commit
8451ac7913
  1. 4
      .gitignore
  2. 15
      conf/keybinding_game.json
  3. 6
      conf/keybinding_paused.json
  4. 6
      conf/keybinding_start_menu.json
  5. 14
      conf/keybindings.yaml
  6. 29
      conf/keybindings_pc.yaml
  7. 24
      conf/keybindings_r36s.yaml
  8. 71
      engine/controls.py
  9. 8
      engine/sdl2.py
  10. 2
      engine/unit_manager.py
  11. 5
      rats.py
  12. BIN
      units/__pycache__/rat.cpython-313.pyc
  13. BIN
      units/__pycache__/unit.cpython-313.pyc
  14. 8
      units/mine.py

4
.gitignore vendored

@ -11,4 +11,6 @@ dist/
rats rats
rats.spec rats.spec
.env .env
release/ release/
unit/__pycache__
conf/keybindings.yaml

15
conf/keybinding_game.json

@ -1,15 +0,0 @@
{
"new_rat": [["keyup", "Return"], ["keydown", "Return"]],
"kill_rat": ["D"],
"toggle_audio": ["M"],
"toggle_full_screen": ["F"],
"scroll_up": [["keydown", "Up"], ["keydown", "Up"]],
"scroll_down": ["Down", 9],
"scroll_left": ["Left", 10],
"scroll_right": ["Right", 11],
"spawn_bomb": ["Space", 1],
"spawn_mine": ["Left Ctrl", 2, 17],
"spawn_nuclear_bomb": ["N", 3],
"pause": ["P", 16]
}

6
conf/keybinding_paused.json

@ -1,6 +0,0 @@
{
"reset_game": ["Return", 13],
"pause": ["P", 16],
"quit": ["Q", 12]
}

6
conf/keybinding_start_menu.json

@ -1,6 +0,0 @@
{
"start_game": ["Return", 13],
"toggle_full_screen": ["F"],
"quit": ["Q", 12]
}

14
conf/keybindings.yaml

@ -12,8 +12,18 @@ keybinding_game:
keyup_Left: stop_scrolling keyup_Left: stop_scrolling
keyup_Right: stop_scrolling keyup_Right: stop_scrolling
keydown_Space: spawn_new_bomb keydown_Space: spawn_new_bomb
keydown_N: spawn_nuclear_bomb keydown_N: spawn_new_nuclear_bomb
keydown_Left_Ctrl: spawn_new_mine
keydown_P: toggle_pause
keybinding_start_menu: keybinding_start_menu:
keydown_Return: reset_game keydown_Return: reset_game
keydown_Escape: quit_game keydown_Escape: quit_game
keydown_M: toggle_audio
keydown_F: toggle_full_screen
keybinding_paused:
keydown_Return: reset_game
keydown_Escape: quit_game
keydown_M: toggle_audio
keydown_F: toggle_full_screen

29
conf/keybindings_pc.yaml

@ -0,0 +1,29 @@
keybinding_game:
keydown_Return: spawn_rat
keydown_D: kill_rat
keydown_M: toggle_audio
keydown_F: toggle_full_screen
keydown_Up: start_scrolling|Up
keydown_Down: start_scrolling|Down
keydown_Left: start_scrolling|Left
keydown_Right: start_scrolling|Right
keyup_Up: stop_scrolling
keyup_Down: stop_scrolling
keyup_Left: stop_scrolling
keyup_Right: stop_scrolling
keydown_Space: spawn_new_bomb
keydown_N: spawn_new_nuclear_bomb
keydown_Left_Ctrl: spawn_new_mine
keydown_P: toggle_pause
keybinding_start_menu:
keydown_Return: reset_game
keydown_Escape: quit_game
keydown_M: toggle_audio
keydown_F: toggle_full_screen
keybinding_paused:
keydown_Return: reset_game
keydown_Escape: quit_game
keydown_M: toggle_audio
keydown_F: toggle_full_screen

24
conf/keybindings_r36s.yaml

@ -0,0 +1,24 @@
keybinding_game:
joybuttondown_13: spawn_rat
joybuttondown_8: start_scrolling|Up
joybuttondown_9: start_scrolling|Down
joybuttondown_10: start_scrolling|Left
joybuttondown_11: start_scrolling|Right
joybuttonup_8: stop_scrolling
joybuttonup_9: stop_scrolling
joybuttonup_10: stop_scrolling
joybuttonup_11: stop_scrolling
joybuttondown_1: spawn_new_bomb
joybuttondown_3: spawn_new_nuclear_bomb
joybuttondown_2: spawn_new_mine
joybuttondown_16: toggle_pause
keybinding_start_menu:
joybuttondown_13: reset_game
joybuttondown_16: toggle_pause
joybuttondown_12: quit_game
keybinding_paused:
joybuttondown_13: reset_game
joybuttondown_16: toggle_pause
joybuttondown_12: quit_game

71
engine/controls.py

@ -11,73 +11,44 @@ with open("conf/keybindings.yaml", "r") as f:
class KeyBindings: class KeyBindings:
def trigger(self, action): def trigger(self, action):
print(f"Triggering action: {action}") #print(f"Triggering action: {action}")
# Check if the action is in the bindings # Check if the action is in the bindings
if action in bindings[f"keybinding_{self.game_status}"]: if action in bindings[f"keybinding_{self.game_status}"]:
value = bindings[f"keybinding_{self.game_status}"][action] value = bindings[f"keybinding_{self.game_status}"][action]
# Call the corresponding method # Call the corresponding method
if value: if value:
print(f"Calling method: {value}") #print(f"Calling method: {value}")
if "|" in value: if "|" in value:
method_name, *args = value.split("|") method_name, *args = value.split("|")
method = getattr(self, method_name) method = getattr(self, method_name)
method(*args) method(*args)
else: else:
getattr(self, value)() getattr(self, value)()
else: #else:
print(f"Action {action} not found in keybindings for {self.game_status}") #print(f"Action {action} not found in keybindings for {self.game_status}")
return return
print(f"Action {action} not found in keybindings for {self.game_status}") #print(f"Action {action} not found in keybindings for {self.game_status}")
return None return None
def key_pressed(self, key, coords=None):
if key != "mouse":
key = [key, coords]
print(f"Key pressed: {key}")
keybindings = self.configs[f"keybinding_{self.game_status}"]
if key in keybindings.get("quit", []):
self.render_engine.close()
elif key in keybindings.get("new_rat", []):
self.spawn_rat()
elif key in keybindings.get("kill_rat", []):
if self.units:
self.units[random.choice(list(self.units.keys()))].die(score=5)
elif key in keybindings.get("toggle_audio", []):
self.audio = not self.audio
elif key in keybindings.get("toggle_full_screen", []):
self.full_screen = not self.full_screen
self.render_engine.full_screen(self.full_screen)
elif key in keybindings.get("scroll_up", []):
self.start_scrolling("Up")
elif key in keybindings.get("scroll_down", []):
self.start_scrolling("Down")
elif key in keybindings.get("scroll_left", []):
self.start_scrolling("Left")
elif key in keybindings.get("scroll_right", []):
self.start_scrolling("Right")
elif key in keybindings.get("spawn_bomb", []):
self.spawn_bomb(self.pointer)
elif key in keybindings.get("spawn_mine", []):
self.spawn_mine(self.pointer)
elif key in keybindings.get("spawn_nuclear_bomb", []):
self.spawn_nuclear_bomb(self.pointer)
elif key in keybindings.get("pause", []):
self.game_status = "paused" if self.game_status == "game" else "game"
elif key in keybindings.get("start_game", []):
self.pause = False
self.game_status = "game"
self.start_game()
elif key in keybindings.get("reset_game", []):
self.pause = False
self.game_status = "game"
self.game_end = (False, None)
self.units.clear()
self.points = 0
self.start_game()
def spawn_new_bomb(self): def spawn_new_bomb(self):
self.spawn_bomb(self.pointer) self.spawn_bomb(self.pointer)
def spawn_new_mine(self):
self.spawn_mine(self.pointer)
def spawn_new_nuclear_bomb(self):
self.spawn_nuclear_bomb(self.pointer)
def toggle_audio(self):
self.render_engine.audio = not self.render_engine.audio
def toggle_pause(self):
self.game_status = "paused" if self.game_status == "game" else "game"
def toggle_full_screen(self):
self.full_screen = not self.full_screen
self.render_engine.full_screen(self.full_screen)
def quit_game(self): def quit_game(self):
self.render_engine.close() self.render_engine.close()
def start_scrolling(self, direction): def start_scrolling(self, direction):

8
engine/sdl2.py

@ -74,7 +74,7 @@ class GameWindow:
# Audio system initialization # Audio system initialization
self._init_audio_system() self._init_audio_system()
self.audio = True
# Input devices # Input devices
self.load_joystick() self.load_joystick()
@ -279,7 +279,7 @@ class GameWindow:
self.renderer.copy(self.ammo_background, dstrect=sdl2.SDL_Rect(position[0] - 5, position[1] - 2, text_width + 10, text_height + 4)) self.renderer.copy(self.ammo_background, dstrect=sdl2.SDL_Rect(position[0] - 5, position[1] - 2, text_width + 10, text_height + 4))
self.renderer.copy(self.ammo_sprite, dstrect=sdl2.SDL_Rect(position[0], position[1], text_width, text_height)) self.renderer.copy(self.ammo_sprite, dstrect=sdl2.SDL_Rect(position[0], position[1], text_width, text_height))
self.renderer.copy(assets["BMP_BOMB0"], dstrect=sdl2.SDL_Rect(position[0]+25, position[1], 20, 20)) self.renderer.copy(assets["BMP_BOMB0"], dstrect=sdl2.SDL_Rect(position[0]+25, position[1], 20, 20))
self.renderer.copy(assets["mine"], dstrect=sdl2.SDL_Rect(position[0]+80, position[1], 20, 20)) self.renderer.copy(assets["BMP_POISON"], dstrect=sdl2.SDL_Rect(position[0]+80, position[1], 20, 20))
self.renderer.copy(assets["BMP_NUCLEAR"], dstrect=sdl2.SDL_Rect(position[0]+130, position[1], 20, 20)) self.renderer.copy(assets["BMP_NUCLEAR"], dstrect=sdl2.SDL_Rect(position[0]+130, position[1], 20, 20))
# ====================== # ======================
# VIEW & NAVIGATION # VIEW & NAVIGATION
@ -319,6 +319,8 @@ class GameWindow:
def play_sound(self, sound_file, tag="base"): def play_sound(self, sound_file, tag="base"):
"""Play a sound file on the specified audio channel""" """Play a sound file on the specified audio channel"""
if not self.audio:
return
sound_path = os.path.join("sound", sound_file) sound_path = os.path.join("sound", sound_file)
rw = sdl2.SDL_RWFromFile(byteify(sound_path, "utf-8"), b"rb") rw = sdl2.SDL_RWFromFile(byteify(sound_path, "utf-8"), b"rb")
if not rw: if not rw:
@ -383,10 +385,12 @@ class GameWindow:
# print in file keycode # print in file keycode
keycode = event.key.keysym.sym keycode = event.key.keysym.sym
key = sdl2.SDL_GetKeyName(event.key.keysym.sym).decode('utf-8') key = sdl2.SDL_GetKeyName(event.key.keysym.sym).decode('utf-8')
key = key.replace(" ", "_")
# Check for Right Ctrl key to trigger white flash # Check for Right Ctrl key to trigger white flash
self.trigger(f"keydown_{key}") self.trigger(f"keydown_{key}")
elif event.type == sdl2.SDL_KEYUP: elif event.type == sdl2.SDL_KEYUP:
key = sdl2.SDL_GetKeyName(event.key.keysym.sym).decode('utf-8') key = sdl2.SDL_GetKeyName(event.key.keysym.sym).decode('utf-8')
key = key.replace(" ", "_")
self.trigger(f"keyup_{key}") self.trigger(f"keyup_{key}")
elif event.type == sdl2.SDL_MOUSEMOTION: elif event.type == sdl2.SDL_MOUSEMOTION:
self.trigger(f"mousemove_{event.motion.x}, {event.motion.y}") self.trigger(f"mousemove_{event.motion.x}, {event.motion.y}")

2
engine/unit_manager.py

@ -1,6 +1,6 @@
import random import random
import uuid import uuid
from units import rat, bomb, mine from units import rat, bomb, mine, points
class UnitManager: class UnitManager:
def count_rats(self): def count_rats(self):

5
rats.py

@ -5,6 +5,7 @@ import os
import json import json
from engine import maze, sdl2 as engine, controls, graphics, unit_manager, scoring from engine import maze, sdl2 as engine, controls, graphics, unit_manager, scoring
from units import points
class MiceMaze( class MiceMaze(
controls.KeyBindings, controls.KeyBindings,
@ -118,7 +119,7 @@ class MiceMaze(
def run(self): def run(self):
self.render_engine.mainloop(update=self.update_maze, bg_update=self.draw_maze) self.render_engine.mainloop(update=self.update_maze, bg_update=self.draw_maze)
# ==================== GAME OVER LOGIC ==================== # ==================== GAME OVER LOGIC ====================
def game_over(self): def game_over(self):
@ -137,7 +138,7 @@ class MiceMaze(
self.game_end = (True, False) self.game_end = (True, False)
self.game_status = "paused" self.game_status = "paused"
return True return True
if not count_rats: if not count_rats and not any(isinstance(unit, points.Point) for unit in self.units.values()):
self.render_engine.stop_sound() self.render_engine.stop_sound()
self.render_engine.play_sound("VICTORY.WAV") self.render_engine.play_sound("VICTORY.WAV")
self.render_engine.play_sound("WELLDONE.WAV", tag="effects") self.render_engine.play_sound("WELLDONE.WAV", tag="effects")

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

Binary file not shown.

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

Binary file not shown.

8
units/mine.py

@ -26,9 +26,8 @@ class Mine(Unit):
"""Mine explodes, killing the rat and destroying itself.""" """Mine explodes, killing the rat and destroying itself."""
if not self.armed: if not self.armed:
return return
print("MINE EXPLOSION!") self.game.render_engine.play_sound("POISON.WAV")
self.game.render_engine.play_sound("BOMB.WAV")
# Kill the rat that stepped on the mine # Kill the rat that stepped on the mine
if victim_rat.id in self.game.units: if victim_rat.id in self.game.units:
@ -43,7 +42,7 @@ class Mine(Unit):
return return
# Use mine asset # Use mine asset
image = self.game.assets["mine"] image = self.game.assets["BMP_POISON"]
image_size = self.game.render_engine.get_image_size(image) image_size = self.game.render_engine.get_image_size(image)
# Center the mine in the cell # Center the mine in the cell
@ -55,5 +54,4 @@ class Mine(Unit):
def die(self, score=None): def die(self, score=None):
"""Remove mine from game and disarm it.""" """Remove mine from game and disarm it."""
self.armed = False self.armed = False
Explosion(self.game, self.position).draw()
super().die(score) super().die(score)

Loading…
Cancel
Save