Browse Source

Aggiungi file di configurazione per i binding dei tasti e implementa la gestione degli input nel gioco

master
Matteo Benedetto 12 months ago
parent
commit
98a9e5fb8b
  1. 13
      conf/keybinding_game.json
  2. BIN
      cover.jpg
  3. 33
      engine/controls.py
  4. 47
      engine/sdl2.py
  5. 0
      engine/statuses.py
  6. 20
      rats.py
  7. BIN
      sound/BOMB.WAV
  8. BIN
      sound/PUTDOWN.WAV
  9. BIN
      sound/converted/Death.wav
  10. BIN
      sound/converted_BOMB.wav
  11. 3
      units/rat.py
  12. 19
      wgdzh

13
conf/keybinding_game.json

@ -0,0 +1,13 @@
{
"quit": ["Q", 12],
"new_rat": ["Return", 13],
"kill_rat": ["D"],
"toggle_audio": ["M"],
"toggle_full_screen": ["F"],
"scroll_up": ["Up", 8],
"scroll_down": ["Down", 9],
"scroll_left": ["Left", 10],
"scroll_right": ["Right", 11],
"spawn_bomb": ["Space", 1],
"pause": ["P", 16]
}

BIN
cover.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

33
engine/controls.py

@ -5,37 +5,34 @@ import random
class KeyBindings:
def key_pressed(self, key, coords=None):
#print(key)
if key == "Q" or key == 12:
if key in self.keybindings["quit"]:
self.engine.close()
elif key == "Return" or key == 13:
elif key in self.keybindings["new_rat"]:
self.new_rat()
elif key == "D":
elif key in self.keybindings["kill_rat"]:
if self.units:
self.units[random.choice(list(self.units.keys()))].die(score=5)
elif key == "M":
elif key in self.keybindings["toggle_audio"]:
self.audio = not self.audio
elif key == "F":
elif key in self.keybindings["toggle_full_screen"]:
self.full_screen = not self.full_screen
self.engine.full_screen(self.full_screen)
elif key == "Up" or key == 8:
elif key in self.keybindings["scroll_up"]:
self.start_scrolling("Up")
elif key == "Down" or key == 9:
elif key in self.keybindings["scroll_down"]:
self.start_scrolling("Down")
elif key == "Left" or key == 10:
elif key in self.keybindings["scroll_left"]:
self.start_scrolling("Left")
elif key == "Right" or key == 11:
elif key in self.keybindings["scroll_right"]:
self.start_scrolling("Right")
elif key == "Space" or key == 1:
self.play_sound("PUTDOWN.WAV")
elif key in self.keybindings["spawn_bomb"]:
self.play_sound("PUTDOWN.WAV", tag="effects")
self.spawn_bomb(self.pointer)
elif key == "P" or key == 16:
elif key in self.keybindings["pause"]:
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
# self.scroll_cursor()
def quit_game(self):
self.engine.close()
def key_released(self, key):
if key in ["Up", "Down", "Left", "Right", 8, 9, 10, 11]:
self.stop_scrolling()

47
engine/sdl2.py

@ -7,7 +7,7 @@ from ctypes import *
from PIL import Image
from sdl2 import SDL_AudioSpec
import random
class GameWindow:
def __init__(self, width, height, cell_size, title="Default", key_callback=None):
@ -23,6 +23,7 @@ class GameWindow:
self.h_offset = self.h_start_offset
self.max_w_offset = self.target_size[0] - self.width
self.max_h_offset = self.target_size[1] - self.height
self.scale = self.target_size[1] // self.cell_size
print(f"Screen size: {self.width}x{self.height}")
sdl2.ext.init(joystick=True)
sdl2.SDL_Init(sdl2.SDL_INIT_AUDIO)
@ -37,11 +38,12 @@ class GameWindow:
self.running = True
self.key_down, self.key_up, self.axis_scroll = key_callback
self.performance = 0
self.audio_devs = []
#for i in range(5):
# self.audio_devs.append((True, sdl2.SDL_OpenAudioDevice(None, 0, SDL_AudioSpec(freq=22050, aformat=sdl2.AUDIO_U8, channels=1, samples=2048), None, 0)))
self.audio_dev = sdl2.SDL_OpenAudioDevice(None, 0, SDL_AudioSpec(freq=22050, aformat=sdl2.AUDIO_U8, channels=1, samples=2048), None, 0)
self.audio_devs = {}
self.button_cursor = [0, 0]
self.buttons = {}
self.audio_devs["base"] = sdl2.SDL_OpenAudioDevice(None, 0, SDL_AudioSpec(freq=22050, aformat=sdl2.AUDIO_U8, channels=1, samples=2048), None, 0)
self.audio_devs["effects"] = sdl2.SDL_OpenAudioDevice(None, 0, SDL_AudioSpec(freq=22050, aformat=sdl2.AUDIO_U8, channels=1, samples=2048), None, 0)
self.audio_devs["music"] = sdl2.SDL_OpenAudioDevice(None, 0, SDL_AudioSpec(freq=22050, aformat=sdl2.AUDIO_U8, channels=1, samples=2048), None, 0)
def create_texture(self, tiles: list):
bg_surface = sdl2.SDL_CreateRGBSurface(0, self.width, self.height, 32, 0, 0, 0, 0)
for tile in tiles:
@ -97,8 +99,8 @@ class GameWindow:
sprite.position = (x+self.w_offset, y+self.h_offset)
self.renderer.copy(sprite, dstrect=sprite.position)
def draw_rectangle(self, x, y, width, height, tag, outline="red", filling=None):
x, y = x + self.w_offset, y + self.h_offset
if filling:
self.renderer.fill((x, y, width, height), sdl2.ext.Color(*filling))
else:
@ -113,8 +115,8 @@ class GameWindow:
def delete_tag(self, tag):
pass
def win_screen(self, text, **kwargs):
self.draw_rectangle(50 - self.w_offset, 50 - self.h_offset,
def dialog(self, text, **kwargs):
self.draw_rectangle(50, 50,
self.target_size[0] - 100, self.target_size[1] - 100, "win", filling=(255, 255, 255))
self.draw_text(text, self.fonts[self.target_size[1]//20], "center", sdl2.ext.Color(0, 0, 0))
if image := kwargs.get("image"):
@ -133,10 +135,6 @@ class GameWindow:
sprite_score.position = (self.target_size[0] // 2 - 50-sprite_score.size[0] // 4,
self.target_size[1] // 2 + 60 + 20 * (i + 1))
self.renderer.copy(sprite_score, dstrect=sprite_score.position)
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[self.target_size[1]//20], "center", sdl2.ext.Color(0, 0, 0))
def get_image_size(self, image):
return image.size
@ -159,6 +157,9 @@ class GameWindow:
def is_in_visible_area(self, x, y):
return -self.w_offset -self.cell_size <= x <= self.width - self.w_offset and -self.h_offset -self.cell_size <= y <= self.height - self.h_offset
def get_perf_counter(self):
return sdl2.SDL_GetPerformanceCounter()
def mainloop(self, **kwargs):
while self.running:
performance_start = sdl2.SDL_GetPerformanceCounter()
@ -228,7 +229,7 @@ class GameWindow:
self.w_offset = x
self.h_offset = y
def play_sound(self, sound_file):
def play_sound(self, sound_file, tag="base"):
print(sound_file)
sound_file = os.path.join("sound", sound_file)
rw = sdl2.SDL_RWFromFile(byteify(sound_file, "utf-8"), b"rb")
@ -237,12 +238,12 @@ class GameWindow:
_buf = POINTER(sdl2.Uint8)()
_length = sdl2.Uint32()
spec = SDL_AudioSpec(freq=22050, aformat=sdl2.AUDIO_U8, channels=1, samples=2048)
spec = SDL_AudioSpec(freq=22050, aformat=sdl2.AUDIO_U8, channels=1, samples=2048)
if sdl2.SDL_LoadWAV_RW(rw, 1, byref(spec), byref(_buf), byref(_length)) == None:
raise RuntimeError("Failed to load WAV")
devid = self.audio_dev
sdl2.SDL_ClearQueuedAudio(devid)
devid = self.audio_devs[tag]
# Clear any queued audio
sdl2.SDL_ClearQueuedAudio(devid)
# Start playing audio
@ -255,4 +256,16 @@ class GameWindow:
sdl2.SDL_PauseAudioDevice(dev[1], 1)
sdl2.SDL_ClearQueuedAudio(dev[1])
def start_dialog(self, **kwargs):
self.dialog("Welcome to the Mice!", **kwargs)
center = self.get_view_center()
self.draw_button(center[0], center[1] + 10 * self.scale, "Start", 120, 50, (0, 0))
def draw_button(self, x, y, text, width, height, coords):
if self.button_cursor[0] == coords[0] and self.button_cursor[1] == coords[1]:
color = (0, 0, 255)
self.draw_rectangle(x, y, width, height, "button", outline8u=color)
self.draw_text(text, self.fonts[20], (x + 10, y + 10), (0,0,0))
def get_view_center(self):
return self.w_offset + self.width // 2, self.h_offset + self.height // 2

0
engine/statuses.py

20
rats.py

@ -7,6 +7,7 @@ from engine import maze, sdl2 as engine, controls
import os
import datetime
import subprocess
import json
class MiceMaze(controls.KeyBindings):
def __init__(self, maze_file):
@ -27,12 +28,18 @@ class MiceMaze(controls.KeyBindings):
self.scrolling_direction = None
self.pause = False
self.game_end = (False, None)
self.dialog = "start_menu"
self.scrolling = False
self.sounds = {}
for _ in range(5):
self.new_rat()
self.start_game()
self.background_texture = None
keybindings_file, = "keybinding_game.json",
with open(os.path.join("conf", keybindings_file)) as f:
self.keybindings = json.load(f)
def start_game(self):
for _ in range(5):
self.new_rat()
def count_rats(self):
count = 0
@ -78,9 +85,9 @@ class MiceMaze(controls.KeyBindings):
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"])
self.engine.dialog("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"], scores=self.read_score())
self.engine.dialog(f"You Win! Points: {self.points}", image=self.assets["BMP_WEWIN"], scores=self.read_score())
return True
@ -106,7 +113,9 @@ class MiceMaze(controls.KeyBindings):
def update_maze(self):
if self.pause:
self.engine.pause_screen("Paused")
if self.dialog != "start_menu":
self.engine.dialog("Pause")
self.engine.start_dialog(image=self.assets["BMP_WEWIN"])
return
if self.game_over():
return
@ -128,7 +137,6 @@ class MiceMaze(controls.KeyBindings):
def run(self):
self.draw_maze()
self.engine.mainloop(update=self.update_maze, bg_update=self.draw_maze)
def scroll_cursor(self, x=0, y=0):

BIN
sound/BOMB.WAV

Binary file not shown.

BIN
sound/PUTDOWN.WAV

Binary file not shown.

BIN
sound/converted/Death.wav

Binary file not shown.

BIN
sound/converted_BOMB.wav

Binary file not shown.

3
units/rat.py

@ -103,7 +103,9 @@ class Rat(Unit):
self.game.spawn_unit(Point, unit.position_before, value=score)
def draw(self):
start_perf = self.game.engine.get_perf_counter()
direction = self.calculate_rat_direction()
sex = self.sex if self.age > AGE_THRESHOLD else "BABY"
image = self.game.rat_assets[sex][direction]
image_size = self.game.engine.get_image_size(image)
@ -117,7 +119,6 @@ class Rat(Unit):
x_pos = self.position_before[0] * self.game.cell_size + (self.game.cell_size - image_size[0]) // 2 + partial_x
y_pos = self.position_before[1] * self.game.cell_size + (self.game.cell_size - image_size[1]) // 2 + partial_y
self.game.engine.draw_image(x_pos, y_pos, image, anchor="nw", tag="unit")
self.bbox = (x_pos, y_pos, x_pos + image_size[0], y_pos + image_size[1])
#self.game.engine.draw_rectangle(self.bbox[0], self.bbox[1], self.bbox[2] - self.bbox[0], self.bbox[3] - self.bbox[1], "unit")

19
wgdzh

@ -1,15 +1,12 @@
<game>
<path>./dRally.sh</path>
<name>Death Rally</name>
<desc>Death Rally is a strategic top-down racing game where players start with a modest budget and car, competing across 19 tracks in races against increasingly challenging opponents to earn money for upgrades. With choices of six car models and enhancements in engi>
In addition to race earnings, players can score bonuses for achievements like wiping out all competition, completing races unscathed, or fulfilling sponsor missions. Bonuses vary based on the chosen car, with the ultimate goal being to top the championship table and defeat the Adve>
<image>./drally/cover.png</image>
<releasedate>19960101T000000</releasedate>
<developer>Remedy Entertainment Ltd.</developer>
<publisher>Apogee Software</publisher>
<genre>Simulation-Race 3rd Pers. view-Race, Driving</genre>
<players>1-4</players>
<path>/roms/tools/mice/rats</path>
<name>Mice!</name>
<desc>Mice! is a strategic game where players must kill rats with bombs before they reproduce and become too numerous. The game is a clone of the classic game Rats! for Windows 95. <image>./drally/cover.png</image>
<releasedate>20241225T000000</releasedate>
<developer>Matteo Benedetto</developer>
<publisher>Check Mate Corp.</publisher>
<genre>Casual</genre>
<players>1</players>
<playcount>1</playcount>
<lastplayed>20240915T212155</lastplayed>
</game>
Loading…
Cancel
Save