e2D 1.3.9__tar.gz → 1.3.11__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.3.9 → e2D-1.3.11}/PKG-INFO +1 -1
- {e2D-1.3.9 → e2D-1.3.11}/e2D/__init__.py +26 -3
- {e2D-1.3.9 → e2D-1.3.11}/e2D/envs.py +9 -5
- {e2D-1.3.9 → e2D-1.3.11}/e2D/plots.py +144 -91
- {e2D-1.3.9 → e2D-1.3.11}/e2D/utils.py +4 -0
- {e2D-1.3.9 → e2D-1.3.11}/e2D.egg-info/PKG-INFO +1 -1
- {e2D-1.3.9 → e2D-1.3.11}/setup.cfg +1 -1
- {e2D-1.3.9 → e2D-1.3.11}/LICENSE +0 -0
- {e2D-1.3.9 → e2D-1.3.11}/README.md +0 -0
- {e2D-1.3.9 → e2D-1.3.11}/e2D.egg-info/SOURCES.txt +0 -0
- {e2D-1.3.9 → e2D-1.3.11}/e2D.egg-info/dependency_links.txt +0 -0
- {e2D-1.3.9 → e2D-1.3.11}/e2D.egg-info/requires.txt +0 -0
- {e2D-1.3.9 → e2D-1.3.11}/e2D.egg-info/top_level.txt +0 -0
- {e2D-1.3.9 → e2D-1.3.11}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: e2D
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.11
|
|
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
|
|
@@ -15,7 +15,7 @@ DOUBLE_PI = PI*2
|
|
|
15
15
|
#
|
|
16
16
|
|
|
17
17
|
class Vector2D:
|
|
18
|
-
round_values_on_print :float=
|
|
18
|
+
round_values_on_print :int|float= 2
|
|
19
19
|
def __init__(self:"V2|Vector2D", x:int|float=0.0, y:int|float=0.0) -> None:
|
|
20
20
|
"""
|
|
21
21
|
# Initialize a 2D vector with the specified x and y components.
|
|
@@ -666,11 +666,25 @@ class Vector2D:
|
|
|
666
666
|
other = self.__normalize__(other)
|
|
667
667
|
return Vector2D(max(self.x, other.x), max(self.y, other.y))
|
|
668
668
|
|
|
669
|
+
def advanced_stringify(self:"V2|Vector2D", precision:float|None=None, use_scientific_notation:bool=False, return_as_list=False) -> str:
|
|
670
|
+
precision = self.round_values_on_print if precision == None else precision
|
|
671
|
+
def optimize(value) -> str:
|
|
672
|
+
abs_value = abs(value)
|
|
673
|
+
if abs_value < 1/10**precision and abs_value != 0:
|
|
674
|
+
return f"{value:.{precision}e}"
|
|
675
|
+
elif abs_value < 10**precision:
|
|
676
|
+
return f"{value:.{precision}f}".rstrip('0').rstrip('.')
|
|
677
|
+
else:
|
|
678
|
+
return f"{value:.{precision}e}"
|
|
679
|
+
if return_as_list:
|
|
680
|
+
return [optimize(self.x), optimize(self.y)] if use_scientific_notation else [f"{self.x:.{precision}f}" f"{self.y:.{precision}f}"]
|
|
681
|
+
return f"{optimize(self.x)}, {optimize(self.y)}" if use_scientific_notation else f"{self.x:.{precision}f}, {self.y:.{precision}f}"
|
|
682
|
+
|
|
669
683
|
def __str__(self:"V2|Vector2D") -> str:
|
|
670
|
-
return f"{self.x
|
|
684
|
+
return f"{self.x:.{self.round_values_on_print}f}, {self.y:.{self.round_values_on_print}f}"
|
|
671
685
|
|
|
672
686
|
def __repr__(self:"V2|Vector2D") -> str:
|
|
673
|
-
return f"x:{self.x
|
|
687
|
+
return f"x:{self.x:.{self.round_values_on_print}f}\ty:{self.y:.{self.round_values_on_print}f}"
|
|
674
688
|
|
|
675
689
|
def __call__(self:"V2|Vector2D", return_tuple=False) -> list|tuple:
|
|
676
690
|
return (self.x, self.y) if return_tuple else [self.x, self.y]
|
|
@@ -1250,3 +1264,12 @@ def distance_line_point(line_point_a:Vector2D|V2, line_point_b:Vector2D|V2, poin
|
|
|
1250
1264
|
The result is returned as a float representing the distance between the line segment and the point.
|
|
1251
1265
|
"""
|
|
1252
1266
|
return float(_np.linalg.norm(_np.cross((line_point_b-line_point_a)(), (line_point_a-point_c)()))/_np.linalg.norm((line_point_b-line_point_a)()))
|
|
1267
|
+
|
|
1268
|
+
def optimize_value_string(value:int|float, precision:int) -> str:
|
|
1269
|
+
abs_value = abs(value)
|
|
1270
|
+
if abs_value < 1/10**precision and abs_value != 0:
|
|
1271
|
+
return f"{value:.{precision}e}"
|
|
1272
|
+
elif abs_value < 10**precision:
|
|
1273
|
+
return f"{value:.{precision}f}".rstrip('0').rstrip('.')
|
|
1274
|
+
else:
|
|
1275
|
+
return f"{value:.{precision}e}"
|
|
@@ -22,9 +22,9 @@ while not rootEnv.quit:
|
|
|
22
22
|
|
|
23
23
|
pg.init()
|
|
24
24
|
pg.font.init()
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
FONT_ARIAL_16 = pg.font.SysFont("Arial", 16)
|
|
26
|
+
FONT_ARIAL_32 = pg.font.SysFont("Arial", 32)
|
|
27
|
+
FONT_ARIAL_64 = pg.font.SysFont("Arial", 64)
|
|
28
28
|
create_arial_font_size = lambda size: pg.font.SysFont("Arial", size)
|
|
29
29
|
|
|
30
30
|
TEXT_FIXED_SIDES_TOP_LEFT = 0
|
|
@@ -44,6 +44,8 @@ class RootEnv:
|
|
|
44
44
|
self.screen_size :V2|Vector2D= screen_size
|
|
45
45
|
self.screen = pg.display.set_mode(self.screen_size(), vsync=vsync, flags=window_flag)
|
|
46
46
|
self.target_fps = target_fps
|
|
47
|
+
self.current_fps = self.target_fps
|
|
48
|
+
self.current_frame = 0
|
|
47
49
|
self.show_fps = show_fps
|
|
48
50
|
self.clock = pg.time.Clock()
|
|
49
51
|
self.keyboard = Keyboard(self)
|
|
@@ -62,7 +64,7 @@ class RootEnv:
|
|
|
62
64
|
def clear_rect(self, position:V2|Vector2D, size:V2|Vector2D) -> None:
|
|
63
65
|
self.screen.fill(self.background_color, position() + size())
|
|
64
66
|
|
|
65
|
-
def print(self, text:str, position:V2|Vector2D, color:tuple[float,float,float]=(255,255,255), fixed_sides=TEXT_FIXED_SIDES_TOP_LEFT, font:pg.font.Font=
|
|
67
|
+
def print(self, text:str, position:V2|Vector2D, color:tuple[float,float,float]=(255,255,255), fixed_sides=TEXT_FIXED_SIDES_TOP_LEFT, font:pg.font.Font=FONT_ARIAL_32, bg_color:None|tuple[int,int,int]|list[int]=None, border_color:None|tuple[int,int,int]|list[int]=None, border_width:float=0, border_radius:int|list[int]|tuple[int,int,int,int]=-1, margin:V2|Vector2D=V2z, personalized_surface:pg.Surface|None=None) -> None:
|
|
66
68
|
text_box = font.render(text, True, color)
|
|
67
69
|
size = V2(*text_box.get_size()) + margin * 2
|
|
68
70
|
position = position - size * self.__fixed_sides_multiplier[fixed_sides] + margin
|
|
@@ -76,8 +78,9 @@ class RootEnv:
|
|
|
76
78
|
|
|
77
79
|
def __draw__(self) -> None:
|
|
78
80
|
self.clock.tick(self.target_fps)
|
|
81
|
+
self.current_fps = self.clock.get_fps()
|
|
79
82
|
if self.clear_screen_each_frame: self.clear()
|
|
80
|
-
if self.show_fps: self.print(str(round(self.
|
|
83
|
+
if self.show_fps: self.print(str(round(self.current_fps,2)), self.screen_size * .01, bg_color=(0,0,0))
|
|
81
84
|
|
|
82
85
|
self.env.draw()
|
|
83
86
|
pg.display.update()
|
|
@@ -91,6 +94,7 @@ class RootEnv:
|
|
|
91
94
|
self.__update__()
|
|
92
95
|
self.__draw__()
|
|
93
96
|
|
|
97
|
+
self.current_frame += 1
|
|
94
98
|
self.events = pg.event.get()
|
|
95
99
|
for event in self.events:
|
|
96
100
|
if event.type == pg.QUIT or ((event.type == pg.KEYDOWN and event.key == self._quit_on_key_pressed) if self._quit_on_key_pressed != None else False):
|
|
@@ -2,35 +2,38 @@ from __future__ import annotations
|
|
|
2
2
|
from .envs import *
|
|
3
3
|
import numpy as np
|
|
4
4
|
|
|
5
|
-
def no_error_complex_function(function, args) -> V2|Vector2D:
|
|
6
|
-
res :complex= function(args)
|
|
7
|
-
return V2(res.real, res.imag)
|
|
8
|
-
|
|
9
|
-
sign = lambda value: -1 if value < 0 else (1 if value > 0 else 0)
|
|
10
|
-
|
|
11
5
|
class Function:
|
|
12
|
-
def __init__(self
|
|
6
|
+
def __init__(self) -> None:
|
|
13
7
|
self.plot : Plot
|
|
14
|
-
self.color = color
|
|
15
|
-
self.function = function
|
|
16
8
|
self.__layer_surface__ :pg.Surface= None #type: ignore
|
|
17
9
|
|
|
18
|
-
def
|
|
19
|
-
|
|
10
|
+
def update(self) -> None: pass
|
|
11
|
+
|
|
12
|
+
def render(self) -> None: pass
|
|
13
|
+
|
|
14
|
+
def draw(self) -> None:
|
|
15
|
+
self.plot.canvas.blit(self.__layer_surface__, (0,0))
|
|
16
|
+
|
|
17
|
+
class MathFunction(Function):
|
|
18
|
+
def __init__(self, function, color:list[float]|tuple[float,float,float]=(255,255,255)) -> None:
|
|
19
|
+
super().__init__()
|
|
20
|
+
self.color = color
|
|
21
|
+
self.function = function
|
|
20
22
|
|
|
21
23
|
def get_points(self) -> list:
|
|
22
24
|
signs_self = np.sign(self.function(*self.plot.meshgrid))
|
|
23
25
|
signs_sum = signs_self + np.roll(signs_self, axis=1, shift=1) + np.roll(signs_self, axis=0, shift=-1) + np.roll(signs_self, axis=(1,0), shift=(1,-1))
|
|
24
26
|
return np.column_stack(np.where(((-4 < signs_sum) & (signs_sum < 4))[:-1, 1:])[::-1]) / self.plot.scale()
|
|
25
27
|
|
|
26
|
-
def
|
|
27
|
-
|
|
28
|
+
def update(self, new_function=None) -> None:
|
|
29
|
+
if new_function != None:
|
|
30
|
+
self.function = new_function
|
|
28
31
|
self.points = self.get_points()
|
|
29
32
|
self.render()
|
|
30
33
|
|
|
31
|
-
def get_derivative(self, delta:float=.01, color:None|list[float]|tuple[float,float,float]=None) ->
|
|
32
|
-
return
|
|
33
|
-
|
|
34
|
+
def get_derivative(self, delta:float=.01, color:None|list[float]|tuple[float,float,float]=None) -> MathFunction:
|
|
35
|
+
return MathFunction(lambda x,y: (self.function(x + delta, y) - self.function(x,y))/delta - y, color if color != None else self.color)
|
|
36
|
+
|
|
34
37
|
def render(self) -> None:
|
|
35
38
|
self.__layer_surface__.fill((0,0,0,0))
|
|
36
39
|
offset = self.plot.dragging - self.plot.start_dragging if (self.plot.dragging != None) and (not self.plot.settings.get("use_real_time_rendering")) else V2z
|
|
@@ -44,44 +47,70 @@ class Function:
|
|
|
44
47
|
point = point.astype(int).tolist()
|
|
45
48
|
if self.plot.dragging != None:
|
|
46
49
|
point = round(point + offset)()
|
|
47
|
-
self.__layer_surface__.set_at(point, self.color)
|
|
50
|
+
self.__layer_surface__.set_at(point, self.color) #type: ignore
|
|
48
51
|
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
class PointsFunction(Function):
|
|
53
|
+
def __init__(self, points:list[V2|Vector2D]=[], points_color:list[float]|tuple[float,float,float]=(255,0,0), color:list[float]|tuple[float,float,float]=(255,255,255)) -> None:
|
|
54
|
+
super().__init__()
|
|
55
|
+
self.color = color
|
|
56
|
+
self.points = points
|
|
57
|
+
self.points_color = points_color
|
|
58
|
+
|
|
59
|
+
def update(self, points:list[V2|Vector2D]|None=None) -> None:
|
|
60
|
+
if points != None: self.points = points
|
|
61
|
+
self.plot_points = [self.plot.__plot2real__(point)() for point in self.points if \
|
|
62
|
+
self.plot.top_left_x < point.x < self.plot.bottom_right_x and \
|
|
63
|
+
self.plot.bottom_right_y < point.y < self.plot.top_left_y]
|
|
64
|
+
self.render()
|
|
51
65
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
#
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
def render(self) -> None:
|
|
67
|
+
self.__layer_surface__.fill((0,0,0,0))
|
|
68
|
+
if len(self.plot_points)>=2: pg.draw.lines(self.__layer_surface__, self.color, False, self.plot_points)
|
|
69
|
+
# for point in self.points:
|
|
70
|
+
# pg.draw.circle(self.__layer_surface__,
|
|
71
|
+
# self.points_color,
|
|
72
|
+
# self.plot.__plot2real__(point),
|
|
73
|
+
# 5)
|
|
74
|
+
|
|
75
|
+
"""
|
|
76
|
+
def no_error_complex_function(function, args) -> V2|Vector2D:
|
|
77
|
+
res :complex= function(args)
|
|
78
|
+
return V2(res.real, res.imag)
|
|
79
|
+
sign = lambda value: -1 if value < 0 else (1 if value > 0 else 0)
|
|
80
|
+
class ComplexFunction:
|
|
81
|
+
def __init__(self, function, plot:"Plot", starting_t:float=-10, ending_t:float=10, step=.01, color=(255,255,255), auto_connect_treshold=float("inf"), points_radius=2, points_color=None) -> None:
|
|
82
|
+
self.auto_connect_treshold = auto_connect_treshold
|
|
83
|
+
self.plot = plot
|
|
84
|
+
self.starting_t = starting_t
|
|
85
|
+
self.ending_t = ending_t
|
|
86
|
+
self.color = color
|
|
87
|
+
self.step = step
|
|
88
|
+
self.points_color = points_color
|
|
89
|
+
self.points_radius = points_radius
|
|
90
|
+
self.update_function(function)
|
|
63
91
|
|
|
64
|
-
|
|
65
|
-
|
|
92
|
+
def update_points(self) -> None:
|
|
93
|
+
self.update_function(self.function)
|
|
66
94
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
95
|
+
def update_function(self, new_function) -> None:
|
|
96
|
+
self.function = new_function
|
|
97
|
+
self.points :list[V2|Vector2D]= [point for t in range(int(self.starting_t / self.step), int(self.ending_t / self.step)) if (self.plot.bottom_right_y < (point:=no_error_complex_function(new_function, t * self.step)).y < self.plot.top_left_y) and (self.plot.top_left_x < point.x < self.plot.bottom_right_x)]
|
|
98
|
+
self.full_auto_connect = not any(point.distance_to(self.points[i]) > self.auto_connect_treshold for i,point in enumerate(self.points[1:]))
|
|
99
|
+
|
|
100
|
+
def draw(self) -> None:
|
|
101
|
+
if self.points_radius:
|
|
102
|
+
for point in self.points:
|
|
103
|
+
pg.draw.circle(self.plot.canvas, self.color if self.points_color == None else self.points_color, self.plot.__plot2real__(point)(), self.points_radius)
|
|
104
|
+
|
|
105
|
+
if len(self.points) < 2: return
|
|
106
|
+
if self.full_auto_connect:
|
|
107
|
+
pg.draw.lines(self.plot.canvas, self.color, False, [self.plot.__plot2real__(point)() for point in self.points])
|
|
108
|
+
else:
|
|
109
|
+
real_points = [self.plot.__plot2real__(point)() for point in self.points]
|
|
110
|
+
for i,(point, real_point) in enumerate(zip(self.points[1:], real_points[1:])):
|
|
111
|
+
if point.distance_to(self.points[i]) < self.auto_connect_treshold:
|
|
112
|
+
pg.draw.line(self.plot.canvas, self.color, real_points[i], real_point) #type: ignore
|
|
113
|
+
"""
|
|
85
114
|
|
|
86
115
|
class __PlotSettings__:
|
|
87
116
|
def __init__(self, plot:Plot) -> None:
|
|
@@ -91,7 +120,6 @@ class __PlotSettings__:
|
|
|
91
120
|
"distance_to_axis_for_scalar_zoom" : 10,
|
|
92
121
|
|
|
93
122
|
# cursor
|
|
94
|
-
"show_cursor_coords" : False,
|
|
95
123
|
"zoom_on_center" : False,
|
|
96
124
|
|
|
97
125
|
# plot visual options
|
|
@@ -123,6 +151,9 @@ class __PlotSettings__:
|
|
|
123
151
|
"show_pointer" : True,
|
|
124
152
|
"pointer_radius" : 15,
|
|
125
153
|
"pointer_color" : rgb(255, 255, 255),
|
|
154
|
+
|
|
155
|
+
# cursor
|
|
156
|
+
"show_cursor_coords" : False,
|
|
126
157
|
|
|
127
158
|
#rect
|
|
128
159
|
"render_bg" : True,
|
|
@@ -134,8 +165,9 @@ class __PlotSettings__:
|
|
|
134
165
|
|
|
135
166
|
# info options
|
|
136
167
|
"show_zoom_info": True,
|
|
137
|
-
"top_left_info_position" : self.plot.position + V2(
|
|
138
|
-
"info_interline_space" : V2(0,
|
|
168
|
+
"top_left_info_position" : self.plot.position + V2(15, 75),
|
|
169
|
+
"info_interline_space" : V2(0, 24),
|
|
170
|
+
"info_font" : create_arial_font_size(24),
|
|
139
171
|
"info_precision" : 2,
|
|
140
172
|
}
|
|
141
173
|
|
|
@@ -182,11 +214,6 @@ class Plot:
|
|
|
182
214
|
self.scale = scale
|
|
183
215
|
|
|
184
216
|
self.settings = __PlotSettings__(self)
|
|
185
|
-
|
|
186
|
-
self.current_zoom = V2one * -np.log2(10)*10
|
|
187
|
-
self.current_offset = V2(0,0)
|
|
188
|
-
self.update_grid(True)
|
|
189
|
-
|
|
190
217
|
self.functions :list[Function]= []
|
|
191
218
|
|
|
192
219
|
self.canvas = pg.Surface(self.size(), pg.SRCALPHA, 32).convert_alpha()
|
|
@@ -195,6 +222,8 @@ class Plot:
|
|
|
195
222
|
self.is_mouse_in_rect = False
|
|
196
223
|
self.mouse_scalar = V2one.copy()
|
|
197
224
|
|
|
225
|
+
self.focus(V2(0,0), 10)
|
|
226
|
+
|
|
198
227
|
def set_borders_by_position_and_zoom(self) -> None:
|
|
199
228
|
self.top_left_plot_coord = self.current_offset - (.5**(.1*self.current_zoom)) * self.__y_axis_multiplier__
|
|
200
229
|
self.bottom_right_plot_coord = self.current_offset + (.5**(.1*self.current_zoom)) * self.__y_axis_multiplier__
|
|
@@ -214,7 +243,7 @@ class Plot:
|
|
|
214
243
|
def load_function(self, function:Function) -> None:
|
|
215
244
|
function.plot = self
|
|
216
245
|
function.__layer_surface__ = pg.Surface(self.size(), pg.SRCALPHA, 32).convert_alpha()
|
|
217
|
-
function.
|
|
246
|
+
function.update()
|
|
218
247
|
self.functions.append(function)
|
|
219
248
|
|
|
220
249
|
def __plot2real__(self, plot_position:V2|Vector2D) -> V2|Vector2D:
|
|
@@ -234,31 +263,31 @@ class Plot:
|
|
|
234
263
|
grid_width = self.settings.get("grid_width")
|
|
235
264
|
clamped_top_left = grid_step * (self.top_left_plot_coord / grid_step).__ceil__()
|
|
236
265
|
clamped_bottom_right = grid_step * (self.bottom_right_plot_coord / grid_step).__ceil__()
|
|
237
|
-
for x_value in np.arange(clamped_top_left.x, clamped_bottom_right.x, grid_step.x):
|
|
238
|
-
pg.draw.line( self.canvas, grid_color, self.__plot2real__((x_value, self.top_left_y))(), self.__plot2real__((x_value, self.bottom_right_y))(), grid_width)
|
|
239
|
-
for y_value in np.arange(clamped_bottom_right.y, clamped_top_left.y, grid_step.y):
|
|
240
|
-
pg.draw.line(self.canvas, grid_color, self.__plot2real__((self.top_left_x, y_value))(), self.__plot2real__((self.bottom_right_x, y_value))(), grid_width)
|
|
266
|
+
for x_value in np.arange(clamped_top_left.x, clamped_bottom_right.x, grid_step.x): #type: ignore
|
|
267
|
+
pg.draw.line( self.canvas, grid_color, self.__plot2real__((x_value, self.top_left_y))(), self.__plot2real__((x_value, self.bottom_right_y))(), grid_width) #type: ignore
|
|
268
|
+
for y_value in np.arange(clamped_bottom_right.y, clamped_top_left.y, grid_step.y): #type: ignore
|
|
269
|
+
pg.draw.line(self.canvas, grid_color, self.__plot2real__((self.top_left_x, y_value))(), self.__plot2real__((self.bottom_right_x, y_value))(), grid_width) #type: ignore
|
|
241
270
|
|
|
242
271
|
# draw functions
|
|
243
272
|
for function in self.functions: function.draw()
|
|
244
273
|
|
|
245
274
|
# draw rect, pointer and corner coords
|
|
246
275
|
if self.settings.get("draw_rect"):
|
|
247
|
-
pg.draw.rect(self.canvas, self.settings.get("rect_color"), V2z() + self.size(), self.settings.get("rect_width"))
|
|
276
|
+
pg.draw.rect(self.canvas, self.settings.get("rect_color"), V2z() + self.size(), self.settings.get("rect_width")) #type: ignore
|
|
248
277
|
|
|
249
278
|
if self.settings.get("show_pointer"):
|
|
250
279
|
center = self.size * .5
|
|
251
280
|
aimer_radius = self.settings.get("pointer_radius")
|
|
252
281
|
pointer_color = self.settings.get("pointer_color")
|
|
253
|
-
pg.draw.line(self.canvas, pointer_color, (center + aimer_radius)(), (center - aimer_radius)(), 1)
|
|
254
|
-
pg.draw.line(self.canvas, pointer_color, (center + self.__y_axis_multiplier__ * aimer_radius)(), (center - self.__y_axis_multiplier__ * aimer_radius)(), 1)
|
|
255
|
-
pg.draw.circle(self.canvas, pointer_color, (self.size * .5)(), 15, 1)
|
|
282
|
+
pg.draw.line(self.canvas, pointer_color, (center + aimer_radius)(), (center - aimer_radius)(), 1) #type: ignore
|
|
283
|
+
pg.draw.line(self.canvas, pointer_color, (center + self.__y_axis_multiplier__ * aimer_radius)(), (center - self.__y_axis_multiplier__ * aimer_radius)(), 1) #type: ignore
|
|
284
|
+
pg.draw.circle(self.canvas, pointer_color, (self.size * .5)(), 15, 1) #type: ignore
|
|
256
285
|
|
|
257
286
|
if self.settings.get("show_corners_coords"):
|
|
258
|
-
self.rootEnv.print(
|
|
259
|
-
self.rootEnv.print(
|
|
260
|
-
self.rootEnv.print(
|
|
261
|
-
self.rootEnv.print(
|
|
287
|
+
self.rootEnv.print(self.top_left_plot_coord.advanced_stringify(4, True), V2z.copy(), bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
|
|
288
|
+
self.rootEnv.print(V2(self.top_left_plot_coord.x, self.bottom_right_plot_coord.y).advanced_stringify(4, True), self.size * V2(0, 1), fixed_sides=TEXT_FIXED_SIDES_BOTTOM_LEFT, bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
|
|
289
|
+
self.rootEnv.print(self.bottom_right_plot_coord.advanced_stringify(4, True), self.size.copy(), fixed_sides=TEXT_FIXED_SIDES_BOTTOM_RIGHT, bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
|
|
290
|
+
self.rootEnv.print(V2(self.bottom_right_plot_coord.x, self.top_left_plot_coord.y).advanced_stringify(4, True), self.size * V2(1, 0), fixed_sides=TEXT_FIXED_SIDES_TOP_RIGHT, bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
|
|
262
291
|
|
|
263
292
|
def update(self) -> None:
|
|
264
293
|
# update mouse and center positions
|
|
@@ -271,10 +300,7 @@ class Plot:
|
|
|
271
300
|
# render the functions when i stop dragging (when i release the left mouse key)
|
|
272
301
|
if self.rootEnv.mouse.just_released[0] and self.dragging != None:
|
|
273
302
|
self.dragging = None
|
|
274
|
-
self.
|
|
275
|
-
for function in self.functions:
|
|
276
|
-
function.update_points()
|
|
277
|
-
self.render()
|
|
303
|
+
self.focus(None, None)
|
|
278
304
|
|
|
279
305
|
if self.is_mouse_in_rect:
|
|
280
306
|
# mouse scalar is needed for checking if the mouse is hovering an axis, in case it is the opposite one zoom value has to be multiplied by 0 so nullifying it.
|
|
@@ -292,10 +318,7 @@ class Plot:
|
|
|
292
318
|
# i have to update the corners of the plot here to use the real2plot function correctly (i cant use shortcuts)
|
|
293
319
|
self.update_grid(False)
|
|
294
320
|
self.current_offset += pre - self.__real2plot__(self.rootEnv.mouse.position)
|
|
295
|
-
self.
|
|
296
|
-
for function in self.functions:
|
|
297
|
-
function.update_points()
|
|
298
|
-
self.render()
|
|
321
|
+
self.focus(None, None)
|
|
299
322
|
|
|
300
323
|
# start dragging whenever mouse left button is just pressed
|
|
301
324
|
if self.rootEnv.mouse.just_pressed[0] and self.dragging == None:
|
|
@@ -304,22 +327,49 @@ class Plot:
|
|
|
304
327
|
|
|
305
328
|
# update the canvas if im dragging
|
|
306
329
|
if self.dragging:
|
|
307
|
-
|
|
330
|
+
moved = False
|
|
331
|
+
if not self.is_mouse_in_rect:
|
|
332
|
+
if self.rootEnv.mouse.position.x < self.position.x:
|
|
333
|
+
self.rootEnv.mouse.set_position(V2(self.position.x + self.size.x, self.rootEnv.mouse.position.y))
|
|
334
|
+
moved = True
|
|
335
|
+
elif self.rootEnv.mouse.position.x > self.position.x + self.size.x:
|
|
336
|
+
self.rootEnv.mouse.set_position(V2(self.position.x, self.rootEnv.mouse.position.y))
|
|
337
|
+
moved = True
|
|
338
|
+
if self.rootEnv.mouse.position.y < self.position.y:
|
|
339
|
+
self.rootEnv.mouse.set_position(V2(self.rootEnv.mouse.position.x, self.position.y + self.size.y))
|
|
340
|
+
moved = True
|
|
341
|
+
elif self.rootEnv.mouse.position.y > self.position.y + self.size.y:
|
|
342
|
+
self.rootEnv.mouse.set_position(V2(self.rootEnv.mouse.position.x, self.position.y))
|
|
343
|
+
moved = True
|
|
344
|
+
if not moved:
|
|
345
|
+
offset = (self.dragging - self.rootEnv.mouse.position)* V2(1, -1) * (abs(self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size)
|
|
346
|
+
self.current_offset += offset
|
|
308
347
|
self.dragging = self.rootEnv.mouse.position.copy()
|
|
309
|
-
self.current_offset += offset
|
|
310
348
|
|
|
311
349
|
# with real time rendering i update the function render each frame whnever im dragging the canvs around
|
|
312
350
|
if self.settings.get("use_real_time_rendering"):
|
|
313
|
-
self.
|
|
314
|
-
for function in self.functions: function.update_points()
|
|
351
|
+
self.focus(None, None)
|
|
315
352
|
else:
|
|
316
353
|
self.update_grid()
|
|
317
|
-
|
|
354
|
+
self.render()
|
|
355
|
+
|
|
356
|
+
def focus(self, center:V2|Vector2D|None=V2z, zoom:float|Vector2D|V2|None=10.0) -> None:
|
|
357
|
+
if center != None:
|
|
358
|
+
self.current_offset = center.copy()
|
|
359
|
+
if zoom != None:
|
|
360
|
+
if any(isinstance(zoom, cls) for cls in {Vector2D, V2}):
|
|
361
|
+
self.current_zoom = 0-V2(np.log2(zoom.x), np.log2(zoom.y)) * 10
|
|
362
|
+
else:
|
|
363
|
+
self.current_zoom = V2one * -np.log2(zoom)*10
|
|
364
|
+
|
|
365
|
+
self.update_grid(True)
|
|
366
|
+
for function in self.functions: function.update()
|
|
367
|
+
self.render()
|
|
318
368
|
|
|
319
369
|
def draw(self) -> None:
|
|
320
370
|
# fill canvas with bg color
|
|
321
371
|
if self.settings.get("render_bg"):
|
|
322
|
-
self.rootEnv.screen.fill(self.settings.get("bg_color"), self.position() + self.size())
|
|
372
|
+
self.rootEnv.screen.fill(self.settings.get("bg_color"), self.position() + self.size()) #type: ignore
|
|
323
373
|
|
|
324
374
|
# render functions before axes
|
|
325
375
|
if render_axes_on_top:=self.settings.get("render_axes_on_top"): self.rootEnv.screen.blit(self.canvas, self.position())
|
|
@@ -327,13 +377,13 @@ class Plot:
|
|
|
327
377
|
# render axes
|
|
328
378
|
if self.top_left_x < 0 < self.bottom_right_x and (self.settings.get("show_x_axis") and self.settings.get("show_axes")):
|
|
329
379
|
pg.draw.line(self.rootEnv.screen,
|
|
330
|
-
(self.settings.get("axes_default_color") if (x_color:=self.settings.get("x_axis_color"))==None else x_color) if self.mouse_scalar.x else (self.settings.get("mouse_hover_axes_color")),
|
|
380
|
+
(self.settings.get("axes_default_color") if (x_color:=self.settings.get("x_axis_color"))==None else x_color) if self.mouse_scalar.x else (self.settings.get("mouse_hover_axes_color")), #type: ignore
|
|
331
381
|
(self.__plot2real__(V2(0, self.top_left_y)) + self.position)(),
|
|
332
382
|
(self.__plot2real__(V2(0, self.bottom_right_y)) + self.position)(),
|
|
333
383
|
self.settings.get("axes_default_width") if (x_width:=self.settings.get("x_axis_width"))==None else x_width) #type: ignore
|
|
334
384
|
if self.bottom_right_y < 0 < self.top_left_y and (self.settings.get("show_y_axis") and self.settings.get("show_axes")):
|
|
335
385
|
pg.draw.line(self.rootEnv.screen,
|
|
336
|
-
(self.settings.get("axes_default_color") if (y_color:=self.settings.get("y_axis_color"))==None else y_color) if self.mouse_scalar.y else (self.settings.get("mouse_hover_axes_color")),
|
|
386
|
+
(self.settings.get("axes_default_color") if (y_color:=self.settings.get("y_axis_color"))==None else y_color) if self.mouse_scalar.y else (self.settings.get("mouse_hover_axes_color")), #type: ignore
|
|
337
387
|
(self.__plot2real__(V2(self.top_left_x, 0)) + self.position)(),
|
|
338
388
|
(self.__plot2real__(V2(self.bottom_right_x, 0)) + self.position)(),
|
|
339
389
|
self.settings.get("axes_default_width") if (y_width:=self.settings.get("y_axis_width"))==None else y_width) #type: ignore
|
|
@@ -342,14 +392,17 @@ class Plot:
|
|
|
342
392
|
if not render_axes_on_top: self.rootEnv.screen.blit(self.canvas, self.position())
|
|
343
393
|
|
|
344
394
|
if self.is_mouse_in_rect and self.settings.get("show_cursor_coords"):
|
|
345
|
-
self.rootEnv.print(
|
|
395
|
+
self.rootEnv.print(self.plot_mouse_position.advanced_stringify(3, True), self.rootEnv.mouse.position, fixed_sides=TEXT_FIXED_SIDES_BOTTOM_MIDDLE) #type: ignore
|
|
396
|
+
|
|
346
397
|
|
|
398
|
+
current_real_zoom = (.5**(.1*self.current_zoom)).advanced_stringify(self.settings.get('info_precision'), True, True)
|
|
347
399
|
data = [
|
|
348
400
|
[f"ZOOM:", TEXT_FIXED_SIDES_TOP_LEFT, self.settings.get("show_zoom_info")],
|
|
349
|
-
[f" x: {
|
|
350
|
-
[f" y: {
|
|
401
|
+
[f" x: {current_real_zoom[0]};", TEXT_FIXED_SIDES_TOP_LEFT, self.settings.get("show_zoom_info")],
|
|
402
|
+
[f" y: {current_real_zoom[1]};", TEXT_FIXED_SIDES_TOP_LEFT, self.settings.get("show_zoom_info")],
|
|
403
|
+
[f" ratio: {optimize_value_string(self.current_zoom.x / self.current_zoom.y, 4)};", TEXT_FIXED_SIDES_TOP_LEFT, self.settings.get("show_zoom_info")],
|
|
351
404
|
]
|
|
352
405
|
|
|
353
406
|
for i, (d, fixed_side, show) in enumerate(data):
|
|
354
407
|
if show:
|
|
355
|
-
self.rootEnv.print(d, self.settings.get("top_left_info_position") + self.settings.get("info_interline_space") * i, fixed_sides=fixed_side)
|
|
408
|
+
self.rootEnv.print(d, self.settings.get("top_left_info_position") + self.settings.get("info_interline_space") * i, fixed_sides=fixed_side, font=self.settings.get("info_font"))
|
|
@@ -18,6 +18,10 @@ class Mouse:
|
|
|
18
18
|
self.last_frame_movement = V2z.copy()
|
|
19
19
|
self.update()
|
|
20
20
|
|
|
21
|
+
def set_position(self, new_position:Vector2D|V2) -> None:
|
|
22
|
+
self.position = new_position
|
|
23
|
+
pg.mouse.set_pos(new_position())
|
|
24
|
+
|
|
21
25
|
def update(self) -> None:
|
|
22
26
|
self.position = V2(*pg.mouse.get_pos()) # type: ignore
|
|
23
27
|
self.last_frame_movement = V2(*pg.mouse.get_rel())
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: e2D
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.11
|
|
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
1
|
[metadata]
|
|
2
2
|
name = e2D
|
|
3
|
-
version = 1.3.
|
|
3
|
+
version = 1.3.11
|
|
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.3.9 → e2D-1.3.11}/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|