Advertisement
microwerx

Ray-Circle Intersection

Jul 31st, 2021
1,296
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.14 KB | None | 0 0
  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.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement