import math import pygame import random from pygame import draw import time pygame.init() size = width, height = 1280, 720 screen = pygame.display.set_mode(size) done = False keys_pressed = dict.fromkeys(range(256)) sprite_x = 0 sprite_y = 0 def dot(A, B): return A[0]*B[0] + A[1]*B[1] def hit_sphere(center, radius, r_origin, r_direction): oc = r_origin[0] - center[0], r_origin[1] - center[1] a = dot(r_direction, r_direction) b = 2.0 * dot(oc, r_direction) c = dot(oc, oc) - radius*radius discriminant = b*b - 4.0*a*c if discriminant < 0: return -1 # apply the quadratic formula to calculate the roots t1 = (-b + math.sqrt(discriminant)) / (2*a) t2 = (-b - math.sqrt(discriminant)) / (2*a) if t1 < t2: return t1 else: return t2 def draw_line(screen, color, start_pos, end_pos): pygame.draw.line(screen, color, start_pos, end_pos) def draw_circle(screen, color, start_pos, end_pos): # pygame.draw.line(screen, color, start_pos, end_pos) width = abs(end_pos[0] - start_pos[0]) height = abs(end_pos[1] - start_pos[1]) rx = width / 2 ry = height / 2 x1 = start_pos[0] + rx y1 = start_pos[1] + ry theta = 0 num_segments = 128 dtheta = 2 * 3.141592653 / (num_segments + 1) x = x1 + rx * math.cos(theta) y = y1 + ry * math.sin(theta) for i in range(num_segments): last_x = x last_y = y theta += dtheta x = x1 + rx * math.cos(theta) y = y1 + ry * math.sin(theta) p0 = (last_x, last_y) p1 = (x, y) pygame.draw.line(screen, color, p0, p1) # screen.fill((0, 0, 0)) # pygame.display.update() # time.sleep(1) # screen.fill((0, 0, 192)) # pygame.display.update() # time.sleep(1) # screen.fill((0, 192, 192)) # pygame.display.update() # time.sleep(1) # screen.fill((192, 192, 192)) # pygame.display.update() # time.sleep(1) draw_count = 0 theta = 0 frame_count = 0 time0 = pygame.time.get_ticks() / 1000.0 while not done: time1 = pygame.time.get_ticks() / 1000.0 time_elapsed = time1 - time0 for event in pygame.event.get(): if event.type == pygame.constants.WINDOWCLOSE: done = True if event.type == pygame.constants.KEYDOWN: keys_pressed[event.key] = True if event.type == pygame.constants.KEYUP: keys_pressed[event.key] = False # check for ESCAPE key if keys_pressed[pygame.constants.K_ESCAPE]: done = True # handle user input for left/right dx = 0 if keys_pressed[pygame.constants.K_a]: dx -= 1 if keys_pressed[pygame.constants.K_d]: dx += 1 sprite_x += dx dy = 0 if keys_pressed[pygame.constants.K_w]: dy -= 1 if keys_pressed[pygame.constants.K_s]: dy += 1 sprite_y += dy screen.fill((25, 25, 25)) # Calculate the location of the sphere C = Cx, Cy = width/3, height/3 R = width/6 # Calculate the origin and direction of the ray A = Ax, Ay = 0.75 * width, 0.75 * height B = Bx, By = math.cos(time1/5), math.sin(time1/5) t = 1000 # * (time1 - int(time1)) # Point on a ray (or point at parameter t): P(t) = A + t*B start_pos = (Ax, Ay) end_pos = (Ax + t * Bx, Ay + t * By) color = (0, 0, 255) draw_line(screen, color, start_pos, end_pos) # Calculate intersection (if any) t = hit_sphere(C, R, A, B) if t < 0: color = (255, 0, 0) else: color = (0, 128, 0) start_pos = (Cx - R, Cy - R) end_pos = (Cx + R, Cy + R) draw_circle(screen, color, start_pos, end_pos) # draw the intersection point if t >= 0: Px = Ax + t * Bx Py = Ay + t * By start_pos = (Ax, Ay) end_pos = (Px, Py) color = (255, 0, 255) draw_line(screen, color, start_pos, end_pos) start_pos = (Px-10, Py-10) end_pos = (Px+10, Py+10) draw_circle(screen, color, start_pos, end_pos) pygame.display.update() theta += time_elapsed / 180 frame_count += 1