 # 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*B + A*B
20.
21. def hit_sphere(center, radius, r_origin, r_direction):
22.     oc = r_origin - center, r_origin - center
23.     a = dot(r_direction, r_direction)
24.     b = 2.0 * dot(oc, r_direction)
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 - start_pos)
45.     height = abs(end_pos - start_pos)
46.
47.     rx = width / 2
48.     ry = height / 2
49.
50.     x1 = start_pos + rx
51.     y1 = start_pos + 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