2025-07-13 23:17:16 -07:00
|
|
|
import pygame
|
|
|
|
|
import random
|
|
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
pygame.init()
|
2025-07-14 09:59:08 -07:00
|
|
|
pygame.mixer.init()
|
2025-07-13 23:17:16 -07:00
|
|
|
pygame.joystick.init()
|
|
|
|
|
|
2025-07-14 09:59:08 -07:00
|
|
|
pygame.mixer.music.load("audio_music.mp3")
|
|
|
|
|
pygame.mixer.music.set_volume(0.5)
|
2025-07-14 10:17:31 -07:00
|
|
|
pygame.mixer.music.play(-1)
|
2025-07-14 09:59:08 -07:00
|
|
|
|
2025-07-13 23:17:16 -07:00
|
|
|
screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
|
|
|
|
|
pygame.mouse.set_visible(False)
|
|
|
|
|
info = pygame.display.Info()
|
|
|
|
|
WIDTH, HEIGHT = info.current_w, info.current_h
|
|
|
|
|
|
|
|
|
|
pygame.display.set_caption("Cat Catcher")
|
|
|
|
|
clock = pygame.time.Clock()
|
|
|
|
|
|
2025-07-13 23:35:52 -07:00
|
|
|
CAT_SIZE = [160, 160]
|
2025-07-13 23:17:16 -07:00
|
|
|
SUSHI_SIZE = (50, 50)
|
|
|
|
|
|
2025-07-13 23:35:52 -07:00
|
|
|
cat_left_base = pygame.image.load("tuna-left.png").convert_alpha()
|
|
|
|
|
cat_right_base = pygame.image.load("tuna-right.png").convert_alpha()
|
2025-07-13 23:17:16 -07:00
|
|
|
|
2025-07-13 23:35:52 -07:00
|
|
|
cat_left = pygame.transform.smoothscale(cat_left_base, CAT_SIZE)
|
|
|
|
|
cat_right = pygame.transform.smoothscale(cat_right_base, CAT_SIZE)
|
2025-07-13 23:17:16 -07:00
|
|
|
|
|
|
|
|
sushi_imgs = []
|
|
|
|
|
for i in [1, 2, 4, 5]:
|
|
|
|
|
img = pygame.image.load(f"sushi{i}.png").convert_alpha()
|
|
|
|
|
img = pygame.transform.smoothscale(img, SUSHI_SIZE)
|
|
|
|
|
sushi_imgs.append(img)
|
|
|
|
|
|
|
|
|
|
wasabi_img = pygame.image.load("sushi3.png").convert_alpha()
|
|
|
|
|
wasabi_img = pygame.transform.smoothscale(wasabi_img, SUSHI_SIZE)
|
|
|
|
|
|
2025-07-14 09:59:08 -07:00
|
|
|
chomp_sound = pygame.mixer.Sound("audio_chomp.mp3")
|
2025-07-14 10:09:35 -07:00
|
|
|
meow_sound = pygame.mixer.Sound("audio_meow.mp3")
|
2025-07-14 09:59:08 -07:00
|
|
|
|
2025-07-13 23:17:16 -07:00
|
|
|
joystick = None
|
|
|
|
|
if pygame.joystick.get_count() > 0:
|
|
|
|
|
joystick = pygame.joystick.Joystick(0)
|
|
|
|
|
joystick.init()
|
|
|
|
|
|
|
|
|
|
font = pygame.font.SysFont(None, 48)
|
|
|
|
|
|
|
|
|
|
cat_img = cat_right
|
2025-07-14 10:32:24 -07:00
|
|
|
cat_facing = "right"
|
2025-07-13 23:17:16 -07:00
|
|
|
cat_rect = cat_img.get_rect()
|
|
|
|
|
cat_rect.centerx = WIDTH // 2
|
2025-07-13 23:35:52 -07:00
|
|
|
cat_rect.bottom = HEIGHT
|
2025-07-13 23:17:16 -07:00
|
|
|
|
|
|
|
|
cat_speed = 14
|
|
|
|
|
score = 0
|
|
|
|
|
game_over = False
|
|
|
|
|
game_over_time = None
|
|
|
|
|
paused = False
|
2025-07-14 10:17:31 -07:00
|
|
|
pause_by_controller = False
|
2025-07-13 23:17:16 -07:00
|
|
|
sushi_fall_speed = 5
|
|
|
|
|
sushi_interval = 125
|
|
|
|
|
objects = []
|
|
|
|
|
|
2025-07-13 23:35:52 -07:00
|
|
|
start_time = pygame.time.get_ticks()
|
|
|
|
|
speed_increase_time = start_time
|
|
|
|
|
|
2025-07-13 23:17:16 -07:00
|
|
|
def draw_text(text, pos, color=(255, 255, 255)):
|
|
|
|
|
surf = font.render(text, True, color)
|
|
|
|
|
screen.blit(surf, pos)
|
|
|
|
|
|
|
|
|
|
def draw_centered_text(text, color=(255, 255, 255)):
|
|
|
|
|
surf = font.render(text, True, color)
|
|
|
|
|
rect = surf.get_rect(center=(WIDTH//2, HEIGHT//2))
|
|
|
|
|
screen.blit(surf, rect)
|
|
|
|
|
|
|
|
|
|
def draw_centered_multiline_text(lines, color=(255,255,255), line_spacing=10):
|
|
|
|
|
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))
|
|
|
|
|
screen.blit(surf, rect)
|
|
|
|
|
y += surf.get_height() + line_spacing
|
|
|
|
|
|
|
|
|
|
def reset_game():
|
2025-07-14 10:32:24 -07:00
|
|
|
global score, objects, game_over, cat_rect, cat_img, cat_facing, game_over_time, paused, pause_by_controller, start_time, speed_increase_time, sushi_fall_speed, CAT_SIZE, cat_left, cat_right
|
2025-07-13 23:17:16 -07:00
|
|
|
score = 0
|
|
|
|
|
objects = []
|
|
|
|
|
game_over = False
|
|
|
|
|
game_over_time = None
|
|
|
|
|
paused = False
|
2025-07-14 10:17:31 -07:00
|
|
|
pause_by_controller = False
|
2025-07-13 23:35:52 -07:00
|
|
|
CAT_SIZE = [160, 160]
|
|
|
|
|
cat_left = pygame.transform.smoothscale(cat_left_base, CAT_SIZE)
|
|
|
|
|
cat_right = pygame.transform.smoothscale(cat_right_base, CAT_SIZE)
|
2025-07-14 10:32:24 -07:00
|
|
|
cat_facing = "right"
|
2025-07-13 23:17:16 -07:00
|
|
|
cat_img = cat_right
|
2025-07-13 23:35:52 -07:00
|
|
|
cat_rect = cat_img.get_rect()
|
|
|
|
|
cat_rect.centerx = WIDTH // 2
|
|
|
|
|
cat_rect.bottom = HEIGHT
|
|
|
|
|
sushi_fall_speed = 5
|
|
|
|
|
start_time = pygame.time.get_ticks()
|
|
|
|
|
speed_increase_time = start_time
|
2025-07-13 23:17:16 -07:00
|
|
|
|
|
|
|
|
def spawn_sushi():
|
|
|
|
|
x = random.randint(50, WIDTH - 50)
|
|
|
|
|
is_wasabi = random.random() < 0.1
|
|
|
|
|
img = wasabi_img if is_wasabi else random.choice(sushi_imgs)
|
|
|
|
|
rect = img.get_rect(midtop=(x, -40))
|
|
|
|
|
objects.append({'img': img, 'rect': rect, 'wasabi': is_wasabi})
|
|
|
|
|
|
|
|
|
|
reset_game()
|
|
|
|
|
last_spawn = pygame.time.get_ticks()
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
dt = clock.tick(60)
|
2025-07-14 10:32:24 -07:00
|
|
|
screen.fill((135, 206, 235))
|
2025-07-13 23:17:16 -07:00
|
|
|
|
|
|
|
|
keys = pygame.key.get_pressed()
|
|
|
|
|
move = 0
|
|
|
|
|
|
|
|
|
|
for event in pygame.event.get():
|
|
|
|
|
if event.type == pygame.QUIT:
|
|
|
|
|
pygame.quit()
|
|
|
|
|
sys.exit()
|
|
|
|
|
if event.type == pygame.KEYDOWN:
|
|
|
|
|
if event.key == pygame.K_ESCAPE:
|
2025-07-14 10:32:24 -07:00
|
|
|
if not game_over:
|
2025-07-13 23:17:16 -07:00
|
|
|
paused = not paused
|
2025-07-14 10:17:31 -07:00
|
|
|
pause_by_controller = False
|
2025-07-14 09:59:08 -07:00
|
|
|
if paused:
|
|
|
|
|
pygame.mixer.music.pause()
|
|
|
|
|
else:
|
|
|
|
|
pygame.mixer.music.unpause()
|
2025-07-13 23:17:16 -07:00
|
|
|
elif event.key == pygame.K_q:
|
|
|
|
|
pygame.quit()
|
|
|
|
|
sys.exit()
|
|
|
|
|
elif game_over and not paused:
|
|
|
|
|
reset_game()
|
|
|
|
|
if joystick and event.type == pygame.JOYBUTTONDOWN:
|
|
|
|
|
if event.button == 7 or event.button == 6:
|
2025-07-14 10:32:24 -07:00
|
|
|
if not game_over:
|
2025-07-13 23:17:16 -07:00
|
|
|
paused = not paused
|
2025-07-14 10:17:31 -07:00
|
|
|
pause_by_controller = True
|
2025-07-14 09:59:08 -07:00
|
|
|
if paused:
|
|
|
|
|
pygame.mixer.music.pause()
|
|
|
|
|
else:
|
|
|
|
|
pygame.mixer.music.unpause()
|
2025-07-13 23:17:16 -07:00
|
|
|
elif paused and event.button == 2:
|
|
|
|
|
pygame.quit()
|
|
|
|
|
sys.exit()
|
|
|
|
|
elif game_over and not paused:
|
|
|
|
|
reset_game()
|
|
|
|
|
|
|
|
|
|
if paused:
|
2025-07-14 10:17:31 -07:00
|
|
|
draw_centered_text("PAUSED", (255, 255, 255))
|
|
|
|
|
small_font = pygame.font.SysFont(None, 32)
|
|
|
|
|
if pause_by_controller:
|
|
|
|
|
instruction = small_font.render("Press START to resume or X to quit.", True, (255, 255, 255))
|
|
|
|
|
else:
|
|
|
|
|
instruction = 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))
|
|
|
|
|
screen.blit(instruction, instr_rect)
|
2025-07-13 23:17:16 -07:00
|
|
|
pygame.display.flip()
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
now = pygame.time.get_ticks()
|
|
|
|
|
|
2025-07-13 23:35:52 -07:00
|
|
|
if now - speed_increase_time > 30000:
|
|
|
|
|
sushi_fall_speed += 1
|
|
|
|
|
speed_increase_time = now
|
|
|
|
|
|
2025-07-14 10:32:24 -07:00
|
|
|
if not game_over:
|
2025-07-13 23:17:16 -07:00
|
|
|
if keys[pygame.K_a]:
|
|
|
|
|
move = -cat_speed
|
2025-07-14 10:32:24 -07:00
|
|
|
cat_facing = "left"
|
2025-07-13 23:17:16 -07:00
|
|
|
elif keys[pygame.K_d]:
|
|
|
|
|
move = cat_speed
|
2025-07-14 10:32:24 -07:00
|
|
|
cat_facing = "right"
|
2025-07-13 23:17:16 -07:00
|
|
|
|
|
|
|
|
if joystick:
|
|
|
|
|
axis = joystick.get_axis(0)
|
|
|
|
|
if abs(axis) > 0.2:
|
|
|
|
|
move = int(axis * cat_speed)
|
2025-07-14 10:32:24 -07:00
|
|
|
cat_facing = "left" if axis < 0 else "right"
|
|
|
|
|
|
|
|
|
|
cat_img = cat_left if cat_facing == "left" else cat_right
|
2025-07-13 23:17:16 -07:00
|
|
|
|
|
|
|
|
cat_rect.x += move
|
|
|
|
|
cat_rect.x = max(0, min(WIDTH - cat_rect.width, cat_rect.x))
|
2025-07-13 23:35:52 -07:00
|
|
|
cat_rect.bottom = HEIGHT
|
2025-07-13 23:17:16 -07:00
|
|
|
|
|
|
|
|
if now - last_spawn > sushi_interval:
|
|
|
|
|
spawn_sushi()
|
|
|
|
|
last_spawn = now
|
|
|
|
|
|
|
|
|
|
tuna_mid_y = cat_rect.top + cat_rect.height // 2
|
|
|
|
|
|
|
|
|
|
for obj in objects[:]:
|
|
|
|
|
obj['rect'].y += sushi_fall_speed
|
|
|
|
|
horizontal_overlap = obj['rect'].right > cat_rect.left and obj['rect'].left < cat_rect.right
|
|
|
|
|
|
|
|
|
|
if horizontal_overlap and obj['rect'].bottom >= tuna_mid_y:
|
|
|
|
|
if obj['wasabi']:
|
2025-07-14 10:09:35 -07:00
|
|
|
meow_sound.play()
|
2025-07-14 10:32:24 -07:00
|
|
|
game_over = True
|
|
|
|
|
game_over_time = None
|
2025-07-13 23:17:16 -07:00
|
|
|
else:
|
|
|
|
|
score += 1
|
2025-07-14 09:59:08 -07:00
|
|
|
chomp_sound.play()
|
2025-07-13 23:35:52 -07:00
|
|
|
mid_x = cat_rect.centerx
|
|
|
|
|
CAT_SIZE[0] += 1
|
|
|
|
|
CAT_SIZE[1] += 1
|
|
|
|
|
cat_left = pygame.transform.smoothscale(cat_left_base, CAT_SIZE)
|
|
|
|
|
cat_right = pygame.transform.smoothscale(cat_right_base, CAT_SIZE)
|
2025-07-14 10:32:24 -07:00
|
|
|
cat_img = cat_left if cat_facing == "left" else cat_right
|
2025-07-13 23:35:52 -07:00
|
|
|
cat_rect = cat_img.get_rect()
|
|
|
|
|
cat_rect.centerx = mid_x
|
|
|
|
|
cat_rect.bottom = HEIGHT
|
2025-07-13 23:17:16 -07:00
|
|
|
objects.remove(obj)
|
|
|
|
|
elif obj['rect'].top > HEIGHT:
|
|
|
|
|
objects.remove(obj)
|
|
|
|
|
else:
|
|
|
|
|
if game_over_time is None:
|
|
|
|
|
game_over_time = now
|
|
|
|
|
elif now - game_over_time >= 3000:
|
|
|
|
|
pygame.quit()
|
|
|
|
|
sys.exit()
|
|
|
|
|
|
2025-07-14 10:32:24 -07:00
|
|
|
screen.blit(cat_img, cat_rect)
|
2025-07-13 23:17:16 -07:00
|
|
|
|
|
|
|
|
for obj in objects:
|
|
|
|
|
screen.blit(obj['img'], obj['rect'])
|
|
|
|
|
|
|
|
|
|
draw_text(f"Score: {score}", (10, 10))
|
|
|
|
|
|
|
|
|
|
if game_over:
|
|
|
|
|
draw_centered_multiline_text([f"Final Score: {score}", "Game Over!"], color=(255, 0, 0))
|
|
|
|
|
|
|
|
|
|
pygame.display.flip()
|
|
|
|
|
|