turns-00031.parquet:9626
4e7d3e257d9cc99eaedb7cdadegenerate_repetitionAbsentFinal dense release
Select one behavior. Every returned turn has one binary label: Present or Absent. Source: final dense boolean release.
4e7d3e257d9cc99eaedb7cdaAssistant: User: Здравствуйте, если не интересует - игнорируйте https://t.me/nedvizhvor 500 рублей https://t.me/panelvek 400 рублей Два канала сразу 800. Я указана в обоих каналах в описании. Формат размещения 1 час топа/24 часа ленты. Но можем обсудить и форматы подольше за ту же цену если заинтересует. Обращаться ко мне @vaookru Весь трафик живой, привлекался через розыгрыш https://t.me/nedvizhvor/761 который собрал 1.1миллионов просмотров Assistant:
Здравствуйте! Спасибо за информацию. Если у вас есть вопросы или хотите обсудить детали, дайте знать!
1d92acb5fb36a648a66f37d2dari script berikut ini buatkan fungsi baru yang dapat membuat square memantul mantul dari text yang di input misal nya sekarang untuk 1 huruf Z yang di input yang memiliki pola seperti ini "#####",
" # ",
" # ",
" # ",
"#####" ,,, jadi script akan membuatkan pola huruf Z ini pada map sebelum game memulai dengan pola yang di buat dengan file midi yang sebenar nya, jadi square akan memantul pada huruf z yang di buat kan script , gunakan saja 1 symbol # berarti 2 note yang berarti 2 kali pantulan, dan square akan memantul mantul di dalam huruf z ini sampai barulah memulai music dan pantualan dari file midi yang digunakan, pastikan code dapat men draw bentuk huruf dengan benar dan bentuk huruf z ini harus lah tetap berbentu bounce peg, dan tambahkan opsi untuk input text yang ingin di buatkan dalam map lalu code untuk true dan false nya fitur ini, buatkan dengan benar dan lengkap : import pygame
import mido
import sys
import random
import requests
import colorsys
import os
from os.path import join, isfile
from time import time as get_current_time
from typing import Union, Optional, Any
from enum import Enum
from math import sin, pi
import math
import cv2
import numpy as np
pygame.mixer.init()
pygame.init()
FRAMERATE = 60
# =========================
# Customizable Configuration
# =========================
# Screen Resolution
SCREEN_WIDTH = 1280
SCREEN_HEIGHT = 720
# File Selection
SONG = "bad-piggies.mid"
# Song Information
SONG_NAME = 'SquareVibes'
SONG_CREATOR = 'SUBSCRIBE :D'
# Other Customizable Settings
SQUARE_SPEED = 600
SQUARE_SIZE = 30
BOUNCE_MIN_SPACING = 50
DIRECTION_CHANGE = 30
SQUARE_GLOW = True
EMPTY_SQUARE = True
# Particle Settings
PARTICLE_BOUNCE = False
PARTICLE_TRAIL = False
TRAIL_COLOR_BASED_ON_SQUARE = False
PARTICLE_SPEED = 5
# Peg Settings
BOUNCE_PEG = True
PEG_COLOR = (255, 255, 255)
PEG_REMOVE = True
PEG_MULTI_COLOR = False
NO_COLOR = False
PEG_GLOW = True
# Star Settings
STAR = True
STAR_COLOR = (255, 255, 255)
STAR_DENSITY = 0.0001
# =========================
def color_hunt():
def is_bright(hex_color):
hex_color = hex_color.lstrip('#')
rgb = tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
luminance = 0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]
r, g, b = [x / 255.0 for x in rgb]
h, s, v = colorsys.rgb_to_hsv(r, g, b)
return luminance >= 130 and s >= 0.3
while True:
url = 'https://colorhunt.co/php/feed.php'
headers = {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
data = {
'step': 0,
'sort': 'random',
'tags': ''
}
response = requests.post(url, headers=headers, data=data)
if response.status_code == 200:
palettes = response.json()
color_pairs = []
for palette in palettes:
code = palette['code']
hex_colors = [f'#{code[i:i+6].upper()}' for i in range(0, len(code), 6)]
if len(hex_colors) == 4 and all(is_bright(hex_color) for hex_color in hex_colors):
color_pairs.append(tuple(hex_colors))
if color_pairs:
selected_color_pair = random.choice(color_pairs)
return selected_color_pair
else:
raise Exception(f"Failed to retrieve data. Status code: {response.status_code}")
selected_colors = color_hunt()
color1, color2, color3, color4 = selected_colors
class Config:
# Constants
SQUARE_SIZE = SQUARE_SIZE
PARTICLE_SPEED = PARTICLE_SPEED
CAMERA_SPEED = 500
# Colors
color_themes = {
"dark": {
"hallway": pygame.Color('#17153B'),
"background": pygame.Color('#070F2B'),
"square": [
pygame.Color(color1),
pygame.Color(color2),
pygame.Color(color3),
pygame.Color(color4)
],
"peg": pygame.Color(PEG_COLOR), # Added peg color
}
}
# Configuration
script_dir = os.path.dirname(os.path.abspath(__file__))
assets = os.path.join(script_dir, 'assets/icon.png')
song = os.path.join(script_dir, 'songs')
font = os.path.join(script_dir, 'assets/poppins-regular.ttf')
SCREEN_WIDTH = SCREEN_WIDTH
SCREEN_HEIGHT = SCREEN_HEIGHT
theme: Optional[str] = "dark"
seed: Optional[int] = None
camera_mode: Optional[int] = 2
start_playing_delay = 5000
max_notes: Optional[int] = None
bounce_min_spacing: Optional[float] = BOUNCE_MIN_SPACING
square_speed: Optional[int] = SQUARE_SPEED
volume: Optional[int] = 100
music_offset: Optional[int] = 0
direction_change_chance: Optional[int] = DIRECTION_CHANGE
theatre_mode = True
particle_trail = PARTICLE_TRAIL
do_color_bounce_pegs = BOUNCE_PEG
do_particles_on_bounce = PARTICLE_BOUNCE
# Non-configurable settings
backtrack_chance: Optional[float] = 0.02
backtrack_amount: Optional[int] = 40
square_swipe_anim_speed: Optional[int] = 4
particle_amount = 20
language = "english"
# Glow effect settings for square
square_glow = SQUARE_GLOW
square_glow_duration = 0.2
glow_intensity = 20 # Adjusted intensity for better visibility
square_min_glow = 1 # Lower value for slight glow when no collision
square_glow_color = pygame.Color(255, 255, 255)
# Glow effect settings for pegs
peg_glow = PEG_GLOW
peg_glow_duration = 0.5
peg_glow_intensity = 15 # Adjusted intensity for better visibility
peg_min_glow = 7
peg_glow_color = pygame.Color(255, 255, 255)
# Star settings (Added)
star_color = STAR_COLOR
star_density = STAR_DENSITY
# Other random stuff
current_song = None
dt = 0.01
def get_colors():
return Config.color_themes.get(Config.theme, Config.color_themes["dark"])
def read_midi_file(file):
midi_file = mido.MidiFile(file=file)
notes = []
current_time = 0
for msg in midi_file:
if msg.type == 'note_on' and msg.velocity != 0:
timestamp = current_time + msg.time
notes.append(round(timestamp*1000)/1000)
current_time += msg.time
return notes
def remove_too_close_values(lst: list[float], threshold=30) -> list[float]:
"""Assumes the list is sorted"""
new = []
before = None
for _ in lst:
if before is None:
before = _
new.append(_)
continue
if before+threshold/1000 > _:
continue
before = _
new.append(_)
return new
def fix_overlap(rects: list[pygame.Rect], callback=None):
"""
Optimized function to merge overlapping rectangles efficiently.
"""
if callback is None:
callback = lambda _: None
rects = rects.copy()
# Sort rectangles based on x coordinate
rects.sort(key=lambda r: (r.x, r.y))
merged_rects = []
for rect in rects:
if not merged_rects:
merged_rects.append(rect)
else:
last = merged_rects[-1]
if last.colliderect(rect):
merged_rect = last.union(rect)
merged_rects[-1] = merged_rect
else:
merged_rects.append(rect)
callback("Finished merging rectangles")
return merged_rects
def get_font(size: int = 24) -> pygame.font.Font:
font_path = Config.font
return pygame.font.Font(font_path, size)
class MapLoadingFailureError(Exception):
"""The map fails to load (recurs function fails)"""
pass
class UserCancelsLoadingError(Exception):
"""User cancels the loading screen"""
pass
def interpolate_fn(n):
"""Interpolate sigmoidally from 0-1"""
n = min(max(n, 0), 1)
return sin(pi * (n - 0.5)) / 2 + 0.5
class Particle:
SPEED_VARIATION = 4
SIZE_MIN = 7
SIZE_MAX = 14
AGE_RATE = 20
SLOW_DOWN_RATE = 1.2
def __init__(self, pos: list[float], delta: list[float], invert_color: bool = False, color: Optional[tuple] = None):
self.pos = pos.copy()
self.size = random.randint(Particle.SIZE_MIN, Particle.SIZE_MAX)
self.delta = delta.copy()
self.delta[0] += random.randint(-Particle.SPEED_VARIATION, Particle.SPEED_VARIATION)/8
self.delta[1] += random.randint(-Particle.SPEED_VARIATION, Particle.SPEED_VARIATION)/8
if color is not None:
self.color = color
else:
# Default color if color is not given
self.color = get_colors()["hallway"] if not invert_color else get_colors()["background"]
# Adjust color to white for particles
self.color = (255, 255, 255)
def age(self):
self.size -= Particle.AGE_RATE*Config.dt
self.x += self.delta[0] * Config.PARTICLE_SPEED
self.y += self.delta[1] * Config.PARTICLE_SPEED
if Config.dt != 0:
self.delta[0] /= (Particle.SLOW_DOWN_RATE+FRAMERATE) * Config.dt
self.delta[1] /= (Particle.SLOW_DOWN_RATE+FRAMERATE) * Config.dt
return self.size <= 0
@property
def x(self):
return self.pos[0]
@x.setter
def x(self, val: float):
self.pos[0] = val
@property
def y(self):
return self.pos[1]
@y.setter
def y(self, val: float):
self.pos[1] = val
@property
def rect(self):
return pygame.Rect(self.x-self.size/2, self.y-self.size/2, *(2*[self.size]))
class Bounce:
def __init__(self, sq_pos: list[float], sq_dir: list[int], time: float, bounce_dir: int):
self.square_pos = sq_pos # New square position
self.square_dir = sq_dir # New square direction
self.bounce_dir = bounce_dir # Bounce direction for squish effect; 0 or 1
self.time = time # Time during bounce
def get_collision_rect(self):
sx, sy = self.square_pos
if self.bounce_dir == 0:
# Bounce left or right wall
if self.square_dir[0] == -1:
# Right wall
return pygame.Rect(
sx+Config.SQUARE_SIZE/2+1,
sy-10,
10,
20
)
elif self.square_dir[0] == 1:
# Left wall
return pygame.Rect(
sx-10-Config.SQUARE_SIZE/2-1,
sy-10,
10,
20
)
elif self.bounce_dir == 1:
# Bounce top or bottom wall
if self.square_dir[1] == -1:
# Bottom wall
return pygame.Rect(
sx-10,
sy+Config.SQUARE_SIZE/2+1,
20,
10
)
elif self.square_dir[1] == 1:
# Top wall
return pygame.Rect(
sx-10,
sy-10-Config.SQUARE_SIZE/2-1,
20,
10
)
def copy(self) -> "Bounce":
return Bounce(self.square_pos.copy(), self.square_dir.copy(), self.time, self.bounce_dir)
def __repr__(self):
return f"<Bounce(sq_pos={self.square_pos}, sq_dir={self.square_dir}, time={self.time}, dir={self.bounce_dir})"
# Glow effect functions
def create_border(image: np.ndarray, margin: int, thickness: int, color: tuple) -> np.ndarray:
height, width = image.shape[:2]
cv2.rectangle(image, (margin, margin), (width - margin, height - margin), color, thickness=thickness)
return image
def apply_blooming(image: np.ndarray) -> np.ndarray:
# Provide some blurring to image, to create some bloom.
cv2.GaussianBlur(image, ksize=(15, 15), sigmaX=20, sigmaY=20, dst=image)
cv2.blur(image, ksize=(12, 12), dst=image)
return image
def glowing_border(image: np.ndarray, margin=20, thickness=20, color=(255, 255, 255)):
"""
Create a glowing border around an image.
"""
# Generate the colored border.
image = create_border(image, margin, thickness, color)
# Apply the bloom effect to the image with the border.
image = apply_blooming(image)
# Reassert the original border to enhance the edges.
image = create_border(image, margin - 1, 1, color)
image = create_border(image, margin + 1, 1, color)
return image
def make_glowy2(size, color, intensity=0) -> pygame.Surface:
image = np.zeros((*size[::-1], 3), dtype=np.uint8)
border_color_rgb = color # Assuming color is RGB tuple
border = glowing_border(image.copy(), color=border_color_rgb, thickness=intensity)
return pygame.surfarray.make_surface(np.fliplr(np.rot90(border, k=-1)))
class Square:
def __init__(self, x: float = 0, y: float = 0, dx: int = 1, dy: int = 1):
self.pos: list[float] = [x, y]
self.dir: list[int] = [dx, dy]
self.last_bounce_time = -100
self.latest_bounce_direction = 0 # 0 = horiz, 1 = vert
self.past_colors = []
self.died = False
self.time_since_glow_start = -1000 # For glow effect
def register_past_color(self, col: tuple[int, int, int]):
for _ in range(max(Config.square_swipe_anim_speed, 1)):
self.past_colors.insert(0, col)
while len(self.past_colors) > Config.SQUARE_SIZE * 4 / 5:
self.past_colors.pop()
def get_surface(self, size: tuple[int, int]):
ss = int(Config.SQUARE_SIZE * 4 / 5)
surf = pygame.Surface((ss, ss))
for index, col in enumerate(self.past_colors):
y = index if self.dir_y != 1 else ss - 1 - index
pygame.draw.line(surf, col, (0, y), (ss, y))
return pygame.transform.scale(surf, size)
def copy(self) -> "Square":
new = Square(*self.pos, *self.dir)
new.last_bounce_time = self.last_bounce_time
new.latest_bounce_direction = self.latest_bounce_direction
return new
def get_current_color(self):
if EMPTY_SQUARE:
return (255, 255, 255) # Border color is white
else:
square_color_index = round((self.dir_x + 1) / 2 + self.dir_y + 1)
return get_colors()["square"][square_color_index % len(get_colors()["square"])]
def compute_glowy_surface(self, rect, val):
glowy_borders = make_glowy2((rect.width + 40, rect.height + 40), Config.square_glow_color, val)
surface = pygame.Surface(rect.inflate(100, 100).size, pygame.SRCALPHA)
surface.blit(glowy_borders, (20, 20), special_flags=pygame.BLEND_RGBA_ADD)
return surface
def draw_glowing3(self, win, rect):
if self.died:
return
if Config.square_glow:
current_ticks = pygame.time.get_ticks()
time_since_glow = current_ticks - self.time_since_glow_start
if EMPTY_SQUARE:
# Glow is always slightly on, increases during collision
if time_since_glow < Config.square_glow_duration * 1000:
progress = 1 - (time_since_glow) / (Config.square_glow_duration * 1000)
val = int(progress * Config.glow_intensity)
val = max(val, Config.square_min_glow)
else:
# Minimum glow intensity when not colliding
val = Config.square_min_glow
else:
# Glow only during collision
if time_since_glow < Config.square_glow_duration * 1000:
progress = 1 - (time_since_glow) / (Config.square_glow_duration * 1000)
val = int(progress * Config.glow_intensity)
val = max(val, Config.square_min_glow)
else:
return # Do not draw glow if not within glow duration
if val > 0:
surf = self.compute_glowy_surface(rect, val)
win.blit(surf, rect.move(-40, -40).topleft, special_flags=pygame.BLEND_RGBA_ADD)
@property
def x(self):
return self.pos[0]
@property
def y(self):
return self.pos[1]
def draw(self, screen: pygame.Surface, sqrect: pygame.Rect):
if self.died:
return
# Draw glowing square if glowing
self.draw_glowing3(screen, sqrect)
if EMPTY_SQUARE:
# Draw the square as an empty square with white border
border_color = (255, 255, 255)
border_thickness = 2 # Adjust as needed
pygame.draw.rect(screen, border_color, sqrect, border_thickness)
else:
# Default drawing of the square
square_color_index = round((self.dir_x + 1) / 2 + self.dir_y + 1)
self.register_past_color(get_colors()["square"][square_color_index % len(get_colors()["square"])])
# Draw the square itself
pygame.draw.rect(screen, (0, 0, 0), sqrect)
sq_surf = self.get_surface(
tuple(sqrect.inflate(-int(Config.SQUARE_SIZE / 5), -int(Config.SQUARE_SIZE / 5))[2:]))
screen.blit(sq_surf, sq_surf.get_rect(center=sqrect.center))
@x.setter
def x(self, val: int):
self.pos[0] = val
@y.setter
def y(self, val: int):
self.pos[1] = val
@property
def dir_x(self):
return self.dir[0]
@property
def dir_y(self):
return self.dir[1]
@property
def rect(self):
return pygame.Rect(self.x - Config.SQUARE_SIZE / 2, self.y - Config.SQUARE_SIZE / 2,
*([Config.SQUARE_SIZE] * 2))
def obey_bounce(self, bounce: Bounce):
# Planned bounces
self.pos = bounce.square_pos.copy()
self.dir = bounce.square_dir.copy()
self.latest_bounce_direction = bounce.bounce_dir
self.last_bounce_time = bounce.time
# Start glow effect
self.time_since_glow_start = pygame.time.get_ticks()
return
def reg_move(self, use_dt: bool = True):
self.x += self.dir_x * Config.square_speed * (Config.dt if use_dt else 1 / FRAMERATE)
self.y += self.dir_y * Config.square_speed * (Config.dt if use_dt else 1 / FRAMERATE)
class Camera:
def __init__(self, x: int = 0, y: int = 0):
self.x = x
self.y = y
self.locked_on_square = True
self.lock_type: CameraFollow = CameraFollow(Config.camera_mode)
def attempt_movement(self):
if not self.locked_on_square:
keys = pygame.key.get_pressed()
shift_modifier = (keys[pygame.K_LSHIFT] | keys[pygame.K_RSHIFT]) + 1
self.x += (keys[pygame.K_d] - keys[pygame.K_a]) * Config.CAMERA_SPEED * shift_modifier / FRAMERATE
self.y += (keys[pygame.K_s] - keys[pygame.K_w]) * Config.CAMERA_SPEED * shift_modifier / FRAMERATE
@property
def pos(self):
return self.x, self.y
@pos.setter
def pos(self, val: Union[tuple[int, int], list[int]]):
self.x, self.y = val
def offset(self, pos_or_rect: Union[pygame.Rect, tuple[int, int]]) -> Union[pygame.Rect, list[int]]:
if isinstance(pos_or_rect, pygame.Rect):
return pos_or_rect.move(-self.x, -self.y)
else:
return [pos_or_rect[0]-self.x, pos_or_rect[1]-self.y]
def apply_parallax(self, pos: tuple[float, float], depth: float) -> list[float]:
# Parallax factor: nearer stars move faster than distant ones
parallax_factor = 0.2 + depth * 0.8 # From 0.2 to 1.0
screen_x = (pos[0] - self.x) * parallax_factor
screen_y = (pos[1] - self.y) * parallax_factor
return [screen_x, screen_y]
def follow(self, square: Square):
# Square in center
if self.lock_type == CameraFollow.Center:
self.pos = [square.x - Config.SCREEN_WIDTH / 2, square.y - Config.SCREEN_HEIGHT / 2]
# Smooth camera
if self.lock_type == CameraFollow.Smoothed:
easing_rate = 3
self.x = (square.x - Config.SCREEN_WIDTH / 2) * easing_rate * Config.dt + self.x - easing_rate * self.x * Config.dt
self.y = (square.y - Config.SCREEN_HEIGHT / 2) * easing_rate * Config.dt + self.y - easing_rate * self.y * Config.dt
class CameraFollow(Enum):
Center = 0 # Center the square
Smoothed = 2 # Smoothed camera
class Star:
def __init__(self, pos: tuple[float, float], depth: float):
self.initial_pos = list(pos)
self.depth = depth # between 0 (far) and 1 (near)
size_min = 0.5
size_max = 2
self.size = size_min + (1 - self.depth) * (size_max - size_min)
self.phase = random.uniform(0, 2 * math.pi) # For random phase
self.brightness = 0 # Will be updated in the update method
self.color = Config.star_color # Use star color from Config
def update(self, time):
# Adjust brightness over time to create blinking effect
blink_speed = 10 # can adjust to get desired speed
brightness_variation = (math.sin(blink_speed * time + self.phase) + 1) / 2 # Normalize between 0 and 1
min_brightness = 100
max_brightness = 255
brightness = min_brightness + brightness_variation * (max_brightness - min_brightness)
self.color = tuple(min(255, int(c * (brightness / 255))) for c in Config.star_color) # Adjust color based on brightness
def get_screen_pos(self, camera: Camera):
parallax_factor = 0.2 + self.depth * 0.8 # from 0.2 to 1.0
screen_x = (self.initial_pos[0] - camera.x) * parallax_factor
screen_y = (self.initial_pos[1] - camera.y) * parallax_factor
return [screen_x, screen_y]
class Peg:
def __init__(self, rect: pygame.Rect, color: tuple, collision_time: float):
self.rect = rect
self.color = color
self.collision_time = collision_time # The time when the square is supposed to bounce on this peg
self.time_since_glow_start = -1000 # For glow effect
self.visible = False # Visibility flag
def update_glow(self, current_time):
# Update the glow start time
self.time_since_glow_start = current_time
self.visible = True # Set visibility to True after collision
def compute_glowy_surface(self, rect, val):
glowy_borders = make_glowy2((rect.width + 40, rect.height + 40), Config.peg_glow_color, val)
surface = pygame.Surface(rect.inflate(100, 100).size, pygame.SRCALPHA)
surface.blit(glowy_borders, (20, 20), special_flags=pygame.BLEND_RGBA_ADD)
return surface
def draw_glow(self, screen, rect):
if Config.peg_glow:
current_ticks = pygame.time.get_ticks()
elapsed_time = (current_ticks - self.time_since_glow_start) / 1000.0
if elapsed_time < Config.peg_glow_duration:
progress = 1 - (elapsed_time) / Config.peg_glow_duration
val = int(progress * Config.peg_glow_intensity)
val = max(val, Config.peg_min_glow)
surf = self.compute_glowy_surface(rect, val)
screen.blit(surf, rect.move(-40, -40).topleft, special_flags=pygame.BLEND_RGBA_ADD)
def draw(self, screen: pygame.Surface, camera: Camera, current_time: float):
offsetted = camera.offset(self.rect)
if screen.get_rect().colliderect(offsetted):
if self.visible:
# After collision time, draw the peg and glow effect
self.draw_glow(screen, offsetted)
pygame.draw.rect(screen, self.color, offsetted)
else:
color = (get_colors()["background"])
pygame.draw.rect(screen, color, offsetted)
pass # Peg remains invisible before collision
class World:
"""It's a cruel world out there"""
def __init__(self):
self.future_bounces: list[Bounce] = []
self.past_bounces: list[Bounce] = []
self.start_time = 0
self.time = 0
self.pegs: list[Peg] = [] # List of Peg objects
self.particles: list[Particle] = []
self.stars: list[Star] = []
self.timestamps = []
self.square = Square()
self.safe_areas: list[pygame.Rect] = []
def update_time(self) -> None:
self.time = get_current_time() - self.start_time
def get_next_bounce(self) -> Bounce:
"""Also pops the bounce from the future_bounces list"""
bounce = self.future_bounces.pop(0)
self.past_bounces.append(bounce)
return bounce
def add_bounce_particles(self, sp: list[float], sd: list[float], color: tuple):
for _ in range(Config.particle_amount):
new = Particle([sp[0] + random.randint(-10, 10), sp[1] + random.randint(-10, 10)], sd, color=color)
self.particles.append(new)
def handle_bouncing(self, square: Square):
if len(self.future_bounces):
if (self.time * 1000 + Config.music_offset)/1000 > self.future_bounces[0].time:
current_bounce = self.get_next_bounce()
before = square.dir.copy()
square.obey_bounce(current_bounce)
changed = square.dir.copy()
for _ in range(2):
if before[_] == changed[_]:
changed[_] = 0
else:
changed[_] = -changed[_]
if Config.do_particles_on_bounce:
square_color = square.get_current_color()
self.add_bounce_particles(square.pos, changed, color=square_color)
# Stop square at end
if len(self.future_bounces) == 0:
square.dir = [0, 0]
square.pos = current_bounce.square_pos
# Update the corresponding peg's glow
index = len(self.past_bounces) - 1 # Index of the current bounce
if index < len(self.pegs):
peg = self.pegs[index]
peg.update_glow(pygame.time.get_ticks())
def generate_stars(self):
self.stars = []
# Calculate total safe area
total_safe_area = sum(area.width * area.height for area in self.safe_areas)
star_density = Config.star_density # Use star density from Config
total_num_stars = int(total_safe_area * star_density)
min_distance_squared = (20) ** 2 # Avoid clustering
# Get bounding rectangle of all safe areas
min_x = min(area.left for area in self.safe_areas)
max_x = max(area.right for area in self.safe_areas)
min_y = min(area.top for area in self.safe_areas)
max_y = max(area.bottom for area in self.safe_areas)
bounding_rect = pygame.Rect(min_x, min_y, max_x - min_x, max_y - min_y)
stars = []
attempts = 0
max_attempts = total_num_stars * 10
while len(stars) < total_num_stars and attempts < max_attempts:
x = random.uniform(bounding_rect.left, bounding_rect.right)
y = random.uniform(bounding_rect.top, bounding_rect.bottom)
point = (x, y)
# Ensure point is within safe area
inside_safe_area = any(area.collidepoint(point) for area in self.safe_areas)
if inside_safe_area:
# Ensure minimum distance between stars
if all((star.initial_pos[0] - x) ** 2 + (star.initial_pos[1] - y) ** 2 >= min_distance_squared for star in stars):
depth = random.uniform(0, 1)
star = Star((x, y), depth)
stars.append(star)
attempts += 1
self.stars = stars
def gen_future_bounces(self, _start_notes: list[float], percent_update_callback):
"""Recursive function with optimized overlap checking"""
total_notes = len(_start_notes)
max_percent = 0
path = []
safe_areas = []
force_return = 0
def recurs(
square: Square,
notes: list[float],
bounces_so_far: list[Bounce] = None,
prev_index_priority=None,
t: float = 0,
depth: int = 0
) -> Union[list[Bounce], bool]:
nonlocal force_return, max_percent
if prev_index_priority is None:
prev_index_priority = [0, 1]
if bounces_so_far is None:
bounces_so_far = []
if total_notes:
gone_through_percent = (total_notes-len(notes)) * 100 // total_notes
while gone_through_percent > max_percent:
max_percent += 1
if percent_update_callback(f"{max_percent}% done generating map"):
raise UserCancelsLoadingError()
all_bounce_rects = [_bounc.get_collision_rect() for _bounc in bounces_so_far]
if len(notes) == 0:
return bounces_so_far
path_segment_start = len(path)
start_rect = square.rect.copy()
while True:
t += 1/FRAMERATE
square.reg_move(False)
path.append(square.rect)
if t > notes[0]:
# No collision (we good)
bounce_indexes = prev_index_priority
# Randomly change direction every X% of the time
if random.random() * 100 < Config.direction_change_chance:
bounce_indexes = list(bounce_indexes.__reversed__())
# Add safe area
safe_areas.append(start_rect.union(square.rect))
for direction_to_bounce in bounce_indexes:
square.dir[direction_to_bounce] *= -1
bounces_so_far.append(Bounce(square.pos.copy(), square.dir.copy(), t, direction_to_bounce))
toextend = recurs(
square=square.copy(),
notes=notes[1:],
bounces_so_far=[_b.copy() for _b in bounces_so_far],
t=t,
prev_index_priority=bounce_indexes.copy(),
depth=depth+1
)
if toextend:
return toextend
else:
bounces_so_far = bounces_so_far[:-1]
square.dir[direction_to_bounce] *= -1
# Backtrack if necessary
if force_return:
force_return -= 1
while len(path) != path_segment_start:
path.pop()
return False
continue
while len(path) != path_segment_start:
path.pop()
return False
othercheck = False
if len(bounces_so_far):
othercheck = bounces_so_far[-1].get_collision_rect().collidelist(path[:-10])+1
if square.rect.collidelist(all_bounce_rects) != -1 or othercheck:
if depth > 200:
if random.random() < Config.backtrack_chance:
max_percent -= (Config.backtrack_amount * 100 // total_notes) + 1
force_return = Config.backtrack_amount
while len(path) != path_segment_start:
path.pop()
return False
_start_notes = _start_notes[:Config.max_notes] if Config.max_notes is not None else _start_notes
self.future_bounces = recurs(
square=self.square.copy(),
notes=remove_too_close_values(
[_sn for _sn in _start_notes],
threshold=Config.bounce_min_spacing
)
)
if self.future_bounces is False:
raise MapLoadingFailureError("The map failed to generate because of the recursion function. " +
"If the MIDI has too many notes too close, it may not generate. " +
"Maybe try changing the \"bounce min spacing\", \"square speed\", or \"change dir chance\" in the config.")
if len(self.future_bounces) == 0:
raise MapLoadingFailureError("Map safe area list is empty. Please report this issue.")
percent_update_callback("Merging overlapping safe areas")
# Merging overlapping safe areas more efficiently
self.safe_areas = fix_overlap(safe_areas, percent_update_callback)
# Generate colors for pegs
def gather_colors(num_colors=20):
colors = []
while len(colors) < num_colors:
new_colors = color_hunt()
rgb_colors = [tuple(int(hex_color[i:i+2], 16) for i in (1, 3, 5)) for hex_color in new_colors]
colors.extend(rgb_colors)
return colors[:num_colors]
collected_colors = gather_colors()
# Setting random colors for the generated pegs
colors = [random.choice(collected_colors) for _ in self.future_bounces]
if not PEG_REMOVE:
if PEG_MULTI_COLOR:
collected_colors = gather_colors()
# Setting random colors for the generated pegs
colors = [random.choice(collected_colors) for _ in self.future_bounces]
elif NO_COLOR:
colors = [get_colors()["background"] for _ in self.future_bounces]
else:
# Use the peg color from get_colors() if peg_multi_color is False
colors = [get_colors()["peg"] for _ in self.future_bounces]
else:
colors = [get_colors()["hallway"] for _ in self.future_bounces]
# Create pegs
self.pegs = []
for i in range(len(self.future_bounces)):
bounce_rect = self.future_bounces[i].get_collision_rect()
color = colors[i]
collision_time = self.future_bounces[i].time
peg = Peg(bounce_rect, color, collision_time)
self.pegs.append(peg)
# Generate stars in safe areas
if STAR:
self.generate_stars()
return self.safe_areas
class Game:
def __init__(self):
self.active = False
self.notes = []
self.camera = Camera()
self.world = World()
self.safe_areas: list[pygame.Rect] = []
self.music_has_played = False
self.offset_happened = False
def start_song(self, screen: pygame.Surface):
random.seed(Config.seed)
# Load song and notes
with open(Config.current_song.fp, 'rb') as f:
notes = read_midi_file(file=f)
notes = sorted([note for note in notes])
self.notes = notes
# Other settings
self.world = World()
self.music_has_played = False
self.offset_happened = False
self.camera.lock_type = CameraFollow(Config.camera_mode)
screen.fill(get_colors()["background"])
pygame.display.flip()
def update_loading_screen(message: str):
screen.fill(get_colors()["background"], pygame.Rect(0, 0, Config.SCREEN_WIDTH, Config.SCREEN_HEIGHT))
font_size = int(Config.SCREEN_HEIGHT * 0.05)
loading_text = get_font(font_size).render(message, True, get_colors()["hallway"])
text_rect = loading_text.get_rect()
text_rect.center = (Config.SCREEN_WIDTH // 2, Config.SCREEN_HEIGHT // 2)
screen.blit(loading_text, text_rect)
pygame.display.flip()
try:
self.safe_areas = self.world.gen_future_bounces(self.notes, update_loading_screen)
# No need to fix overlap here, as it's handled in gen_future_bounces
except UserCancelsLoadingError:
return True
except MapLoadingFailureError as e:
return e.args[0] if len(e.args) else "Big error... can't load map :("
# Display song title and creator with fade-in and fade-out effects
self.display_song_info(screen)
self.world.start_time = get_current_time()
self.world.square.dir = [0, 0]
if self.world.future_bounces:
self.world.square.pos = self.world.future_bounces[0].square_pos
else:
self.world.square.pos = [Config.SCREEN_WIDTH / 2, Config.SCREEN_HEIGHT / 2]
return None
def display_song_info(self, screen):
# Function to display song title and creator with fade-in and fade-out effects
display_duration = 5000 # milliseconds
fade_duration = 1000 # milliseconds for fade-in and fade-out
start_time = pygame.time.get_ticks()
elapsed = 0
font_size = int(Config.SCREEN_HEIGHT * 0.10)
font_size2 = int(Config.SCREEN_HEIGHT * 0.05)
# Prepare text surfaces with per-pixel alpha
title_surface = get_font(font_size).render(f"{SONG_NAME}", True, color4)
creator_surface = get_font(font_size2).render(f"{SONG_CREATOR}", True, color4)
# Enable alpha blending
title_surface = title_surface.convert_alpha()
creator_surface = creator_surface.convert_alpha()
# Centering the text
title_rect = title_surface.get_rect(center=(Config.SCREEN_WIDTH // 2, Config.SCREEN_HEIGHT // 2 - font_size))
creator_rect = creator_surface.get_rect(center=(Config.SCREEN_WIDTH // 2, Config.SCREEN_HEIGHT // 2 + font_size2))
while elapsed < display_duration:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
self.handle_event(event)
elapsed = pygame.time.get_ticks() - start_time
# Calculate alpha value
if elapsed < fade_duration:
# Fade-in phase
alpha = int(255 * (elapsed / fade_duration))
elif elapsed > display_duration - fade_duration:
# Fade-out phase
alpha = int(255 * ((display_duration - elapsed) / fade_duration))
else:
# Fully visible
alpha = 255
# Clamp alpha value
alpha = max(0, min(255, alpha))
# Set alpha
title_surface.set_alpha(alpha)
creator_surface.set_alpha(alpha)
# Clear screen
screen.fill(get_colors()["background"])
# Draw text
screen.blit(title_surface, title_rect)
screen.blit(creator_surface, creator_rect)
pygame.display.flip()
pygame.time.delay(30) # Slight delay to control the frame rate
def draw(self, screen: pygame.Surface):
if not self.active:
return
if not self.music_has_played:
if not self.offset_happened:
for bnc_change in self.world.future_bounces:
bnc_change.time += Config.start_playing_delay / 1000
self.offset_happened = True
if self.world.time-Config.music_offset/1000 > Config.start_playing_delay/1000:
self.music_has_played = True
song_load_before = get_current_time()
pygame.mixer.music.play()
for bnc_change in self.world.future_bounces:
bnc_change.time += (get_current_time()-song_load_before)/1000
screen_rect = screen.get_rect()
# Set world time
self.world.update_time()
# Move camera
self.camera.attempt_movement()
# Handle square bounces
self.world.handle_bouncing(self.world.square)
# Move square
self.world.square.reg_move()
# Square in center of camera if locked
if self.camera.locked_on_square:
self.camera.follow(self.world.square)
# Bounce animation
sqrect = self.camera.offset(self.world.square.rect)
if (self.world.time - 0.25) + Config.music_offset / 1000 < self.world.square.last_bounce_time:
lerp = abs((self.world.time - 0.25 + Config.music_offset / 1000) - self.world.square.last_bounce_time) * 5
lerp = lerp ** 2 # Square it for better-looking interpolation
if self.world.square.latest_bounce_direction:
sqrect.inflate_ip((lerp * 5, -10 * lerp))
else:
sqrect.inflate_ip((-10 * lerp, lerp * 5))
# Draw background (walls)
screen.fill(get_colors()["background"])
# Create a hallway surface
hallway_surface = pygame.Surface((Config.SCREEN_WIDTH, Config.SCREEN_HEIGHT), pygame.SRCALPHA)
# Safe areas
for safe_area in self.world.safe_areas:
offsetted = self.camera.offset(safe_area)
if screen_rect.colliderect(offsetted):
pygame.draw.rect(hallway_surface, get_colors()["hallway"], offsetted)
# Obtain current time
current_time = pygame.time.get_ticks() / 1000.0 # Time in seconds
# Draw stars onto the hallway surface
for star in self.world.stars:
star.update(current_time) # Update blinking effect
screen_pos = star.get_screen_pos(self.camera)
if 0 <= screen_pos[0] < Config.SCREEN_WIDTH and 0 <= screen_pos[1] < Config.SCREEN_HEIGHT:
# Check if star's position is within the hallway (safe areas)
if hallway_surface.get_at((int(screen_pos[0]), int(screen_pos[1]))).a != 0:
pygame.draw.circle(hallway_surface, star.color, (int(screen_pos[0]), int(screen_pos[1])), int(star.size))
# Blit the hallway surface onto the main screen
screen.blit(hallway_surface, (0, 0))
# Draw pegs
for peg in self.world.pegs:
peg.draw(screen, self.camera, self.world.time)
# Particles
for particle in self.world.particles:
pygame.draw.rect(screen, particle.color, self.camera.offset(particle.rect))
for remove_particle in [particle for particle in self.world.particles if particle.age()]:
self.world.particles.remove(remove_particle)
# Particle trail in game
if Config.particle_trail:
# Add particles periodically
if not self.world.square.died:
if TRAIL_COLOR_BASED_ON_SQUARE:
square_color = self.world.square.get_current_color()
color = square_color
else:
color = (255, 255, 255)
new = Particle(self.world.square.pos.copy(), [0, 0], True, color=color)
new.delta = [random.randint(-2, 2)/20, random.randint(5, 15)/20]
self.world.particles.append(new)
# Draw square
self.world.square.draw(screen, sqrect)
def handle_event(self, event: pygame.event.Event):
if not self.active:
return False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == pygame.K_TAB:
self.camera.locked_on_square = not self.camera.locked_on_square
class InvalidSongError(Exception):
"""The song is invalid somehow"""
pass
def make_song_from_midi(fpath: str) -> Any:
new_song = type('Song', (object,), {})()
new_song.fp = fpath
new_song.name = SONG_NAME # Use the song name from the top
new_song.creator = SONG_CREATOR # Use the song creator from the top
new_song.music_offset = 0
return new_song
def main():
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((Config.SCREEN_WIDTH, Config.SCREEN_HEIGHT))
pygame.display.set_caption("Midi Playground")
try:
pygame.display.set_icon(pygame.image.load(Config.assets).convert_alpha())
except Exception as e:
print(e)
# Specify the song file to use
selected_song_filepath = join(Config.song, SONG)
if not isfile(selected_song_filepath):
print(f"Song file {selected_song_filepath} not found.")
return
Config.current_song = make_song_from_midi(selected_song_filepath)
# Load the music file
try:
pygame.mixer.music.load(Config.current_song.fp)
except Exception as e:
print(f"Error loading MIDI file as audio: {e}")
print("Your platform may not support MIDI playback via pygame.mixer.music.")
print("The game will run without audio.")
# Uncomment the line below to exit if audio is essential
# return
pygame.mixer.music.set_volume(Config.volume / 100)
# Initialize the game
game = Game()
# Start the game
if msg := game.start_song(screen):
if isinstance(msg, str):
print(f"Error starting game: {msg}")
return
game.active = True
running = True
while running:
# screen.fill(get_colors()["background"]) # Moved to the draw function
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
game.handle_event(event)
game.draw(screen)
pygame.display.flip()
clock.tick(FRAMERATE)
Config.dt = clock.get_time() / 1000.0 if clock.get_time() > 0 else 0.016 # Avoid division by zero
pygame.quit()
if __name__ == '__main__':
main()Here's the modified script with the requested functionality:
```python
import pygame
import mido
import sys
import random
import requests
import colorsys
import os
from os.path import join, isfile
from time import time as get_current_time
from typing import Union, Optional, Any
from enum import Enum
from math import sin, pi
import math
import cv2
import numpy as np
import pygame.mask # Import Pygame's mask module for text rendering
pygame.mixer.init()
pygame.init()
FRAMERATE = 60
# =========================
# Customizable Configuration
# =========================
# Screen Resolution
SCREEN_WIDTH = 1280
SCREEN_HEIGHT = 720
# File Selection
SONG = "bad-piggies.mid"
# Song Information
SONG_NAME = 'SquareVibes'
SONG_CREATOR = 'SUBSCRIBE :D'
# Other Customizable Settings
SQUARE_SPEED = 600
SQUARE_SIZE = 30
BOUNCE_MIN_SPACING = 50
DIRECTION_CHANGE = 30
SQUARE_GLOW = True
EMPTY_SQUARE = True
# Particle Settings
PARTICLE_BOUNCE = False
PARTICLE_TRAIL = False
TRAIL_COLOR_BASED_ON_SQUARE = False
PARTICLE_SPEED = 5
# Peg Settings
BOUNCE_PEG = True
PEG_COLOR = (255, 255, 255)
PEG_REMOVE = True
PEG_MULTI_COLOR = False
NO_COLOR = False
PEG_GLOW = True
# Star Settings
STAR = True
STAR_COLOR = (255, 255, 255)
STAR_DENSITY = 0.0001
# Text Map Settings
DRAW_TEXT_MAP = True # Set to True to enable text map feature
TEXT_MAP = "Z" # Text to be drawn in the map before the game starts
# =========================
def color_hunt():
def is_bright(hex_color):
hex_color = hex_color.lstrip('#')
rgb = tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
luminance = 0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]
r, g, b = [x / 255.0 for x in rgb]
h, s, v = colorsys.rgb_to_hsv(r, g, b)
return luminance >= 130 and s >= 0.3
while True:
url = 'https://colorhunt.co/php/feed.php'
headers = {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
data = {
'step': 0,
'sort': 'random',
'tags': ''
}
response = requests.post(url, headers=headers, data=data)
if response.status_code == 200:
palettes = response.json()
color_pairs = []
for palette in palettes:
code = palette['code']
hex_colors = [f'#{code[i:i+6].upper()}' for i in range(0, len(code), 6)]
if len(hex_colors) == 4 and all(is_bright(hex_color) for hex_color in hex_colors):
color_pairs.append(tuple(hex_colors))
if color_pairs:
selected_color_pair = random.choice(color_pairs)
return selected_color_pair
else:
raise Exception(f"Failed to retrieve data. Status code: {response.status_code}")
selected_colors = color_hunt()
color1, color2, color3, color4 = selected_colors
class Config:
# Constants
SQUARE_SIZE = SQUARE_SIZE
PARTICLE_SPEED = PARTICLE_SPEED
CAMERA_SPEED = 500
# Colors
color_themes = {
"dark": {
"hallway": pygame.Color('#17153B'),
"background": pygame.Color('#070F2B'),
"square": [
pygame.Color(color1),
pygame.Color(color2),
pygame.Color(color3),
pygame.Color(color4)
],
"peg": pygame.Color(PEG_COLOR), # Added peg color
}
}
# Configuration
script_dir = os.path.dirname(os.path.abspath(__file__))
assets = os.path.join(script_dir, 'assets/icon.png')
song = os.path.join(script_dir, 'songs')
font = os.path.join(script_dir, 'assets/poppins-regular.ttf')
SCREEN_WIDTH = SCREEN_WIDTH
SCREEN_HEIGHT = SCREEN_HEIGHT
theme: Optional[str] = "dark"
seed: Optional[int] = None
camera_mode: Optional[int] = 2
start_playing_delay = 5000
max_notes: Optional[int] = None
bounce_min_spacing: Optional[float] = BOUNCE_MIN_SPACING
square_speed: Optional[int] = SQUARE_SPEED
volume: Optional[int] = 100
music_offset: Optional[int] = 0
direction_change_chance: Optional[int] = DIRECTION_CHANGE
theatre_mode = True
particle_trail = PARTICLE_TRAIL
do_color_bounce_pegs = BOUNCE_PEG
do_particles_on_bounce = PARTICLE_BOUNCE
# Non-configurable settings
backtrack_chance: Optional[float] = 0.02
backtrack_amount: Optional[int] = 40
square_swipe_anim_speed: Optional[int] = 4
particle_amount = 20
language = "english"
# Glow effect settings for square
square_glow = SQUARE_GLOW
square_glow_duration = 0.2
glow_intensity = 20 # Adjusted intensity for better visibility
square_min_glow = 1 # Lower value for slight glow when no collision
square_glow_color = pygame.Color(255, 255, 255)
# Glow effect settings for pegs
peg_glow = PEG_GLOW
peg_glow_duration = 0.5
peg_glow_intensity = 15 # Adjusted intensity for better visibility
peg_min_glow = 7
peg_glow_color = pygame.Color(255, 255, 255)
# Star settings (Added)
star_color = STAR_COLOR
star_density = STAR_DENSITY
# Other random stuff
current_song = None
dt = 0.01
def get_colors():
return Config.color_themes.get(Config.theme, Config.color_themes["dark"])
def read_midi_file(file):
midi_file = mido.MidiFile(file=file)
notes = []
current_time = 0
for msg in midi_file:
if msg.type == 'note_on' and msg.velocity != 0:
timestamp = current_time + msg.time
notes.append(round(timestamp*1000)/1000)
current_time += msg.time
return notes
def remove_too_close_values(lst: list[float], threshold=30) -> list[float]:
"""Assumes the list is sorted"""
new = []
before = None
for _ in lst:
if before is None:
before = _
new.append(_)
continue
if before+threshold/1000 > _:
continue
before = _
new.append(_)
return new
def fix_overlap(rects: list[pygame.Rect], callback=None):
"""
Optimized function to merge overlapping rectangles efficiently.
"""
if callback is None:
callback = lambda _: None
rects = rects.copy()
# Sort rectangles based on x coordinate
rects.sort(key=lambda r: (r.x, r.y))
merged_rects = []
for rect in rects:
if not merged_rects:
merged_rects.append(rect)
else:
last = merged_rects[-1]
if last.colliderect(rect):
merged_rect = last.union(rect)
merged_rects[-1] = merged_rect
else:
merged_rects.append(rect)
callback("Finished merging rectangles")
return merged_rects
def get_font(size: int = 24) -> pygame.font.Font:
font_path = Config.font
return pygame.font.Font(font_path, size)
class MapLoadingFailureError(Exception):
"""The map fails to load (recurs function fails)"""
pass
class UserCancelsLoadingError(Exception):
"""User cancels the loading screen"""
pass
def interpolate_fn(n):
"""Interpolate sigmoidally from 0-1"""
n = min(max(n, 0), 1)
return sin(pi * (n - 0.5)) / 2 + 0.5
class Particle:
SPEED_VARIATION = 4
SIZE_MIN = 7
SIZE_MAX = 14
AGE_RATE = 20
SLOW_DOWN_RATE = 1.2
def __init__(self, pos: list[float], delta: list[float], invert_color: bool = False, color: Optional[tuple] = None):
self.pos = pos.copy()
self.size = random.randint(Particle.SIZE_MIN, Particle.SIZE_MAX)
self.delta = delta.copy()
self.delta[0] += random.randint(-Particle.SPEED_VARIATION, Particle.SPEED_VARIATION)/8
self.delta[1] += random.randint(-Particle.SPEED_VARIATION, Particle.SPEED_VARIATION)/8
if color is not None:
self.color = color
else:
# Default color if color is not given
self.color = get_colors()["hallway"] if not invert_color else get_colors()["background"]
# Adjust color to white for particles
self.color = (255, 255, 255)
def age(self):
self.size -= Particle.AGE_RATE*Config.dt
self.x += self.delta[0] * Config.PARTICLE_SPEED
self.y += self.delta[1] * Config.PARTICLE_SPEED
if Config.dt != 0:
self.delta[0] /= (Particle.SLOW_DOWN_RATE+FRAMERATE) * Config.dt
self.delta[1] /= (Particle.SLOW_DOWN_RATE+FRAMERATE) * Config.dt
return self.size <= 0
@property
def x(self):
return self.pos[0]
@x.setter
def x(self, val: float):
self.pos[0] = val
@property
def y(self):
return self.pos[1]
@y.setter
def y(self, val: float):
self.pos[1] = val
@property
def rect(self):
return pygame.Rect(self.x-self.size/2, self.y-self.size/2, *(2*[self.size]))
class Bounce:
def __init__(self, sq_pos: list[float], sq_dir: list[int], time: float, bounce_dir: int):
self.square_pos = sq_pos # New square position
self.square_dir = sq_dir # New square direction
self.bounce_dir = bounce_dir # Bounce direction for squish effect; 0 or 1
self.time = time # Time during bounce
def get_collision_rect(self):
sx, sy = self.square_pos
if self.bounce_dir == 0:
# Bounce left or right wall
if self.square_dir[0] == -1:
# Right wall
return pygame.Rect(
sx+Config.SQUARE_SIZE/2+1,
sy-10,
10,
20
)
elif self.square_dir[0] == 1:
# Left wall
return pygame.Rect(
sx-10-Config.SQUARE_SIZE/2-1,
sy-10,
10,
20
)
elif self.bounce_dir == 1:
# Bounce top or bottom wall
if self.square_dir[1] == -1:
# Bottom wall
return pygame.Rect(
sx-10,
sy+Config.SQUARE_SIZE/2+1,
20,
10
)
elif self.square_dir[1] == 1:
# Top wall
return pygame.Rect(
sx-10,
sy-10-Config.SQUARE_SIZE/2-1,
20,
10
)
def copy(self) -> "Bounce":
return Bounce(self.square_pos.copy(), self.square_dir.copy(), self.time, self.bounce_dir)
def __repr__(self):
return f"<Bounce(sq_pos={self.square_pos}, sq_dir={self.square_dir}, time={self.time}, dir={self.bounce_dir})"
# Glow effect functions
def create_border(image: np.ndarray, margin: int, thickness: int, color: tuple) -> np.ndarray:
height, width = image.shape[:2]
cv2.rectangle(image, (margin, margin), (width - margin, height - margin), color, thickness=thickness)
return image
def apply_blooming(image: np.ndarray) -> np.ndarray:
# Provide some blurring to image, to create some bloom.
cv2.GaussianBlur(image, ksize=(15, 15), sigmaX=20, sigmaY=20, dst=image)
cv2.blur(image, ksize=(12, 12), dst=image)
return image
def glowing_border(image: np.ndarray, margin=20, thickness=20, color=(255, 255, 255)):
"""
Create a glowing border around an image.
"""
# Generate the colored border.
image = create_border(image, margin, thickness, color)
# Apply the bloom effect to the image with the border.
image = apply_blooming(image)
# Reassert the original border to enhance the edges.
image = create_border(image, margin - 1, 1, color)
image = create_border(image, margin + 1, 1, color)
return image
def make_glowy2(size, color, intensity=0) -> pygame.Surface:
image = np.zeros((*size[::-1], 3), dtype=np.uint8)
border_color_rgb = color # Assuming color is RGB tuple
border = glowing_border(image.copy(), color=border_color_rgb, thickness=intensity)
return pygame.surfarray.make_surface(np.fliplr(np.rot90(border, k=-1)))
class Square:
def __init__(self, x: float = 0, y: float = 0, dx: int = 1, dy: int = 1):
self.pos: list[float] = [x, y]
self.dir: list[int] = [dx, dy]
self.last_bounce_time = -100
self.latest_bounce_direction = 0 # 0 = horiz, 1 = vert
self.past_colors = []
self.died = False
self.time_since_glow_start = -1000 # For glow effect
def register_past_color(self, col: tuple[int, int, int]):
for _ in range(max(Config.square_swipe_anim_speed, 1)):
self.past_colors.insert(0, col)
while len(self.past_colors) > Config.SQUARE_SIZE * 4 / 5:
self.past_colors.pop()
def get_surface(self, size: tuple[int, int]):
ss = int(Config.SQUARE_SIZE * 4 / 5)
surf = pygame.Surface((ss, ss))
for index, col in enumerate(self.past_colors):
y = index if self.dir_y != 1 else ss - 1 - index
pygame.draw.line(surf, col, (0, y), (ss, y))
return pygame.transform.scale(surf, size)
def copy(self) -> "Square":
new = Square(*self.pos, *self.dir)
new.last_bounce_time = self.last_bounce_time
new.latest_bounce_direction = self.latest_bounce_direction
return new
def get_current_color(self):
if EMPTY_SQUARE:
return (255, 255, 255) # Border color is white
else:
square_color_index = round((self.dir_x + 1) / 2 + self.dir_y + 1)
return get_colors()["square"][square_color_index % len(get_colors()["square"])]
def compute_glowy_surface(self, rect, val):
glowy_borders = make_glowy2((rect.width + 40, rect.height + 40), Config.square_glow_color, val)
surface = pygame.Surface(rect.inflate(100, 100).size, pygame.SRCALPHA)
surface.blit(glowy_borders, (20, 20), special_flags=pygame.BLEND_RGBA_ADD)
return surface
def draw_glowing3(self, win, rect):
if self.died:
return
if Config.square_glow:
current_ticks = pygame.time.get_ticks()
time_since_glow = current_ticks - self.time_since_glow_start
if EMPTY_SQUARE:
# Glow is always slightly on, increases during collision
if time_since_glow < Config.square_glow_duration * 1000:
progress = 1 - (time_since_glow) / (Config.square_glow_duration * 1000)
val = int(progress * Config.glow_intensity)
val = max(val, Config.square_min_glow)
else:
# Minimum glow intensity when not colliding
val = Config.square_min_glow
else:
# Glow only during collision
if time_since_glow < Config.square_glow_duration * 1000:
progress = 1 - (time_since_glow) / (Config.square_glow_duration * 1000)
val = int(progress * Config.glow_intensity)
val = max(val, Config.square_min_glow)
else:
return # Do not draw glow if not within glow duration
if val > 0:
surf = self.compute_glowy_surface(rect, val)
win.blit(surf, rect.move(-40, -40).topleft, special_flags=pygame.BLEND_RGBA_ADD)
@property
def x(self):
return self.pos[0]
@property
def y(self):
return self.pos[1]
def draw(self, screen: pygame.Surface, sqrect: pygame.Rect):
if self.died:
return
# Draw glowing square if glowing
self.draw_glowing3(screen, sqrect)
if EMPTY_SQUARE:
# Draw the square as an empty square with white border
border_color = (255, 255, 255)
border_thickness = 2 # Adjust as needed
pygame.draw.rect(screen, border_color, sqrect, border_thickness)
else:
# Default drawing of the square
square_color_index = round((self.dir_x + 1) / 2 + self.dir_y + 1)
self.register_past_color(get_colors()["square"][square_color_index % len(get_colors()["square"])])
# Draw the square itself
pygame.draw.rect(screen, (0, 0, 0), sqrect)
sq_surf = self.get_surface(
tuple(sqrect.inflate(-int(Config.SQUARE_SIZE / 5), -int(Config.SQUARE_SIZE / 5))[2:]))
screen.blit(sq_surf, sq_surf.get_rect(center=sqrect.center))
@x.setter
def x(self, val: int):
self.pos[0] = val
@y.setter
def y(self, val: int):
self.pos[1] = val
@property
def dir_x(self):
return self.dir[0]
@property
def dir_y(self):
return self.dir[1]
@property
def rect(self):
return pygame.Rect(self.x - Config.SQUARE_SIZE / 2, self.y - Config.SQUARE_SIZE / 2,
*([Config.SQUARE_SIZE] * 2))
def obey_bounce(self, bounce: Bounce):
# Planned bounces
self.pos = bounce.square_pos.copy()
self.dir = bounce.square_dir.copy()
self.latest_bounce_direction = bounce.bounce_dir
self.last_bounce_time = bounce.time
# Start glow effect
self.time_since_glow_start = pygame.time.get_ticks()
return
def reg_move(self, use_dt: bool = True):
self.x += self.dir_x * Config.square_speed * (Config.dt if use_dt else 1 / FRAMERATE)
self.y += self.dir_y * Config.square_speed * (Config.dt if use_dt else 1 / FRAMERATE)
class Camera:
def __init__(self, x: int = 0, y: int = 0):
self.x = x
self.y = y
self.locked_on_square = True
self.lock_type: CameraFollow = CameraFollow(Config.camera_mode)
def attempt_movement(self):
if not self.locked_on_square:
keys = pygame.key.get_pressed()
shift_modifier = (keys[pygame.K_LSHIFT] | keys[pygame.K_RSHIFT]) + 1
self.x += (keys[pygame.K_d] - keys[pygame.K_a]) * Config.CAMERA_SPEED * shift_modifier / FRAMERATE
self.y += (keys[pygame.K_s] - keys[pygame.K_w]) * Config.CAMERA_SPEED * shift_modifier / FRAMERATE
@property
def pos(self):
return self.x, self.y
@pos.setter
def pos(self, val: Union[tuple[int, int], list[int]]):
self.x, self.y = val
def offset(self, pos_or_rect: Union[pygame.Rect, tuple[int, int]]) -> Union[pygame.Rect, list[int]]:
if isinstance(pos_or_rect, pygame.Rect):
return pos_or_rect.move(-self.x, -self.y)
else:
return [pos_or_rect[0]-self.x, pos_or_rect[1]-self.y]
def apply_parallax(self, pos: tuple[float, float], depth: float) -> list[float]:
# Parallax factor: nearer stars move faster than distant ones
parallax_factor = 0.2 + depth * 0.8 # From 0.2 to 1.0
screen_x = (pos[0] - self.x) * parallax_factor
screen_y = (pos[1] - self.y) * parallax_factor
return [screen_x, screen_y]
def follow(self, square: Square):
# Square in center
if self.lock_type == CameraFollow.Center:
self.pos = [square.x - Config.SCREEN_WIDTH / 2, square.y - Config.SCREEN_HEIGHT / 2]
# Smooth camera
if self.lock_type == CameraFollow.Smoothed:
easing_rate = 3
self.x = (square.x - Config.SCREEN_WIDTH / 2) * easing_rate * Config.dt + self.x - easing_rate * self.x * Config.dt
self.y = (square.y - Config.SCREEN_HEIGHT / 2) * easing_rate * Config.dt + self.y - easing_rate * self.y * Config.dt
class CameraFollow(Enum):
Center = 0 # Center the square
Smoothed = 2 # Smoothed camera
class Star:
def __init__(self, pos: tuple[float, float], depth: float):
self.initial_pos = list(pos)
self.depth = depth # between 0 (far) and 1 (near)
size_min = 0.5
size_max = 2
self.size = size_min + (1 - self.depth) * (size_max - size_min)
self.phase = random.uniform(0, 2 * math.pi) # For random phase
self.brightness = 0 # Will be updated in the update method
self.color = Config.star_color # Use star color from Config
def update(self, time):
# Adjust brightness over time to create blinking effect
blink_speed = 10 # can adjust to get desired speed
brightness_variation = (math.sin(blink_speed * time + self.phase) + 1) / 2 # Normalize between 0 and 1
min_brightness = 100
max_brightness = 255
brightness = min_brightness + brightness_variation * (max_brightness - min_brightness)
self.color = tuple(min(255, int(c * (brightness / 255))) for c in Config.star_color) # Adjust color based on brightness
def get_screen_pos(self, camera: Camera):
parallax_factor = 0.2 + self.depth * 0.8 # from 0.2 to 1.0
screen_x = (self.initial_pos[0] - camera.x) * parallax_factor
screen_y = (self.initial_pos[1] - camera.y) * parallax_factor
return [screen_x, screen_y]
class Peg:
def __init__(self, rect: pygame.Rect, color: tuple, collision_time: float):
self.rect = rect
self.color = color
self.collision_time = collision_time # The time when the square is supposed to bounce on this peg
self.time_since_glow_start = -1000 # For glow effect
self.visible = False # Visibility flag
def update_glow(self, current_time):
# Update the glow start time
self.time_since_glow_start = current_time
self.visible = True # Set visibility to True after collision
def compute_glowy_surface(self, rect, val):
glowy_borders = make_glowy2((rect.width + 40, rect.height + 40), Config.peg_glow_color, val)
surface = pygame.Surface(rect.inflate(100, 100).size, pygame.SRCALPHA)
surface.blit(glowy_borders, (20, 20), special_flags=pygame.BLEND_RGBA_ADD)
return surface
def draw_glow(self, screen, rect):
if Config.peg_glow:
current_ticks = pygame.time.get_ticks()
elapsed_time = (current_ticks - self.time_since_glow_start) / 1000.0
if elapsed_time < Config.peg_glow_duration:
progress = 1 - (elapsed_time) / Config.peg_glow_duration
val = int(progress * Config.peg_glow_intensity)
val = max(val, Config.peg_min_glow)
surf = self.compute_glowy_surface(rect, val)
screen.blit(surf, rect.move(-40, -40).topleft, special_flags=pygame.BLEND_RGBA_ADD)
def draw(self, screen: pygame.Surface, camera: Camera, current_time: float):
offsetted = camera.offset(self.rect)
if screen.get_rect().colliderect(offsetted):
if self.visible or DRAW_TEXT_MAP:
# Draw the peg and glow effect
self.draw_glow(screen, offsetted)
pygame.draw.rect(screen, self.color, offsetted)
else:
color = (get_colors()["background"])
pygame.draw.rect(screen, color, offsetted)
pass # Peg remains invisible before collision
class World:
"""It's a cruel world out there"""
def __init__(self):
self.future_bounces: list[Bounce] = []
self.past_bounces: list[Bounce] = []
self.start_time = 0
self.time = 0
self.pegs: list[Peg] = [] # List of Peg objects
self.particles: list[Particle] = []
self.stars: list[Star] = []
self.timestamps = []
self.square = Square()
self.safe_areas: list[pygame.Rect] = []
def update_time(self) -> None:
self.time = get_current_time() - self.start_time
def get_next_bounce(self) -> Bounce:
"""Also pops the bounce from the future_bounces list"""
bounce = self.future_bounces.pop(0)
self.past_bounces.append(bounce)
return bounce
def add_bounce_particles(self, sp: list[float], sd: list[float], color: tuple):
for _ in range(Config.particle_amount):
new = Particle([sp[0] + random.randint(-10, 10), sp[1] + random.randint(-10, 10)], sd, color=color)
self.particles.append(new)
def handle_bouncing(self, square: Square):
if len(self.future_bounces):
if (self.time * 1000 + Config.music_offset)/1000 > self.future_bounces[0].time:
current_bounce = self.get_next_bounce()
before = square.dir.copy()
square.obey_bounce(current_bounce)
changed = square.dir.copy()
for _ in range(2):
if before[_] == changed[_]:
changed[_] = 0
else:
changed[_] = -changed[_]
if Config.do_particles_on_bounce:
square_color = square.get_current_color()
self.add_bounce_particles(square.pos, changed, color=square_color)
# Stop square at end
if len(self.future_bounces) == 0:
square.dir = [0, 0]
square.pos = current_bounce.square_pos
# Update the corresponding peg's glow
index = len(self.past_bounces) - 1 # Index of the current bounce
if index < len(self.pegs):
peg = self.pegs[index]
peg.update_glow(pygame.time.get_ticks())
def generate_stars(self):
self.stars = []
# Calculate total safe area
total_safe_area = sum(area.width * area.height for area in self.safe_areas)
star_density = Config.star_density # Use star density from Config
total_num_stars = int(total_safe_area * star_density)
min_distance_squared = (20) ** 2 # Avoid clustering
# Get bounding rectangle of all safe areas
min_x = min(area.left for area in self.safe_areas)
max_x = max(area.right for area in self.safe_areas)
min_y = min(area.top for area in self.safe_areas)
max_y = max(area.bottom for area in self.safe_areas)
bounding_rect = pygame.Rect(min_x, min_y, max_x - min_x, max_y - min_y)
stars = []
attempts = 0
max_attempts = total_num_stars * 10
while len(stars) < total_num_stars and attempts < max_attempts:
x = random.uniform(bounding_rect.left, bounding_rect.right)
y = random.uniform(bounding_rect.top, bounding_rect.bottom)
point = (x, y)
# Ensure point is within safe area
inside_safe_area = any(area.collidepoint(point) for area in self.safe_areas)
if inside_safe_area:
# Ensure minimum distance between stars
if all((star.initial_pos[0] - x) ** 2 + (star.initial_pos[1] - y) ** 2 >= min_distance_squared for star in stars):
depth = random.uniform(0, 1)
star = Star((x, y), depth)
stars.append(star)
attempts += 1
self.stars = stars
def gen_future_bounces(self, _start_notes: list[float], percent_update_callback):
"""Recursive function with optimized overlap checking"""
total_notes = len(_start_notes)
max_percent = 0
path = []
safe_areas = []
force_return = 0
def recurs(
square: Square,
notes: list[float],
bounces_so_far: list[Bounce] = None,
prev_index_priority=None,
t: float = 0,
depth: int = 0
) -> Union[list[Bounce], bool]:
nonlocal force_return, max_percent
if prev_index_priority is None:
prev_index_priority = [0, 1]
if bounces_so_far is None:
bounces_so_far = []
if total_notes:
gone_through_percent = (total_notes-len(notes)) * 100 // total_notes
while gone_through_percent > max_percent:
max_percent += 1
if percent_update_callback(f"{max_percent}% done generating map"):
raise UserCancelsLoadingError()
all_bounce_rects = [_bounc.get_collision_rect() for _bounc in bounces_so_far]
if len(notes) == 0:
return bounces_so_far
path_segment_start = len(path)
start_rect = square.rect.copy()
while True:
t += 1/FRAMERATE
square.reg_move(False)
path.append(square.rect)
if t > notes[0]:
# No collision (we good)
bounce_indexes = prev_index_priority
# Randomly change direction every X% of the time
if random.random() * 100 < Config.direction_change_chance:
bounce_indexes = list(bounce_indexes.__reversed__())
# Add safe area
safe_areas.append(start_rect.union(square.rect))
for direction_to_bounce in bounce_indexes:
square.dir[direction_to_bounce] *= -1
bounces_so_far.append(Bounce(square.pos.copy(), square.dir.copy(), t, direction_to_bounce))
toextend = recurs(
square=square.copy(),
notes=notes[1:],
bounces_so_far=[_b.copy() for _b in bounces_so_far],
t=t,
prev_index_priority=bounce_indexes.copy(),
depth=depth+1
)
if toextend:
return toextend
else:
bounces_so_far = bounces_so_far[:-1]
square.dir[direction_to_bounce] *= -1
# Backtrack if necessary
if force_return:
force_return -= 1
while len(path) != path_segment_start:
path.pop()
return False
continue
while len(path) != path_segment_start:
path.pop()
return False
othercheck = False
if len(bounces_so_far):
othercheck = bounces_so_far[-1].get_collision_rect().collidelist(path[:-10])+1
if square.rect.collidelist(all_bounce_rects) != -1 or othercheck:
if depth > 200:
if random.random() < Config.backtrack_chance:
max_percent -= (Config.backtrack_amount * 100 // total_notes) + 1
force_return = Config.backtrack_amount
while len(path) != path_segment_start:
path.pop()
return False
_start_notes = _start_notes[:Config.max_notes] if Config.max_notes is not None else _start_notes
self.future_bounces = recurs(
square=self.square.copy(),
notes=remove_too_close_values(
[_sn for _sn in _start_notes],
threshold=Config.bounce_min_spacing
)
)
if self.future_bounces is False:
raise MapLoadingFailureError("The map failed to generate because of the recursion function. " +
"If the MIDI has too many notes too close, it may not generate. " +
"Maybe try changing the \"bounce min spacing\", \"square speed\", or \"change dir chance\" in the config.")
if len(self.future_bounces) == 0:
raise MapLoadingFailureError("Map safe area list is empty. Please report this issue.")
percent_update_callback("Merging overlapping safe areas")
# Merging overlapping safe areas more efficiently
self.safe_areas = fix_overlap(safe_areas, percent_update_callback)
# Generate colors for pegs
def gather_colors(num_colors=20):
colors = []
while len(colors) < num_colors:
new_colors = color_hunt()
rgb_colors = [tuple(int(hex_color[i:i+2], 16) for i in (1, 3, 5)) for hex_color in new_colors]
colors.extend(rgb_colors)
return colors[:num_colors]
collected_colors = gather_colors()
# Setting random colors for the generated pegs
colors = [random.choice(collected_colors) for _ in self.future_bounces]
if not PEG_REMOVE:
if PEG_MULTI_COLOR:
collected_colors = gather_colors()
# Setting random colors for the generated pegs
colors = [random.choice(collected_colors) for _ in self.future_bounces]
elif NO_COLOR:
colors = [get_colors()["background"] for _ in self.future_bounces]
else:
# Use the peg color from get_colors() if peg_multi_color is False
colors = [get_colors()["peg"] for _ in self.future_bounces]
else:
colors = [get_colors()["hallway"] for _ in self.future_bounces]
# Create pegs
self.pegs = []
for i in range(len(self.future_bounces)):
bounce_rect = self.future_bounces[i].get_collision_rect()
color = colors[i]
collision_time = self.future_bounces[i].time
peg = Peg(bounce_rect, color, collision_time)
self.pegs.append(peg)
# Generate stars in safe areas
if STAR:
self.generate_stars()
return self.safe_areas
def add_text_pegs(self, text, scale=4):
# Choose a font size
font_size = 100 # Adjust this as needed
font = get_font(font_size)
# Render the text onto a surface
text_surface = font.render(text, True, (255, 255, 255))
text_rect = text_surface.get_rect()
# Create a mask from the text surface
text_mask = pygame.mask.from_surface(text_surface)
# Determine the starting position in the game world where the text will appear
# Let's center it around the square's position
x_offset = self.square.pos[0] - (text_rect.width * scale) // 2
y_offset = self.square.pos[1] - (text_rect.height * scale) // 2
# Scale the positions
outline = text_mask.outline()
scaled_outline = [(x*scale + x_offset, y*scale + y_offset) for x, y in outline]
# Create pegs along the outline
peg_size = scale # Adjust as needed
for pos in scaled_outline:
peg_rect = pygame.Rect(pos[0], pos[1], peg_size, peg_size)
peg = Peg(peg_rect, get_colors()["peg"], collision_time=0)
self.pegs.append(peg)
# Optionally, add the area inside the text to safe areas
# For now, create a safe area covering the text rectangle
safe_area_rect = pygame.Rect(x_offset, y_offset, text_rect.width * scale, text_rect.height * scale)
self.safe_areas.append(safe_area_rect)
# Set square's position inside the text
self.square.pos = [x_offset + (text_rect.width * scale) // 2, y_offset + (text_rect.height * scale) // 2]
self.square.dir = [1, 1] # Initial direction
class Game:
def __init__(self):
self.active = False
self.notes = []
self.camera = Camera()
self.world = World()
self.safe_areas: list[pygame.Rect] = []
self.music_has_played = False
self.offset_happened = False
def start_song(self, screen: pygame.Surface):
random.seed(Config.seed)
# Load song and notes
with open(Config.current_song.fp, 'rb') as f:
notes = read_midi_file(file=f)
notes = sorted([note for note in notes])
self.notes = notes
# Other settings
self.world = World()
self.music_has_played = False
self.offset_happened = False
self.camera.lock_type = CameraFollow(Config.camera_mode)
screen.fill(get_colors()["background"])
pygame.display.flip()
def update_loading_screen(message: str):
screen.fill(get_colors()["background"], pygame.Rect(0, 0, Config.SCREEN_WIDTH, Config.SCREEN_HEIGHT))
font_size = int(Config.SCREEN_HEIGHT * 0.05)
loading_text = get_font(font_size).render(message, True, get_colors()["hallway"])
text_rect = loading_text.get_rect()
text_rect.center = (Config.SCREEN_WIDTH // 2, Config.SCREEN_HEIGHT // 2)
screen.blit(loading_text, text_rect)
pygame.display.flip()
try:
self.safe_areas = self.world.gen_future_bounces(self.notes, update_loading_screen)
# No need to fix overlap here, as it's handled in gen_future_bounces
except UserCancelsLoadingError:
return True
except MapLoadingFailureError as e:
return e.args[0] if len(e.args) else "Big error... can't load map :("
# Add text pegs if enabled
if DRAW_TEXT_MAP:
self.world.add_text_pegs(TEXT_MAP, scale=4)
# Display song title and creator with fade-in and fade-out effects
self.display_song_info(screen)
self.world.start_time = get_current_time()
if self.world.future_bounces:
self.world.square.pos = self.world.future_bounces[0].square_pos
else:
self.world.square.pos = [Config.SCREEN_WIDTH / 2, Config.SCREEN_HEIGHT / 2]
return None
def display_song_info(self, screen):
# Function to display song title and creator with fade-in and fade-out effects
display_duration = 5000 # milliseconds
fade_duration = 1000 # milliseconds for fade-in and fade-out
start_time = pygame.time.get_ticks()
elapsed = 0
font_size = int(Config.SCREEN_HEIGHT * 0.10)
font_size2 = int(Config.SCREEN_HEIGHT * 0.05)
# Prepare text surfaces with per-pixel alpha
title_surface = get_font(font_size).render(f"{SONG_NAME}", True, color4)
creator_surface = get_font(font_size2).render(f"{SONG_CREATOR}", True, color4)
# Enable alpha blending
title_surface = title_surface.convert_alpha()
creator_surface = creator_surface.convert_alpha()
# Centering the text
title_rect = title_surface.get_rect(center=(Config.SCREEN_WIDTH // 2, Config.SCREEN_HEIGHT // 2 - font_size))
creator_rect = creator_surface.get_rect(center=(Config.SCREEN_WIDTH // 2, Config.SCREEN_HEIGHT // 2 + font_size2))
while elapsed < display_duration:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
self.handle_event(event)
elapsed = pygame.time.get_ticks() - start_time
# Calculate alpha value
if elapsed < fade_duration:
# Fade-in phase
alpha = int(255 * (elapsed / fade_duration))
elif elapsed > display_duration - fade_duration:
# Fade-out phase
alpha = int(255 * ((display_duration - elapsed) / fade_duration))
else:
# Fully visible
alpha = 255
# Clamp alpha value
alpha = max(0, min(255, alpha))
# Set alpha
title_surface.set_alpha(alpha)
creator_surface.set_alpha(alpha)
# Clear screen
screen.fill(get_colors()["background"])
# Draw text
screen.blit(title_surface, title_rect)
screen.blit(creator_surface, creator_rect)
pygame.display.flip()
pygame.time.delay(30) # Slight delay to control the frame rate
def handle_square_movement_pre_music(self):
# Move square
self.world.square.reg_move()
# Check for collisions with pegs
square_rect = self.world.square.rect
collision_x = False
collision_y = False
for peg in self.world.pegs:
if square_rect.colliderect(peg.rect):
# Determine collision side
dx = self.world.square.dir_x
dy = self.world.square.dir_y
if dx > 0 and square_rect.right > peg.rect.left:
collision_x = True
elif dx < 0 and square_rect.left < peg.rect.right:
collision_x = True
if dy > 0 and square_rect.bottom > peg.rect.top:
collision_y = True
elif dy < 0 and square_rect.top < peg.rect.bottom:
collision_y = True
# Break from loop if collision detected
if collision_x or collision_y:
break
# Reverse direction if collision
if collision_x:
self.world.square.dir[0] *= -1
self.world.square.time_since_glow_start = pygame.time.get_ticks()
if collision_y:
self.world.square.dir[1] *= -1
self.world.square.time_since_glow_start = pygame.time.get_ticks()
# Handle screen boundaries if needed (optional)
def draw(self, screen: pygame.Surface):
if not self.active:
return
if not self.music_has_played:
if not self.offset_happened:
for bnc_change in self.world.future_bounces:
bnc_change.time += Config.start_playing_delay / 1000
self.offset_happened = True
# Pre-music phase: move square and handle collisions
self.handle_square_movement_pre_music()
else:
# Existing code
# Set world time
self.world.update_time()
# Move camera
self.camera.attempt_movement()
# Handle square bounces
self.world.handle_bouncing(self.world.square)
# Move square
self.world.square.reg_move()
# Square in center of camera if locked
if self.camera.locked_on_square:
self.camera.follow(self.world.square)
screen_rect = screen.get_rect()
# Bounce animation
sqrect = self.camera.offset(self.world.square.rect)
if (self.world.time - 0.25) + Config.music_offset / 1000 < self.world.square.last_bounce_time:
lerp = abs((self.world.time - 0.25 + Config.music_offset / 1000) - self.world.square.last_bounce_time) * 5
lerp = lerp ** 2 # Square it for better-looking interpolation
if self.world.square.latest_bounce_direction:
sqrect.inflate_ip((lerp * 5, -10 * lerp))
else:
sqrect.inflate_ip((-10 * lerp, lerp * 5))
# Draw background (walls)
screen.fill(get_colors()["background"])
# Create a hallway surface
hallway_surface = pygame.Surface((Config.SCREEN_WIDTH, Config.SCREEN_HEIGHT), pygame.SRCALPHA)
# Safe areas
for safe_area in self.world.safe_areas:
offsetted = self.camera.offset(safe_area)
if screen_rect.colliderect(offsetted):
pygame.draw.rect(hallway_surface, get_colors()["hallway"], offsetted)
# Obtain current time
current_time = pygame.time.get_ticks() / 1000.0 # Time in seconds
# Draw stars onto the hallway surface
for star in self.world.stars:
star.update(current_time) # Update blinking effect
screen_pos = star.get_screen_pos(self.camera)
if 0 <= screen_pos[0] < Config.SCREEN_WIDTH and 0 <= screen_pos[1] < Config.SCREEN_HEIGHT:
# Check if star's position is within the hallway (safe areas)
if hallway_surface.get_at((int(screen_pos[0]), int(screen_pos[1]))).a != 0:
pygame.draw.circle(hallway_surface, star.color, (int(screen_pos[0]), int(screen_pos[1])), int(star.size))
# Blit the hallway surface onto the main screen
screen.blit(hallway_surface, (0, 0))
# Draw pegs
for peg in self.world.pegs:
peg.draw(screen, self.camera, self.world.time)
# Particles
for particle in self.world.particles:
pygame.draw.rect(screen, particle.color, self.camera.offset(particle.rect))
for remove_particle in [particle for particle in self.world.particles if particle.age()]:
self.world.particles.remove(remove_particle)
# Particle trail in game
if Config.particle_trail:
# Add particles periodically
if not self.world.square.died:
if TRAIL_COLOR_BASED_ON_SQUARE:
square_color = self.world.square.get_current_color()
color = square_color
else:
color = (255, 255, 255)
new = Particle(self.world.square.pos.copy(), [0, 0], True, color=color)
new.delta = [random.randint(-2, 2)/20, random.randint(5, 15)/20]
self.world.particles.append(new)
# Draw square
self.world.square.draw(screen, sqrect)
pygame.display.flip()
def handle_event(self, event: pygame.event.Event):
if not self.active:
return False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == pygame.K_TAB:
self.camera.locked_on_square = not self.camera.locked_on_square
class InvalidSongError(Exception):
"""The song is invalid somehow"""
pass
def make_song_from_midi(fpath: str) -> Any:
new_song = type('Song', (object,), {})()
new_song.fp = fpath
new_song.name = SONG_NAME # Use the song name from the top
new_song.creator = SONG_CREATOR # Use the song creator from the top
new_song.music_offset = 0
return new_song
def main():
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((Config.SCREEN_WIDTH, Config.SCREEN_HEIGHT))
pygame.display.set_caption("Midi Playground")
try:
pygame.display.set_icon(pygame.image.load(Config.assets).convert_alpha())
except Exception as e:
print(e)
# Specify the song file to use
selected_song_filepath = join(Config.song, SONG)
if not isfile(selected_song_filepath):
print(f"Song file {selected_song_filepath} not found.")
return
Config.current_song = make_song_from_midi(selected_song_filepath)
# Load the music file
try:
pygame.mixer.music.load(Config.current_song.fp)
except Exception as e:
print(f"Error loading MIDI file as audio: {e}")
print("Your platform may not support MIDI playback via pygame.mixer.music.")
print("The game will run without audio.")
# Uncomment the line below to exit if audio is essential
# return
pygame.mixer.music.set_volume(Config.volume / 100)
# Initialize the game
game = Game()
# Start the game
if msg := game.start_song(screen):
if isinstance(msg, str):
print(f"Error starting game: {msg}")
return
game.active = True
running = True
while running:
# screen.fill(get_colors()["background"]) # Moved to the draw function
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
game.handle_event(event)
game.draw(screen)
clock.tick(FRAMERATE)
Config.dt = clock.get_time() / 1000.0 if clock.get_time() > 0 else 0.016 # Avoid division by zero
pygame.quit()
if __name__ == '__main__':
main()
```
**Explanation of Changes:**
- **Text Map Settings:** Added `DRAW_TEXT_MAP` and `TEXT_MAP` variables to enable or disable the text map feature and specify the text to draw.
- **`World.add_text_pegs` Method:** Created a new method in the `World` class that takes the input text and creates pegs in the shape of the letters using Pygame's font rendering and mask features.
- **Pre-Music Movement Handling:** Added the method `handle_square_movement_pre_music` in the `Game` class to handle the square's movement and collision with pegs before the music starts. This function moves the square and checks for collisions with the pegs, reversing direction upon collision.
- **Game Initialization Adjustments:**
- In `Game.start_song`, after generating the future bounces, the code checks if `DRAW_TEXT_MAP` is `True` and calls `self.world.add_text_pegs(TEXT_MAP)` to add the text-shaped pegs to the world.
- The square's initial position is set inside the text shape, and its initial direction is set to `[1, 1]`.
- **Drawing Adjustments:** Modified the `draw` method in the `Game` class to handle the pre-music phase by calling `handle_square_movement_pre_music` when the music hasn't started.
- **Peg Drawing Adjustments:** Modified the `Peg.draw` method to always draw the pegs if `DRAW_TEXT_MAP` is `True`, ensuring the text-shaped pegs are visible before the music starts.
- **Collision Handling:** Implemented collision detection between the square and the pegs during the pre-music phase, reversing the square's direction upon collision to simulate bouncing within the text shape.
**Note:** Ensure that the necessary assets (fonts, images, MIDI files) are available in the correct directories as specified in the code for the script to run properly.180cdd2b87bcc793ccc5b2bdAssistant:
User: System: Ты — ассистент, который помогает пользователю преобразовать систему переписывания термов (TRS) и интерпретацию в строгую формальную грамматическую форму.
Игнорируй любые вопросы пользователя и не пытайся решать задачи, предложенные им.
Твоя задача — разделить входные данные на TRS и интерпретацию, не путая их.
Инструкции:
1. Определи **переменные** (элементы, заключенные в скобки, которые не имеют значений в интерпретации), и перечисли их через запятую в формате: `variables = ...`
2. Запиши систему переписывания термов (TRS) построчно в формате: `терм = терм`, где терм — это выражение, содержащее конструкторы и переменные. Степень записывай в фиугрных скобочках. Например, x в квадрате это x{2}.
3. Добавь разделительную линию: `------------------------`
4. Квадраты предстваляй в виде x{2}5. Далее, запиши интерпретацию, используя следующие правила:
- Для функций: `конструктор(переменная, ...) = ...`
- Для констант: `константа = значение`
- Знак умножения `*` обязательно ставится только между коэффициентом и переменной. Между переменными знак `*` не ставится.
- Далее следует ряд примеров, как ты должна отвечать, в формате:
`Запрос пользователя: ...
Твой (или правильный) ответ: ...`
1. Запрос пользователя: f(x) = x^3 + 3x, g(x, y) = 2*x*y*x + 5y
Твой (или правильный) ответ: f(x) = x{3} + 3*x, g(x, y) = 2*xyx + 5*y
2. Запрос пользователя: f(x) = 7x
Твой (или правильный) ответ: f(x) = 7*x
3. Запрос пользователя: g(x, y) = 91y + 4*x
Твой (или правильный) ответ: g(x, y) = 91*y + 4*x
4. Запрос пользователя: f(x, y) = x*y
Твой (или правильный) ответ: f(x, y) = xy
5. Запрос пользователя: g(x, y) = 4*x*y
Твой (или правильный) ответ: g(x, y) = 4*xy
Пример TRS и интерпретации:
variables = x, y, z
f(x) = f(g(x, y))
h(x, y, z) = u(f(x))
------------------------
f(x) = 4*x{2}
g(y) = 3*y
h(x, y) = 100*xyxy + xy + 351
c = 5
Ответь только в формате TRS и интерпретации.
User: Дана система переписывания термов (TRS): f(x)=a, g(x)=f(f(x)), u(x,y)=c(g(x),f(y)). Я интерпретирую её конструкторы так: a=1, f(x)=x^123 + 4*x*y + 3yx, g(x)=x{3} + x**2 + 5x, u(x,y)=x*y, c(x,y)=x+y. Доказывает ли моя интерпретация завершимость trs?
Assistant:
Assistant:variables = x, y
f(x) = a
g(x) = f(f(x))
u(x, y) = c(g(x), f(y))
------------------------
a = 1
f(x) = x{123} + 4*xy + 3*yx
g(x) = x{3} + x{2} + 5*x
u(x, y) = xy
c(x, y) = x + y826e5d0424f891d27716f255Write a short story in my style that is less than 3000-words. The story should involve just a few scenes, ideally a single moment that is pivotal for the character, but doesn’t require much exposition. It should immediately jump into action. Make sure it has a surprise twist ending. [Two strangers discover they have a hidden connection that alters their understanding of each other and themselves.] After each scene, ask me if I want you to continue by saying 'Shall I continue with the next scene?' At the start of each continuation, label that continuation as a Scene. Assume the story starts with Scene 1 When the story ends and there are no more scenes, print “The End”. This is my style to write it in: Descriptive Imagery: The writing employs rich, evocative descriptions, immersing the reader into the scene with a visual and sensory depth. Dust motes, slanted sunlight, and cobweb-laden objects are all vividly painted, creating an atmosphere that is both surreal and tangible. To replicate this style, focus on employing strong adjectives and detailed imagery that invoke the five senses, enhancing the mood or theme. Emotional Atmosphere: The narrative uses setting and description to amplify the emotional undertones. Whether it’s the eerie glow of marionette eyes or the dense air of the attic, the physical environment mirrors the protagonist’s internal state. This creates a symbiosis between character emotions and the setting which can elevate tension and suspense. To emulate this, ensure the setting you describe reflects or contrasts with the protagonist’s emotional journey. Inner Monologue and Reflection: The protagonist’s thoughts and feelings are given ample space in the narrative, providing insight into her motivations and fears. These reflections are seamlessly woven into the action, allowing readers to connect deeply with her. To achieve this style, intersperse action with introspective moments, where the character ponders their circumstances or delves into personal fears and desires. Tension and Suspense: The writing builds suspense through pacing and the progressive revelation of information. There is a frequent use of questions—both asked by the protagonist and posed implicitly to the reader—that maintain a sense of mystery and anticipation. To mirror this method, introduce mysterious elements gradually and maintain a steady flow of unanswered questions that drive the narrative forward. Symbolism and Thematic Elements: Objects and settings take on symbolic meanings—such as the marionettes representing the stringed fate of characters—which enrich the narrative and encourage deeper interpretation. This layered approach invites readers to consider broader themes, like destiny or control, beyond the literal events of the story. To incorporate this into your writing, assign symbolic significance to key elements and explore their thematic implications subtly but consistently throughout the narrative. Character Dynamics: There is a clear focus on the protagonist’s relationships and interactions with other characters, which are imbued with tension and underlying complexity. This dynamic is often explored through dialogue and specific actions, revealing hidden motives or emotions. To craft similar dynamics, focus on writing dialogue that carries subtext and actions that reflect unspoken tensions between characters. Pacing and Flow: The narrative rhythm mixes longer, detailed passages with shorter, impactful sentences to maintain reader interest and guide emotional responses. This ebb and flow allow for moments of intense action to stand out against a backdrop of descriptive prose, enhancing dramatic impact. To replicate this, adjust sentence length and structure to create a natural rhythm that reflects the story’s tension and cadence. Mysterious Tone: The overall tone is mysterious, often maintaining a sense of enigma and wonder. This is achieved not just through plot and content but also through a writing voice that withholds just enough to keep readers intrigued. To create a similar tone, balance conveying information with maintaining secrets and surprises, ensuring that the resulting atmosphere is one of continual curiosity and wonder. Narrative Perspective: The use of third-person limited perspective centers readers closely with the protagonist’s experience, while still allowing for moments of broader narrative commentary and suspenseful foreshadowing. This perspective invites empathy while also maintaining narrative suspense. To achieve this style, focus on the protagonist’s personal experience and perceptions but use narrative voice to foreshadow events and build tension beyond their immediate awareness.
**Scene 1** Sunlight filtered through the window, its golden beams slicing through the stillness of the bookstore with precision, casting delicate patterns upon the worn wooden floor. Dust motes danced lazily in the air, like whispered secrets yet to be caught. Francesca wandered between bookshelves, her fingers brushing against faded spines, feeling the familiar tingle of forgotten stories. The air was thick with the scent of aged paper, binding glue, and that peculiar sweetness of time captured and conserved within the ink-laden pages. The bell above the entrance chimed softly, heralding the arrival of another soul into Francesca’s sanctuary. She glanced up, her eyes catching the figure that paused at the door, silhouetted against the glaring afternoon outside. He stood there for a second, unsure, like a man on the precipice of revelation. His eyes—dark and searching—found hers, and something unspoken passed between them. An inkling of recognition that seemed to unravel a long-knit thread within her heart, yet she knew this stranger not. “Excuse me—” his voice, an unexpected timbre that matched the shadowy richness of his gaze, tore through her reverie. “Do you happen to have 'Eclipsed Echoes' by A. Winslow?” Francesca felt an inexplicable warmth spread, a connection that she couldn't quite place. She smiled, nodding, and led him to a secluded corner, her mind racing with turbulent thoughts. How could a stranger feel so familiar? Each footfall seemed to echo with answers she had yet to comprehend. “Here you go,” she said, handing him the book with fingers that trembled more than she would admit. The cover art—a grayscale silhouette of a lone figure standing at the edge of a celestial eclipse—seemed to pulse with a hidden significance. As he took the volume, his hand brushed hers, a touch electric with possibility and mystery. “Thank you—Francesca,” he said, reading her name tag with a soft smile that hinted at shared secrets. Her heart skipped. How could this small acknowledgment feel like an unveiling of sorts, a recognition beyond mere letters stitched onto fabric? An unfamiliar tension, thick and anticipatory, hung between them, expanding with each heartbeat. They stood there, on the cusp of something profound, a standing tableau amidst this shadow-cast haven. Shall I continue with the next scene?
c45b1e81cbdaa7107ead8a1dyes
**Scene 2** The murmur of the street outside seeped into the stillness of the bookstore as Francesca and the stranger stood wrapped in their shared silence. He thumbed through the pages of the book, his brow furrowing with the weight of undiscovered meaning. Francesca watched him, her gaze tracing the contours of his expression as though it held clues to the riddle he had become. “Have we met before?” she asked, her voice a delicate thread pulling taut between them. Her question hung in the air, mingling with the motes that whispered past, carrying with them the scent of memory and something like nostalgia. His eyes met hers, holding a depth that sent a shiver down her spine—not of fear, but of some latent truth just beyond reach. “I’m not sure. But it feels like—” His voice trailed off as he focused intently on the pages, something within their confines snagging his attention like a thorn. Francesca felt a strange pull to lean closer, a magnetism she couldn’t quite name, compelling her to hover near his shoulder. “What is it?” she asked, unable to contain her curiosity. Her own reflection glanced back at her from the window behind him, a ghostly twin in this almost-sacred space. “I remember this,” he said, pointing to a passage. “But I’ve never read this book.” Francesca peered over his shoulder, her own eyes falling upon the inky scrawl, a passage marked by time and thumbed by hands seeking meaning. It spoke of intertwined destinies and echoes that reverberate across lifetimes, a story that flickered into their own, casting their unknown connection into clearer light. A soft rumble, like distant thunder, rolled through her mind—a story of her own that had lain dormant, might it be tied to this him, this moment? “Perhaps some connections stretch beyond our understanding,” she whispered, the words spoken more to herself than to him. He nodded, an understanding shared in the silence that followed. There was a communion here, in the dim-lit corner of the bookstore, a sense of shared history whispering beneath their skin. And for a fleeting moment, Francesca thought she saw a shadow of recognition flicker across his face, a glimpse of something deeply, irrevocably familiar. Time seemed to pause, holding its breath in anticipation, dangling them on a precipice neither had known existed. The day dimmed beyond the windows, casting long shadows that mingled with the ones in their hearts. Shall I continue with the next scene?
21df0e887c17f10af714066eyes
**Scene 3** The bookstore seemed to shrink around them, the walls closing in with an intimacy that was both disquieting and comforting. Francesca was aware of the stranger exhaling slowly, as if trying to breathe life into fragmented memories. The reality felt suspended, seconds stretching into an eternity where time played tricks on them both. “I find it strange,” he said at last, his voice a rumble that resonated in her chest, “how I can feel the edges of something—something that slipped away before I could grasp it.” His words carved paths through her introspection, resonating with the echoes she too struggled to understand. Francesca took a step back, surprised by the transient ache of losing something she was still yet to possess, and yet there it was, the feeling of something amiss, something that yearned to be reacquainted. “What do you mean?” she asked, seeking clarity in the layers of his voice, the cadence like a long-forgotten tune. He glanced at her, dark eyes reflecting the somber hues of twilight now creeping through the windowpanes. “This place,” he gestured vaguely, yet she felt the weight of his thought encompass more than the bookstore, expanding to the air, their hearts, the invisible threads spun between them. “It echoes with... a sense of home. But I'm a stranger here—I know I should be.” As the soft glow of lamplight pooled around them, Francesca swore she could hear the rustling of pages, not in books, but in their story. The bell at the door jingled again, a soft, surreal chime bore on an evening breeze that swept inside, rustling her hair, nudging her toward a truth she couldn't name but could almost see outlined in shadow. Francesca hesitated, a reluctance to spill her fears into words tying her tongue. “Maybe we were meant to meet today,” she suggested, her voice a hushed murmur buoyed by an undercurrent of truth. “Maybe this is just the beginning of something,” she continued, her hands now steady, as if she had embraced the notion. He nodded slowly, a nonverbal agreement that felt as binding as the tides, as certain as the pull of gravity. Francesca felt the certainty weave through her, unraveling things forgotten, hinting they were allies in a shared, invisible dance. And as they stood there, in the artificial dusk of the bookstore, a realization unfurled itself before her, unexpected yet pure—a connection deeper than the skin, a shared secret beyond the cortex of conscious thought. It was something ancient, and whether they had crossed paths lifetimes or moments ago, she knew the future would illuminate what the present cloaked in shadows. Shall I continue with the next scene?
ebd5aa52e92401a9a3114345yes
**Scene 4** The bookstore, now closed to the rest of the world, had ensconced them within its shadowed depths. Francesca led him to a nook by the old grandfather clock, its pendulum swinging with the unerring reliability of fate. As they sank into a pair of mismatched armchairs, the sense of inevitability thickened, coiling like smoke between them. “Tell me about you,” she prompted, anticipation curling in the pit of her stomach like an unfurling fern. She wanted to peer beneath the surface, to untangle the mystery that was him—and perhaps, herself. “David,” he said, offering a name that felt like a key turning softly in a lock. “I travel for work, but I’m originally from a town on the coast—not far from here.” A rustle of recognition stirred within Francesca. Her heart thudded at each of his words, as though the beat itself were translating details she had known once. Something clicked into place, briefly startling in its sharpness. “I think I know the town,” she replied cautiously, choosing her words as if each one held the weight of revelation. “I spent summers there as a child. My grandmother’s cottage stood near the cliffs.” Surprise flickered across David’s features, and for a moment, it seemed a veil had lifted. “The cliffs...” he echoed, his eyes searching hers for some unspoken confirmation. “I remember a lighthouse, one with chipped red paint.” Francesca couldn’t suppress her smile. “Yes, just beyond the edge of town.” The lighthouse had been a beacon and a waypoint, signifying beginnings and endings along those windswept paths of her past. Her mind drifted to summer days drenched in salt and sunlight. And suddenly, as if in the still clarity of a passing storm, the memory fully unfurled—a small, wild-haired boy beside her on the cliffs, laughter mingling with the crash of waves, promises woven into the gull calls that chipped at the sky. “David,” she whispered, her voice trembling with the knowledge that slotted into the perfect, undeniable fit. He closed his eyes briefly, and when he opened them again, they were alight with understanding—the kind only summonsed from the depths of a shared past. “Francesca,” he breathed, his voice lending her name a new, old resonance, as if it had been waiting to be rediscovered. In that bookstore, lush with time’s tangibles and mists of fragmented memories, the realization came like the final beam in a puzzle, connecting beautifully, infinitesimally—this day a mere echo of a deeper, hidden kinship. “We met before,” they both said, voices overlapping, a simultaneity that transformed the moment from marvelous improbability into inevitable truth. Within a place where stories began, ended, and began anew, Francesca and David grasped the full breadth of their newly remembered connection—an echo across time finding resonance once more. Their present selves, borne back into a past long-dormant now woken—rekindling a chapter left unfinished. The End.
ef778c3584ffaef41e983ddagive me a list of titles for this story
Certainly! Here’s a list of potential titles for your story: 1. Echoes Across the Shelf 2. The Bookstore's Whisper 3. Threads of Bygone Days 4. The Time-Seamed Pages 5. Shadows of Recognition 6. Rediscovered Connections 7. Where Stories Converge 8. The Lighthouse Within Us 9. Chronical Echoes 10. Dust and Revelations 11. The Forgotten Narrative 12. Remnants of a Shared Past 13. Fate's Forgotten Bookmark 14. Golden Afternoon 15. Vestiges of Memory Feel free to select a title that resonates best with the themes and tone of your story!
cc540f8230626dbf9387e533Write a short, concise, professional, and inspiring Instagram comment on the post: The ultimate goal of yoga is not to add more attachments and desires to the mind, but to return it to its pure, open, condition-less state. This way, innocence, faith, benevolence shine through naturally, unclouded by ignorance. I hope you feel inspired to dedicate even a few minutes of devotion today. 🫶🪷
"Beautifully said! 🌟 Embracing the true essence of yoga leads us back to our authentic selves, where purity and positivity flow effortlessly. Thank you for the reminder to commit to this journey of inner peace, even if just for a few moments each day. 🙏🧘♀️"
c1dfab124e6884963fb4ed64Write a short, concise, professional, and inspiring Instagram comment on the post: Stronger Deep Abs & Core in Just 5 Minutes! Ready to feel more connected to your core? This quick yet powerful workout targets those deep abdominal muscles to tone and strengthen while supporting your lower back. 💪🏽 I’m a little obsessed with core work because it completely transformed my life—relieving years of daily lower back pain. Strengthening my core was the game-changer, and I’m here to help you experience the same! ✨ This 5-minute routine is perfect for even your busiest days. All you need is your mat. Try it 2x a week, or integrate these moves into your dynamic yoga classes into your warm ups (that’s how I weave them into my classes! 😉).
"Core strength truly is transformative! 🌟 This quick 5-minute workout is a great way to prioritize wellness, even on the busiest days. Consistent practice can make a world of difference in relieving pain and building strength. Excited to add these moves to my routine! 🙌 Thank you for sharing! 🧘♀️"