import os import pygame from pygame.locals import * import sys import random import time pygame.init() vec = pygame.math.Vector2 # Automatically use the screen resolution for fullscreen WIDTH, HEIGHT = pygame.display.Info().current_w, pygame.display.Info().current_h ACC = 0.5 FRIC = -0.12 FPS = 60 PLAYER_SIZE = (30, 30) FramePerSec = pygame.time.Clock() displaysurface = pygame.display.set_mode((WIDTH, HEIGHT), pygame.FULLSCREEN) # Fullscreen mode pygame.display.set_caption("Cat Platformer") # --- Load Animated Background Frames --- bg_frames = [] bg_folder = "bg_frames" # Folder containing split gif frames like frame_001.png if os.path.exists(bg_folder): for filename in sorted(os.listdir(bg_folder)): if filename.endswith(('.png', '.jpg', '.gif')): # Handles images in the folder try: frame = pygame.image.load(os.path.join(bg_folder, filename)).convert() frame = pygame.transform.scale(frame, (WIDTH, HEIGHT)) # Resize each background frame to screen size bg_frames.append(frame) except pygame.error as e: print(f"Failed to load {filename}: {e}") else: print("❌ Folder 'bg_frames' does not exist.") pygame.quit() sys.exit() if not bg_frames: print("❌ No background frames were loaded! Make sure you have .png/.jpg/.gif files in 'bg_frames'") pygame.quit() sys.exit() bg_frame_index = 0 bg_frame_delay = 5 bg_timer = 0 unlocked_cats = [True, False, False] CHARACTER_IMAGES = [ pygame.transform.scale(pygame.image.load("cat1.gif").convert_alpha(), PLAYER_SIZE), pygame.transform.scale(pygame.image.load("cat2.gif").convert_alpha(), PLAYER_SIZE), pygame.transform.scale(pygame.image.load("cat3.gif").convert_alpha(), PLAYER_SIZE), ] def update_background(): global bg_timer, bg_frame_index bg_timer += 1 if bg_timer >= bg_frame_delay: bg_timer = 0 bg_frame_index = (bg_frame_index + 1) % len(bg_frames) displaysurface.blit(bg_frames[bg_frame_index], (0, 0)) def draw_text(text, font_size, color, center): font = pygame.font.SysFont("Verdana", font_size) surface = font.render(text, True, color) rect = surface.get_rect(center=center) displaysurface.blit(surface, rect) def start_screen(): selected = 0 cat_spacing = WIDTH // 6 # Adjust cat spacing based on screen size total_width = cat_spacing * (len(CHARACTER_IMAGES) - 1) start_x = WIDTH // 2 - total_width // 2 play_button = pygame.Rect(WIDTH//2 - 60, HEIGHT//2 + 80, 120, 40) while True: update_background() draw_text("Choose Your Cat!", 30, (255, 255, 255), (WIDTH // 2, HEIGHT // 6)) for i, img in enumerate(CHARACTER_IMAGES): x = start_x + i * cat_spacing y = HEIGHT // 3 border_rect = pygame.Rect(x - 5, y - 5, PLAYER_SIZE[0] + 10, PLAYER_SIZE[1] + 10) if i == selected: pygame.draw.rect(displaysurface, (255, 255, 0), border_rect, 3) if unlocked_cats[i]: displaysurface.blit(img, (x, y)) else: draw_text("?", 40, (200, 200, 200), (x + PLAYER_SIZE[0] // 2, y + PLAYER_SIZE[1] // 2)) pygame.draw.rect(displaysurface, (50, 200, 50), play_button, border_radius=5) draw_text("PLAY", 20, (255, 255, 255), play_button.center) pygame.display.update() for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == KEYDOWN: if event.key == K_LEFT: selected = (selected - 1) % len(CHARACTER_IMAGES) elif event.key == K_RIGHT: selected = (selected + 1) % len(CHARACTER_IMAGES) elif event.type == MOUSEBUTTONDOWN: if play_button.collidepoint(event.pos) and unlocked_cats[selected]: return selected def level_menu(): selected = 0 level_names = ["Level 1", "Level 2", "Level 3"] level_rects = [] while True: update_background() draw_text("Select Level", 30, (255, 255, 255), (WIDTH // 2, HEIGHT // 6)) for i, name in enumerate(level_names): rect = pygame.Rect(WIDTH//2 - 60, HEIGHT//4 + i * 60, 120, 40) level_rects.append(rect) color = (255, 255, 0) if i == selected else (50, 150, 200) pygame.draw.rect(displaysurface, color, rect, border_radius=5) draw_text(name, 20, (0, 0, 0), rect.center) pygame.display.update() level_rects.clear() for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == KEYDOWN: if event.key == K_UP: selected = (selected - 1) % len(level_names) elif event.key == K_DOWN: selected = (selected + 1) % len(level_names) elif event.key == K_RETURN: return selected elif event.type == MOUSEBUTTONDOWN: for i, rect in enumerate(level_rects): if rect.collidepoint(event.pos): return i class Player(pygame.sprite.Sprite): def __init__(self, image, gravity): super().__init__() self.surf = image self.rect = self.surf.get_rect() self.pos = vec((WIDTH // 10, HEIGHT // 1.3)) # Position dynamically self.vel = vec(0, 0) self.acc = vec(0, gravity) self.gravity = gravity self.jumping = False self.score = 0 def move(self): self.acc = vec(0, self.gravity) pressed_keys = pygame.key.get_pressed() if pressed_keys[K_LEFT]: self.acc.x = -ACC if pressed_keys[K_RIGHT]: self.acc.x = ACC self.acc.x += self.vel.x * FRIC self.vel += self.acc self.pos += self.vel + 0.5 * self.acc if self.pos.x > WIDTH: self.pos.x = 0 if self.pos.x < 0: self.pos.x = WIDTH self.rect.midbottom = self.pos def jump(self): hits = pygame.sprite.spritecollide(self, platforms, False) if hits and not self.jumping: self.jumping = True self.vel.y = -15 def cancel_jump(self): if self.jumping and self.vel.y < -3: self.vel.y = -3 def update(self): hits = pygame.sprite.spritecollide(self, platforms, False) if self.vel.y > 0 and hits: if self.pos.y < hits[0].rect.bottom: if hits[0].point: hits[0].point = False self.score += 1 self.pos.y = hits[0].rect.top + 1 self.vel.y = 0 self.jumping = False class Platform(pygame.sprite.Sprite): def __init__(self, speed_range): super().__init__() self.surf = pygame.Surface((random.randint(50, 100), 12)) self.surf.fill((0, 255, 0)) self.rect = self.surf.get_rect(center=(random.randint(0, WIDTH - 10), random.randint(0, HEIGHT - 30))) self.point = True self.speed = random.randint(*speed_range) self.moving = True def move(self): hits = self.rect.colliderect(P1.rect) if self.moving: self.rect.move_ip(self.speed, 0) if hits: P1.pos += (self.speed, 0) if self.rect.left > WIDTH: self.rect.right = 0 if self.rect.right < 0: self.rect.left = WIDTH def plat_gen(speed_range): while len(platforms) < 6: p = Platform(speed_range) while check(p, platforms): p = Platform(speed_range) platforms.add(p) all_sprites.add(p) def check(platform, groupies): if pygame.sprite.spritecollideany(platform, groupies): return True for entity in groupies: if abs(platform.rect.top - entity.rect.bottom) < 50 and abs(platform.rect.bottom - entity.rect.top) < 50: return True return False def game_over_screen(score): while True: update_background() draw_text("You Lose!", 40, (255, 0, 0), (WIDTH // 2, HEIGHT // 6)) draw_text(f"Score: {score}", 25, (255, 255, 255), (WIDTH // 2, HEIGHT // 4)) draw_text("Press ENTER to restart", 20, (255, 255, 255), (WIDTH // 2, HEIGHT // 2)) pygame.display.update() for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() if event.type == KEYDOWN and event.key == K_RETURN: return def main_game(level, selected_cat): global P1, all_sprites, platforms, unlocked_cats gravity = 0.5 + level * 0.2 platform_speed_range = (-1 - level, 1 + level) P1 = Player(CHARACTER_IMAGES[selected_cat], gravity) PT1 = Platform((0, 0)) PT1.surf = pygame.Surface((WIDTH, 20)) PT1.surf.fill((255, 0, 0)) PT1.rect = PT1.surf.get_rect(center=(WIDTH / 2, HEIGHT - 10)) PT1.point = False PT1.moving = False all_sprites = pygame.sprite.Group() platforms = pygame.sprite.Group() all_sprites.add(P1) all_sprites.add(PT1) platforms.add(PT1) for _ in range(random.randint(4, 5)): pl = Platform(platform_speed_range) while check(pl, platforms): pl = Platform(platform_speed_range) platforms.add(pl) all_sprites.add(pl) while True: P1.update() for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() if event.type == KEYDOWN: if event.key == K_SPACE: P1.jump() if event.type == KEYUP: if event.key == K_SPACE: P1.cancel_jump() if P1.rect.top > HEIGHT: if P1.score >= 5: unlocked_cats[1] = True if P1.score >= 10: unlocked_cats[2] = True game_over_screen(P1.score) return if P1.rect.top <= HEIGHT / 3: P1.pos.y += abs(P1.vel.y) for plat in platforms: plat.rect.y += abs(P1.vel.y) if plat.rect.top >= HEIGHT: plat.kill() plat_gen(platform_speed_range) update_background() score_text = pygame.font.SysFont("Verdana", 20).render(str(P1.score), True, (123, 255, 0)) displaysurface.blit(score_text, (WIDTH / 2, 10)) for entity in all_sprites: displaysurface.blit(entity.surf, entity.rect) entity.move() pygame.display.update() FramePerSec.tick(FPS) # Game loop while True: cat_index = start_screen() level = level_menu() main_game(level, cat_index)