Fixed Game Over bug.

This commit is contained in:
justin committed 2025-07-16 09:55:53 -07:00
1 parent 699bf1f064
commit 486e7f5187
12 files changed
+524 -12

No files matched your search

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+15 -12
View File
@@ -162,28 +162,28 @@ class Game:
pygame.mouse.set_visible(False) pygame.mouse.set_visible(False)
pygame.display.set_caption("Maguro Cat Game") pygame.display.set_caption("Maguro Cat Game")
self.wallpaper = pygame.image.load("wallpaper.jpg").convert() self.wallpaper = pygame.image.load("image_wallpaper.jpg").convert()
self.wallpaper = pygame.transform.scale(self.wallpaper, SCREEN_SIZE) self.wallpaper = pygame.transform.scale(self.wallpaper, SCREEN_SIZE)
self.cat_right_base = pygame.image.load("cat.png").convert_alpha() self.cat_right_base = pygame.image.load("image_cat.png").convert_alpha()
self.sushi_images = [] self.sushi_images = []
for i in [1, 2, 4, 3]: for i in [1, 2, 4, 3]:
img = pygame.image.load(f"sushi{i}.png").convert_alpha() img = pygame.image.load(f"image_sushi{i}.png").convert_alpha()
img = pygame.transform.smoothscale(img, SUSHI_SIZE) img = pygame.transform.smoothscale(img, SUSHI_SIZE)
self.sushi_images.append(img) self.sushi_images.append(img)
self.wasabi_img = pygame.image.load("wasabi.png").convert_alpha() self.wasabi_img = pygame.image.load("image_wasabi.png").convert_alpha()
self.wasabi_img = pygame.transform.smoothscale(self.wasabi_img, SUSHI_SIZE) self.wasabi_img = pygame.transform.smoothscale(self.wasabi_img, SUSHI_SIZE)
self.cloud_base = pygame.image.load("cloud.png").convert_alpha() self.cloud_base = pygame.image.load("image_cloud.png").convert_alpha()
self.cloud_img = pygame.transform.smoothscale(self.cloud_base, CLOUD_SIZE) self.cloud_img = pygame.transform.smoothscale(self.cloud_base, CLOUD_SIZE)
self.petal_base = pygame.image.load("petal.png").convert_alpha() self.petal_base = pygame.image.load("image_petal.png").convert_alpha()
self.petal_img = pygame.transform.smoothscale(self.petal_base, PETAL_SIZE) self.petal_img = pygame.transform.smoothscale(self.petal_base, PETAL_SIZE)
self.petal_img_flipped = pygame.transform.flip(self.petal_img, True, False) self.petal_img_flipped = pygame.transform.flip(self.petal_img, True, False)
self.edamame_img = pygame.image.load("edamame.png").convert_alpha() self.edamame_img = pygame.image.load("image_edamame.png").convert_alpha()
self.edamame_img = pygame.transform.smoothscale(self.edamame_img, SUSHI_SIZE) self.edamame_img = pygame.transform.smoothscale(self.edamame_img, SUSHI_SIZE)
self.music_file = "audio_music.mp3" self.music_file = "audio_music.mp3"
@@ -322,8 +322,6 @@ class Game:
self.pause(by_controller=False) self.pause(by_controller=False)
elif event.key == pygame.K_q: elif event.key == pygame.K_q:
quit_game() quit_game()
elif self.game_over and not self.paused:
self.reset_game()
if event.type == pygame.JOYBUTTONDOWN: if event.type == pygame.JOYBUTTONDOWN:
if event.button in [7, 6]: if event.button in [7, 6]:
if not self.game_over and not self.show_intro: if not self.game_over and not self.show_intro:
@@ -472,7 +470,8 @@ class Game:
self.draw_text(f"Score: {self.score}", (10, 10)) self.draw_text(f"Score: {self.score}", (10, 10))
if self.game_over: if self.game_over:
self.draw_centered_multiline_text([f"Final Score: {self.score}", "Game Over!"], color=(255, 0, 0)) big_font = pygame.font.Font(None, 96)
self.draw_centered_multiline_text(["GAME OVER"], color=(255, 0, 0), font=big_font)
pygame.display.flip() pygame.display.flip()
@@ -485,14 +484,18 @@ class Game:
rect = surf.get_rect(center=(WIDTH // 2, HEIGHT // 2)) rect = surf.get_rect(center=(WIDTH // 2, HEIGHT // 2))
self.screen.blit(surf, rect) self.screen.blit(surf, rect)
def draw_centered_multiline_text(self, lines, color=(255, 255, 255), line_spacing=10): def draw_centered_multiline_text(self, lines, color=(255, 255, 255), line_spacing=10, font=None):
if font is None:
font = self.small_font # fallback to default
total_height = 0 total_height = 0
rendered_lines = [] rendered_lines = []
for line in lines: for line in lines:
surf = self.small_font.render(line, True, color) surf = font.render(line, True, color)
rendered_lines.append(surf) rendered_lines.append(surf)
total_height += surf.get_height() + line_spacing total_height += surf.get_height() + line_spacing
total_height -= line_spacing total_height -= line_spacing
y = (HEIGHT - total_height) // 2 y = (HEIGHT - total_height) // 2
for surf in rendered_lines: for surf in rendered_lines:
rect = surf.get_rect(center=(WIDTH // 2, y + surf.get_height() // 2)) rect = surf.get_rect(center=(WIDTH // 2, y + surf.get_height() // 2))
+509
View File
@@ -0,0 +1,509 @@
import pygame
import random
import sys
import math
pygame.init()
pygame.mixer.init()
pygame.joystick.init()
WIDTH, HEIGHT = pygame.display.Info().current_w, pygame.display.Info().current_h
SCREEN_SIZE = (WIDTH, HEIGHT)
CAT_INITIAL_SIZE = [160, 160]
CAT_MAX_SIZE = [320, 320]
SUSHI_SIZE = (50, 50)
CLOUD_SIZE = (200, 120)
PETAL_SIZE = (30, 30)
GAME_OVER_DELAY = 3000
WASABI_CHANCE = 0.1
def quit_game():
pygame.quit()
sys.exit()
class Cat:
def __init__(self, cat_right_img, pos, speed):
self.cat_right_base = cat_right_img
self.size = CAT_INITIAL_SIZE.copy()
self.speed = speed
self.facing = "right"
self.image_right = pygame.transform.smoothscale(self.cat_right_base, self.size)
self.image_left = pygame.transform.flip(self.image_right, True, False)
self.image = self.image_right
self.rect = self.image.get_rect()
self.rect.centerx, self.rect.bottom = pos
self.grow_step = 1
def update_image(self):
if self.facing == "left":
self.image = pygame.transform.flip(self.image_right, True, False)
else:
self.image = self.image_right
def move(self, dx):
self.rect.x += dx * self.speed
self.rect.x = max(0, min(WIDTH - self.rect.width, self.rect.x))
self.rect.bottom = HEIGHT
def grow(self):
self.size[0] = min(self.size[0] + self.grow_step, CAT_MAX_SIZE[0])
self.size[1] = min(self.size[1] + self.grow_step, CAT_MAX_SIZE[1])
self.image_right = pygame.transform.smoothscale(self.cat_right_base, self.size)
self.update_image()
mid_x = self.rect.centerx
self.rect = self.image.get_rect()
self.rect.centerx = mid_x
self.rect.bottom = HEIGHT
def draw(self, surface):
surface.blit(self.image, self.rect)
class Sushi:
def __init__(self, image, pos, wasabi=False, speed=5):
self.image = image
self.rect = self.image.get_rect(midtop=pos)
self.wasabi = wasabi
self.speed = speed
def update(self, dt):
self.rect.y += self.speed * dt / 16.67
def draw(self, surface):
surface.blit(self.image, self.rect)
def off_screen(self):
return self.rect.top > HEIGHT
class Cloud:
def __init__(self, image, speed_multiplier=1.0):
self.image = image
self.speed_multiplier = speed_multiplier
self.size = self.image.get_size()
self.y = 50
self.phase = random.uniform(0, 2 * math.pi)
self.speed = random.choice([-1.5, 1.5]) * speed_multiplier
if self.speed > 0:
self.rect = self.image.get_rect(topleft=(-self.size[0], self.y))
else:
self.rect = self.image.get_rect(topleft=(WIDTH + self.size[0], self.y))
self.base_y = self.y
def update(self, dt, now):
self.rect.x += self.speed * dt / 16.67
vertical_offset = 10 * math.sin(2 * math.pi * now / 1000 + self.phase)
self.rect.y = self.base_y + vertical_offset
def off_screen(self):
if self.speed > 0:
return self.rect.left > WIDTH
else:
return self.rect.right < 0
def draw(self, surface):
surface.blit(self.image, self.rect)
class Petal:
def __init__(self, image, pos, petal_toggle, speed_multiplier=1.0):
self.image = image
self.rect = self.image.get_rect(topleft=pos)
self.speed_multiplier = speed_multiplier
self.drift = random.uniform(-0.5, 0.5)
self.phase = random.uniform(0, 2 * math.pi)
self.base_x = pos[0]
self.spawn_time = pygame.time.get_ticks()
self.petal_toggle = petal_toggle
def update(self, dt, now):
self.rect.y += 3 * self.speed_multiplier * dt / 16.67
sway = 15 * math.sin(0.5 * now / 1000 + self.phase)
time_since_spawn = (now - self.spawn_time) / 1000
drift_speed = 0.5 * self.speed_multiplier
self.rect.x = self.base_x + sway + self.drift * self.speed_multiplier + drift_speed * time_since_spawn * 60
def off_screen(self):
return self.rect.top > HEIGHT
def draw(self, surface):
surface.blit(self.image, self.rect)
class Edamame:
def __init__(self, image, pos, speed=4):
self.image = image
self.rect = self.image.get_rect(midtop=pos)
self.speed = speed
self.phase = random.uniform(0, 2 * math.pi)
self.base_x = self.rect.x
def update(self, dt, now):
self.rect.y += self.speed * dt / 16.67
sway = 20 * math.sin(0.005 * now + self.phase)
self.rect.x = self.base_x + sway
def off_screen(self):
return self.rect.top > HEIGHT
def draw(self, surface):
surface.blit(self.image, self.rect)
class Spawner:
def __init__(self, spawn_interval_ms):
self.spawn_interval = spawn_interval_ms
self.last_spawn = 0
def can_spawn(self, now):
return now - self.last_spawn > self.spawn_interval
def update_spawn_time(self, now):
self.last_spawn = now
class Game:
def __init__(self):
self.screen = pygame.display.set_mode(SCREEN_SIZE, pygame.FULLSCREEN)
pygame.mouse.set_visible(False)
pygame.display.set_caption("Maguro Cat Game")
self.wallpaper = pygame.image.load("image_wallpaper.jpg").convert()
self.wallpaper = pygame.transform.scale(self.wallpaper, SCREEN_SIZE)
self.cat_right_base = pygame.image.load("image_cat.png").convert_alpha()
self.sushi_images = []
for i in [1, 2, 4, 3]:
img = pygame.image.load(f"image_sushi{i}.png").convert_alpha()
img = pygame.transform.smoothscale(img, SUSHI_SIZE)
self.sushi_images.append(img)
self.wasabi_img = pygame.image.load("wasabi.png").convert_alpha()
self.wasabi_img = pygame.transform.smoothscale(self.wasabi_img, SUSHI_SIZE)
self.cloud_base = pygame.image.load("image_cloud.png").convert_alpha()
self.cloud_img = pygame.transform.smoothscale(self.cloud_base, CLOUD_SIZE)
self.petal_base = pygame.image.load("image_petal.png").convert_alpha()
self.petal_img = pygame.transform.smoothscale(self.petal_base, PETAL_SIZE)
self.petal_img_flipped = pygame.transform.flip(self.petal_img, True, False)
self.edamame_img = pygame.image.load("image_edamame.png").convert_alpha()
self.edamame_img = pygame.transform.smoothscale(self.edamame_img, SUSHI_SIZE)
self.music_file = "audio_music.mp3"
self.chomp_sounds = [
pygame.mixer.Sound("audio_chomp_low.mp3"),
pygame.mixer.Sound("audio_chomp.mp3"),
pygame.mixer.Sound("audio_chomp_high.mp3")
]
self.meow_sound = pygame.mixer.Sound("audio_meow.mp3")
self.gamestart_sound = pygame.mixer.Sound("audio_gamestart.mp3")
self.gameover_sound = pygame.mixer.Sound("audio_gameover.mp3")
self.paused_sound = pygame.mixer.Sound("audio_paused.mp3")
self.unpaused_sound = pygame.mixer.Sound("audio_unpaused.mp3")
self.oof_sound = pygame.mixer.Sound("audio_oof.mp3")
self.joysticks = []
self.check_controllers()
self.font = pygame.font.Font("font_8bit.otf", 160)
self.jp_font = pygame.font.Font("font_notosansjp.ttf", 64)
self.small_font = pygame.font.SysFont(None, 32)
self.clock = pygame.time.Clock()
self.sushis = []
self.clouds = []
self.petals = []
self.edamames = []
self.reset_game()
def check_controllers(self):
self.joysticks.clear()
for i in range(pygame.joystick.get_count()):
joy = pygame.joystick.Joystick(i)
joy.init()
self.joysticks.append(joy)
def draw_intro(self):
now = pygame.time.get_ticks()
elapsed = now - self.intro_start_time
if elapsed >= 3000:
pygame.mixer.music.load(self.music_file)
pygame.mixer.music.set_volume(0.5)
pygame.mixer.music.play(-1)
return False
maguro_surf = self.font.render("MAGURO", True, (255, 255, 255))
jp_surf = self.jp_font.render("マグロ", True, (255, 255, 255))
self.screen.blit(maguro_surf, maguro_surf.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 80)))
self.screen.blit(jp_surf, jp_surf.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 40)))
return True
def spawn_sushi(self):
x = random.randint(50, WIDTH - 50)
is_wasabi = random.random() < WASABI_CHANCE
img = self.wasabi_img if is_wasabi else random.choice(self.sushi_images)
sushi = Sushi(img, (x, -40), wasabi=is_wasabi, speed=self.sushi_fall_speed)
self.sushis.append(sushi)
def spawn_cloud(self):
cloud = Cloud(self.cloud_img, self.cloud_speed_multiplier)
self.clouds.append(cloud)
def spawn_petal(self):
x = random.randint(0, WIDTH)
image = self.petal_img_flipped if self.petal_toggle else self.petal_img
self.petal_toggle = not self.petal_toggle
petal = Petal(image, (x, -PETAL_SIZE[1]), self.petal_toggle, self.petal_speed_multiplier)
self.petals.append(petal)
def spawn_edamame(self):
x = random.randint(50, WIDTH - 50)
flipped = random.choice([True, False])
image = pygame.transform.flip(self.edamame_img, True, False) if flipped else self.edamame_img
edamame = Edamame(image, (x, -40), speed=self.edamame_fall_speed)
self.edamames.append(edamame)
def reset_game(self):
self.score = 0
self.sushis.clear()
self.clouds.clear()
self.petals.clear()
self.edamames.clear()
self.petal_toggle = False
self.game_over = False
self.game_over_time = None
self.paused = False
self.pause_by_controller = False
self.sushi_fall_speed = 5
self.cloud_speed_multiplier = 1.0
self.petal_speed_multiplier = 1.0
self.edamame_fall_speed = 4
self.cat = Cat(self.cat_right_base, (WIDTH // 2, HEIGHT), 14)
self.sushi_spawner = Spawner(125)
self.cloud_spawner = Spawner(4000)
self.petal_spawner = Spawner(200)
self.edamame_spawner = Spawner(1500)
self.speed_increase_time = pygame.time.get_ticks()
self.intro_start_time = pygame.time.get_ticks()
self.gamestart_sound.play()
def pause(self, by_controller=False):
if not self.paused and not self.show_intro:
self.paused = True
self.pause_by_controller = by_controller
pygame.mixer.music.pause()
self.paused_sound.play()
def unpause(self):
if self.paused:
self.paused = False
pygame.mixer.music.unpause()
self.unpaused_sound.play()
def run(self):
deadzone = 0.2
self.show_intro = True
while True:
dt = self.clock.tick(60)
now = pygame.time.get_ticks()
self.screen.blit(self.wallpaper, (0, 0))
keys = pygame.key.get_pressed()
move = 0
self.check_controllers()
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit_game()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
if not self.game_over and not self.show_intro:
if self.paused:
self.unpause()
else:
self.pause(by_controller=False)
elif event.key == pygame.K_q:
quit_game()
if event.type == pygame.JOYBUTTONDOWN:
if event.button in [7, 6]:
if not self.game_over and not self.show_intro:
if self.paused:
self.unpause()
else:
self.pause(by_controller=True)
elif self.paused and event.button == 2:
quit_game()
elif self.game_over and not self.paused:
self.reset_game()
if self.show_intro:
if self.draw_intro():
pygame.display.flip()
continue
else:
self.show_intro = False
if self.paused:
self.draw_centered_text("PAUSED", (255, 255, 255))
if self.pause_by_controller:
instruction = self.small_font.render("Press START to resume or X to quit.", True, (255, 255, 255))
else:
instruction = self.small_font.render("Press ESC to resume or Q to quit.", True, (255, 255, 255))
instr_rect = instruction.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 40))
self.screen.blit(instruction, instr_rect)
pygame.display.flip()
continue
if now - self.speed_increase_time > 30000:
self.sushi_fall_speed += 1
self.cloud_speed_multiplier += 0.1
self.petal_speed_multiplier += 0.1
self.edamame_fall_speed += 0.1
self.speed_increase_time = now
if self.cloud_spawner.can_spawn(now):
self.spawn_cloud()
self.cloud_spawner.update_spawn_time(now)
if self.petal_spawner.can_spawn(now):
self.spawn_petal()
self.petal_spawner.update_spawn_time(now)
if self.edamame_spawner.can_spawn(now):
self.spawn_edamame()
self.edamame_spawner.update_spawn_time(now)
if not self.game_over and self.sushi_spawner.can_spawn(now):
self.spawn_sushi()
self.sushi_spawner.update_spawn_time(now)
for cloud in self.clouds[:]:
cloud.update(dt, now)
if cloud.off_screen():
self.clouds.remove(cloud)
for petal in self.petals[:]:
petal.update(dt, now)
if petal.off_screen():
self.petals.remove(petal)
for edamame in self.edamames[:]:
edamame.update(dt, now)
if edamame.off_screen():
self.edamames.remove(edamame)
if not self.game_over:
if keys[pygame.K_a] or keys[pygame.K_LEFT]:
move = -1
self.cat.facing = "left"
elif keys[pygame.K_d] or keys[pygame.K_RIGHT]:
move = 1
self.cat.facing = "right"
for joy in self.joysticks:
axis0 = joy.get_axis(0)
axis2 = joy.get_axis(2)
if joy.get_numhats() > 0:
hat_x, _ = joy.get_hat(0)
else:
hat_x = 0
if move == 0:
if abs(axis0) > deadzone:
move = int(axis0 / abs(axis0))
self.cat.facing = "left" if axis0 < 0 else "right"
elif abs(axis2) > deadzone:
move = int(axis2 / abs(axis2))
self.cat.facing = "left" if axis2 < 0 else "right"
elif hat_x != 0:
move = hat_x
self.cat.facing = "left" if hat_x < 0 else "right"
self.cat.update_image()
self.cat.move(move)
cat_mid_y = self.cat.rect.top + self.cat.rect.height // 2
for sushi in self.sushis[:]:
sushi.speed = self.sushi_fall_speed
sushi.update(dt)
horizontal_overlap = sushi.rect.right > self.cat.rect.left and sushi.rect.left < self.cat.rect.right
if horizontal_overlap and sushi.rect.bottom >= cat_mid_y:
if sushi.wasabi:
self.meow_sound.play()
pygame.mixer.music.stop()
self.gameover_sound.play()
self.game_over = True
self.game_over_time = None
else:
self.score += 1
random.choice(self.chomp_sounds).play()
self.cat.grow()
self.sushis.remove(sushi)
elif sushi.off_screen():
self.sushis.remove(sushi)
for edamame in self.edamames[:]:
edamame.speed = self.edamame_fall_speed
edamame.update(dt, now)
horizontal_overlap = edamame.rect.right > self.cat.rect.left and edamame.rect.left < self.cat.rect.right
if horizontal_overlap and edamame.rect.bottom >= cat_mid_y:
self.oof_sound.play()
self.score += 1
self.edamames.remove(edamame)
elif edamame.off_screen():
self.edamames.remove(edamame)
else:
if self.game_over_time is None:
self.game_over_time = now
elif now - self.game_over_time >= GAME_OVER_DELAY:
quit_game()
for cloud in self.clouds:
cloud.draw(self.screen)
for petal in self.petals:
petal.draw(self.screen)
self.cat.draw(self.screen)
for sushi in self.sushis:
sushi.draw(self.screen)
for edamame in self.edamames:
edamame.draw(self.screen)
self.draw_text(f"Score: {self.score}", (10, 10))
if self.game_over:
big_font = pygame.font.Font(None, 96)
self.draw_centered_multiline_text(["GAME OVER"], color=(255, 0, 0), font=big_font)
pygame.display.flip()
def draw_text(self, text, pos, color=(255, 255, 255)):
surf = self.small_font.render(text, True, color)
self.screen.blit(surf, pos)
def draw_centered_text(self, text, color=(255, 255, 255)):
surf = self.small_font.render(text, True, color)
rect = surf.get_rect(center=(WIDTH // 2, HEIGHT // 2))
self.screen.blit(surf, rect)
def draw_centered_multiline_text(self, lines, color=(255, 255, 255), line_spacing=10, font=None):
if font is None:
font = self.small_font # fallback to default
total_height = 0
rendered_lines = []
for line in lines:
surf = font.render(line, True, color)
rendered_lines.append(surf)
total_height += surf.get_height() + line_spacing
total_height -= line_spacing
y = (HEIGHT - total_height) // 2
for surf in rendered_lines:
rect = surf.get_rect(center=(WIDTH // 2, y + surf.get_height() // 2))
self.screen.blit(surf, rect)
y += surf.get_height() + line_spacing
if __name__ == "__main__":
game = Game()
game.reset_game()
game.run()