-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvector.py
203 lines (157 loc) · 6.83 KB
/
vector.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#!/usr/bin/env python
""" Pre-code for INF-1400
21 January 2019 Revision 4 (Joakim Alslie):
Deleted Vector2D and replaced it with pygames own Vector2-class. Applied
changes to intersect_circles and intersect_rectangle_circle to be custom for
Vector2. Applied changes to example_code avoid type-errors.
16 January 2017 Revision 3 (Mads Johansen):
Rewritten to conform to Python 3 standard. Made class iterable, added property
as_point, replaced magnitude with __abs__ (to reflect mathematical vector
notation), added rotate method.
22 January 2012 Revision 2 (Martin Ernstsen):
Reraise exception after showing error message.
11 February 2011 Revision 1 (Martin Ernstsen):
Fixed bug in intersect_circle. Updated docstrings to Python standard.
Improved __mul__. Added some exception handling. Put example code in separate
function.
"""
from pygame import Vector2
from math import hypot
import pygame
def copy_Vector2(input_vector):
new_vector = Vector2(0,0)
new_vector.x = input_vector.x
new_vector.y = input_vector.y
return new_vector
def intersect_rectangle_circle(rec_pos, sx, sy,
circle_pos, circle_radius, circle_speed):
""" Determine if a rectangle and a circle intersects.
Only works for a rectangle aligned with the axes.
Parameters:
rec_pos - A Vector2 representing the position of the rectangles upper,
left corner.
sx - Width of rectangle.
sy - Height of rectangle.
circle_pos - A Vector2 representing the circle's position.
circle_radius - The circle's radius.
circle_speed - A Vector2 representing the circles speed.
Returns:
False, None if no intersection. If the rectangle and the circle intersect,
returns True, normalized Vector2 pointing in the direction the circle will
move after the collision.
"""
# Position of the walls relative to the ball
top = (rec_pos.y) - circle_pos.y
bottom = (rec_pos.y + sy) - circle_pos.y
left = (rec_pos.x) - circle_pos.x
right = (rec_pos.x + sx) - circle_pos.x
r = circle_radius
intersecting = left <= r and top <= r and right >= -r and bottom >= -r
if intersecting:
# Now need to figure out the vector to return.
impulse = circle_speed.normalize()
if abs(left) <= r and impulse.x > 0:
impulse.x = -impulse.x
if abs(right) <= r and impulse.x < 0:
impulse.x = -impulse.x
if abs(top) <= r and impulse.y > 0:
impulse.y = -impulse.y
if abs(bottom) <= r and impulse.y < 0:
impulse.y = -impulse.y
return True, impulse.normalize()
return False, None
def intersect_circles(circle_a_position, circle_a_radius,
circle_b_position, circle_b_radius):
""" Determine if two circles intersect
Parameters:
circle_a_position - A Vector2D representing circle A's position
circle_a_radius - Circle A's radius
circle_b_position - A Vector2D representing circle B's position
circle_b_radius - Circle B's radius
Returns:
False, None if no intersection.
If the circles intersect, returns True, normalized
Vector2 pointing from circle A to circle B.
"""
# vector from A to B
dp1p2 = circle_b_position - circle_a_position
if circle_a_radius + circle_b_radius >= abs(dp1p2.x + dp1p2.y):
return True, dp1p2.normalize()
else:
return False, None
def example_code():
""" Example showing the use of the above code. """
screen_res = (640, 480)
pygame.init()
rectangle_a_position = Vector2(320, 320)
rectangle_a_size_x = rectangle_a_size_y = 20
rectangle_b_position = Vector2(250, 250)
rectangle_b_size_x = rectangle_b_size_y = 10
circle_a_position = Vector2(10, 10)
circle_a_radius = 6
circle_a_speed = Vector2(5, 5)
circle_b_position = Vector2(150, 150)
circle_b_radius = 10
screen = pygame.display.set_mode(screen_res)
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
pygame.draw.rect(screen, (0, 0, 0), ((0, 0), screen_res))
clock.tick(30)
x, y = pygame.mouse.get_pos()
circle_a_position = Vector2(x, y)
pygame.draw.rect(screen, (255, 255, 255),
(rectangle_a_position.x,
rectangle_a_position.y,
rectangle_a_size_x,
rectangle_a_size_y))
pygame.draw.rect(screen, (255, 255, 255),
(rectangle_b_position.x,
rectangle_b_position.y,
rectangle_b_size_x,
rectangle_b_size_y))
pygame.draw.circle(screen, (255, 255, 255),
(int(circle_b_position.x),
int(circle_b_position.y)),
circle_b_radius)
pygame.draw.circle(screen, (255, 0, 0),
(int(circle_a_position.x),
int(circle_a_position.y)),
circle_a_radius)
def draw_vec_from_ball(vec, col):
""" Draw a vector from the mouse controlled circle. """
pygame.draw.line(screen, col,
(circle_a_position.x, circle_a_position.y),
(circle_a_position.x + vec.x * 20,
circle_a_position.y + vec.y * 20), 3)
draw_vec_from_ball(circle_a_speed, (255, 255, 0))
impact, impulse = intersect_rectangle_circle(rectangle_a_position,
rectangle_a_size_x,
rectangle_a_size_y,
circle_a_position,
circle_a_radius,
circle_a_speed)
if impact:
draw_vec_from_ball(impulse, (0, 255, 255))
impact, impulse = intersect_rectangle_circle(rectangle_b_position,
rectangle_b_size_x,
rectangle_b_size_y,
circle_a_position,
circle_a_radius,
circle_a_speed)
if impact:
draw_vec_from_ball(impulse, (0, 255, 255))
impact, impulse = intersect_circles(circle_a_position, circle_a_radius,
circle_b_position, circle_b_radius)
if impact:
draw_vec_from_ball(impulse, (0, 255, 255))
pygame.display.update()
def example2():
V1 = Vector2(300, 300)
V2 = Vector2(100, 100)
V3 = V1 + V2
print(V3)
if __name__ == '__main__':
example_code()