Created
January 23, 2025 00:06
-
-
Save danielvarga/a8ee28cc63e209d587375fdda2052e6a to your computer and use it in GitHub Desktop.
Squid Game Dalgona Challenge
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import pygame | |
| import math | |
| import random | |
| # Initialize Pygame | |
| pygame.init() | |
| # Screen dimensions | |
| WIDTH, HEIGHT = 800, 800 | |
| screen = pygame.display.set_mode((WIDTH, HEIGHT)) | |
| pygame.display.set_caption("Dalgona Challenge") | |
| # Colors | |
| WHITE = (255, 255, 255) | |
| BLACK = (0, 0, 0) | |
| RED = (255, 0, 0) | |
| GREEN = (0, 255, 0) | |
| BLUE = (0, 0, 255) | |
| GREY = (200, 200, 200) | |
| # Parameters | |
| FPS = 60 | |
| polygon_radius = 300 | |
| polygon_sides = 200 | |
| threshold = 50 | |
| TIME_LIMIT = 15 # Time limit in seconds | |
| # Generate random radius perturbation | |
| def smooth_random_multiplier(angle): | |
| return 1 + 0.2 * math.sin(6 * angle) + 0.1 * math.cos(10 * angle) | |
| # Generate irregular polygon vertices | |
| def generate_polygon_vertices(sides, radius, center): | |
| vertices = [] | |
| angle_step = 2 * math.pi / sides | |
| for i in range(sides): | |
| angle = i * angle_step | |
| perturbed_radius = radius * smooth_random_multiplier(angle) | |
| x = center[0] + perturbed_radius * math.cos(angle) | |
| y = center[1] + perturbed_radius * math.sin(angle) | |
| vertices.append((x, y)) | |
| return vertices | |
| center = (WIDTH // 2, HEIGHT // 2) | |
| polygon_vertices = generate_polygon_vertices(polygon_sides, polygon_radius, center) | |
| # Game variables | |
| completed_vertices = [False] * polygon_sides | |
| closest_distances = [float('inf')] * polygon_sides | |
| max_distance_penalty = 0 | |
| running = True | |
| measuring_started = False | |
| clock = pygame.time.Clock() | |
| start_time = pygame.time.get_ticks() / 1000 # Start time in seconds | |
| # Font for score display | |
| font = pygame.font.Font(None, 36) | |
| # Game loop | |
| while running: | |
| screen.fill(WHITE) | |
| # Event handling | |
| for event in pygame.event.get(): | |
| if event.type == pygame.QUIT: | |
| running = False | |
| # Get mouse position | |
| mouse_x, mouse_y = pygame.mouse.get_pos() | |
| for i in range(polygon_sides): | |
| # Draw grey boundary | |
| next_i = (i + 1) % polygon_sides | |
| pygame.draw.circle(screen, GREY, polygon_vertices[i], threshold) | |
| for i in range(polygon_sides): | |
| next_i = (i + 1) % polygon_sides | |
| # Draw polygon | |
| pygame.draw.line(screen, BLACK, polygon_vertices[i], polygon_vertices[next_i], 2) | |
| # Draw vertices | |
| for i, vertex in enumerate(polygon_vertices): | |
| # Calculate distance to mouse | |
| distance = math.hypot(mouse_x - vertex[0], mouse_y - vertex[1]) | |
| # Update closest distance for this vertex | |
| closest_distances[i] = min(closest_distances[i], distance) | |
| # Mark vertex as completed if within threshold | |
| if closest_distances[i] <= threshold: | |
| completed_vertices[i] = True | |
| color = GREEN if completed_vertices[i] else RED | |
| pygame.draw.circle(screen, color, (int(vertex[0]), int(vertex[1])), 5) | |
| # Draw mouse cursor | |
| # pygame.draw.circle(screen, BLUE, (mouse_x, mouse_y), 5) | |
| # Calculate distance to closest vertex and update penalty | |
| distances_to_vertices = [math.hypot(mouse_x - vx, mouse_y - vy) for vx, vy in polygon_vertices] | |
| min_distance = min(distances_to_vertices) | |
| if not measuring_started and min_distance < threshold / 10: | |
| measuring_started = True | |
| if measuring_started: | |
| max_distance_penalty = max(max_distance_penalty, min_distance) | |
| score = int(1000 * max_distance_penalty / threshold) | |
| # Display current score (maximum distance penalty) | |
| score_text = font.render(f"Penalty: {score:05d}", True, BLACK) | |
| screen.blit(score_text, (10, 10)) | |
| # Display remaining time | |
| current_time = pygame.time.get_ticks() / 1000 # Current time in seconds | |
| if not measuring_started: | |
| start_time = current_time | |
| elapsed_time = current_time - start_time | |
| remaining_time = max(0, TIME_LIMIT - elapsed_time) | |
| time_text = font.render(f"Time Left: {remaining_time:.2f}s", True, BLACK) | |
| screen.blit(time_text, (10, 40)) | |
| # Check if time is up | |
| if remaining_time <= 0: | |
| font_large = pygame.font.Font(None, 74) | |
| text = font_large.render("Time's Up! You lose!", True, RED) | |
| screen.blit(text, (WIDTH // 2 - text.get_width() // 2, HEIGHT // 2 - text.get_height() // 2)) | |
| pygame.display.flip() | |
| pygame.time.wait(3000) | |
| running = False | |
| # Check if game is completed | |
| if all(completed_vertices): | |
| font_large = pygame.font.Font(None, 74) | |
| text = font_large.render("You win!", True, BLACK) | |
| screen.blit(text, (WIDTH // 2 - text.get_width() // 2, HEIGHT // 2 - text.get_height() // 2)) | |
| pygame.display.flip() | |
| pygame.time.wait(3000) | |
| running = False | |
| # Update display | |
| pygame.display.flip() | |
| clock.tick(FPS) | |
| # Print final penalty | |
| print(f"Final score: {max_distance_penalty}") | |
| # Quit Pygame | |
| pygame.quit() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # this one works just as well in python, but does not like the global variables | |
| # when run in pygbag. TODO port. | |
| import pygame | |
| import math | |
| import random | |
| # Initialize Pygame | |
| pygame.init() | |
| # Screen dimensions | |
| WIDTH, HEIGHT = 800, 800 | |
| screen = pygame.display.set_mode((WIDTH, HEIGHT)) | |
| pygame.display.set_caption("Dalgona Challenge") | |
| # Colors | |
| WHITE = (255, 255, 255) | |
| BLACK = (0, 0, 0) | |
| RED = (255, 0, 0) | |
| GREEN = (0, 255, 0) | |
| BLUE = (0, 0, 255) | |
| GREY = (200, 200, 200) | |
| # Parameters | |
| FPS = 60 | |
| polygon_radius = 300 | |
| polygon_sides = 200 | |
| threshold = 50 | |
| TIME_LIMIT = 15 # Time limit in seconds | |
| # Generate random radius perturbation | |
| def smooth_random_multiplier(angle): | |
| return 1 + 0.2 * math.sin(6 * angle) + 0.1 * math.cos(10 * angle) | |
| # Generate irregular polygon vertices | |
| def generate_polygon_vertices(sides, radius, center): | |
| vertices = [] | |
| angle_step = 2 * math.pi / sides | |
| for i in range(sides): | |
| angle = i * angle_step | |
| perturbed_radius = radius * smooth_random_multiplier(angle) | |
| x = center[0] + perturbed_radius * math.cos(angle) | |
| y = center[1] + perturbed_radius * math.sin(angle) | |
| vertices.append((x, y)) | |
| return vertices | |
| # Restart game function | |
| def restart_game(): | |
| global polygon_vertices, completed_vertices, closest_distances, max_distance_penalty, running, measuring_started, start_time, game_completed | |
| polygon_vertices = generate_polygon_vertices(polygon_sides, polygon_radius, (WIDTH // 2, HEIGHT // 2)) | |
| completed_vertices = [False] * polygon_sides | |
| closest_distances = [float('inf')] * polygon_sides | |
| max_distance_penalty = 0 | |
| measuring_started = False | |
| start_time = pygame.time.get_ticks() / 1000 | |
| game_completed = False | |
| game_loop() | |
| # Game variables | |
| polygon_vertices = generate_polygon_vertices(polygon_sides, polygon_radius, (WIDTH // 2, HEIGHT // 2)) | |
| completed_vertices = [False] * polygon_sides | |
| closest_distances = [float('inf')] * polygon_sides | |
| max_distance_penalty = 0 | |
| running = True | |
| measuring_started = False | |
| clock = pygame.time.Clock() | |
| start_time = pygame.time.get_ticks() / 1000 # Start time in seconds | |
| game_completed = False | |
| # Font for score display | |
| font = pygame.font.Font(None, 36) | |
| # Game loop | |
| def game_loop(): | |
| global running, max_distance_penalty, measuring_started, game_completed | |
| while running: | |
| screen.fill(WHITE) | |
| # Event handling | |
| for event in pygame.event.get(): | |
| if event.type == pygame.QUIT: | |
| running = False | |
| if event.type == pygame.MOUSEBUTTONDOWN: | |
| mouse_x, mouse_y = event.pos | |
| if WIDTH // 2 - 100 <= mouse_x <= WIDTH // 2 + 100 and HEIGHT // 2 + 50 <= mouse_y <= HEIGHT // 2 + 100: | |
| restart_game() | |
| # Get mouse position | |
| mouse_x, mouse_y = pygame.mouse.get_pos() | |
| for i in range(polygon_sides): | |
| # Draw grey boundary | |
| next_i = (i + 1) % polygon_sides | |
| pygame.draw.circle(screen, GREY, polygon_vertices[i], threshold) | |
| for i in range(polygon_sides): | |
| next_i = (i + 1) % polygon_sides | |
| # Draw polygon | |
| pygame.draw.line(screen, BLACK, polygon_vertices[i], polygon_vertices[next_i], 2) | |
| # Draw vertices | |
| for i, vertex in enumerate(polygon_vertices): | |
| # Calculate distance to mouse | |
| distance = math.hypot(mouse_x - vertex[0], mouse_y - vertex[1]) | |
| # Update closest distance for this vertex | |
| closest_distances[i] = min(closest_distances[i], distance) | |
| # Mark vertex as completed if within threshold | |
| if closest_distances[i] <= threshold and not game_completed: | |
| completed_vertices[i] = True | |
| color = GREEN if completed_vertices[i] else RED | |
| pygame.draw.circle(screen, color, (int(vertex[0]), int(vertex[1])), 5) | |
| # Calculate distance to closest vertex and update penalty | |
| distances_to_vertices = [math.hypot(mouse_x - vx, mouse_y - vy) for vx, vy in polygon_vertices] | |
| min_distance = min(distances_to_vertices) | |
| if not measuring_started and min_distance < threshold / 10: | |
| measuring_started = True | |
| if measuring_started and not game_completed: | |
| max_distance_penalty = max(max_distance_penalty, min_distance) | |
| score = int(1000 * max_distance_penalty / threshold) | |
| # Display current score (maximum distance penalty) | |
| score_text = font.render(f"Penalty: {score:05d}", True, BLACK) | |
| screen.blit(score_text, (10, 10)) | |
| # Display remaining time | |
| if not game_completed: | |
| current_time = pygame.time.get_ticks() / 1000 # Current time in seconds | |
| if not measuring_started: | |
| start_time = current_time | |
| elapsed_time = current_time - start_time | |
| remaining_time = max(0, TIME_LIMIT - elapsed_time) | |
| time_text = font.render(f"Time Left: {remaining_time:.2f}s", True, BLACK) | |
| screen.blit(time_text, (10, 40)) | |
| # Check if game is completed | |
| if all(completed_vertices): | |
| game_completed = True | |
| font_large = pygame.font.Font(None, 74) | |
| text = font_large.render("You win!", True, BLACK) | |
| screen.blit(text, (WIDTH // 2 - text.get_width() // 2, HEIGHT // 2 - text.get_height() // 2)) | |
| # Draw restart button | |
| pygame.draw.rect(screen, GREY, (WIDTH // 2 - 100, HEIGHT // 2 + 50, 200, 50)) | |
| restart_text = font.render("Restart", True, BLACK) | |
| screen.blit(restart_text, (WIDTH // 2 - restart_text.get_width() // 2, HEIGHT // 2 + 60)) | |
| # Check if time is up | |
| if remaining_time <= 0: | |
| game_completed = True | |
| font_large = pygame.font.Font(None, 74) | |
| text = font_large.render("Time's Up! You lose!", True, RED) | |
| screen.blit(text, (WIDTH // 2 - text.get_width() // 2, HEIGHT // 2 - text.get_height() // 2)) | |
| # Draw restart button | |
| pygame.draw.rect(screen, GREY, (WIDTH // 2 - 100, HEIGHT // 2 + 50, 200, 50)) | |
| restart_text = font.render("Restart", True, BLACK) | |
| screen.blit(restart_text, (WIDTH // 2 - restart_text.get_width() // 2, HEIGHT // 2 + 60)) | |
| # Update display | |
| pygame.display.flip() | |
| clock.tick(FPS) | |
| # Start game loop | |
| if __name__ == "__main__": | |
| game_loop() | |
| # Quit Pygame | |
| pygame.quit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment