13 changed files with 277 additions and 6 deletions
|
After Width: | Height: | Size: 273 B |
@ -0,0 +1,77 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
""" |
||||||
|
Audio conversion script to convert mine.wav to u8 22100 Hz format |
||||||
|
""" |
||||||
|
|
||||||
|
from pydub import AudioSegment |
||||||
|
import os |
||||||
|
|
||||||
|
def convert_mine_wav(): |
||||||
|
"""Convert mine.wav to u8 format at 22100 Hz""" |
||||||
|
|
||||||
|
# Input and output paths |
||||||
|
input_path = "sound/mine.wav" |
||||||
|
output_path = "sound/mine_converted.wav" |
||||||
|
|
||||||
|
if not os.path.exists(input_path): |
||||||
|
print(f"Error: {input_path} not found!") |
||||||
|
return |
||||||
|
|
||||||
|
try: |
||||||
|
# Load the audio file |
||||||
|
print(f"Loading {input_path}...") |
||||||
|
audio = AudioSegment.from_wav(input_path) |
||||||
|
|
||||||
|
# Print current format info |
||||||
|
print(f"Original format:") |
||||||
|
print(f" Sample rate: {audio.frame_rate} Hz") |
||||||
|
print(f" Channels: {audio.channels}") |
||||||
|
print(f" Sample width: {audio.sample_width} bytes ({audio.sample_width * 8} bits)") |
||||||
|
print(f" Duration: {len(audio)} ms") |
||||||
|
|
||||||
|
# Convert to mono if stereo |
||||||
|
if audio.channels > 1: |
||||||
|
print("Converting to mono...") |
||||||
|
audio = audio.set_channels(1) |
||||||
|
|
||||||
|
# Convert to 22100 Hz sample rate |
||||||
|
print("Converting sample rate to 22100 Hz...") |
||||||
|
audio = audio.set_frame_rate(22100) |
||||||
|
|
||||||
|
# Convert to 8-bit unsigned (u8) |
||||||
|
print("Converting to 8-bit unsigned format...") |
||||||
|
audio = audio.set_sample_width(1) # 1 byte = 8 bits |
||||||
|
|
||||||
|
# Export the converted audio |
||||||
|
print(f"Saving to {output_path}...") |
||||||
|
audio.export(output_path, format="wav") |
||||||
|
|
||||||
|
# Print new format info |
||||||
|
converted_audio = AudioSegment.from_wav(output_path) |
||||||
|
print(f"\nConverted format:") |
||||||
|
print(f" Sample rate: {converted_audio.frame_rate} Hz") |
||||||
|
print(f" Channels: {converted_audio.channels}") |
||||||
|
print(f" Sample width: {converted_audio.sample_width} bytes ({converted_audio.sample_width * 8} bits)") |
||||||
|
print(f" Duration: {len(converted_audio)} ms") |
||||||
|
|
||||||
|
print(f"\nConversion complete! Output saved as: {output_path}") |
||||||
|
|
||||||
|
# Optionally replace the original file |
||||||
|
replace = input("\nReplace original mine.wav with converted version? (y/n): ").lower() |
||||||
|
if replace == 'y': |
||||||
|
import shutil |
||||||
|
# Backup original |
||||||
|
backup_path = "sound/mine_original.wav" |
||||||
|
shutil.copy2(input_path, backup_path) |
||||||
|
print(f"Original file backed up as: {backup_path}") |
||||||
|
|
||||||
|
# Replace original |
||||||
|
shutil.copy2(output_path, input_path) |
||||||
|
os.remove(output_path) |
||||||
|
print(f"Original file replaced with converted version.") |
||||||
|
|
||||||
|
except Exception as e: |
||||||
|
print(f"Error during conversion: {e}") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
convert_mine_wav() |
||||||
@ -0,0 +1,123 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
""" |
||||||
|
Script to resize PNG asset files to 18x18 pixels and center them on a 20x20 canvas. |
||||||
|
Saves the result back to the same file. |
||||||
|
""" |
||||||
|
|
||||||
|
import os |
||||||
|
import glob |
||||||
|
from PIL import Image, ImageOps |
||||||
|
import argparse |
||||||
|
|
||||||
|
def resize_and_center_image(image_path, target_size=(18, 18), canvas_size=(20, 20)): |
||||||
|
""" |
||||||
|
Resize an image to target_size and center it on a canvas of canvas_size. |
||||||
|
|
||||||
|
Args: |
||||||
|
image_path (str): Path to the image file |
||||||
|
target_size (tuple): Size to resize the image to (width, height) |
||||||
|
canvas_size (tuple): Size of the final canvas (width, height) |
||||||
|
""" |
||||||
|
try: |
||||||
|
# Open the image |
||||||
|
with Image.open(image_path) as img: |
||||||
|
# Convert to RGBA to handle transparency |
||||||
|
img = img.convert("RGBA") |
||||||
|
|
||||||
|
# Resize the image to target size using high-quality resampling |
||||||
|
resized_img = img.resize(target_size, Image.Resampling.LANCZOS) |
||||||
|
|
||||||
|
# Create a new transparent canvas |
||||||
|
canvas = Image.new("RGBA", canvas_size, (0, 0, 0, 0)) |
||||||
|
|
||||||
|
# Calculate position to center the resized image |
||||||
|
x_offset = (canvas_size[0] - target_size[0]) // 2 |
||||||
|
y_offset = (canvas_size[1] - target_size[1]) // 2 |
||||||
|
|
||||||
|
# Paste the resized image onto the canvas |
||||||
|
canvas.paste(resized_img, (x_offset, y_offset), resized_img) |
||||||
|
|
||||||
|
# Save back to the same file |
||||||
|
canvas.save(image_path, "PNG", optimize=True) |
||||||
|
|
||||||
|
print(f"✓ Processed: {os.path.basename(image_path)}") |
||||||
|
|
||||||
|
except Exception as e: |
||||||
|
print(f"✗ Error processing {image_path}: {str(e)}") |
||||||
|
|
||||||
|
def process_directory(directory_path, file_pattern="*.png"): |
||||||
|
""" |
||||||
|
Process all PNG files in a directory. |
||||||
|
|
||||||
|
Args: |
||||||
|
directory_path (str): Path to the directory containing PNG files |
||||||
|
file_pattern (str): Pattern to match files (default: "*.png") |
||||||
|
""" |
||||||
|
if not os.path.exists(directory_path): |
||||||
|
print(f"Error: Directory '{directory_path}' does not exist.") |
||||||
|
return |
||||||
|
|
||||||
|
# Find all PNG files matching the pattern |
||||||
|
search_pattern = os.path.join(directory_path, file_pattern) |
||||||
|
png_files = glob.glob(search_pattern) |
||||||
|
|
||||||
|
if not png_files: |
||||||
|
print(f"No PNG files found in '{directory_path}' matching pattern '{file_pattern}'") |
||||||
|
return |
||||||
|
|
||||||
|
print(f"Found {len(png_files)} PNG files to process...") |
||||||
|
|
||||||
|
# Process each file |
||||||
|
for png_file in png_files: |
||||||
|
resize_and_center_image(png_file) |
||||||
|
|
||||||
|
print(f"\nCompleted processing {len(png_files)} files.") |
||||||
|
|
||||||
|
def process_single_file(file_path): |
||||||
|
""" |
||||||
|
Process a single PNG file. |
||||||
|
|
||||||
|
Args: |
||||||
|
file_path (str): Path to the PNG file |
||||||
|
""" |
||||||
|
if not os.path.exists(file_path): |
||||||
|
print(f"Error: File '{file_path}' does not exist.") |
||||||
|
return |
||||||
|
|
||||||
|
if not file_path.lower().endswith('.png'): |
||||||
|
print(f"Error: File '{file_path}' is not a PNG file.") |
||||||
|
return |
||||||
|
|
||||||
|
print(f"Processing single file: {os.path.basename(file_path)}") |
||||||
|
resize_and_center_image(file_path) |
||||||
|
print("Processing complete.") |
||||||
|
|
||||||
|
def main(): |
||||||
|
parser = argparse.ArgumentParser(description="Resize PNG assets to 18x18px and center on 20x20px canvas") |
||||||
|
parser.add_argument("path", help="Path to PNG file or directory containing PNG files") |
||||||
|
parser.add_argument("--pattern", default="*.png", help="File pattern to match (default: *.png)") |
||||||
|
|
||||||
|
args = parser.parse_args() |
||||||
|
|
||||||
|
if os.path.isfile(args.path): |
||||||
|
process_single_file(args.path) |
||||||
|
elif os.path.isdir(args.path): |
||||||
|
process_directory(args.path, args.pattern) |
||||||
|
else: |
||||||
|
print(f"Error: '{args.path}' is not a valid file or directory.") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
# If run without arguments, process the assets/Rat directory by default |
||||||
|
import sys |
||||||
|
if len(sys.argv) == 1: |
||||||
|
# Default to processing the assets/Rat directory |
||||||
|
script_dir = os.path.dirname(os.path.abspath(__file__)) |
||||||
|
assets_dir = os.path.join(script_dir, "assets", "Rat") |
||||||
|
if os.path.exists(assets_dir): |
||||||
|
print("No arguments provided. Processing assets/Rat directory by default...") |
||||||
|
process_directory(assets_dir) |
||||||
|
else: |
||||||
|
print("assets/Rat directory not found. Please provide a path as argument.") |
||||||
|
print("Usage: python resize_assets.py <path_to_file_or_directory>") |
||||||
|
else: |
||||||
|
main() |
||||||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,59 @@ |
|||||||
|
from .unit import Unit |
||||||
|
from .bomb import Explosion |
||||||
|
class Mine(Unit): |
||||||
|
def __init__(self, game, position=(0,0), id=None): |
||||||
|
super().__init__(game, position, id) |
||||||
|
self.speed = 1.0 # Mine doesn't move but needs speed for consistency |
||||||
|
self.armed = True # Mine is active and ready to explode |
||||||
|
|
||||||
|
def move(self): |
||||||
|
"""Mines don't move, but we need to check for collision with rats each frame.""" |
||||||
|
pass |
||||||
|
|
||||||
|
def collisions(self): |
||||||
|
"""Check if a rat steps on the mine (has position_before on mine's position).""" |
||||||
|
if not self.armed: |
||||||
|
return |
||||||
|
|
||||||
|
# Check for rats that have position_before on this mine's position |
||||||
|
for rat_unit in self.game.unit_positions_before.get(self.position, []): |
||||||
|
if hasattr(rat_unit, 'sex'): # Check if it's a rat (rats have sex attribute) |
||||||
|
# Mine explodes and kills the rat |
||||||
|
self.explode(rat_unit) |
||||||
|
break |
||||||
|
|
||||||
|
def explode(self, victim_rat): |
||||||
|
"""Mine explodes, killing the rat and destroying itself.""" |
||||||
|
if not self.armed: |
||||||
|
return |
||||||
|
|
||||||
|
print("MINE EXPLOSION!") |
||||||
|
self.game.render_engine.play_sound("BOMB.WAV") |
||||||
|
|
||||||
|
# Kill the rat that stepped on the mine |
||||||
|
if victim_rat.id in self.game.units: |
||||||
|
victim_rat.die(score=5) |
||||||
|
|
||||||
|
# Remove the mine from the game |
||||||
|
self.die() |
||||||
|
|
||||||
|
def draw(self): |
||||||
|
"""Draw the mine using the mine asset.""" |
||||||
|
if not self.armed: |
||||||
|
return |
||||||
|
|
||||||
|
# Use mine asset |
||||||
|
image = self.game.assets["mine"] |
||||||
|
image_size = self.game.render_engine.get_image_size(image) |
||||||
|
|
||||||
|
# Center the mine in the cell |
||||||
|
x_pos = self.position[0] * self.game.cell_size + (self.game.cell_size - image_size[0]) // 2 |
||||||
|
y_pos = self.position[1] * self.game.cell_size + (self.game.cell_size - image_size[1]) // 2 |
||||||
|
|
||||||
|
self.game.render_engine.draw_image(x_pos, y_pos, image, anchor="nw", tag="unit") |
||||||
|
|
||||||
|
def die(self, score=None): |
||||||
|
"""Remove mine from game and disarm it.""" |
||||||
|
self.armed = False |
||||||
|
Explosion(self.game, self.position).draw() |
||||||
|
super().die(score) |
||||||
Loading…
Reference in new issue