Skip to content

Instantly share code, notes, and snippets.

@Khurdhula-Harshavardhan
Created September 30, 2025 22:18
Show Gist options
  • Select an option

  • Save Khurdhula-Harshavardhan/3d459797b23d2047886fc03606961969 to your computer and use it in GitHub Desktop.

Select an option

Save Khurdhula-Harshavardhan/3d459797b23d2047886fc03606961969 to your computer and use it in GitHub Desktop.
Interfaze Simulation Text
import math
import sys
import pygame
# Config
WIDTH, HEIGHT = 800, 800
FPS = 120
# Physics
GRAVITY = 980.0 # pixels/s^2, roughly Earth-like (tunable)
BOUNCE_DAMPING = 0.85 # energy loss on bounce
FRICTION_TANGENTIAL = 0.995 # slight tangential damping on each collision
# Square
SQUARE_SIZE = 500 # side length in pixels
SQUARE_ROT_SPEED = math.radians(10) # radians per second (slow rotation)
# Ball
BALL_RADIUS = 14
BALL_COLOR = (255, 215, 0) # gold/yellow
# Colors
BG = (18, 18, 22)
SQUARE_COLOR = (90, 200, 255)
SQUARE_OUTLINE = (170, 220, 255)
def rotate_point(px, py, angle):
ca = math.cos(angle)
sa = math.sin(angle)
return (px * ca - py * sa, px * sa + py * ca)
def clamp(x, a, b):
return max(a, min(b, x))
def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Bouncing Ball in Rotating Square")
clock = pygame.time.Clock()
# Square state
cx, cy = WIDTH // 2, HEIGHT // 2
half = SQUARE_SIZE / 2
angle = 0.0
# Ball initial state (start near the top-center inside the square)
bx, by = cx, cy - half + BALL_RADIUS + 5
vx, vy = 120.0, 0.0 # give it some initial horizontal motion
running = True
while running:
dt = clock.tick(FPS) / 1000.0 # seconds
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
running = False
# Update square rotation
angle += SQUARE_ROT_SPEED * dt
# 1) Apply gravity in world space
vy += GRAVITY * dt
# 2) Provisional position update in world space
bx += vx * dt
by += vy * dt
# 3) Transform ball into square's local coordinates (unrotated box space)
# Translate to square center, then rotate by -angle
dx, dy = bx - cx, by - cy
local_x, local_y = rotate_point(dx, dy, -angle)
# Transform velocity into local space (rotate by -angle)
local_vx, local_vy = rotate_point(vx, vy, -angle)
# 4) Collision detection/response in local AABB space
# Effective AABB for the ball is reduced by radius so the ball's center stays within.
min_x = -half + BALL_RADIUS
max_x = half - BALL_RADIUS
min_y = -half + BALL_RADIUS
max_y = half - BALL_RADIUS
collided = False
normal_x, normal_y = 0.0, 0.0
if local_x < min_x:
local_x = min_x
local_vx = -local_vx * BOUNCE_DAMPING
local_vy *= FRICTION_TANGENTIAL
collided = True
normal_x, normal_y = 1.0, 0.0
elif local_x > max_x:
local_x = max_x
local_vx = -local_vx * BOUNCE_DAMPING
local_vy *= FRICTION_TANGENTIAL
collided = True
normal_x, normal_y = -1.0, 0.0
if local_y < min_y:
local_y = min_y
local_vy = -local_vy * BOUNCE_DAMPING
local_vx *= FRICTION_TANGENTIAL
collided = True
normal_x, normal_y = 0.0, 1.0
elif local_y > max_y:
local_y = max_y
local_vy = -local_vy * BOUNCE_DAMPING
local_vx *= FRICTION_TANGENTIAL
collided = True
normal_x, normal_y = 0.0, -1.0
# 5) Transform corrected local position/velocity back to world space
world_dx, world_dy = rotate_point(local_x, local_y, angle)
bx, by = cx + world_dx, cy + world_dy
world_vx, world_vy = rotate_point(local_vx, local_vy, angle)
vx, vy = world_vx, world_vy
# Optional: small global damping to avoid runaway energies
vx *= 0.999
vy *= 0.999
# 6) Render
screen.fill(BG)
# Compute square corners for drawing
corners_local = [
(-half, -half),
(half, -half),
(half, half),
(-half, half),
]
corners_world = []
for px, py in corners_local:
rx, ry = rotate_point(px, py, angle)
corners_world.append((cx + rx, cy + ry))
# Filled square (slightly transparent effect by drawing polygon then outline)
pygame.draw.polygon(screen, SQUARE_COLOR, corners_world, width=0)
pygame.draw.polygon(screen, SQUARE_OUTLINE, corners_world, width=3)
# Ball
pygame.draw.circle(screen, BALL_COLOR, (int(bx), int(by)), BALL_RADIUS)
# HUD
font = pygame.font.SysFont(None, 22)
info = f"Angle: {math.degrees(angle) % 360:6.2f} deg | v=({vx:7.2f},{vy:7.2f}) | dt={dt * 1000:5.1f}ms"
screen.blit(font.render(info, True, (230, 230, 235)), (10, 10))
pygame.display.flip()
pygame.quit()
sys.exit()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment