import pygame import random import sys # Initialize Pygame pygame.init() # Game Constants SCREEN_WIDTH = 800 SCREEN_HEIGHT = 500 FPS = 60 # Physics Configurations GRAVITY = 1.1 JUMP_STRENGTH = -16 # Color Palette Presets (Primary, Secondary) COLOR_PALETTES = [ ((0, 255, 200), (0, 150, 255)), # Neon Cyan & Blue (Default) ((255, 230, 0), (255, 100, 0)), # Electric Yellow & Orange ((200, 0, 255), (255, 0, 150)), # Cyber Purple & Pink ((50, 255, 50), (0, 120, 0)), # Acid Green & Dark Emerald ((255, 255, 255), (100, 100, 100)) # Monochrome White & Gray ] COLOR_BG = (15, 12, 30) # Dark Cyberpunk Purple COLOR_FLOOR = (40, 30, 70) # Floor Color COLOR_SPIKE = (255, 40, 100) # Neon Red/Pink COLOR_TEXT = (255, 255, 255) class Player: def __init__(self): self.size = 40 self.x = 150 self.floor_y = SCREEN_HEIGHT - 100 self.y = self.floor_y - self.size self.velocity_y = 0 self.is_grounded = True self.rotation = 0 self.particles = [] # Customization States self.icon_style = "classic" # Options: classic, cross, smiley self.palette_index = 0 def jump(self): if self.is_grounded: self.velocity_y = JUMP_STRENGTH self.is_grounded = False def update(self, scroll_speed): # Apply Gravity self.velocity_y += GRAVITY self.y += self.velocity_y # Floor Collision Matrix if self.y >= self.floor_y - self.size: self.y = self.floor_y - self.size self.velocity_y = 0 self.is_grounded = True # Snap rotation perfectly back to flat square grid on land remainder = self.rotation % 90 if remainder != 0: if remainder > 45: self.rotation += (90 - remainder) else: self.rotation -= remainder # Rotates mid-air to mimic Geometry Dash movement if not self.is_grounded: self.rotation += 8.5 # Handle trail particles if self.is_grounded: if random.random() = 20: self.current_level = 3 self.scroll_speed = 12.0 # Hyper Speed 3x Mode elif self.score >= 8: self.current_level = 2 self.scroll_speed = 9.5 # Normal Speed 2x Mode else: self.current_level = 1 self.scroll_speed = 7.5 # Normal Speed 1x Mode def run(self): running = True while running: self.clock.tick(FPS) # 1. Input Handler Matrix for event in pygame.event.get(): if event.type == pygame.QUIT: running = False pygame.quit() sys.exit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: running = False # Customizer Interface Control Mappings elif self.game_over or self.score == 0: if event.key == pygame.K_1: self.player.icon_style = "classic" elif event.key == pygame.K_2: self.player.icon_style = "cross" elif event.key == pygame.K_3: self.player.icon_style = "smiley" elif event.key == pygame.K_c: self.player.palette_index = (self.player.palette_index + 1) % len(COLOR_PALETTES) if self.game_over: if event.key not in [pygame.K_1, pygame.K_2, pygame.K_3, pygame.K_c]: self.reset_game() else: if event.key in [pygame.K_SPACE, pygame.K_UP]: self.player.jump() elif event.type == pygame.MOUSEBUTTONDOWN and not self.game_over: self.player.jump() # 2. Logic Step Engine Update if not self.game_over: self.update_level_progression() self.player.update(self.scroll_speed) # Dynamic obstacle spawning frequency depends directly on running rate velocity self.spawn_timer += 1 spawn_threshold = random.randint(35, 75) if self.current_level > 1 else random.randint(50, 90) if self.spawn_timer > spawn_threshold: self.obstacles.append(Obstacle(SCREEN_WIDTH + 50)) self.spawn_timer = 0 for obs in self.obstacles[:]: obs.update(self.scroll_speed) if obs.x < -100: self.obstacles.remove(obs) self.score += 1 if self.player.get_hitbox().colliderect(obs.get_hitbox()): self.game_over = True # 3. GUI Frame Buffer Rendering self.screen.fill(COLOR_BG) # Draw Ground Plane Surface Layers pygame.draw.rect(self.screen, COLOR_FLOOR, (0, SCREEN_HEIGHT - 100, SCREEN_WIDTH, 100)) pygame.draw.line(self.screen, COLOR_TEXT, (0, SCREEN_HEIGHT - 100), (SCREEN_WIDTH, SCREEN_HEIGHT - 100), 3) # Draw Game Entities for obs in self.obstacles: obs.draw(self.screen) self.player.draw(self.screen) # Display Hud Overlays score_txt = self.font_main.render(f"SCORE: {self.score}", True, COLOR_TEXT) level_txt = self.font_main.render(f"LEVEL {self.current_level}", True, COLOR_PALETTES[self.player.palette_index][0]) speed_txt = self.font_sub.render(f"SPEED: {self.scroll_speed} PPS", True, COLOR_TEXT)