import pygame import random import time # Initialize pygame pygame.init() # Constants SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 INITIAL_NOTE_SPEED = 16 # Adjusted to match Osu!Mania scroll speed 28 NOTE_WIDTH = 50 NOTE_HEIGHT = 50 NOTE_INTERVAL = 90 # Increased spacing factor to reduce note frequency KEYBIND = {'e': pygame.K_e, 'r': pygame.K_r, 'u': pygame.K_u, 'i': pygame.K_i} # Proper pygame key bindings KEY_POSITIONS = {'e': 200, 'r': 300, 'u': 400, 'i': 500} # Adjusted order (left to right) # Set up the screen screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption('Osu!Mania Type Game') # Set up fonts font = pygame.font.SysFont('Arial', 30) # Colors WHITE = (255, 255, 255) RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) BLACK = (0, 0, 0) GRAY = (100, 100, 100) YELLOW = (255, 255, 0) # Set up clock for FPS clock = pygame.time.Clock() # Note Class class Note: def __init__(self, x, y, key, speed): self.x = x self.y = y self.key = key self.speed = speed def move(self): self.y += self.speed def draw(self): pygame.draw.rect(screen, WHITE, (self.x, self.y, NOTE_WIDTH, NOTE_HEIGHT)) # Function to check if a key press matches def check_hit(note, key): return note.key == key and SCREEN_HEIGHT - 120 <= note.y <= SCREEN_HEIGHT - 80 # Effect class for visual feedback class Effect: def __init__(self, x, y): self.x = x self.y = y self.timer = 10 # Frames the effect lasts def draw(self): if self.timer > 0: pygame.draw.circle(screen, YELLOW, (self.x + NOTE_WIDTH // 2, self.y + NOTE_HEIGHT // 2), 20) self.timer -= 1 # Main game function def game(): notes = [] effects = [] score = 0 missed_notes = 0 note_speed = INITIAL_NOTE_SPEED note_spawn_timer = 0 running = True keys_pressed = set() while running: screen.fill(BLACK) # Draw hit area for key, x in KEY_POSITIONS.items(): pygame.draw.rect(screen, GRAY, (x, SCREEN_HEIGHT - 100, NOTE_WIDTH, NOTE_HEIGHT)) # Increase note speed over time note_speed = min(40, note_speed + 0.002) note_spawn_timer += note_speed # Adjust spawn spacing dynamically # Generate new notes with spacing based on speed if note_spawn_timer >= NOTE_INTERVAL: note_spawn_timer = 0 if random.random() < 0.7: # 70% chance to spawn a note, reducing overall density key = random.choice(list(KEY_POSITIONS.keys())) x = KEY_POSITIONS[key] note = Note(x, -NOTE_HEIGHT, key, note_speed) notes.append(note) # Handle events for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == pygame.KEYDOWN: for key, pygame_key in KEYBIND.items(): if event.key == pygame_key: keys_pressed.add(key) elif event.type == pygame.KEYUP: for key, pygame_key in KEYBIND.items(): if event.key == pygame_key: keys_pressed.discard(key) # Check for simultaneous key hits for key in list(keys_pressed): hit = False for note in notes[:]: # Copy list to avoid modification issues if check_hit(note, key): notes.remove(note) score += 15 # Increased reward for hits effects.append(Effect(KEY_POSITIONS[key], SCREEN_HEIGHT - 100)) # Add effect on hit hit = True if not hit: score -= 10 # Increased miss penalty # Move and draw notes for note in notes[:]: note.move() note.draw() if note.y > SCREEN_HEIGHT: notes.remove(note) missed_notes += 1 score -= 15 # Draw effects for effect in effects[:]: effect.draw() if effect.timer <= 0: effects.remove(effect) # Display score and missed notes score_text = font.render(f"Score: {score}", True, WHITE) miss_text = font.render(f"Missed: {missed_notes}", True, RED) screen.blit(score_text, (10, 10)) screen.blit(miss_text, (10, 50)) # Refresh the screen pygame.display.flip() # Cap the frame rate clock.tick(60) pygame.quit() if __name__ == "__main__": game()