e2D 1.4.13__tar.gz → 1.4.14__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {e2d-1.4.13 → e2d-1.4.14}/PKG-INFO +1 -1
- {e2d-1.4.13 → e2d-1.4.14}/e2D/__init__.py +35 -41
- {e2d-1.4.13 → e2d-1.4.14}/e2D/__init__.pyi +32 -32
- {e2d-1.4.13 → e2d-1.4.14}/e2D/envs.py +1 -1
- {e2d-1.4.13 → e2d-1.4.14}/e2D/plots.py +3 -3
- {e2d-1.4.13 → e2d-1.4.14}/e2D/utils.py +7 -3
- {e2d-1.4.13 → e2d-1.4.14}/e2D/winrec.py +1 -1
- {e2d-1.4.13 → e2d-1.4.14}/e2D.egg-info/PKG-INFO +1 -1
- {e2d-1.4.13 → e2d-1.4.14}/e2D.egg-info/SOURCES.txt +0 -1
- {e2d-1.4.13 → e2d-1.4.14}/pyproject.toml +6 -6
- {e2d-1.4.13 → e2d-1.4.14}/setup.cfg +1 -1
- e2d-1.4.13/e2D/cvb.py +0 -831
- {e2d-1.4.13 → e2d-1.4.14}/LICENSE +0 -0
- {e2d-1.4.13 → e2d-1.4.14}/README.md +0 -0
- {e2d-1.4.13 → e2d-1.4.14}/e2D.egg-info/dependency_links.txt +0 -0
- {e2d-1.4.13 → e2d-1.4.14}/e2D.egg-info/requires.txt +0 -0
- {e2d-1.4.13 → e2d-1.4.14}/e2D.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: e2D
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.14
|
|
4
4
|
Summary: Python library for 2D games. Streamlines dev with keyboard/mouse input, vector calculations, color manipulation, and collision detection. Simplify game creation and unleash creativity!
|
|
5
5
|
Home-page: https://github.com/marick-py/e2D
|
|
6
6
|
Author: Riccardo Mariani
|
|
@@ -17,9 +17,9 @@ class Vector2D:
|
|
|
17
17
|
self.x = x
|
|
18
18
|
self.y = y
|
|
19
19
|
|
|
20
|
-
def distance_to(self, other,
|
|
20
|
+
def distance_to(self, other, rooted=True) -> int|float:
|
|
21
21
|
d = (self.x - other.x)**2 + (self.y - other.y)**2
|
|
22
|
-
return
|
|
22
|
+
return d**(1/2) if rooted else d
|
|
23
23
|
|
|
24
24
|
def angle_to(self, other) -> int|float:
|
|
25
25
|
return _mt.atan2(other.y - self.y, other.x - self.x)
|
|
@@ -32,8 +32,8 @@ class Vector2D:
|
|
|
32
32
|
return _mt.atan2(self.y, self.x)
|
|
33
33
|
|
|
34
34
|
@angle.setter
|
|
35
|
-
def angle(self,
|
|
36
|
-
|
|
35
|
+
def angle(self, new_angle) -> None:
|
|
36
|
+
self.rotate(new_angle - self.angle)
|
|
37
37
|
|
|
38
38
|
@property
|
|
39
39
|
def copy(self) -> "Vector2D":
|
|
@@ -42,13 +42,13 @@ class Vector2D:
|
|
|
42
42
|
@property
|
|
43
43
|
def sign(self) -> "Vector2D":
|
|
44
44
|
return Vector2D(sign(self.x), sign(self.y))
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
@property
|
|
47
47
|
def normalize(self) -> "Vector2D":
|
|
48
48
|
if (mag:=self.length) == 0:
|
|
49
49
|
return self.copy
|
|
50
50
|
return Vector2D(self.x / mag, self.y / mag)
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
@property
|
|
53
53
|
def length(self) -> float:
|
|
54
54
|
return (self.x ** 2 + self.y ** 2) ** .5
|
|
@@ -93,16 +93,12 @@ class Vector2D:
|
|
|
93
93
|
def reflection(self, normal) -> "Vector2D":
|
|
94
94
|
return self - self.projection(normal) * 2
|
|
95
95
|
|
|
96
|
-
def cartesian_to_polar(self) -> tuple:
|
|
97
|
-
|
|
98
|
-
theta = _mt.atan2(self.y, self.x)
|
|
99
|
-
return r, theta
|
|
96
|
+
def cartesian_to_polar(self) -> tuple[float, float]:
|
|
97
|
+
return self.length, _mt.atan2(self.y, self.x)
|
|
100
98
|
|
|
101
99
|
@classmethod
|
|
102
100
|
def polar_to_cartesian(cls, r, theta) -> "Vector2D":
|
|
103
|
-
|
|
104
|
-
y = r * _mt.sin(theta)
|
|
105
|
-
return cls(x, y)
|
|
101
|
+
return cls(r * _mt.cos(theta), r * _mt.sin(theta))
|
|
106
102
|
|
|
107
103
|
def cartesian_to_complex(self) -> complex:
|
|
108
104
|
return self.x + self.y * 1j
|
|
@@ -112,19 +108,17 @@ class Vector2D:
|
|
|
112
108
|
return cls(complex_n.real, complex_n.imag)
|
|
113
109
|
|
|
114
110
|
def lerp(self, other, t=.1) -> "Vector2D":
|
|
115
|
-
other = Vector2D.__normalize__(other)
|
|
116
|
-
if not 0 <= t <= 1:
|
|
117
|
-
raise ValueError("t must be between 0 and 1 for linear interpolation.")
|
|
118
111
|
return Vector2D(self.x + (other.x - self.x) * t, self.y + (other.y - self.y) * t)
|
|
119
112
|
|
|
120
|
-
def rotate(self, angle, center=None) ->
|
|
121
|
-
if center
|
|
113
|
+
def rotate(self, angle, center=None) -> None:
|
|
114
|
+
if center == None: center = Vector2D.zero()
|
|
122
115
|
translated = self - center
|
|
123
116
|
cos_angle = _mt.cos(angle)
|
|
124
117
|
sin_angle = _mt.sin(angle)
|
|
125
|
-
|
|
118
|
+
self.x = translated.x * cos_angle - translated.y * sin_angle + center.x
|
|
119
|
+
self.y = translated.x * sin_angle + translated.y * cos_angle + center.y
|
|
126
120
|
|
|
127
|
-
def no_zero_div_error(self, n, error_mode="zero") -> "Vector2D":
|
|
121
|
+
def no_zero_div_error(self, n, error_mode=Literal["zero", "null", "nan"]) -> "Vector2D":
|
|
128
122
|
if isinstance(n, (int, float)):
|
|
129
123
|
if n == 0:
|
|
130
124
|
return Vector2D(0 if error_mode == "zero" else (self.x if error_mode == "null" else _mt.nan), 0 if error_mode == "zero" else (self.y if error_mode == "null" else _mt.nan))
|
|
@@ -171,20 +165,20 @@ class Vector2D:
|
|
|
171
165
|
def sub(self, both=.0, x=.0, y=.0) -> Vector2D:
|
|
172
166
|
return Vector2D(self.x - (x + both), self.y - (y + both))
|
|
173
167
|
|
|
174
|
-
def mult(self, both
|
|
175
|
-
return Vector2D(self.x *
|
|
168
|
+
def mult(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
169
|
+
return Vector2D(self.x * x * both, self.y * y * both)
|
|
176
170
|
|
|
177
|
-
def pow(self, both
|
|
171
|
+
def pow(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
178
172
|
return Vector2D(self.x ** (x + both), self.y ** (y + both))
|
|
179
173
|
|
|
180
|
-
def mod(self, both
|
|
174
|
+
def mod(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
181
175
|
return Vector2D(self.x % (x + both), self.y % (y + both))
|
|
182
176
|
|
|
183
|
-
def div(self, both
|
|
184
|
-
return Vector2D(self.x /
|
|
177
|
+
def div(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
178
|
+
return Vector2D(self.x / x / both, self.y / y / both)
|
|
185
179
|
|
|
186
|
-
def fdiv(self, both
|
|
187
|
-
return Vector2D(self.x //
|
|
180
|
+
def fdiv(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
181
|
+
return Vector2D(self.x // x // both, self.y // y // both)
|
|
188
182
|
|
|
189
183
|
# fast inplace operations Vector2D.ioperation(both,x,y)
|
|
190
184
|
def set(self, both=.0, x=.0, y=.0) -> Vector2D:
|
|
@@ -202,29 +196,29 @@ class Vector2D:
|
|
|
202
196
|
self.y -= y + both
|
|
203
197
|
return self
|
|
204
198
|
|
|
205
|
-
def imult(self, both
|
|
206
|
-
self.x *= x
|
|
207
|
-
self.y *= y
|
|
199
|
+
def imult(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
200
|
+
self.x *= x * both
|
|
201
|
+
self.y *= y * both
|
|
208
202
|
return self
|
|
209
203
|
|
|
210
|
-
def ipow(self, both
|
|
204
|
+
def ipow(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
211
205
|
self.x **= x + both
|
|
212
206
|
self.y **= y + both
|
|
213
207
|
return self
|
|
214
208
|
|
|
215
|
-
def imod(self, both
|
|
209
|
+
def imod(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
216
210
|
self.x %= x + both
|
|
217
211
|
self.y %= y + both
|
|
218
212
|
return self
|
|
219
213
|
|
|
220
|
-
def idiv(self, both
|
|
221
|
-
self.x /= x
|
|
222
|
-
self.y /= y
|
|
214
|
+
def idiv(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
215
|
+
self.x /= x * both
|
|
216
|
+
self.y /= y * both
|
|
223
217
|
return self
|
|
224
218
|
|
|
225
|
-
def ifdiv(self, both
|
|
226
|
-
self.x //= x
|
|
227
|
-
self.y //= y
|
|
219
|
+
def ifdiv(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
220
|
+
self.x //= x * both
|
|
221
|
+
self.y //= y * both
|
|
228
222
|
return self
|
|
229
223
|
|
|
230
224
|
# normal operations Vector2D + a
|
|
@@ -518,9 +512,9 @@ def weighted_color_fade(colors_dict:dict) -> tuple[float, float, float]:
|
|
|
518
512
|
if float("inf") in weights: return list(colors)[list(weights).index(float("inf"))]
|
|
519
513
|
return tuple(sum(n[i]*w for n,w in zip(colors, weights)) / sum(weights) for i in range(3)) #type: ignore
|
|
520
514
|
|
|
521
|
-
def color_distance(starting_c:list|tuple, final_c:list|tuple,
|
|
515
|
+
def color_distance(starting_c:list|tuple, final_c:list|tuple, rooted) -> float:
|
|
522
516
|
distance = sum([(starting_c[i]-final_c[i])**2 for i in range(3)])
|
|
523
|
-
return (distance ** .5) if
|
|
517
|
+
return (distance ** .5) if rooted else distance
|
|
524
518
|
|
|
525
519
|
def lerp(starting, ending, step=.1) -> float:
|
|
526
520
|
return starting + (ending - starting) * step
|
|
@@ -39,31 +39,31 @@ class Vector2D:
|
|
|
39
39
|
self.x : int|float
|
|
40
40
|
self.y : int|float
|
|
41
41
|
|
|
42
|
-
def distance_to(self:"Vector2D", other:"Vector2D",
|
|
42
|
+
def distance_to(self:"Vector2D", other:"Vector2D", rooted:bool=True) -> int|float:
|
|
43
43
|
"""
|
|
44
44
|
# Calculate the distance between the current Vector2D other and another other.
|
|
45
45
|
|
|
46
46
|
## Parameters:
|
|
47
47
|
other (float or int or Vector2D or list|tuple): The other other to which the distance is calculated.
|
|
48
|
-
|
|
48
|
+
rooted (bool, optional): If True, return the normal distance. If False, return the square distance.
|
|
49
49
|
Default is True.
|
|
50
50
|
|
|
51
51
|
## Returns:
|
|
52
|
-
int|float: The
|
|
53
|
-
otherwise the
|
|
52
|
+
int|float: The distance between the current Vector2D other and the other other if `rooted` is True,
|
|
53
|
+
otherwise the squared distance.
|
|
54
54
|
|
|
55
55
|
## Example:
|
|
56
56
|
point1 = Vector2D(0, 0)
|
|
57
57
|
|
|
58
58
|
point2 = Vector2D(3, 4)
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
normal_distance = point1.distance_to(point2)
|
|
61
61
|
|
|
62
|
-
print(f"
|
|
62
|
+
print(f"Normal Distance: {normal_distance}")
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
squared_distance = point1.distance_to(point2, rooted=False)
|
|
65
65
|
|
|
66
|
-
print(f"
|
|
66
|
+
print(f"Squared Distance: {distance}")
|
|
67
67
|
|
|
68
68
|
This will calculate the squared and actual distances between the two points.
|
|
69
69
|
|
|
@@ -71,7 +71,7 @@ class Vector2D:
|
|
|
71
71
|
The function calculates the squared distance between the current Vector2D other (self) and another other
|
|
72
72
|
(other) using the formula: (self.x - other.x)**2 + (self.y - other.y)**2.
|
|
73
73
|
|
|
74
|
-
The result is returned as the squared distance if `
|
|
74
|
+
The result is returned as the squared distance if `rooted` is False, or as the actual distance if `rooted` is True.
|
|
75
75
|
"""
|
|
76
76
|
...
|
|
77
77
|
|
|
@@ -391,7 +391,7 @@ class Vector2D:
|
|
|
391
391
|
"""
|
|
392
392
|
...
|
|
393
393
|
|
|
394
|
-
def cartesian_to_polar(self:"Vector2D") -> tuple:
|
|
394
|
+
def cartesian_to_polar(self:"Vector2D") -> tuple[float, float]:
|
|
395
395
|
"""
|
|
396
396
|
# Convert Cartesian Coordinates to Polar Coordinates
|
|
397
397
|
|
|
@@ -483,7 +483,7 @@ class Vector2D:
|
|
|
483
483
|
"""
|
|
484
484
|
...
|
|
485
485
|
|
|
486
|
-
def rotate(self:"Vector2D", angle: int|float, center:"Vector2D|None"=None) ->
|
|
486
|
+
def rotate(self:"Vector2D", angle: int|float, center:"Vector2D|None"=None) -> None:
|
|
487
487
|
"""
|
|
488
488
|
# Rotate the vector by a given angle around the origin or a specified center.
|
|
489
489
|
|
|
@@ -493,7 +493,7 @@ class Vector2D:
|
|
|
493
493
|
If None, the vector is rotated around the origin (0, 0).
|
|
494
494
|
|
|
495
495
|
## Returns:
|
|
496
|
-
|
|
496
|
+
None
|
|
497
497
|
|
|
498
498
|
## Example:
|
|
499
499
|
v = Vector2D(3, 4)
|
|
@@ -581,32 +581,32 @@ class Vector2D:
|
|
|
581
581
|
|
|
582
582
|
def sub(self, both:int|float=.0, x:int|float=.0, y:int|float=.0) -> Vector2D: ...
|
|
583
583
|
|
|
584
|
-
def mult(self, both:int|float
|
|
584
|
+
def mult(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
585
585
|
|
|
586
|
-
def pow(self, both:int|float
|
|
586
|
+
def pow(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
587
587
|
|
|
588
|
-
def mod(self, both:int|float
|
|
588
|
+
def mod(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
589
589
|
|
|
590
|
-
def div(self, both:int|float
|
|
590
|
+
def div(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
591
591
|
|
|
592
|
-
def fdiv(self, both:int|float
|
|
592
|
+
def fdiv(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
593
593
|
|
|
594
594
|
# fast inplace operations Vector2D.ioperation(both,x,y)
|
|
595
|
-
def set(self, both
|
|
595
|
+
def set(self, both:int|float=.0, x:int|float=.0, y:int|float=.0) -> Vector2D: ...
|
|
596
596
|
|
|
597
|
-
def iadd(self, both:int|float, x:int|float, y
|
|
597
|
+
def iadd(self, both:int|float=.0, x:int|float=.0, y:int|float=.0) -> Vector2D: ...
|
|
598
598
|
|
|
599
|
-
def isub(self, both:int|float, x:int|float, y
|
|
599
|
+
def isub(self, both:int|float=.0, x:int|float=.0, y:int|float=.0) -> Vector2D: ...
|
|
600
600
|
|
|
601
|
-
def imult(self, both:int|float, x:int|float, y
|
|
601
|
+
def imult(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
602
602
|
|
|
603
|
-
def ipow(self, both:int|float, x:int|float, y
|
|
603
|
+
def ipow(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
604
604
|
|
|
605
|
-
def imod(self, both:int|float, x:int|float, y
|
|
605
|
+
def imod(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
606
606
|
|
|
607
|
-
def idiv(self, both:int|float, x:int|float, y
|
|
607
|
+
def idiv(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
608
608
|
|
|
609
|
-
def ifdiv(self, both:int|float, x:int|float, y
|
|
609
|
+
def ifdiv(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
610
610
|
|
|
611
611
|
# normal operations Vector2D + a
|
|
612
612
|
def __add__(self:"Vector2D", other:"int|float|Vector2D|list|tuple") -> "Vector2D": ...
|
|
@@ -889,18 +889,18 @@ def weighted_color_fade(colors_dict:dict) -> tuple[float, float, float]:
|
|
|
889
889
|
"""
|
|
890
890
|
...
|
|
891
891
|
|
|
892
|
-
def color_distance(starting_c: list|tuple, final_c: list|tuple,
|
|
892
|
+
def color_distance(starting_c: list|tuple, final_c: list|tuple, rooted:bool=True) -> float:
|
|
893
893
|
"""
|
|
894
894
|
# Calculate the distance between two colors in RGB space.
|
|
895
895
|
|
|
896
896
|
## Parameters:
|
|
897
897
|
starting_c (list or tuple): The RGB values of the starting color.
|
|
898
898
|
final_c (list or tuple): The RGB values of the final color.
|
|
899
|
-
|
|
899
|
+
rooted (bool, optional): If True, return the rooted distance. If False, return
|
|
900
900
|
the actual distance. Default is True.
|
|
901
901
|
|
|
902
902
|
## Returns:
|
|
903
|
-
float: The squared distance between the two colors if `
|
|
903
|
+
float: The squared distance between the two colors if `rooted` is False, otherwise
|
|
904
904
|
the actual distance.
|
|
905
905
|
|
|
906
906
|
## Example:
|
|
@@ -912,7 +912,7 @@ def color_distance(starting_c: list|tuple, final_c: list|tuple, sqrd:bool=True)
|
|
|
912
912
|
|
|
913
913
|
print(f"Squared Distance: {squared_distance}")
|
|
914
914
|
|
|
915
|
-
distance = color_distance(starting_c, final_c,
|
|
915
|
+
distance = color_distance(starting_c, final_c, rooted=True)
|
|
916
916
|
|
|
917
917
|
print(f"Actual Distance: {distance}")
|
|
918
918
|
|
|
@@ -924,9 +924,9 @@ def color_distance(starting_c: list|tuple, final_c: list|tuple, sqrd:bool=True)
|
|
|
924
924
|
components for each color. The squared distance is obtained by taking the square
|
|
925
925
|
root of this sum.
|
|
926
926
|
|
|
927
|
-
The `
|
|
928
|
-
distance or the actual distance. If `
|
|
929
|
-
|
|
927
|
+
The `rooted` parameter allows the user to choose between returning the squared
|
|
928
|
+
distance or the actual distance. If `rooted` is True, the function returns the
|
|
929
|
+
actual distance, and if `rooted` is False, it returns the squared distance.
|
|
930
930
|
"""
|
|
931
931
|
...
|
|
932
932
|
|
|
@@ -127,8 +127,8 @@ class MathFunction(Function):
|
|
|
127
127
|
id:int|str,
|
|
128
128
|
function:Callable[[int|float, int|float], int|float],
|
|
129
129
|
domain:list[float]=[-np.inf, np.inf],
|
|
130
|
-
codomain:list[float]=[-np.inf, np.inf],
|
|
131
|
-
:list[float]|tuple[float,float,float]=(255,255,255)) -> None:
|
|
130
|
+
codomain:list[float]=[-np.inf, np.inf],
|
|
131
|
+
color:list[float]|tuple[float,float,float]=(255,255,255)) -> None:
|
|
132
132
|
super().__init__()
|
|
133
133
|
self.id = id
|
|
134
134
|
self.color = color
|
|
@@ -398,7 +398,7 @@ class Plot:
|
|
|
398
398
|
self.focus_using_corners(top_left_plot_coord, bottom_right_plot_coord)
|
|
399
399
|
|
|
400
400
|
def set_borders_by_position_and_zoom(self) -> None:
|
|
401
|
-
self.top_left_plot_coord = self.current_offset - 2**(
|
|
401
|
+
self.top_left_plot_coord = self.current_offset - 2**(self.current_zoom.mult(-.1)) * self.__y_axis_multiplier__
|
|
402
402
|
self.bottom_right_plot_coord = self.current_offset + 2**(-.1*self.current_zoom) * self.__y_axis_multiplier__
|
|
403
403
|
self.top_left_x, self.top_left_y = self.top_left_plot_coord
|
|
404
404
|
self.bottom_right_x, self.bottom_right_y = self.bottom_right_plot_coord
|
|
@@ -3,6 +3,8 @@ from typing import Any, Callable, Literal
|
|
|
3
3
|
import pygame as pg
|
|
4
4
|
from e2D import *
|
|
5
5
|
|
|
6
|
+
import math as _mt
|
|
7
|
+
|
|
6
8
|
pg.font.init()
|
|
7
9
|
|
|
8
10
|
__KEY_MODE_TYPES_DICT__ = dict(zip(["pressed", "just_pressed", "just_released"], range(3)))
|
|
@@ -95,6 +97,7 @@ class Util:
|
|
|
95
97
|
self.rootEnv = None
|
|
96
98
|
self.surface : pg.Surface
|
|
97
99
|
self.id : int|str
|
|
100
|
+
self.is_hovered :bool= False
|
|
98
101
|
def draw(self) -> None: pass
|
|
99
102
|
def update(self) -> None: pass
|
|
100
103
|
|
|
@@ -153,14 +156,15 @@ class InputCell(Util):
|
|
|
153
156
|
if self.border_width:
|
|
154
157
|
pg.draw.rect(self.text_surface, self.border_color, self.margin_rect, self.border_width, -1, *self.border_radius)
|
|
155
158
|
else:
|
|
156
|
-
pg.draw.rect(self.text_surface, [127 + 127 * _mt.sin(self.rootEnv.
|
|
159
|
+
pg.draw.rect(self.text_surface, [127 + 127 * _mt.sin(self.rootEnv.runtime_seconds * 10)]*3, self.margin_rect, self.border_width if self.border_width else 10, -1, *self.border_radius)
|
|
157
160
|
|
|
158
161
|
self.surface.blit(self.text_surface, self.position())
|
|
159
162
|
|
|
160
163
|
def update(self) -> None:
|
|
164
|
+
self.is_hovered = self.position.x < self.rootEnv.mouse.position.x < self.position.x + self.size.x and\
|
|
165
|
+
self.position.y < self.rootEnv.mouse.position.y < self.position.y + self.size.y
|
|
161
166
|
if self.rootEnv.mouse.get_key(0, "just_pressed"):
|
|
162
|
-
if self.
|
|
163
|
-
self.position.y < self.rootEnv.mouse.position.y < self.position.y + self.size.y:
|
|
167
|
+
if self.is_hovered:
|
|
164
168
|
self.rootEnv.selected_util = self if self.rootEnv.selected_util != self else None
|
|
165
169
|
self.update_text()
|
|
166
170
|
if self.rootEnv.selected_util == self:
|
|
@@ -18,7 +18,7 @@ class WinRec:
|
|
|
18
18
|
return self.rootEnv.current_frame/self.fps
|
|
19
19
|
|
|
20
20
|
def draw(self, draw_on_screen=False) -> None:
|
|
21
|
-
text = f"[cfps:{self.rootEnv.current_frame} || realtime:{round(self.get_rec_seconds(),2)} || apptime:{round(self.rootEnv.
|
|
21
|
+
text = f"[cfps:{self.rootEnv.current_frame} || realtime:{round(self.get_rec_seconds(),2)} || apptime:{round(self.rootEnv.runtime_seconds,2)}]"
|
|
22
22
|
pg.display.set_caption(text)
|
|
23
23
|
if draw_on_screen: self.rootEnv.print(text, self.rootEnv.screen_size, pivot_position='bottom_right')
|
|
24
24
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: e2D
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.14
|
|
4
4
|
Summary: Python library for 2D games. Streamlines dev with keyboard/mouse input, vector calculations, color manipulation, and collision detection. Simplify game creation and unleash creativity!
|
|
5
5
|
Home-page: https://github.com/marick-py/e2D
|
|
6
6
|
Author: Riccardo Mariani
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
[build-system]
|
|
2
|
-
requires = [
|
|
3
|
-
"setuptools>=54",
|
|
4
|
-
"wheel"
|
|
5
|
-
]
|
|
6
|
-
build-backend = "setuptools.build_meta"
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"setuptools>=54",
|
|
4
|
+
"wheel"
|
|
5
|
+
]
|
|
6
|
+
build-backend = "setuptools.build_meta"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[metadata]
|
|
2
2
|
name = e2D
|
|
3
|
-
version = 1.4.
|
|
3
|
+
version = 1.4.14
|
|
4
4
|
author = Riccardo Mariani
|
|
5
5
|
author_email = ricomari2006@gmail.com
|
|
6
6
|
description = Python library for 2D games. Streamlines dev with keyboard/mouse input, vector calculations, color manipulation, and collision detection. Simplify game creation and unleash creativity!
|
e2d-1.4.13/e2D/cvb.py
DELETED
|
@@ -1,831 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
__all__ = ['cV2', 'cVector2D']
|
|
4
|
-
|
|
5
|
-
class Vector2D:
|
|
6
|
-
round_values_on_print :int|float= 2
|
|
7
|
-
def __init__(self:"Vector2D", x:int|float=0.0, y:int|float=0.0) -> None:
|
|
8
|
-
"""
|
|
9
|
-
# Initialize a 2D vector with the specified x and y components.
|
|
10
|
-
|
|
11
|
-
## Parameters:
|
|
12
|
-
x (int | float, optional): The x-component of the vector. Default is 0.
|
|
13
|
-
y (int | float, optional): The y-component of the vector. Default is 0.
|
|
14
|
-
|
|
15
|
-
## Example:
|
|
16
|
-
vector1 = Vector2D() # Creates a vector with x=0 and y=0
|
|
17
|
-
vector2 = Vector2D(3, -2.5) # Creates a vector with x=3 and y=-2.5
|
|
18
|
-
|
|
19
|
-
## Explanation:
|
|
20
|
-
This constructor initializes a 2D vector with the specified x and y components.
|
|
21
|
-
|
|
22
|
-
If no arguments are provided, the default values for x and y are both set to 0.
|
|
23
|
-
|
|
24
|
-
The x and y components can be integers or floating-point numbers.
|
|
25
|
-
|
|
26
|
-
Example usage is shown in the "Example" section above.
|
|
27
|
-
"""
|
|
28
|
-
self.x = x
|
|
29
|
-
self.y = y
|
|
30
|
-
|
|
31
|
-
def set(self:"Vector2D", x:int|float=0, y:int|float=0) -> None:
|
|
32
|
-
"""
|
|
33
|
-
# Change the components of the Vector2D other without creating a new one.
|
|
34
|
-
|
|
35
|
-
## Parameters:
|
|
36
|
-
x (int | float, optional): The new x-component to set. Default is 0.
|
|
37
|
-
y (int | float, optional): The new y-component to set. Default is 0.
|
|
38
|
-
|
|
39
|
-
## Example:
|
|
40
|
-
vector = Vector2D(1, 2)
|
|
41
|
-
vector.set(3, -4)
|
|
42
|
-
print(vector.x, vector.y) # Output: 3, -4
|
|
43
|
-
|
|
44
|
-
## Explanation:
|
|
45
|
-
The method updates the x and y components of the Vector2D other to the specified values.
|
|
46
|
-
|
|
47
|
-
If no arguments are provided, the default values for x and y are both set to 0.
|
|
48
|
-
|
|
49
|
-
The x and y components can be integers or floating-point numbers.
|
|
50
|
-
|
|
51
|
-
The method does not return any value, but it modifies the Vector2D other in place.
|
|
52
|
-
|
|
53
|
-
Example usage is shown in the "Example" section above.
|
|
54
|
-
"""
|
|
55
|
-
self.x = x
|
|
56
|
-
self.y = y
|
|
57
|
-
|
|
58
|
-
def distance_to(self:"Vector2D", other:"float|int|Vector2D|list|tuple", sqrd:bool=True) -> int|float:
|
|
59
|
-
"""
|
|
60
|
-
# Calculate the distance between the current Vector2D other and another other.
|
|
61
|
-
|
|
62
|
-
## Parameters:
|
|
63
|
-
other (float or int or Vector2D or list|tuple): The other other to which the distance is calculated.
|
|
64
|
-
squared (bool, optional): If True, return the squared distance. If False, return the actual distance.
|
|
65
|
-
Default is True.
|
|
66
|
-
|
|
67
|
-
## Returns:
|
|
68
|
-
int|float: The squared distance between the current Vector2D other and the other other if `squared` is True,
|
|
69
|
-
otherwise the actual distance.
|
|
70
|
-
|
|
71
|
-
## Example:
|
|
72
|
-
point1 = Vector2D(0, 0)
|
|
73
|
-
|
|
74
|
-
point2 = Vector2D(3, 4)
|
|
75
|
-
|
|
76
|
-
squared_distance = point1.distance_to(point2)
|
|
77
|
-
|
|
78
|
-
print(f"Squared Distance: {squared_distance}")
|
|
79
|
-
|
|
80
|
-
distance = point1.distance_to(point2, squared=False)
|
|
81
|
-
|
|
82
|
-
print(f"Actual Distance: {distance}")
|
|
83
|
-
|
|
84
|
-
This will calculate the squared and actual distances between the two points.
|
|
85
|
-
|
|
86
|
-
## Explanation:
|
|
87
|
-
The function calculates the squared distance between the current Vector2D other (self) and another other
|
|
88
|
-
(other) using the formula: (self.x - other.x)**2 + (self.y - other.y)**2.
|
|
89
|
-
|
|
90
|
-
The result is returned as the squared distance if `squared` is True, or as the actual distance if `squared` is False.
|
|
91
|
-
"""
|
|
92
|
-
other = self.__normalize__(other)
|
|
93
|
-
d = (self.x - other.x)**2 + (self.y - other.y)**2
|
|
94
|
-
return (d**(1/2) if sqrd else d)
|
|
95
|
-
|
|
96
|
-
def angle_to(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> int|float:
|
|
97
|
-
"""
|
|
98
|
-
# Calculate the angle between the current Vector2D other and another other.
|
|
99
|
-
|
|
100
|
-
## Parameters:
|
|
101
|
-
other (float or int or Vector2D or list|tuple): The other other to which the angle is calculated.
|
|
102
|
-
|
|
103
|
-
## Returns:
|
|
104
|
-
int|float: The angle in radians between the current Vector2D other and the other other.
|
|
105
|
-
|
|
106
|
-
## Example:
|
|
107
|
-
point1 = Vector2D(0, 0)
|
|
108
|
-
|
|
109
|
-
point2 = Vector2D(1, 1)
|
|
110
|
-
|
|
111
|
-
angle = point1.angle_to(point2)
|
|
112
|
-
|
|
113
|
-
print(f"Angle in radians: {angle}")
|
|
114
|
-
|
|
115
|
-
This will calculate the angle in radians between the two points.
|
|
116
|
-
|
|
117
|
-
## Explanation:
|
|
118
|
-
The function calculates the angle in radians between the current Vector2D other (self) and another other
|
|
119
|
-
(other) using the `atan2` function from the `math` module.
|
|
120
|
-
|
|
121
|
-
The result is returned as the angle in radians.
|
|
122
|
-
"""
|
|
123
|
-
other = self.__normalize__(other)
|
|
124
|
-
return _mt.atan2(other.y - self.y, other.x - self.x)
|
|
125
|
-
|
|
126
|
-
def point_from_degs(self:"Vector2D", degs:int|float, radius:int|float) -> "Vector2D":
|
|
127
|
-
"""
|
|
128
|
-
# Calculate a new Vector2D point from the current point based on an angle in degs and a radius.
|
|
129
|
-
|
|
130
|
-
## Parameters:
|
|
131
|
-
rad (int|float): The angle in degs.
|
|
132
|
-
radius (int|float): The distance from the current point.
|
|
133
|
-
|
|
134
|
-
## Returns:
|
|
135
|
-
Vector2D: A new Vector2D point calculated from the current point.
|
|
136
|
-
|
|
137
|
-
## Example:
|
|
138
|
-
point1 = Vector2D(0, 0)
|
|
139
|
-
|
|
140
|
-
angle = 45
|
|
141
|
-
|
|
142
|
-
distance = 5
|
|
143
|
-
|
|
144
|
-
new_point = point1.point_from_degs(angle, distance)
|
|
145
|
-
|
|
146
|
-
print(new_point.x, new_point.y)
|
|
147
|
-
|
|
148
|
-
This will calculate a new point 5 units away from point1 at a 45-degree angle.
|
|
149
|
-
|
|
150
|
-
## Explanation:
|
|
151
|
-
The function calculates a new Vector2D point based on an angle in degs (degs) and a distance (radius)
|
|
152
|
-
from the current Vector2D point.
|
|
153
|
-
|
|
154
|
-
It computes the new x and y coordinates of the point using the trigonometric functions `cos` and `sin`
|
|
155
|
-
to determine the horizontal and vertical components of the new point.
|
|
156
|
-
|
|
157
|
-
The result is returned as a new Vector2D point with the calculated coordinates.
|
|
158
|
-
"""
|
|
159
|
-
x = radius * _mt.cos(_mt.radians(degs)) + self.x
|
|
160
|
-
y = radius * _mt.sin(_mt.radians(degs)) + self.y
|
|
161
|
-
return Vector2D(x, y)
|
|
162
|
-
|
|
163
|
-
def point_from_rads(self:"Vector2D", rad:int|float, radius:int|float) -> "Vector2D":
|
|
164
|
-
"""
|
|
165
|
-
# Calculate a new Vector2D point from the current point based on an angle in radians and a radius.
|
|
166
|
-
|
|
167
|
-
## Parameters:
|
|
168
|
-
rad (int|float): The angle in radians.
|
|
169
|
-
radius (int|float): The distance from the current point.
|
|
170
|
-
|
|
171
|
-
## Returns:
|
|
172
|
-
Vector2D: A new Vector2D point calculated from the current point.
|
|
173
|
-
|
|
174
|
-
## Example:
|
|
175
|
-
point1 = Vector2D(0, 0)
|
|
176
|
-
|
|
177
|
-
angle = 45
|
|
178
|
-
|
|
179
|
-
distance = 5
|
|
180
|
-
|
|
181
|
-
new_point = point1.point_from_degs(_mt.radians(angle), distance)
|
|
182
|
-
|
|
183
|
-
print(new_point.x, new_point.y)
|
|
184
|
-
|
|
185
|
-
This will calculate a new point 5 units away from point1 at a 45-degree angle.
|
|
186
|
-
|
|
187
|
-
## Explanation:
|
|
188
|
-
The function calculates a new Vector2D point based on an angle in radians (rad) and a distance (radius)
|
|
189
|
-
from the current Vector2D point.
|
|
190
|
-
|
|
191
|
-
It computes the new x and y coordinates of the point using the trigonometric functions `cos` and `sin`
|
|
192
|
-
to determine the horizontal and vertical components of the new point.
|
|
193
|
-
|
|
194
|
-
The result is returned as a new Vector2D point with the calculated coordinates.
|
|
195
|
-
"""
|
|
196
|
-
x = radius * _mt.cos(rad) + self.x
|
|
197
|
-
y = radius * _mt.sin(rad) + self.y
|
|
198
|
-
return Vector2D(x, y)
|
|
199
|
-
|
|
200
|
-
def copy(self:"Vector2D") -> "Vector2D":
|
|
201
|
-
"""
|
|
202
|
-
# Create a copy of the current Vector2D other.
|
|
203
|
-
|
|
204
|
-
## Returns:
|
|
205
|
-
Vector2D: A new Vector2D other with the same x and y coordinates as the current other.
|
|
206
|
-
|
|
207
|
-
## Example:
|
|
208
|
-
point1 = Vector2D(1, 2)
|
|
209
|
-
|
|
210
|
-
point2 = point1.copy()
|
|
211
|
-
|
|
212
|
-
print(point2.x, point2.y)
|
|
213
|
-
|
|
214
|
-
This will print the x and y coordinates of the copied Vector2D other (1, 2).
|
|
215
|
-
|
|
216
|
-
## Explanation:
|
|
217
|
-
The function creates a new Vector2D other with the same x and y coordinates as the current other.
|
|
218
|
-
|
|
219
|
-
The result is returned as a new Vector2D other, effectively making a copy of the original other.
|
|
220
|
-
"""
|
|
221
|
-
return Vector2D(self.x, self.y)
|
|
222
|
-
|
|
223
|
-
def sign(self:"Vector2D") -> "Vector2D":
|
|
224
|
-
"""
|
|
225
|
-
# Perform an "absolute round" operation on the Vector2D other.
|
|
226
|
-
|
|
227
|
-
## Parameters:
|
|
228
|
-
n (int|float, optional): The numeric value to scale the "absolute rounded" vector. Default is 1.
|
|
229
|
-
|
|
230
|
-
## Returns:
|
|
231
|
-
Vector2D: The "absolute rounded" Vector2D other scaled by the provided numeric value.
|
|
232
|
-
|
|
233
|
-
## Example:
|
|
234
|
-
vector1 = Vector2D(3.3, -4.7)
|
|
235
|
-
|
|
236
|
-
result1 = vector1.absolute_round(0.5)
|
|
237
|
-
|
|
238
|
-
print(result1.x, result1.y)
|
|
239
|
-
|
|
240
|
-
vector2 = Vector2D(-2.8, 1.1)
|
|
241
|
-
|
|
242
|
-
result2 = vector2.absolute_round()
|
|
243
|
-
|
|
244
|
-
print(result2.x, result2.y)
|
|
245
|
-
|
|
246
|
-
## Explanation:
|
|
247
|
-
The function performs an "absolute round" operation on the Vector2D other.
|
|
248
|
-
|
|
249
|
-
The "absolute round" operation involves taking the absolute values of both the x and y components of the Vector2D other,
|
|
250
|
-
and then scaling the resulting vector by the provided numeric value (n).
|
|
251
|
-
|
|
252
|
-
The default value of n is 1, which means the "absolute rounded" vector will have the same magnitude as the original vector.
|
|
253
|
-
|
|
254
|
-
If the provided numeric value (n) is 0, the function returns a Vector2D other with zeros for both components.
|
|
255
|
-
|
|
256
|
-
If the provided numeric value (n) is negative, the resulting "absolute rounded" vector will point in the opposite direction
|
|
257
|
-
as the original vector but will have the same magnitude.
|
|
258
|
-
|
|
259
|
-
Note: The "absolute round" operation does not perform standard mathematical rounding; instead, it ensures the resulting
|
|
260
|
-
vector points in the same direction as the original vector but has non-negative components.
|
|
261
|
-
"""
|
|
262
|
-
return self.no_zero_div_error(abs(self), "zero")
|
|
263
|
-
|
|
264
|
-
def floor(self:"Vector2D", n:"int|float|Vector2D"=1) -> "Vector2D":
|
|
265
|
-
return self.__floor__(n)
|
|
266
|
-
|
|
267
|
-
def ceil(self:"Vector2D", n:"int|float|Vector2D"=1) -> "Vector2D":
|
|
268
|
-
return self.__ceil__(n)
|
|
269
|
-
|
|
270
|
-
def round(self:"Vector2D", n:"int|float|Vector2D"=1) -> "Vector2D":
|
|
271
|
-
return self.__round__(n)
|
|
272
|
-
|
|
273
|
-
def randomize(start:"int|float|Vector2D|None"=None, end:"int|float|Vector2D|None"=None) -> "Vector2D": #type: ignore
|
|
274
|
-
"""
|
|
275
|
-
# Generate a random Vector2D point within the specified range.
|
|
276
|
-
|
|
277
|
-
## Parameters:
|
|
278
|
-
start (int|float or Vector2D or None, optional): The starting point of the range.
|
|
279
|
-
Default is None, which corresponds to (0, 0).
|
|
280
|
-
If numeric, both x and y will have the same value.
|
|
281
|
-
end (int|float or Vector2D or None, optional): The ending point of the range.
|
|
282
|
-
Default is None, which corresponds to (1, 1).
|
|
283
|
-
If numeric, both x and y will have the same value.
|
|
284
|
-
|
|
285
|
-
## Returns:
|
|
286
|
-
Vector2D: A new random Vector2D point within the specified range.
|
|
287
|
-
|
|
288
|
-
## Example:
|
|
289
|
-
random_point = randomize(Vector2D(10, 20), Vector2D(50, 70))
|
|
290
|
-
|
|
291
|
-
print(random_point.x, random_point.y)
|
|
292
|
-
|
|
293
|
-
This will print a random point between (10, 20) and (50, 70).
|
|
294
|
-
|
|
295
|
-
## Explanation:
|
|
296
|
-
The function generates a random Vector2D point within the specified range defined by `start` and `end`.
|
|
297
|
-
|
|
298
|
-
If `start` and `end` are numeric values (int or float), both x and y coordinates will have the same value.
|
|
299
|
-
|
|
300
|
-
If `start` and `end` are None, the default range is assumed to be (0, 0) to (1, 1).
|
|
301
|
-
|
|
302
|
-
The function first checks if `start` and `end` are Vector2D others. If not, it creates new Vector2D others
|
|
303
|
-
based on the numeric values provided or the default values.
|
|
304
|
-
|
|
305
|
-
It then generates random x and y coordinates in the range [0, 1) using the `random()` function from the `random` module.
|
|
306
|
-
These random values are then scaled by (end - start) and added to the start point to obtain the final random Vector2D point.
|
|
307
|
-
"""
|
|
308
|
-
if not any(isinstance(start, cls) for cls in {Vector2D, V2}):
|
|
309
|
-
if type(start) in int|float: start = Vector2D(start, start) #type: ignore
|
|
310
|
-
elif type(start) == None: start = Vector2D(0,0)
|
|
311
|
-
else: raise Exception(f"\nArg start must be in [Vector2D, int, float, tuple, list] not a [{type(start)}]\n")
|
|
312
|
-
if not any(isinstance(end, cls) for cls in {Vector2D, V2}):
|
|
313
|
-
if type(end) in int|float: end = Vector2D(end, end) #type: ignore
|
|
314
|
-
elif type(end) == None: end = Vector2D(1,1)
|
|
315
|
-
else: raise Exception(f"\nArg end must be in [Vector2D, int, float, tuple, list] not a [{type(end)}]\n")
|
|
316
|
-
return start + Vector2D(_rnd.random(), _rnd.random()) * (end - start) #type: ignore
|
|
317
|
-
|
|
318
|
-
def dot_product(self, other:"float|int|Vector2D|list|tuple") -> float:
|
|
319
|
-
other = self.__normalize__(other)
|
|
320
|
-
"""
|
|
321
|
-
# Calculate the dot product of the current vector with another vector.
|
|
322
|
-
|
|
323
|
-
## Parameters:
|
|
324
|
-
other (Vector2D): The other vector for the dot product calculation.
|
|
325
|
-
|
|
326
|
-
## Returns:
|
|
327
|
-
float: The dot product value.
|
|
328
|
-
|
|
329
|
-
## Example:
|
|
330
|
-
v1 = Vector2D(2, 3)
|
|
331
|
-
v2 = Vector2D(4, -1)
|
|
332
|
-
result = v1.dot_product(v2)
|
|
333
|
-
print(result) # Output: 5
|
|
334
|
-
|
|
335
|
-
## Explanation:
|
|
336
|
-
The dot product of two vectors (A and B) is given by the formula: dot_product = A.x * B.x + A.y * B.y
|
|
337
|
-
|
|
338
|
-
The method takes another vector (other) as input and returns the dot product value.
|
|
339
|
-
|
|
340
|
-
Example usage is shown in the "Example" section above.
|
|
341
|
-
"""
|
|
342
|
-
return self.x * other.x + self.y * other.y
|
|
343
|
-
|
|
344
|
-
def normalize(self) -> "Vector2D":
|
|
345
|
-
"""
|
|
346
|
-
# Vector Normalization
|
|
347
|
-
|
|
348
|
-
## Returns:
|
|
349
|
-
Vector2D: A new vector with the same direction as the current vector but with a magnitude of 1.
|
|
350
|
-
|
|
351
|
-
## Raises:
|
|
352
|
-
ValueError: If the magnitude of the current vector is zero (zero vector).
|
|
353
|
-
|
|
354
|
-
## Example:
|
|
355
|
-
v = Vector2D(3, 4)
|
|
356
|
-
normalized_v = v.normalize() # Normalize the vector (3, 4)
|
|
357
|
-
print(normalized_v) # Output: (0.6, 0.8)
|
|
358
|
-
|
|
359
|
-
## Explanation:
|
|
360
|
-
This method calculates the normalized version of the current vector, which means a new vector with the same direction as the original but with a magnitude of 1.
|
|
361
|
-
|
|
362
|
-
The method first calculates the magnitude of the current vector using the 'magnitude' method.
|
|
363
|
-
|
|
364
|
-
If the magnitude is zero (zero vector), a ValueError is raised, as normalization is not defined for zero vectors.
|
|
365
|
-
|
|
366
|
-
The normalized vector is obtained by dividing each component of the current vector by its magnitude.
|
|
367
|
-
|
|
368
|
-
The resulting normalized vector is returned.
|
|
369
|
-
|
|
370
|
-
Example usage is shown in the "Example" section above.
|
|
371
|
-
"""
|
|
372
|
-
mag = self.length()
|
|
373
|
-
if mag == 0:
|
|
374
|
-
return self
|
|
375
|
-
return Vector2D(self.x / mag, self.y / mag)
|
|
376
|
-
|
|
377
|
-
def projection(self, other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
378
|
-
"""
|
|
379
|
-
# Vector Projection
|
|
380
|
-
|
|
381
|
-
## Parameters:
|
|
382
|
-
other (float, int, Vector2D, V2, list, tuple): The vector onto which to project.
|
|
383
|
-
|
|
384
|
-
## Returns:
|
|
385
|
-
Vector2D or V2: The projection of the current vector onto the 'other' vector.
|
|
386
|
-
|
|
387
|
-
## Raises:
|
|
388
|
-
ValueError: If 'other' is a zero vector.
|
|
389
|
-
|
|
390
|
-
## Example:
|
|
391
|
-
v1 = Vector2D(3, 4)
|
|
392
|
-
v2 = Vector2D(1, 0)
|
|
393
|
-
projection_v = v1.projection(v2) # Calculate the projection of v1 onto v2
|
|
394
|
-
print(projection_v) # Output: (3.0, 0.0)
|
|
395
|
-
|
|
396
|
-
## Explanation:
|
|
397
|
-
This method calculates the projection of the current vector onto the 'other' vector.
|
|
398
|
-
The projection is a vector that represents the component of the current vector in the direction of the 'other' vector.
|
|
399
|
-
|
|
400
|
-
If 'other' is not a Vector2D instance, it will be converted to one using the '__normalize__' method.
|
|
401
|
-
The method first normalizes the 'other' vector using the '__normalize__' method of the vector.
|
|
402
|
-
|
|
403
|
-
Next, it calculates the dot product of the current vector and the normalized 'other' vector using the 'dot_product' method.
|
|
404
|
-
It also calculates the squared magnitude of the 'other' vector using the 'magnitude' method.
|
|
405
|
-
|
|
406
|
-
If the magnitude of 'other' is zero (a zero vector), a ValueError is raised, as projection is not defined for zero vectors.
|
|
407
|
-
|
|
408
|
-
The projection is then obtained by scaling the 'other' vector by the dot product divided by the squared magnitude.
|
|
409
|
-
|
|
410
|
-
The resulting projection vector is returned.
|
|
411
|
-
|
|
412
|
-
Example usage is shown in the "Example" section above.
|
|
413
|
-
"""
|
|
414
|
-
other = self.__normalize__(other)
|
|
415
|
-
dot_product = self.dot_product(other)
|
|
416
|
-
magnitude_product = other.length() ** 2
|
|
417
|
-
if magnitude_product == 0:
|
|
418
|
-
raise ValueError("Cannot calculate projection for zero vectors.")
|
|
419
|
-
return other * (dot_product / magnitude_product)
|
|
420
|
-
|
|
421
|
-
def reflection(self, normal:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
422
|
-
"""
|
|
423
|
-
# Vector Reflection
|
|
424
|
-
|
|
425
|
-
## Parameters:
|
|
426
|
-
normal (float, int, Vector2D, V2, list, tuple): The normal vector representing the surface of reflection.
|
|
427
|
-
|
|
428
|
-
## Returns:
|
|
429
|
-
Vector2D or V2: The reflected vector.
|
|
430
|
-
|
|
431
|
-
## Example:
|
|
432
|
-
incident_vector = Vector2D(3, 4)
|
|
433
|
-
normal_vector = Vector2D(1, 0)
|
|
434
|
-
reflected_vector = incident_vector.reflection(normal_vector) # Calculate the reflection of the incident vector over the given normal
|
|
435
|
-
print(reflected_vector) # Output: (-3.0, 4.0)
|
|
436
|
-
|
|
437
|
-
## Explanation:
|
|
438
|
-
This method calculates the reflection of the current vector over the given normal vector.
|
|
439
|
-
The normal vector represents the surface of reflection, and it should be normalized (unit vector).
|
|
440
|
-
|
|
441
|
-
The method first normalizes the 'normal' vector using the '__normalize__' method of the vector.
|
|
442
|
-
Next, it calculates the projection of the current vector onto the 'normal' vector using the 'projection' method.
|
|
443
|
-
The reflected vector is obtained by subtracting twice the projection from the current vector.
|
|
444
|
-
|
|
445
|
-
The resulting reflected vector is returned.
|
|
446
|
-
|
|
447
|
-
Example usage is shown in the "Example" section above.
|
|
448
|
-
"""
|
|
449
|
-
normal = self.__normalize__(normal)
|
|
450
|
-
projection = self.projection(normal)
|
|
451
|
-
return self - projection * 2
|
|
452
|
-
|
|
453
|
-
def cartesian_to_polar(self) -> tuple:
|
|
454
|
-
"""
|
|
455
|
-
# Convert Cartesian Coordinates to Polar Coordinates
|
|
456
|
-
|
|
457
|
-
## Returns:
|
|
458
|
-
tuple: A tuple containing the radial distance (magnitude) 'r' and the angle 'theta' in radians.
|
|
459
|
-
|
|
460
|
-
## Example:
|
|
461
|
-
v = Vector2D(3, 4)
|
|
462
|
-
r, theta = v.cartesian_to_polar() # Convert Cartesian coordinates (3, 4) to polar
|
|
463
|
-
print(r, theta) # Output: (5.0, 0.9272952180016122)
|
|
464
|
-
|
|
465
|
-
## Explanation:
|
|
466
|
-
This method converts Cartesian coordinates (x, y) to polar coordinates (r, theta).
|
|
467
|
-
'r' is the radial distance (magnitude) from the origin to the point, and 'theta' is the angle
|
|
468
|
-
(in radians) measured from the positive x-axis to the point.
|
|
469
|
-
|
|
470
|
-
The method calculates the radial distance 'r' using the 'magnitude' method of the vector.
|
|
471
|
-
The angle 'theta' is calculated using the arctan2 function, which takes the y and x components of the vector.
|
|
472
|
-
|
|
473
|
-
The resulting 'r' and 'theta' are returned as a tuple.
|
|
474
|
-
|
|
475
|
-
Example usage is shown in the "Example" section above.
|
|
476
|
-
"""
|
|
477
|
-
r = self.length()
|
|
478
|
-
theta = _mt.atan2(self.y, self.x)
|
|
479
|
-
return r, theta
|
|
480
|
-
|
|
481
|
-
@classmethod
|
|
482
|
-
def polar_to_cartesian(cls, r: float|int, theta: float|int) -> "Vector2D":
|
|
483
|
-
"""
|
|
484
|
-
# Convert Polar Coordinates to Cartesian Coordinates
|
|
485
|
-
|
|
486
|
-
## Parameters:
|
|
487
|
-
r (float or int): The radial distance (magnitude) from the origin to the point.
|
|
488
|
-
theta (float or int): The angle (in radians or degrees) measured from the positive x-axis to the point.
|
|
489
|
-
|
|
490
|
-
## Returns:
|
|
491
|
-
Vector2D or V2: A new vector representing the Cartesian coordinates (x, y) of the point.
|
|
492
|
-
|
|
493
|
-
## Example:
|
|
494
|
-
cartesian_point = Vector2D.polar_to_cartesian(5, math.pi/4) # Convert polar coordinates (r=5, theta=45 degrees) to Cartesian
|
|
495
|
-
print(cartesian_point) # Output: (3.5355339059327378, 3.5355339059327373)
|
|
496
|
-
|
|
497
|
-
## Explanation:
|
|
498
|
-
This class method converts polar coordinates (r, theta) to Cartesian coordinates (x, y).
|
|
499
|
-
'r' is the radial distance (magnitude) from the origin to the point, and 'theta' is the angle
|
|
500
|
-
(in radians or degrees) measured from the positive x-axis to the point.
|
|
501
|
-
|
|
502
|
-
The method calculates the x and y components using trigonometric functions (cosine and sine) based on 'r' and 'theta'.
|
|
503
|
-
|
|
504
|
-
Example usage is shown in the "Example" section above.
|
|
505
|
-
"""
|
|
506
|
-
x = r * _mt.cos(theta)
|
|
507
|
-
y = r * _mt.sin(theta)
|
|
508
|
-
return cls(x, y)
|
|
509
|
-
|
|
510
|
-
def cartesian_to_complex(self) -> complex:
|
|
511
|
-
return self.x + self.y * 1j
|
|
512
|
-
|
|
513
|
-
@classmethod
|
|
514
|
-
def complex_to_cartesian(cls, complex_n: complex) -> "Vector2D":
|
|
515
|
-
return cls(complex_n.real, complex_n.imag)
|
|
516
|
-
|
|
517
|
-
def length(self) -> float:
|
|
518
|
-
return (self.x ** 2 + self.y ** 2) ** .5
|
|
519
|
-
|
|
520
|
-
def lerp(self, other:"float|int|Vector2D|list|tuple", t: float) -> "Vector2D":
|
|
521
|
-
"""
|
|
522
|
-
# Linear Interpolation (LERP)
|
|
523
|
-
|
|
524
|
-
## Parameters:
|
|
525
|
-
other (float, int, Vector2D, V2, list, tuple): The vector to interpolate towards.
|
|
526
|
-
t (float): The interpolation parameter. Must be between 0 and 1.
|
|
527
|
-
|
|
528
|
-
## Returns:
|
|
529
|
-
Vector2D or V2: The result of the linear interpolation.
|
|
530
|
-
|
|
531
|
-
## Raises:
|
|
532
|
-
ValueError: If t is not within the range [0, 1].
|
|
533
|
-
|
|
534
|
-
## Example:
|
|
535
|
-
v1 = Vector2D(1, 2)
|
|
536
|
-
v2 = Vector2D(5, 7)
|
|
537
|
-
interpolated_v = v1.lerp(v2, 0.5) # Linearly interpolate between v1 and v2 with t = 0.5
|
|
538
|
-
print(interpolated_v) # Output: (3.0, 4.5)
|
|
539
|
-
|
|
540
|
-
## Explanation:
|
|
541
|
-
This method performs linear interpolation between the current vector and the 'other' vector.
|
|
542
|
-
The 't' parameter represents the interpolation parameter, which controls how much the interpolation
|
|
543
|
-
leans towards the 'other' vector. When 't' is 0, the result will be equal to the current vector (self).
|
|
544
|
-
When 't' is 1, the result will be equal to the 'other' vector. For intermediate values of 't', the
|
|
545
|
-
result will be a linear combination of the two vectors, smoothly transitioning between them.
|
|
546
|
-
|
|
547
|
-
If 'other' is not a Vector2D instance, it will be converted to one using the '__normalize__' method.
|
|
548
|
-
If 't' is not within the range [0, 1], a ValueError is raised.
|
|
549
|
-
|
|
550
|
-
Example usage is shown in the "Example" section above.
|
|
551
|
-
"""
|
|
552
|
-
other = self.__normalize__(other)
|
|
553
|
-
if not 0 <= t <= 1:
|
|
554
|
-
raise ValueError("t must be between 0 and 1 for linear interpolation.")
|
|
555
|
-
return Vector2D(self.x + (other.x - self.x) * t, self.y + (other.y - self.y) * t)
|
|
556
|
-
|
|
557
|
-
def rotate(self, angle: int|float, center:"float|int|Vector2D|list|tuple|None"=None) -> "Vector2D":
|
|
558
|
-
"""
|
|
559
|
-
# Rotate the vector by a given angle around the origin or a specified center.
|
|
560
|
-
|
|
561
|
-
## Parameters:
|
|
562
|
-
angle (int or float): The angle of rotation in radians or degrees, depending on the trigonometric functions used.
|
|
563
|
-
center (float, int, Vector2D, V2, list, tuple, or None): The center of rotation.
|
|
564
|
-
If None, the vector is rotated around the origin (0, 0).
|
|
565
|
-
|
|
566
|
-
## Returns:
|
|
567
|
-
Vector2D or V2: The rotated vector.
|
|
568
|
-
|
|
569
|
-
## Example:
|
|
570
|
-
v = Vector2D(3, 4)
|
|
571
|
-
rotated_v = v.rotate(math.pi / 4) # Rotate 45 degrees around the origin
|
|
572
|
-
print(rotated_v) # Output: (0.7071067811865476, 5.656854249492381)
|
|
573
|
-
|
|
574
|
-
center = Vector2D(1, 1)
|
|
575
|
-
rotated_v = v.rotate(math.pi / 4, center) # Rotate 45 degrees around the center (1, 1)
|
|
576
|
-
print(rotated_v) # Output: (1.7071067811865475, 2.656854249492381)
|
|
577
|
-
|
|
578
|
-
## Explanation:
|
|
579
|
-
This method rotates the vector by the specified angle around the given center.
|
|
580
|
-
If no center is provided, the vector is rotated around the origin (0, 0).
|
|
581
|
-
|
|
582
|
-
The method calculates the trigonometric functions (cosine and sine) of the angle to perform the rotation.
|
|
583
|
-
The translated vector is obtained by subtracting the center from the current vector.
|
|
584
|
-
The rotated vector is then obtained by applying the rotation transformation to the translated vector.
|
|
585
|
-
The center is added back to the rotated vector to obtain the final result.
|
|
586
|
-
|
|
587
|
-
Example usage is shown in the "Example" section above.
|
|
588
|
-
"""
|
|
589
|
-
if center is None: center = V2z
|
|
590
|
-
else: center = self.__normalize__(center)
|
|
591
|
-
translated = self - center
|
|
592
|
-
cos_angle = _mt.cos(angle)
|
|
593
|
-
sin_angle = _mt.sin(angle)
|
|
594
|
-
return Vector2D(translated.x * cos_angle - translated.y * sin_angle, translated.x * sin_angle + translated.y * cos_angle) + center
|
|
595
|
-
|
|
596
|
-
def no_zero_div_error(self:"Vector2D", n:"int|float|Vector2D", error_mode:str="zero") -> "Vector2D":
|
|
597
|
-
"""
|
|
598
|
-
# Handle division between the Vector2D other and a numeric value or another Vector2D other.
|
|
599
|
-
|
|
600
|
-
## Parameters:
|
|
601
|
-
n (int|float or Vector2D): The numeric value or Vector2D other for division.
|
|
602
|
-
error_mode (str, optional): The mode to handle division by zero scenarios.
|
|
603
|
-
- "zero" (default): Return a Vector2D other with zeros for both components.
|
|
604
|
-
- "null": Return a Vector2D other with the original x or y component if available,
|
|
605
|
-
otherwise, return NaN (Not a Number) for the component.
|
|
606
|
-
|
|
607
|
-
## Returns:
|
|
608
|
-
Vector2D: A new Vector2D other after division or handling division by zero scenarios.
|
|
609
|
-
|
|
610
|
-
## Example:
|
|
611
|
-
vector1 = Vector2D(3, 4)
|
|
612
|
-
|
|
613
|
-
result1 = vector1.no_zero_div_error(2)
|
|
614
|
-
|
|
615
|
-
print(result1.x, result1.y)
|
|
616
|
-
|
|
617
|
-
vector2 = Vector2D(5, 0)
|
|
618
|
-
|
|
619
|
-
result2 = vector1.no_zero_div_error(vector2, error_mode="null")
|
|
620
|
-
|
|
621
|
-
print(result2.x, result2.y)
|
|
622
|
-
|
|
623
|
-
## Explanation:
|
|
624
|
-
The function handles division between the Vector2D other and a numeric value or another Vector2D other.
|
|
625
|
-
|
|
626
|
-
If n is a numeric value (int or float):
|
|
627
|
-
- If n is zero, the function returns a Vector2D other with zeros for both components if error_mode is "zero".
|
|
628
|
-
- If error_mode is "null", the function returns a Vector2D other with the original x or y component if available,
|
|
629
|
-
otherwise, return NaN (Not a Number) for the component.
|
|
630
|
-
|
|
631
|
-
If n is a Vector2D other:
|
|
632
|
-
- If n's x or y component is zero, the function returns a Vector2D other with zeros for the corresponding component
|
|
633
|
-
if error_mode is "zero".
|
|
634
|
-
- If error_mode is "null", the function returns a Vector2D other with the original x or y component if available,
|
|
635
|
-
otherwise, return NaN (Not a Number) for the component.
|
|
636
|
-
|
|
637
|
-
If n is neither a numeric value nor a Vector2D other, the function raises an exception.
|
|
638
|
-
"""
|
|
639
|
-
if any(isinstance(n, cls) for cls in {int, float}):
|
|
640
|
-
if n == 0:
|
|
641
|
-
return Vector2D(0 if error_mode == "zero" else (self.x if error_mode == "null" else _mt.nan), 0 if error_mode == "zero" else (self.y if error_mode == "null" else _mt.nan))
|
|
642
|
-
else:
|
|
643
|
-
return self / n
|
|
644
|
-
elif any(isinstance(n, cls) for cls in {Vector2D, V2}):
|
|
645
|
-
return Vector2D((0 if error_mode == "zero" else (self.x if error_mode == "null" else _mt.nan)) if n.x == 0 else self.x / n.x, (0 if error_mode == "zero" else (self.y if error_mode == "null" else _mt.nan)) if n.y == 0 else self.y / n.y) #type: ignore
|
|
646
|
-
else:
|
|
647
|
-
raise Exception(f"\nArg n must be in [Vector2D, int, float, tuple, list] not a [{type(n)}]\n")
|
|
648
|
-
|
|
649
|
-
def min(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
650
|
-
other = self.__normalize__(other)
|
|
651
|
-
return Vector2D(min(self.x, other.x), min(self.y, other.y))
|
|
652
|
-
|
|
653
|
-
def max(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
654
|
-
other = self.__normalize__(other)
|
|
655
|
-
return Vector2D(max(self.x, other.x), max(self.y, other.y))
|
|
656
|
-
|
|
657
|
-
def advanced_stringify(self:"Vector2D", precision:float|None=None, use_scientific_notation:bool=False, return_as_list=False) -> str:
|
|
658
|
-
precision = self.round_values_on_print if precision == None else precision
|
|
659
|
-
def optimize(value) -> str:
|
|
660
|
-
abs_value = abs(value)
|
|
661
|
-
if abs_value < 1/10**precision and abs_value != 0:
|
|
662
|
-
return f"{value:.{precision}e}"
|
|
663
|
-
elif abs_value < 10**precision:
|
|
664
|
-
return f"{value:.{precision}f}".rstrip('0').rstrip('.')
|
|
665
|
-
else:
|
|
666
|
-
return f"{value:.{precision}e}"
|
|
667
|
-
if return_as_list:
|
|
668
|
-
return [optimize(self.x), optimize(self.y)] if use_scientific_notation else [f"{self.x:.{precision}f}", f"{self.y:.{precision}f}"] #type: ignore
|
|
669
|
-
return f"{optimize(self.x)}, {optimize(self.y)}" if use_scientific_notation else f"{self.x:.{precision}f}, {self.y:.{precision}f}"
|
|
670
|
-
|
|
671
|
-
def __str__(self:"Vector2D") -> str:
|
|
672
|
-
return f"{self.x:.{self.round_values_on_print}f}, {self.y:.{self.round_values_on_print}f}"
|
|
673
|
-
|
|
674
|
-
def __repr__(self:"Vector2D") -> str:
|
|
675
|
-
return f"x:{self.x:.{self.round_values_on_print}f}\ty:{self.y:.{self.round_values_on_print}f}"
|
|
676
|
-
|
|
677
|
-
def __call__(self:"Vector2D", return_tuple=False) -> list|tuple:
|
|
678
|
-
return (self.x, self.y) if return_tuple else [self.x, self.y]
|
|
679
|
-
|
|
680
|
-
# normal operations Vector2D + a
|
|
681
|
-
def __add__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
682
|
-
other = self.__normalize__(other)
|
|
683
|
-
return Vector2D(self.x + other.x, self.y + other.y)
|
|
684
|
-
|
|
685
|
-
def __sub__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
686
|
-
other = self.__normalize__(other)
|
|
687
|
-
return Vector2D(self.x - other.x, self.y - other.y)
|
|
688
|
-
|
|
689
|
-
def __mul__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
690
|
-
other = self.__normalize__(other)
|
|
691
|
-
return Vector2D(self.x * other.x, self.y * other.y)
|
|
692
|
-
|
|
693
|
-
def __mod__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
694
|
-
other = self.__normalize__(other)
|
|
695
|
-
return Vector2D(self.x % other.x, self.y % other.y)
|
|
696
|
-
|
|
697
|
-
def __pow__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
698
|
-
other = self.__normalize__(other)
|
|
699
|
-
return Vector2D(self.x ** other.x, self.y ** other.y)
|
|
700
|
-
|
|
701
|
-
def __truediv__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
702
|
-
other = self.__normalize__(other)
|
|
703
|
-
return Vector2D(self.x / other.x, self.y / other.y)
|
|
704
|
-
|
|
705
|
-
def __floordiv__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
706
|
-
other = self.__normalize__(other)
|
|
707
|
-
return Vector2D(self.x // other.x, self.y // other.y)
|
|
708
|
-
|
|
709
|
-
# right operations a + Vector2D
|
|
710
|
-
def __radd__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
711
|
-
return self.__add__(other)
|
|
712
|
-
|
|
713
|
-
def __rsub__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
714
|
-
other = self.__normalize__(other)
|
|
715
|
-
return Vector2D(other.x - self.x, other.y - self.y)
|
|
716
|
-
|
|
717
|
-
def __rmul__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
718
|
-
return self.__mul__(other)
|
|
719
|
-
|
|
720
|
-
def __rmod__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
721
|
-
other = self.__normalize__(other)
|
|
722
|
-
return Vector2D(other.x % self.x, other.y % self.y)
|
|
723
|
-
|
|
724
|
-
def __rpow__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
725
|
-
other = self.__normalize__(other)
|
|
726
|
-
return Vector2D(other.x ** self.x, other.y ** self.y)
|
|
727
|
-
|
|
728
|
-
def __rtruediv__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
729
|
-
other = self.__normalize__(other)
|
|
730
|
-
return Vector2D(other.x / self.x, other.y / self.y)
|
|
731
|
-
|
|
732
|
-
def __rfloordiv__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
733
|
-
other = self.__normalize__(other)
|
|
734
|
-
return Vector2D(other.x // self.x, other.y // self.y)
|
|
735
|
-
|
|
736
|
-
# in-place operations Vector2D += a
|
|
737
|
-
def __iadd__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
738
|
-
other = self.__normalize__(other)
|
|
739
|
-
self.x += other.x
|
|
740
|
-
self.y += other.y
|
|
741
|
-
return self
|
|
742
|
-
|
|
743
|
-
def __isub__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
744
|
-
other = self.__normalize__(other)
|
|
745
|
-
self.x -= other.x
|
|
746
|
-
self.y -= other.y
|
|
747
|
-
return self
|
|
748
|
-
|
|
749
|
-
def __imul__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
750
|
-
other = self.__normalize__(other)
|
|
751
|
-
self.x *= other.x
|
|
752
|
-
self.y *= other.y
|
|
753
|
-
return self
|
|
754
|
-
|
|
755
|
-
def __itruediv__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
756
|
-
other = self.__normalize__(other)
|
|
757
|
-
self.x /= other.x
|
|
758
|
-
self.y /= other.y
|
|
759
|
-
return self
|
|
760
|
-
|
|
761
|
-
def __imod__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
762
|
-
other = self.__normalize__(other)
|
|
763
|
-
self.x %= other.x
|
|
764
|
-
self.y %= other.y
|
|
765
|
-
return self
|
|
766
|
-
|
|
767
|
-
def __ipow__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
768
|
-
other = self.__normalize__(other)
|
|
769
|
-
self.x **= other.x
|
|
770
|
-
self.y **= other.y
|
|
771
|
-
return self
|
|
772
|
-
|
|
773
|
-
def __ifloordiv__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
|
|
774
|
-
other = self.__normalize__(other)
|
|
775
|
-
self.x //= other.x
|
|
776
|
-
self.y //= other.y
|
|
777
|
-
return self
|
|
778
|
-
|
|
779
|
-
# comparasion
|
|
780
|
-
def __eq__(self, other) -> bool:
|
|
781
|
-
try: other = self.__normalize__(other)
|
|
782
|
-
except: return False
|
|
783
|
-
return self.x == other.x and self.y == other.y
|
|
784
|
-
|
|
785
|
-
def __ne__(self, other) -> bool:
|
|
786
|
-
return not self.__eq__(other)
|
|
787
|
-
|
|
788
|
-
def __abs__(self:"Vector2D") -> "Vector2D":
|
|
789
|
-
return Vector2D(abs(self.x), abs(self.y))
|
|
790
|
-
|
|
791
|
-
def __round__(self:"Vector2D", n:"int|float|Vector2D"=1) -> "Vector2D":
|
|
792
|
-
n = self.__normalize__(n)
|
|
793
|
-
return Vector2D(round(self.x / n.x) * n.x, round(self.y / n.y) * n.y)
|
|
794
|
-
|
|
795
|
-
def __floor__(self:"Vector2D", n:"int|float|Vector2D"=1) -> "Vector2D":
|
|
796
|
-
n = self.__normalize__(n)
|
|
797
|
-
return Vector2D(_mt.floor(self.x / n.x) * n.x, _mt.floor(self.y / n.y) * n.y)
|
|
798
|
-
|
|
799
|
-
def __ceil__(self:"Vector2D", n:"int|float|Vector2D"=1) -> "Vector2D":
|
|
800
|
-
n = self.__normalize__(n)
|
|
801
|
-
return Vector2D(_mt.ceil(self.x / n.x) * n.x, _mt.ceil(self.y / n.y) * n.y)
|
|
802
|
-
|
|
803
|
-
def __float__(self:"Vector2D") -> "Vector2D":
|
|
804
|
-
return Vector2D(float(self.x), float(self.y))
|
|
805
|
-
|
|
806
|
-
def __getitem__(self:"Vector2D", n) -> int|float:
|
|
807
|
-
if n in [0, "x"]:
|
|
808
|
-
return self.x
|
|
809
|
-
elif n in [1, "y"]:
|
|
810
|
-
return self.y
|
|
811
|
-
else:
|
|
812
|
-
raise IndexError("V2 has only x,y...")
|
|
813
|
-
|
|
814
|
-
def __normalize__(self:"Vector2D", other) -> "Vector2D":
|
|
815
|
-
if not isinstance(other, Vector2D):
|
|
816
|
-
if any(isinstance(other, cls) for cls in {int, float}):
|
|
817
|
-
return Vector2D(other, other)
|
|
818
|
-
elif any(isinstance(other, cls) for cls in {list, tuple}):
|
|
819
|
-
return Vector2D(*other[:2])
|
|
820
|
-
else:
|
|
821
|
-
raise TypeError(f"The value {other} is not a num type: [{int|float}] nor an array type: [{list|tuple}]")
|
|
822
|
-
return other
|
|
823
|
-
|
|
824
|
-
try:
|
|
825
|
-
from .Cmain import * #type: ignore
|
|
826
|
-
cV2 = Vector2D
|
|
827
|
-
cVector2D = Vector2D
|
|
828
|
-
except Exception as err:
|
|
829
|
-
print(Warning(f"Unable to load the C-version on Vector2D: \n\t{err}"))
|
|
830
|
-
cV2 = None
|
|
831
|
-
cVector2D = None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|