e2D 1.3.2__tar.gz → 1.3.4__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.2 → e2D-1.3.4}/PKG-INFO +1 -1
- {e2D-1.3.2 → e2D-1.3.4}/e2D/__init__.py +7 -7
- {e2D-1.3.2 → e2D-1.3.4}/e2D/envs.py +2 -1
- e2D-1.3.4/e2D/plots.py +272 -0
- {e2D-1.3.2 → e2D-1.3.4}/e2D/utils.py +1 -0
- {e2D-1.3.2 → e2D-1.3.4}/e2D.egg-info/PKG-INFO +1 -1
- {e2D-1.3.2 → e2D-1.3.4}/setup.cfg +1 -1
- e2D-1.3.2/e2D/plots.py +0 -159
- {e2D-1.3.2 → e2D-1.3.4}/LICENSE +0 -0
- {e2D-1.3.2 → e2D-1.3.4}/README.md +0 -0
- {e2D-1.3.2 → e2D-1.3.4}/e2D.egg-info/SOURCES.txt +0 -0
- {e2D-1.3.2 → e2D-1.3.4}/e2D.egg-info/dependency_links.txt +0 -0
- {e2D-1.3.2 → e2D-1.3.4}/e2D.egg-info/requires.txt +0 -0
- {e2D-1.3.2 → e2D-1.3.4}/e2D.egg-info/top_level.txt +0 -0
- {e2D-1.3.2 → e2D-1.3.4}/pyproject.toml +0 -0
{e2D-1.3.2 → e2D-1.3.4}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: e2D
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.4
|
|
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
|
|
@@ -315,11 +315,11 @@ class Vector2D:
|
|
|
315
315
|
It then generates random x and y coordinates in the range [0, 1) using the `random()` function from the `random` module.
|
|
316
316
|
These random values are then scaled by (end - start) and added to the start point to obtain the final random Vector2D point.
|
|
317
317
|
"""
|
|
318
|
-
if not isinstance(start, Vector2D
|
|
318
|
+
if not any(isinstance(start, cls) for cls in {Vector2D, V2}):
|
|
319
319
|
if type(start) in int|float: start = Vector2D(start, start) #type: ignore
|
|
320
320
|
elif type(start) == None: start = Vector2D(0,0)
|
|
321
321
|
else: raise Exception(f"\nArg start must be in [Vector2D, int, float, tuple, list] not a [{type(start)}]\n")
|
|
322
|
-
if not isinstance(end, Vector2D
|
|
322
|
+
if not any(isinstance(end, cls) for cls in {Vector2D, V2}):
|
|
323
323
|
if type(end) in int|float: end = Vector2D(end, end) #type: ignore
|
|
324
324
|
elif type(end) == None: end = Vector2D(1,1)
|
|
325
325
|
else: raise Exception(f"\nArg end must be in [Vector2D, int, float, tuple, list] not a [{type(end)}]\n")
|
|
@@ -704,12 +704,12 @@ class Vector2D:
|
|
|
704
704
|
|
|
705
705
|
If n is neither a numeric value nor a Vector2D other, the function raises an exception.
|
|
706
706
|
"""
|
|
707
|
-
if isinstance(n, int
|
|
707
|
+
if any(isinstance(n, cls) for cls in {int, float}):
|
|
708
708
|
if n == 0:
|
|
709
709
|
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))
|
|
710
710
|
else:
|
|
711
711
|
return self / n
|
|
712
|
-
elif isinstance(n, Vector2D
|
|
712
|
+
elif any(isinstance(n, cls) for cls in {Vector2D, V2}):
|
|
713
713
|
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)
|
|
714
714
|
else:
|
|
715
715
|
raise Exception(f"\nArg n must be in [Vector2D, int, float, tuple, list] not a [{type(n)}]\n")
|
|
@@ -832,7 +832,7 @@ class Vector2D:
|
|
|
832
832
|
|
|
833
833
|
# comparasion
|
|
834
834
|
def __eq__(self, other) -> bool:
|
|
835
|
-
if not isinstance(other, Vector2D
|
|
835
|
+
if not any(isinstance(other, cls) for cls in {Vector2D, V2, list, tuple}):
|
|
836
836
|
return False
|
|
837
837
|
other = self.__normalize__(other)
|
|
838
838
|
return self.x == other.x and self.y == other.y
|
|
@@ -868,9 +868,9 @@ class Vector2D:
|
|
|
868
868
|
|
|
869
869
|
def __normalize__(self:"V2|Vector2D", other) -> "Vector2D|V2":
|
|
870
870
|
if not isinstance(other, Vector2D):
|
|
871
|
-
if isinstance(other, int
|
|
871
|
+
if any(isinstance(other, cls) for cls in {int, float}):
|
|
872
872
|
return Vector2D(other, other)
|
|
873
|
-
elif isinstance(other, list
|
|
873
|
+
elif any(isinstance(other, cls) for cls in {list, tuple}):
|
|
874
874
|
return Vector2D(*other[:2])
|
|
875
875
|
else:
|
|
876
876
|
raise TypeError(f"The value {other} is not a num type: [{int|float}] nor an array type: [{list|tuple}]")
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
from .utils import *
|
|
2
3
|
import pygame as pg
|
|
3
4
|
|
|
@@ -65,7 +66,7 @@ class RootEnv:
|
|
|
65
66
|
text_box = font.render(text, True, color)
|
|
66
67
|
size = V2(*text_box.get_size()) + margin * 2
|
|
67
68
|
position = position - size * self.__fixed_sides_multiplier[fixed_sides] + margin
|
|
68
|
-
if not isinstance(border_radius, tuple
|
|
69
|
+
if not any(isinstance(border_radius, cls) for cls in {tuple, list}): border_radius = [border_radius]*4
|
|
69
70
|
surface = (self.screen if personalized_surface == None else personalized_surface)
|
|
70
71
|
if bg_color != None:
|
|
71
72
|
pg.draw.rect(surface, bg_color, (position - margin)() + size(), 0, -1, *border_radius)
|
e2D-1.3.4/e2D/plots.py
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from .envs import *
|
|
3
|
+
import numpy as np
|
|
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
|
+
class Function:
|
|
12
|
+
def __init__(self, function, color) -> None:
|
|
13
|
+
self.plot : Plot
|
|
14
|
+
self.color = color
|
|
15
|
+
self.function = function
|
|
16
|
+
|
|
17
|
+
def update_points(self) -> None:
|
|
18
|
+
self.update_function(self.function)
|
|
19
|
+
|
|
20
|
+
def get_points(self) -> list:
|
|
21
|
+
signs_self = np.sign(self.function(*self.plot.meshgrid))
|
|
22
|
+
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))
|
|
23
|
+
return np.column_stack(np.where(((-4 < signs_sum) & (signs_sum < 4))[:-1, 1:])[::-1]) / self.plot.scale()
|
|
24
|
+
|
|
25
|
+
def update_function(self, new_function) -> None:
|
|
26
|
+
self.function = new_function
|
|
27
|
+
self.points = self.get_points()
|
|
28
|
+
self.render()
|
|
29
|
+
|
|
30
|
+
def render(self) -> None:
|
|
31
|
+
self.__layer_surface__.fill((0,0,0,0))
|
|
32
|
+
offset = self.plot.dragging - self.plot.start_dragging if (self.plot.dragging != None) and (not self.plot.settings.get("use_real_time_rendering")) else None
|
|
33
|
+
if any(x < 1 for x in self.plot.scale):
|
|
34
|
+
for point in self.points:
|
|
35
|
+
# radius = max(min(self.plot.pixel_size)*.5, 1)
|
|
36
|
+
# pg.draw.circle(self.plot.canvas, self.color, (point + self.plot.pixel_size*.5)(), radius)
|
|
37
|
+
pg.draw.rect(self.__layer_surface__, self.color, (point.tolist() + (offset if offset != None else V2z))() + self.plot.pixel_size()) #type: ignore
|
|
38
|
+
else:
|
|
39
|
+
for point in self.points:
|
|
40
|
+
point = point.astype(int).tolist()
|
|
41
|
+
if self.plot.dragging != None:
|
|
42
|
+
point = round(point + offset)()
|
|
43
|
+
self.__layer_surface__.set_at(point, self.color)
|
|
44
|
+
|
|
45
|
+
def draw(self) -> None:
|
|
46
|
+
self.plot.canvas.blit(self.__layer_surface__, (0,0))
|
|
47
|
+
|
|
48
|
+
# class ComplexFunction:
|
|
49
|
+
# 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:
|
|
50
|
+
# self.auto_connect_treshold = auto_connect_treshold
|
|
51
|
+
# self.plot = plot
|
|
52
|
+
# self.starting_t = starting_t
|
|
53
|
+
# self.ending_t = ending_t
|
|
54
|
+
# self.color = color
|
|
55
|
+
# self.step = step
|
|
56
|
+
# self.points_color = points_color
|
|
57
|
+
# self.points_radius = points_radius
|
|
58
|
+
# self.update_function(function)
|
|
59
|
+
|
|
60
|
+
# def update_points(self) -> None:
|
|
61
|
+
# self.update_function(self.function)
|
|
62
|
+
|
|
63
|
+
# def update_function(self, new_function) -> None:
|
|
64
|
+
# self.function = new_function
|
|
65
|
+
# 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)]
|
|
66
|
+
# self.full_auto_connect = not any(point.distance_to(self.points[i]) > self.auto_connect_treshold for i,point in enumerate(self.points[1:]))
|
|
67
|
+
|
|
68
|
+
# def draw(self) -> None:
|
|
69
|
+
# if self.points_radius:
|
|
70
|
+
# for point in self.points:
|
|
71
|
+
# pg.draw.circle(self.plot.canvas, self.color if self.points_color == None else self.points_color, self.plot.__plot2real__(point)(), self.points_radius)
|
|
72
|
+
|
|
73
|
+
# if len(self.points) < 2: return
|
|
74
|
+
# if self.full_auto_connect:
|
|
75
|
+
# pg.draw.lines(self.plot.canvas, self.color, False, [self.plot.__plot2real__(point)() for point in self.points])
|
|
76
|
+
# else:
|
|
77
|
+
# real_points = [self.plot.__plot2real__(point)() for point in self.points]
|
|
78
|
+
# for i,(point, real_point) in enumerate(zip(self.points[1:], real_points[1:])):
|
|
79
|
+
# if point.distance_to(self.points[i]) < self.auto_connect_treshold:
|
|
80
|
+
# pg.draw.line(self.plot.canvas, self.color, real_points[i], real_point) #type: ignore
|
|
81
|
+
|
|
82
|
+
class __PlotSettings__:
|
|
83
|
+
def __init__(self, plot:Plot) -> None:
|
|
84
|
+
self.plot = plot
|
|
85
|
+
self.settings :dict[str: bool|V2|Vector2D|int|float]= {
|
|
86
|
+
"use_real_time_rendering" : True,
|
|
87
|
+
"show_corners_coords" : True,
|
|
88
|
+
|
|
89
|
+
"use_inter_pixel_correction" : True,
|
|
90
|
+
|
|
91
|
+
"show_zoom_info": True,
|
|
92
|
+
"top_left_info_position" : self.plot.position + V2(20, 100),
|
|
93
|
+
"info_spacing" : V2(0, 32),
|
|
94
|
+
"info_precision" : 2,
|
|
95
|
+
|
|
96
|
+
"distance_to_axis_for_scalar_zoom" : 10,
|
|
97
|
+
|
|
98
|
+
"bg_color" : (25, 25, 25),
|
|
99
|
+
"axes_default_color" : (100, 100, 100),
|
|
100
|
+
"x_axis_color" : None,
|
|
101
|
+
"y_axis_color" : None,
|
|
102
|
+
|
|
103
|
+
"axes_default_width" : 5,
|
|
104
|
+
"x_axis_width" : None,
|
|
105
|
+
"y_axis_width" : None,
|
|
106
|
+
|
|
107
|
+
"show_cursor_coords" : False,
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
def print_current_settings(self) -> None:
|
|
111
|
+
longest_key = max(map(len, self.settings))
|
|
112
|
+
longest_type = max(map(lambda setting: len(str(type(setting)).split("'")[1]), self.settings.values()))
|
|
113
|
+
for setting in self.settings:
|
|
114
|
+
print(f"{setting}{' '*(longest_key-len(setting))} :{str(type(self.settings[setting])).split("'")[1]}{' '*(longest_type-len(str(type(self.settings[setting])).split("'")[1]))}=\t{self.settings[setting]}")
|
|
115
|
+
|
|
116
|
+
def set(self, key:str, new_value) -> None:
|
|
117
|
+
if not (key in self.settings): raise ValueError(f"The key [{key}] does not exist...")
|
|
118
|
+
self.settings[key] = new_value
|
|
119
|
+
|
|
120
|
+
def multiple_set(self, keys:list[str], new_values:list) -> None:
|
|
121
|
+
for key, new_value in zip(keys, new_values):
|
|
122
|
+
self.set(key, new_value)
|
|
123
|
+
|
|
124
|
+
def get(self, key:str) -> bool|V2|Vector2D|int|float:
|
|
125
|
+
return self.settings[key]
|
|
126
|
+
|
|
127
|
+
def multiple_set(self, keys:list[str]) -> list[bool|V2|Vector2D|int|float]:
|
|
128
|
+
return [self.get(key) for key in keys]
|
|
129
|
+
|
|
130
|
+
class Plot:
|
|
131
|
+
__top_left_multiplier__ = V2(1, -1)
|
|
132
|
+
__bottop_right_multiplier__ = V2(1, -1)
|
|
133
|
+
def __init__(self, rootEnv:"RootEnv", plot_position:V2|Vector2D, plot_size:V2|Vector2D, top_left_plot_coord:V2|Vector2D, bottom_right_plot_coord: V2|Vector2D, scale:V2|Vector2D=V2one) -> None:
|
|
134
|
+
self.rootEnv = rootEnv
|
|
135
|
+
|
|
136
|
+
self.top_left_plot_coord = top_left_plot_coord
|
|
137
|
+
self.bottom_right_plot_coord = bottom_right_plot_coord
|
|
138
|
+
|
|
139
|
+
self.position = plot_position
|
|
140
|
+
self.size = plot_size
|
|
141
|
+
self.scale = scale
|
|
142
|
+
|
|
143
|
+
self.settings = __PlotSettings__(self)
|
|
144
|
+
|
|
145
|
+
self.current_zoom = V2one * -np.log2(10)*10
|
|
146
|
+
self.current_offset = V2(0,0)
|
|
147
|
+
self.update_grid(True)
|
|
148
|
+
|
|
149
|
+
self.functions :list[Function]= []
|
|
150
|
+
|
|
151
|
+
self.canvas = pg.Surface(self.size())
|
|
152
|
+
self.dragging = None
|
|
153
|
+
self.start_dragging = V2z
|
|
154
|
+
self.is_mouse_in_rect = False
|
|
155
|
+
|
|
156
|
+
def set_borders_by_position_and_zoom(self) -> None:
|
|
157
|
+
self.top_left_plot_coord = self.current_offset - (.5**(.1*self.current_zoom)) * self.__top_left_multiplier__
|
|
158
|
+
self.bottom_right_plot_coord = self.current_offset + (.5**(.1*self.current_zoom)) * self.__bottop_right_multiplier__
|
|
159
|
+
self.top_left_x, self.top_left_y = self.top_left_plot_coord
|
|
160
|
+
self.bottom_right_x, self.bottom_right_y = self.bottom_right_plot_coord
|
|
161
|
+
|
|
162
|
+
def update_grid(self, update_step_grid=False) -> None:
|
|
163
|
+
self.set_borders_by_position_and_zoom()
|
|
164
|
+
if update_step_grid:
|
|
165
|
+
self.step = (self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size / self.scale
|
|
166
|
+
X, Y = np.arange(self.top_left_plot_coord.x, self.bottom_right_plot_coord.x, self.step.x), np.arange(self.top_left_plot_coord.y, self.bottom_right_plot_coord.y, self.step.y)
|
|
167
|
+
self.meshgrid = np.meshgrid(X, Y)
|
|
168
|
+
self.pixel_size = abs(self.size / (self.bottom_right_plot_coord - self.top_left_plot_coord) * (self.step * -1))
|
|
169
|
+
if self.settings.get("use_inter_pixel_correction"):
|
|
170
|
+
self.pixel_size += V2one
|
|
171
|
+
|
|
172
|
+
def load_function(self, function:Function) -> None:
|
|
173
|
+
function.plot = self
|
|
174
|
+
function.__layer_surface__ = pg.Surface(self.size(), pg.SRCALPHA, 32).convert_alpha()
|
|
175
|
+
function.update_function(function.function)
|
|
176
|
+
self.functions.append(function)
|
|
177
|
+
|
|
178
|
+
def __plot2real__(self, plot_position:V2|Vector2D) -> V2|Vector2D:
|
|
179
|
+
return (plot_position + self.top_left_plot_coord * -1) * self.size / (self.bottom_right_plot_coord - self.top_left_plot_coord)
|
|
180
|
+
|
|
181
|
+
def __real2plot__(self, real_position:V2|Vector2D) -> V2|Vector2D:
|
|
182
|
+
return (real_position - self.position) * (self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size + self.top_left_plot_coord
|
|
183
|
+
|
|
184
|
+
def render(self) -> None:
|
|
185
|
+
self.canvas.fill(self.settings.get("bg_color"))
|
|
186
|
+
if self.top_left_x < 0 < self.bottom_right_x:
|
|
187
|
+
pg.draw.line(self.canvas,
|
|
188
|
+
self.settings.get("axes_default_color") if (x_color:=self.settings.get("x_axis_color"))==None else x_color,
|
|
189
|
+
self.__plot2real__(V2(0, self.top_left_y))(),
|
|
190
|
+
self.__plot2real__(V2(0, self.bottom_right_y))(),
|
|
191
|
+
self.settings.get("axes_default_width") if (x_width:=self.settings.get("x_axis_width"))==None else x_width)
|
|
192
|
+
if self.bottom_right_y < 0 < self.top_left_y:
|
|
193
|
+
pg.draw.line(self.canvas,
|
|
194
|
+
self.settings.get("axes_default_color") if (y_color:=self.settings.get("y_axis_color"))==None else y_color,
|
|
195
|
+
self.__plot2real__(V2(self.top_left_x, 0))(),
|
|
196
|
+
self.__plot2real__(V2(self.bottom_right_x, 0))(),
|
|
197
|
+
self.settings.get("axes_default_width") if (y_width:=self.settings.get("y_axis_width"))==None else y_width)
|
|
198
|
+
|
|
199
|
+
for function in self.functions: function.draw()
|
|
200
|
+
|
|
201
|
+
pg.draw.rect(self.canvas, (255,255,255), V2z() + self.size(), 5) #type: ignore
|
|
202
|
+
|
|
203
|
+
center = self.size * .5
|
|
204
|
+
aimer_radius = 15
|
|
205
|
+
pg.draw.line(self.canvas, (100,100,100), (center + aimer_radius)(), (center - aimer_radius)(), 1)
|
|
206
|
+
pg.draw.line(self.canvas, (100,100,100), (center + self.__top_left_multiplier__ * aimer_radius)(), (center - self.__top_left_multiplier__ * aimer_radius)(), 1)
|
|
207
|
+
pg.draw.circle(self.canvas, (100,100,100), (self.size * .5)(), 15, 1)
|
|
208
|
+
|
|
209
|
+
if self.settings.get("show_corners_coords"):
|
|
210
|
+
self.rootEnv.print(str(self.top_left_plot_coord.__round__(.1)), 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)
|
|
211
|
+
self.rootEnv.print(str(V2(self.top_left_plot_coord.x, self.bottom_right_plot_coord.y).__round__(.1)), 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)
|
|
212
|
+
self.rootEnv.print(str(self.bottom_right_plot_coord.__round__(.1)), 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)
|
|
213
|
+
self.rootEnv.print(str(V2(self.bottom_right_plot_coord.x, self.top_left_plot_coord.y).__round__(.1)), 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)
|
|
214
|
+
|
|
215
|
+
def update(self) -> None:
|
|
216
|
+
self.plot_mouse_position = self.__real2plot__(self.rootEnv.mouse.position)
|
|
217
|
+
self.plot_center_real_position = self.__plot2real__(V2z) + self.position
|
|
218
|
+
|
|
219
|
+
self.is_mouse_in_rect = self.position.x < self.rootEnv.mouse.position.x < self.position.x + self.size.x and \
|
|
220
|
+
self.position.y < self.rootEnv.mouse.position.y < self.position.y + self.size.y
|
|
221
|
+
|
|
222
|
+
if self.rootEnv.mouse.just_released[0] and self.dragging != None:
|
|
223
|
+
self.dragging = None
|
|
224
|
+
self.update_grid(True)
|
|
225
|
+
for function in self.functions:
|
|
226
|
+
function.update_points()
|
|
227
|
+
self.render()
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
if self.is_mouse_in_rect:
|
|
231
|
+
for event in self.rootEnv.events:
|
|
232
|
+
if event.type == pg.MOUSEWHEEL:
|
|
233
|
+
|
|
234
|
+
range_n = self.settings.get("distance_to_axis_for_scalar_zoom")
|
|
235
|
+
scalar = V2(0 if abs(self.plot_center_real_position.x - self.rootEnv.mouse.position.x) < range_n else 1, 0 if abs(self.plot_center_real_position.y - self.rootEnv.mouse.position.y) < range_n else 1)
|
|
236
|
+
self.current_zoom += event.y * scalar
|
|
237
|
+
|
|
238
|
+
self.update_grid(True)
|
|
239
|
+
for function in self.functions:
|
|
240
|
+
function.update_points()
|
|
241
|
+
self.render()
|
|
242
|
+
|
|
243
|
+
if self.rootEnv.mouse.just_pressed[0] and self.dragging == None:
|
|
244
|
+
self.dragging = self.rootEnv.mouse.position.copy()
|
|
245
|
+
self.start_dragging = self.dragging.copy()
|
|
246
|
+
|
|
247
|
+
if self.dragging:
|
|
248
|
+
offset = (self.dragging - self.rootEnv.mouse.position)* V2(1, -1) * (abs(self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size)
|
|
249
|
+
self.dragging = self.rootEnv.mouse.position.copy()
|
|
250
|
+
self.current_offset += offset
|
|
251
|
+
|
|
252
|
+
if self.settings.get("use_real_time_rendering"):
|
|
253
|
+
self.update_grid(True)
|
|
254
|
+
for function in self.functions: function.update_points()
|
|
255
|
+
else:
|
|
256
|
+
self.update_grid()
|
|
257
|
+
self.render()
|
|
258
|
+
|
|
259
|
+
def draw(self) -> None:
|
|
260
|
+
self.rootEnv.screen.blit(self.canvas, self.position())
|
|
261
|
+
if self.is_mouse_in_rect and self.settings.get("show_cursor_coords"):
|
|
262
|
+
self.rootEnv.print(str(round(self.plot_mouse_position, .1)), self.rootEnv.mouse.position, fixed_sides=TEXT_FIXED_SIDES_BOTTOM_MIDDLE)
|
|
263
|
+
|
|
264
|
+
data = [
|
|
265
|
+
[f"ZOOM:", TEXT_FIXED_SIDES_TOP_LEFT, self.settings.get("show_zoom_info")],
|
|
266
|
+
[f" x: {self.current_zoom.x:.{self.settings.get("info_precision")}f};", TEXT_FIXED_SIDES_TOP_LEFT, self.settings.get("show_zoom_info")],
|
|
267
|
+
[f" y: {self.current_zoom.y:.{self.settings.get("info_precision")}f};", TEXT_FIXED_SIDES_TOP_LEFT, self.settings.get("show_zoom_info")],
|
|
268
|
+
]
|
|
269
|
+
|
|
270
|
+
for i, (d, fixed_side, show) in enumerate(data):
|
|
271
|
+
if show:
|
|
272
|
+
self.rootEnv.print(d, self.settings.get("top_left_info_position") + self.settings.get("info_spacing") * i, fixed_sides=fixed_side)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: e2D
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.4
|
|
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.4
|
|
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.2/e2D/plots.py
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
from .envs import *
|
|
2
|
-
import numpy as np
|
|
3
|
-
import pickle as pk
|
|
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
|
-
class Function:
|
|
12
|
-
def __init__(self, function, plot:"Plot", color) -> None:
|
|
13
|
-
self.plot = plot
|
|
14
|
-
self.color = color
|
|
15
|
-
self.update_function(function)
|
|
16
|
-
|
|
17
|
-
def update_points(self) -> None:
|
|
18
|
-
self.update_function(self.function)
|
|
19
|
-
|
|
20
|
-
def get_points(self) -> list:
|
|
21
|
-
signs_self = np.sign(self.function(*self.plot.meshgrid))
|
|
22
|
-
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))
|
|
23
|
-
return np.column_stack(np.where(((-4 < signs_sum) & (signs_sum < 4))[:-1, 1:])[::-1]) / self.plot.scale()
|
|
24
|
-
|
|
25
|
-
def update_function(self, new_function) -> None:
|
|
26
|
-
self.function = new_function
|
|
27
|
-
self.points = self.get_points()
|
|
28
|
-
|
|
29
|
-
def draw(self) -> None:
|
|
30
|
-
# pg.draw.aalines(self.plot.canvas, self.color, False, self.points)
|
|
31
|
-
for point in self.points:
|
|
32
|
-
self.plot.canvas.set_at(list(map(int, point)), self.color)
|
|
33
|
-
|
|
34
|
-
# class ComplexFunction:
|
|
35
|
-
# 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:
|
|
36
|
-
# self.auto_connect_treshold = auto_connect_treshold
|
|
37
|
-
# self.plot = plot
|
|
38
|
-
# self.starting_t = starting_t
|
|
39
|
-
# self.ending_t = ending_t
|
|
40
|
-
# self.color = color
|
|
41
|
-
# self.step = step
|
|
42
|
-
# self.points_color = points_color
|
|
43
|
-
# self.points_radius = points_radius
|
|
44
|
-
# self.update_function(function)
|
|
45
|
-
|
|
46
|
-
# def update_points(self) -> None:
|
|
47
|
-
# self.update_function(self.function)
|
|
48
|
-
|
|
49
|
-
# def update_function(self, new_function) -> None:
|
|
50
|
-
# self.function = new_function
|
|
51
|
-
# 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)]
|
|
52
|
-
# self.full_auto_connect = not any(point.distance_to(self.points[i]) > self.auto_connect_treshold for i,point in enumerate(self.points[1:]))
|
|
53
|
-
|
|
54
|
-
# def draw(self) -> None:
|
|
55
|
-
# if self.points_radius:
|
|
56
|
-
# for point in self.points:
|
|
57
|
-
# pg.draw.circle(self.plot.canvas, self.color if self.points_color == None else self.points_color, self.plot.__plot2real__(point)(), self.points_radius)
|
|
58
|
-
|
|
59
|
-
# if len(self.points) < 2: return
|
|
60
|
-
# if self.full_auto_connect:
|
|
61
|
-
# pg.draw.lines(self.plot.canvas, self.color, False, [self.plot.__plot2real__(point)() for point in self.points])
|
|
62
|
-
# else:
|
|
63
|
-
# real_points = [self.plot.__plot2real__(point)() for point in self.points]
|
|
64
|
-
# for i,(point, real_point) in enumerate(zip(self.points[1:], real_points[1:])):
|
|
65
|
-
# if point.distance_to(self.points[i]) < self.auto_connect_treshold:
|
|
66
|
-
# pg.draw.line(self.plot.canvas, self.color, real_points[i], real_point) #type: ignore
|
|
67
|
-
|
|
68
|
-
class Plot:
|
|
69
|
-
__top_left_multiplier__ = V2(1, -1)
|
|
70
|
-
__bottop_right_multiplier__ = V2(1, -1)
|
|
71
|
-
def __init__(self, rootEnv:"RootEnv", plot_position:V2|Vector2D, plot_size:V2|Vector2D, top_left_plot_coord:V2|Vector2D, bottom_right_plot_coord: V2|Vector2D, scale:V2|Vector2D=V2one) -> None:
|
|
72
|
-
self.rootEnv = rootEnv
|
|
73
|
-
|
|
74
|
-
self.top_left_plot_coord = top_left_plot_coord
|
|
75
|
-
self.bottom_right_plot_coord = bottom_right_plot_coord
|
|
76
|
-
|
|
77
|
-
self.position = plot_position
|
|
78
|
-
self.size = plot_size
|
|
79
|
-
self.scale = scale
|
|
80
|
-
|
|
81
|
-
self.current_zoom = V2one * -np.log2(10)*10
|
|
82
|
-
self.current_offset = V2(0,0)
|
|
83
|
-
self.update_grid(True)
|
|
84
|
-
|
|
85
|
-
self.functions :list[Function]= []
|
|
86
|
-
|
|
87
|
-
self.canvas = pg.Surface(self.size())
|
|
88
|
-
self.dragging = None
|
|
89
|
-
self.is_mouse_in_rect = False
|
|
90
|
-
|
|
91
|
-
def set_borders_by_position_and_zoom(self) -> None:
|
|
92
|
-
self.top_left_plot_coord = self.current_offset - (.5**(.1*self.current_zoom)) * self.__top_left_multiplier__
|
|
93
|
-
self.bottom_right_plot_coord = self.current_offset + (.5**(.1*self.current_zoom)) * self.__bottop_right_multiplier__
|
|
94
|
-
self.top_left_x, self.top_left_y = self.top_left_plot_coord
|
|
95
|
-
self.bottom_right_x, self.bottom_right_y = self.bottom_right_plot_coord
|
|
96
|
-
|
|
97
|
-
def update_grid(self, update_step_grid=False) -> None:
|
|
98
|
-
self.set_borders_by_position_and_zoom()
|
|
99
|
-
if update_step_grid:
|
|
100
|
-
self.step = (self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size / self.scale
|
|
101
|
-
X, Y = np.arange(self.top_left_plot_coord.x, self.bottom_right_plot_coord.x, self.step.x), np.arange(self.top_left_plot_coord.y, self.bottom_right_plot_coord.y, self.step.y)
|
|
102
|
-
self.meshgrid = np.meshgrid(X, Y)
|
|
103
|
-
|
|
104
|
-
def load_function(self, function:Function) -> None:
|
|
105
|
-
self.functions.append(function)
|
|
106
|
-
|
|
107
|
-
def __plot2real__(self, plot_position:V2|Vector2D) -> V2|Vector2D:
|
|
108
|
-
return (plot_position + self.top_left_plot_coord * -1) * self.size / (self.bottom_right_plot_coord - self.top_left_plot_coord)
|
|
109
|
-
|
|
110
|
-
def __real2plot__(self, real_position:V2|Vector2D) -> V2|Vector2D:
|
|
111
|
-
return (real_position - self.position) * (self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size + self.top_left_plot_coord
|
|
112
|
-
|
|
113
|
-
def render(self) -> None:
|
|
114
|
-
self.canvas.fill((0,0,0))
|
|
115
|
-
if self.bottom_right_y < 0 < self.top_left_y: pg.draw.line(self.canvas, (100,100,100), self.__plot2real__(V2(self.top_left_x, 0))(), self.__plot2real__(V2(self.bottom_right_x, 0))())
|
|
116
|
-
if self.top_left_x < 0 < self.bottom_right_x: pg.draw.line(self.canvas, (100,100,100), self.__plot2real__(V2(0, self.top_left_y))(), self.__plot2real__(V2(0, self.bottom_right_y))())
|
|
117
|
-
|
|
118
|
-
for function in self.functions: function.draw()
|
|
119
|
-
|
|
120
|
-
pg.draw.rect(self.canvas, (255,255,255), V2z() + self.size(), 5) #type: ignore
|
|
121
|
-
self.rootEnv.print(str(self.top_left_plot_coord.__round__(.1)), 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)
|
|
122
|
-
self.rootEnv.print(str(V2(self.top_left_plot_coord.x, self.bottom_right_plot_coord.y).__round__(.1)), 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)
|
|
123
|
-
self.rootEnv.print(str(self.bottom_right_plot_coord.__round__(.1)), 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)
|
|
124
|
-
self.rootEnv.print(str(V2(self.bottom_right_plot_coord.x, self.top_left_plot_coord.y).__round__(.1)), 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)
|
|
125
|
-
|
|
126
|
-
def update(self) -> None:
|
|
127
|
-
self.is_mouse_in_rect = self.position.x < self.rootEnv.mouse.position.x < self.position.x + self.size.x and \
|
|
128
|
-
self.position.y < self.rootEnv.mouse.position.y < self.position.y + self.size.y
|
|
129
|
-
|
|
130
|
-
if self.rootEnv.mouse.just_released[0] and self.dragging != None:
|
|
131
|
-
self.dragging = None
|
|
132
|
-
self.update_grid(True)
|
|
133
|
-
for function in self.functions:
|
|
134
|
-
function.update_points()
|
|
135
|
-
self.render()
|
|
136
|
-
|
|
137
|
-
if self.is_mouse_in_rect:
|
|
138
|
-
for event in self.rootEnv.events:
|
|
139
|
-
if event.type == pg.MOUSEWHEEL:
|
|
140
|
-
self.current_zoom += event.y
|
|
141
|
-
self.update_grid(True)
|
|
142
|
-
for function in self.functions:
|
|
143
|
-
function.update_points()
|
|
144
|
-
self.render()
|
|
145
|
-
|
|
146
|
-
if self.rootEnv.mouse.just_pressed[0] and self.dragging == None:
|
|
147
|
-
self.dragging = self.rootEnv.mouse.position.copy()
|
|
148
|
-
|
|
149
|
-
if self.dragging:
|
|
150
|
-
offset = (self.dragging - self.rootEnv.mouse.position)* V2(1, -1) * (abs(self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size)
|
|
151
|
-
self.dragging = self.rootEnv.mouse.position.copy()
|
|
152
|
-
self.current_offset += offset
|
|
153
|
-
self.update_grid()
|
|
154
|
-
self.render()
|
|
155
|
-
|
|
156
|
-
def draw(self) -> None:
|
|
157
|
-
self.rootEnv.screen.blit(self.canvas, self.position())
|
|
158
|
-
if self.is_mouse_in_rect:
|
|
159
|
-
self.rootEnv.print(str(round(self.__real2plot__(self.rootEnv.mouse.position), .1)), self.rootEnv.mouse.position, fixed_sides=TEXT_FIXED_SIDES_BOTTOM_MIDDLE)
|
{e2D-1.3.2 → e2D-1.3.4}/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|