microwerx

Ray-Circle Intersection

Jul 31st, 2021
1,004
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import math
  2. import pygame
  3. import random
  4.  
  5. from pygame import draw
  6. import time
  7.  
  8. pygame.init()
  9. size = width, height = 1280, 720
  10. screen = pygame.display.set_mode(size)
  11.  
  12. done = False
  13. keys_pressed = dict.fromkeys(range(256))
  14.  
  15. sprite_x = 0
  16. sprite_y = 0
  17.  
  18. def dot(A, B):
  19.     return A[0]*B[0] + A[1]*B[1]
  20.  
  21. def hit_sphere(center, radius, r_origin, r_direction):
  22.     oc = r_origin[0] - center[0], r_origin[1] - center[1]
  23.     a = dot(r_direction, r_direction)
  24.     b = 2.0 * dot(oc, r_direction)
  25.     c = dot(oc, oc) - radius*radius
  26.     discriminant = b*b - 4.0*a*c
  27.     if discriminant < 0:
  28.         return -1
  29.  
  30.     # apply the quadratic formula to calculate the roots
  31.     t1 = (-b + math.sqrt(discriminant)) / (2*a)
  32.     t2 = (-b - math.sqrt(discriminant)) / (2*a)
  33.     if t1 < t2:
  34.         return t1
  35.     else:
  36.         return t2
  37.  
  38. def draw_line(screen, color, start_pos, end_pos):
  39.     pygame.draw.line(screen, color, start_pos, end_pos)
  40.  
  41. def draw_circle(screen, color, start_pos, end_pos):
  42.     # pygame.draw.line(screen, color, start_pos, end_pos)
  43.  
  44.     width = abs(end_pos[0] - start_pos[0])
  45.     height = abs(end_pos[1] - start_pos[1])
  46.  
  47.     rx = width / 2
  48.     ry = height / 2
  49.  
  50.     x1 = start_pos[0] + rx
  51.     y1 = start_pos[1] + ry
  52.  
  53.     theta = 0
  54.     num_segments = 128
  55.     dtheta = 2 * 3.141592653 / (num_segments + 1)
  56.     x = x1 + rx * math.cos(theta)
  57.     y = y1 + ry * math.sin(theta)
  58.     for i in range(num_segments):
  59.         last_x = x
  60.         last_y = y
  61.         theta += dtheta
  62.         x = x1 + rx * math.cos(theta)
  63.         y = y1 + ry * math.sin(theta)
  64.         p0 = (last_x, last_y)
  65.         p1 = (x, y)
  66.         pygame.draw.line(screen, color, p0, p1)
  67.  
  68.  
  69. # screen.fill((0, 0, 0))
  70. # pygame.display.update()
  71. # time.sleep(1)
  72. # screen.fill((0, 0, 192))
  73. # pygame.display.update()
  74. # time.sleep(1)
  75. # screen.fill((0, 192, 192))
  76. # pygame.display.update()
  77. # time.sleep(1)
  78. # screen.fill((192, 192, 192))
  79. # pygame.display.update()
  80. # time.sleep(1)
  81.  
  82. draw_count = 0
  83. theta = 0
  84. frame_count = 0
  85.  
  86. time0 = pygame.time.get_ticks() / 1000.0
  87. while not done:
  88.     time1 = pygame.time.get_ticks() / 1000.0
  89.     time_elapsed = time1 - time0
  90.  
  91.     for event in pygame.event.get():
  92.         if event.type == pygame.constants.WINDOWCLOSE:
  93.             done = True
  94.         if event.type == pygame.constants.KEYDOWN:
  95.             keys_pressed[event.key] = True
  96.         if event.type == pygame.constants.KEYUP:
  97.             keys_pressed[event.key] = False
  98.  
  99.     # check for ESCAPE key
  100.     if keys_pressed[pygame.constants.K_ESCAPE]:
  101.         done = True
  102.  
  103.     # handle user input for left/right
  104.     dx = 0
  105.     if keys_pressed[pygame.constants.K_a]:
  106.         dx -= 1
  107.     if keys_pressed[pygame.constants.K_d]:
  108.         dx += 1
  109.     sprite_x += dx
  110.  
  111.     dy = 0
  112.     if keys_pressed[pygame.constants.K_w]:
  113.         dy -= 1
  114.     if keys_pressed[pygame.constants.K_s]:
  115.         dy += 1
  116.     sprite_y += dy
  117.  
  118.     screen.fill((25, 25, 25))
  119.  
  120.     # Calculate the location of the sphere
  121.     C = Cx, Cy = width/3, height/3
  122.     R = width/6
  123.  
  124.     # Calculate the origin and direction of the ray
  125.     A = Ax, Ay = 0.75 * width, 0.75 * height
  126.     B = Bx, By = math.cos(time1/5), math.sin(time1/5)
  127.  
  128.     t = 1000 # * (time1 - int(time1))
  129.     # Point on a ray (or point at parameter t): P(t) = A + t*B
  130.     start_pos = (Ax, Ay)
  131.     end_pos = (Ax + t * Bx, Ay + t * By)
  132.     color = (0, 0, 255)
  133.     draw_line(screen, color, start_pos, end_pos)
  134.  
  135.     # Calculate intersection (if any)
  136.     t = hit_sphere(C, R, A, B)
  137.     if t < 0:
  138.         color = (255, 0, 0)
  139.     else:
  140.         color = (0, 128, 0)
  141.  
  142.     start_pos = (Cx - R, Cy - R)
  143.     end_pos   = (Cx + R, Cy + R)
  144.     draw_circle(screen, color, start_pos, end_pos)
  145.  
  146.     # draw the intersection point
  147.  
  148.     if t >= 0:
  149.         Px = Ax + t * Bx
  150.         Py = Ay + t * By
  151.         start_pos = (Ax, Ay)
  152.         end_pos   = (Px, Py)
  153.         color     = (255, 0, 255)
  154.         draw_line(screen, color, start_pos, end_pos)
  155.         start_pos = (Px-10, Py-10)
  156.         end_pos   = (Px+10, Py+10)
  157.         draw_circle(screen, color, start_pos, end_pos)
  158.  
  159.     pygame.display.update()
  160.  
  161.     theta += time_elapsed / 180
  162.     frame_count += 1
  163.  
RAW Paste Data