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