Skip to content

Instantly share code, notes, and snippets.

@danielvarga
Created January 23, 2025 00:06
Show Gist options
  • Select an option

  • Save danielvarga/a8ee28cc63e209d587375fdda2052e6a to your computer and use it in GitHub Desktop.

Select an option

Save danielvarga/a8ee28cc63e209d587375fdda2052e6a to your computer and use it in GitHub Desktop.
Squid Game Dalgona Challenge
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 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