simple2d-3d 0.1.0__py3-none-any.whl
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.
- simple2d_3d/__init__.py +5 -0
- simple2d_3d/colors.py +22 -0
- simple2d_3d/render.py +395 -0
- simple2d_3d/setup.py +23 -0
- simple2d_3d-0.1.0.dist-info/METADATA +17 -0
- simple2d_3d-0.1.0.dist-info/RECORD +9 -0
- simple2d_3d-0.1.0.dist-info/WHEEL +5 -0
- simple2d_3d-0.1.0.dist-info/licenses/LICENSE +19 -0
- simple2d_3d-0.1.0.dist-info/top_level.txt +1 -0
simple2d_3d/__init__.py
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
from .setup import Init as init , CleanUp as clean_up
|
|
2
|
+
from .render import Camera , Vector3 , Rect , Line , Circle , Scene , Scene2D , Raycaster2D , BreakObject2D as break_object_2d , CreatePlatform2D as create_platform_2d , CreatePlatform as create_platform , Project2D as project_2d, DrawFilledFace as draw_filled_face, Cube
|
|
3
|
+
from . import colors
|
|
4
|
+
__all__ = [
|
|
5
|
+
"init" , "clean_up" , "Camera" , "Vector3" , "Rect" , "Circle" , "Line" , "Scene" , "Scene2D" , "Raycaster2D" , "break_object_2d" , "create_platform_2d" , "create_platform" , "project_2d" , "draw_filled_face" , "Cube" , "colors"]
|
simple2d_3d/colors.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import sdl2
|
|
2
|
+
RED = sdl2.SDL_Color(255,0,0,255)
|
|
3
|
+
GREEN = sdl2.SDL_Color(0,255,0,255)
|
|
4
|
+
BLUE = sdl2.SDL_Color(0,0,255,255)
|
|
5
|
+
YELLOW = sdl2.SDL_Color(255,255,0,255)
|
|
6
|
+
CYAN = sdl2.SDL_Color(0,255,255,255)
|
|
7
|
+
WHITE = sdl2.SDL_Color(255,255,255,255)
|
|
8
|
+
BLACK = sdl2.SDL_Color(0,0,0,255)
|
|
9
|
+
GHOST_WHITE = sdl2.SDL_Color(248, 248, 255, 128)
|
|
10
|
+
SHADOW = sdl2.SDL_Color(0, 0, 0, 150)
|
|
11
|
+
TERRA_COTTA = sdl2.SDL_Color(226, 114, 91, 255)
|
|
12
|
+
GOLDENROD = sdl2.SDL_Color(218, 165, 32, 255)
|
|
13
|
+
OLIVE_DRAB = sdl2.SDL_Color(107, 142, 35, 255)
|
|
14
|
+
CORAL = sdl2.SDL_Color(255, 127, 80, 255)
|
|
15
|
+
ELECTRIC_PURPLE = sdl2.SDL_Color(191, 0, 255, 255)
|
|
16
|
+
NEON_PINK = sdl2.SDL_Color(255, 20, 147, 255)
|
|
17
|
+
MINT_GREEN = sdl2.SDL_Color(152, 255, 152, 255)
|
|
18
|
+
TURQUOISE = sdl2.SDL_Color(64, 224, 208, 255)
|
|
19
|
+
MIDNIGHT_BLUE = sdl2.SDL_Color(25, 25, 112, 255)
|
|
20
|
+
SLATE_GRAY = sdl2.SDL_Color(112, 128, 144, 255)
|
|
21
|
+
CHARCOAL = sdl2.SDL_Color(54, 69, 79, 255)
|
|
22
|
+
EGGPLANT = sdl2.SDL_Color(49, 18, 59, 255)
|
simple2d_3d/render.py
ADDED
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import math , sdl2 , ctypes
|
|
2
|
+
from .colors import *
|
|
3
|
+
class Camera:
|
|
4
|
+
def __init__(self,x,y,z,yaw,pitch):
|
|
5
|
+
self.pos = Vector3(x,y,z)
|
|
6
|
+
self.yaw = yaw
|
|
7
|
+
self.pitch = pitch
|
|
8
|
+
|
|
9
|
+
class Vector3:
|
|
10
|
+
__slots__ = ['x', 'y', 'z']
|
|
11
|
+
|
|
12
|
+
def __init__(self, x=0.0, y=0.0, z=0.0):
|
|
13
|
+
self.x = float(x)
|
|
14
|
+
self.y = float(y)
|
|
15
|
+
self.z = float(z)
|
|
16
|
+
|
|
17
|
+
def __sub__(self, other):
|
|
18
|
+
return Vector3(self.x - other.x, self.y - other.y, self.z - other.z)
|
|
19
|
+
|
|
20
|
+
def dot(self, other):
|
|
21
|
+
return self.x * other.x + self.y * other.y + self.z * other.z
|
|
22
|
+
|
|
23
|
+
def cross(self, other):
|
|
24
|
+
return Vector3(
|
|
25
|
+
self.y * other.z - self.z * other.y,
|
|
26
|
+
self.z * other.x - self.x * other.z,
|
|
27
|
+
self.x * other.y - self.y * other.x
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
def Project2D(x, y, z , width , height):
|
|
31
|
+
if z <= 1: z = 1
|
|
32
|
+
ratio = height / width
|
|
33
|
+
fov_angle = 110
|
|
34
|
+
fov_rad = 1.0 / math.tan(fov_angle * 0.5 * math.pi / 180.0)
|
|
35
|
+
|
|
36
|
+
px = x * fov_rad * ratio / z
|
|
37
|
+
py = y * fov_rad / z
|
|
38
|
+
|
|
39
|
+
px = (px + 1) * 0.5 * width
|
|
40
|
+
py = (py + 1) * 0.5 * height
|
|
41
|
+
|
|
42
|
+
return px, py
|
|
43
|
+
|
|
44
|
+
def DrawFilledFace(renderer,idx1 , idx2 , idx3,points,color):
|
|
45
|
+
if points[idx1] and points[idx2] and points[idx3]:
|
|
46
|
+
#color = RED
|
|
47
|
+
v1 = sdl2.SDL_Vertex(sdl2.SDL_FPoint(points[idx1].x, points[idx1].y), color, sdl2.SDL_FPoint(0,0))
|
|
48
|
+
#color = BLUE
|
|
49
|
+
v2 = sdl2.SDL_Vertex(sdl2.SDL_FPoint(points[idx2].x, points[idx2].y), color, sdl2.SDL_FPoint(0,0))
|
|
50
|
+
#color = GREEN
|
|
51
|
+
v3 = sdl2.SDL_Vertex(sdl2.SDL_FPoint(points[idx3].x, points[idx3].y), color, sdl2.SDL_FPoint(0,0))
|
|
52
|
+
triangle_verts = (sdl2.SDL_Vertex * 3)(v1, v2, v3)
|
|
53
|
+
sdl2.SDL_RenderGeometry(renderer, None, triangle_verts, 3, None, 0)
|
|
54
|
+
|
|
55
|
+
class Cube:
|
|
56
|
+
def __init__(self,x,y,z,w,h,d,color):
|
|
57
|
+
self.pos = Vector3(x,y,z)
|
|
58
|
+
self.size = Vector3(w,h,d)
|
|
59
|
+
self.color = color
|
|
60
|
+
self.dist = 0
|
|
61
|
+
self.vertices = [
|
|
62
|
+
Vector3(-self.size.x , -self.size.y , -self.size.z), # 0
|
|
63
|
+
Vector3(-self.size.x , -self.size.y , self.size.z), # 1
|
|
64
|
+
Vector3(self.size.x , -self.size.y , self.size.z), # 2
|
|
65
|
+
Vector3(self.size.x, -self.size.y , -self.size.z), # 3
|
|
66
|
+
Vector3(self.size.x , self.size.y , -self.size.z), # 4
|
|
67
|
+
Vector3(-self.size.x , self.size.y , -self.size.z), # 5
|
|
68
|
+
Vector3(-self.size.x , self.size.y , self.size.z), # 6
|
|
69
|
+
Vector3(self.size.x , self.size.y , self.size.z) # 7
|
|
70
|
+
]
|
|
71
|
+
# Each line is ONE triangle (3 indices)
|
|
72
|
+
self.triangle_indices = [
|
|
73
|
+
# FRONT (Z-) - Looking from the front
|
|
74
|
+
0, 3, 4, 0, 4, 5,
|
|
75
|
+
# BACK (Z+) - Looking from the back
|
|
76
|
+
2, 1, 6, 2, 6, 7,
|
|
77
|
+
# RIGHT (X+) - Looking from the right
|
|
78
|
+
3, 2, 7, 3, 7, 4,
|
|
79
|
+
# LEFT (X-) - Looking from the left
|
|
80
|
+
1, 0, 5, 1, 5, 6,
|
|
81
|
+
# TOP (Y-) - Looking from above
|
|
82
|
+
0, 1, 2, 0, 2, 3,
|
|
83
|
+
# BOTTOM (Y+) - Looking from below
|
|
84
|
+
5, 4, 7, 5, 7, 6
|
|
85
|
+
]
|
|
86
|
+
def DrawFilled(self,renderer,camera,sin_y,cos_y,sin_p,cos_p, width , height):
|
|
87
|
+
points = []
|
|
88
|
+
rotated_points = []
|
|
89
|
+
for v in self.vertices:
|
|
90
|
+
worldX = v.x + self.pos.x
|
|
91
|
+
worldY = v.y + self.pos.y
|
|
92
|
+
worldZ = v.z + self.pos.z
|
|
93
|
+
relX = worldX - camera.pos.x
|
|
94
|
+
relY = worldY - camera.pos.y
|
|
95
|
+
relZ = worldZ - camera.pos.z
|
|
96
|
+
rot_x = relX * cos_y + relZ * sin_y
|
|
97
|
+
temp_z = -relX * sin_y + relZ * cos_y
|
|
98
|
+
rot_y = relY * cos_p - temp_z * sin_p
|
|
99
|
+
rot_z = relY * sin_p + temp_z * cos_p
|
|
100
|
+
rotated_points.append(Vector3(rot_x,rot_y,rot_z))
|
|
101
|
+
|
|
102
|
+
result = Project2D(rot_x,rot_y,rot_z, width , height)
|
|
103
|
+
px , py = 0 , 0
|
|
104
|
+
if result == None: points.append(result)
|
|
105
|
+
else: px , py = result
|
|
106
|
+
px = round(px,1)
|
|
107
|
+
py = round(py,1)
|
|
108
|
+
points.append(sdl2.SDL_FPoint(px,py))
|
|
109
|
+
j = 0
|
|
110
|
+
while j < len(self.triangle_indices):
|
|
111
|
+
idx1 = self.triangle_indices[j]
|
|
112
|
+
idx2 = self.triangle_indices[j+1]
|
|
113
|
+
idx3 = self.triangle_indices[j+2]
|
|
114
|
+
v1 = rotated_points[idx1]
|
|
115
|
+
v2 = rotated_points[idx2]
|
|
116
|
+
v3 = rotated_points[idx3]
|
|
117
|
+
edge1 = v2 - v1
|
|
118
|
+
edge2 = v3 - v1
|
|
119
|
+
normal = edge1.cross(edge2)
|
|
120
|
+
if normal.dot(v1) > 0:
|
|
121
|
+
DrawFilledFace(renderer,idx1,idx2,idx3,points,self.color)
|
|
122
|
+
j += 3
|
|
123
|
+
|
|
124
|
+
class Scene:
|
|
125
|
+
def __init__(self,camera,near_limit,far_limit, width , height):
|
|
126
|
+
self.camera = camera
|
|
127
|
+
self.near_limit = near_limit
|
|
128
|
+
self.far_limit = far_limit
|
|
129
|
+
self.width = width
|
|
130
|
+
self.height = height
|
|
131
|
+
self.object_list = []
|
|
132
|
+
|
|
133
|
+
def add(self,object):
|
|
134
|
+
self.object_list.append(object)
|
|
135
|
+
|
|
136
|
+
def remove(self,object):
|
|
137
|
+
self.object_list.remove(object)
|
|
138
|
+
|
|
139
|
+
def draw(self,renderer):
|
|
140
|
+
for object in self.object_list:
|
|
141
|
+
dx = object.pos.x - self.camera.pos.x
|
|
142
|
+
dy = object.pos.y - self.camera.pos.y
|
|
143
|
+
dz = object.pos.z - self.camera.pos.z
|
|
144
|
+
object.dist = math.sqrt(dx*dx + dy*dy + dz*dz)
|
|
145
|
+
self.object_list.sort(key=lambda c: c.dist, reverse=True)
|
|
146
|
+
rad_y = math.radians(-self.camera.yaw)
|
|
147
|
+
rad_p = math.radians(-self.camera.pitch)
|
|
148
|
+
cos_y = math.cos(rad_y)
|
|
149
|
+
sin_y = math.sin(rad_y)
|
|
150
|
+
cos_p = math.cos(rad_p)
|
|
151
|
+
sin_p = math.sin(rad_p)
|
|
152
|
+
for object in self.object_list:
|
|
153
|
+
if object.dist <= self.near_limit or object.dist > self.far_limit:
|
|
154
|
+
continue
|
|
155
|
+
if object.dist > self.far_limit - 10:
|
|
156
|
+
if object.color.a > 0:
|
|
157
|
+
object.color.a -= int(object.color.a - object.dist - 50)
|
|
158
|
+
else: object.color.a = 255
|
|
159
|
+
if isinstance(object,Cube):
|
|
160
|
+
object.DrawFilled(renderer, self.camera,sin_y,cos_y,sin_p,cos_p,self.width,self.height)
|
|
161
|
+
|
|
162
|
+
def CreatePlatform(renderer,scene,x,y,z,w,h,d,size,space,color):
|
|
163
|
+
for i in range(w):
|
|
164
|
+
for j in range(h):
|
|
165
|
+
for k in range(d):
|
|
166
|
+
new_cube = Cube(
|
|
167
|
+
x + i*(size*2+space),
|
|
168
|
+
y + j*(size*2+space),
|
|
169
|
+
z + k*(size*2+space),
|
|
170
|
+
size , size , size,color)
|
|
171
|
+
scene.add(new_cube)
|
|
172
|
+
class Circle:
|
|
173
|
+
def __init__(self , x , y , r , color,cast_shadow=True,breakable=True):
|
|
174
|
+
self.x = x
|
|
175
|
+
self.y = y
|
|
176
|
+
self.r = r
|
|
177
|
+
self.c = color
|
|
178
|
+
self.cast_shadow = cast_shadow
|
|
179
|
+
self.breakable = breakable
|
|
180
|
+
|
|
181
|
+
def Update(self):
|
|
182
|
+
pass
|
|
183
|
+
|
|
184
|
+
def DrawFilled(self , renderer):
|
|
185
|
+
sdl2.SDL_SetRenderDrawColor(renderer,self.c.r , self.c.g , self.c.b , self.c.a)
|
|
186
|
+
for y in range(-self.r , self.r+1):
|
|
187
|
+
x = math.sqrt(self.r*self.r - y*y)
|
|
188
|
+
sdl2.SDL_RenderDrawLineF(renderer, self.x - x, self.y + y , self.x + x , self.y + y)
|
|
189
|
+
|
|
190
|
+
def remove(self):
|
|
191
|
+
pass
|
|
192
|
+
|
|
193
|
+
class Line:
|
|
194
|
+
def __init__(self,x1,y1,x2,y2,color,parent=None,cast_shadow=True,breakable=True):
|
|
195
|
+
self.x1 = x1
|
|
196
|
+
self.x2 = x2
|
|
197
|
+
self.y1 = y1
|
|
198
|
+
self.y2 = y2
|
|
199
|
+
self.c = color
|
|
200
|
+
self.parent = parent
|
|
201
|
+
self.cast_shadow = cast_shadow
|
|
202
|
+
self.breakable = breakable
|
|
203
|
+
|
|
204
|
+
def Update(self):
|
|
205
|
+
pass
|
|
206
|
+
|
|
207
|
+
def DrawFilled(self,renderer):
|
|
208
|
+
if self.parent == None:
|
|
209
|
+
sdl2.SDL_SetRenderDrawColor(renderer,self.c.r , self.c.g , self.c.b , self.c.a)
|
|
210
|
+
sdl2.SDL_RenderDrawLine(renderer,self.x1,self.y1,self.x2,self.y2)
|
|
211
|
+
else: pass
|
|
212
|
+
|
|
213
|
+
def remove(self):
|
|
214
|
+
pass
|
|
215
|
+
|
|
216
|
+
class Rect:
|
|
217
|
+
def __init__(self,x,y,w,h,color,scene,cast_shadow=True,breakable=True):
|
|
218
|
+
self.x = x
|
|
219
|
+
self.y = y
|
|
220
|
+
self.w = w
|
|
221
|
+
self.h = h
|
|
222
|
+
self.c = color
|
|
223
|
+
self.scene = scene
|
|
224
|
+
self.cast_shadow = cast_shadow
|
|
225
|
+
self.breakable = breakable
|
|
226
|
+
self.rect = sdl2.SDL_Rect(x,y,w,h)
|
|
227
|
+
self.line_list = []
|
|
228
|
+
self.line_list.append(Line(x,y,x+w,y,color,1,cast_shadow,breakable))
|
|
229
|
+
self.line_list.append(Line(x,y,x,y+h,color,1,cast_shadow,breakable))
|
|
230
|
+
self.line_list.append(Line(x,y+h,x+w,y+h,color,1,cast_shadow,breakable))
|
|
231
|
+
self.line_list.append(Line(x+w,y,x+w,y+h,color,1,cast_shadow,breakable))
|
|
232
|
+
|
|
233
|
+
def Update(self):
|
|
234
|
+
if len(self.line_list)<4: return
|
|
235
|
+
self.line_list[0].x1 , self.line_list[0].y1 , self.line_list[0].x2 , self.line_list[0].y2 , self.line_list[0].c , self.line_list[0].parent , self.line_list[0].breakable = self.x , self.y, self.x+self.w, self.y , self.c , 1 , self.breakable
|
|
236
|
+
|
|
237
|
+
self.line_list[1].x1 , self.line_list[1].y1 , self.line_list[1].x2 , self.line_list[1].y2 , self.line_list[1].c , self.line_list[1].parent , self.line_list[1].breakable = self.x , self.y, self.x , self.y+self.h , self.c , 1 , self.breakable
|
|
238
|
+
|
|
239
|
+
self.line_list[2].x1 , self.line_list[2].y1 , self.line_list[2].x2 , self.line_list[2].y2 , self.line_list[2].c , self.line_list[2].parent , self.line_list[2].breakable = self.x , self.y+self.h , self.x+self.w , self.y+self.h , self.c , 1 , self.breakable
|
|
240
|
+
|
|
241
|
+
self.line_list[3].x1 , self.line_list[3].y1 , self.line_list[3].x2 , self.line_list[3].y2 , self.line_list[3].c , self.line_list[3].parent , self.line_list[3].breakable = self.x+self.w , self.y , self.x+self.w , self.y+self.h , self.c , 1 , self.breakable
|
|
242
|
+
self.rect.x = self.x
|
|
243
|
+
self.rect.y = self.y
|
|
244
|
+
self.rect.w = self.w
|
|
245
|
+
self.rect.h = self.h
|
|
246
|
+
|
|
247
|
+
def DrawFilled(self,renderer):
|
|
248
|
+
sdl2.SDL_SetRenderDrawColor(renderer,self.c.r , self.c.g , self.c.b , self.c.a)
|
|
249
|
+
sdl2.SDL_RenderFillRect(renderer,ctypes.byref(self.rect))
|
|
250
|
+
return self.rect
|
|
251
|
+
|
|
252
|
+
def remove(self):
|
|
253
|
+
to_remove = list(self.line_list)
|
|
254
|
+
self.line_list.clear()
|
|
255
|
+
for line in to_remove:
|
|
256
|
+
self.scene.remove(line)
|
|
257
|
+
|
|
258
|
+
class Scene2D:
|
|
259
|
+
def __init__(self):
|
|
260
|
+
self.object_list = []
|
|
261
|
+
|
|
262
|
+
def add(self,object):
|
|
263
|
+
if isinstance(object,Rect):
|
|
264
|
+
for line in object.line_list:
|
|
265
|
+
self.object_list.append(line)
|
|
266
|
+
self.object_list.append(object)
|
|
267
|
+
|
|
268
|
+
def remove(self,object):
|
|
269
|
+
if object in self.object_list:
|
|
270
|
+
object.remove()
|
|
271
|
+
self.object_list.remove(object)
|
|
272
|
+
object = None
|
|
273
|
+
|
|
274
|
+
def update(self):
|
|
275
|
+
for object in self.object_list:
|
|
276
|
+
if object in self.object_list:
|
|
277
|
+
object.Update()
|
|
278
|
+
|
|
279
|
+
def draw(self,renderer):
|
|
280
|
+
for obj in self.object_list:
|
|
281
|
+
obj.DrawFilled(renderer)
|
|
282
|
+
|
|
283
|
+
class Raycaster2D:
|
|
284
|
+
def __init__(self,light,scene):
|
|
285
|
+
self.light = light
|
|
286
|
+
self.object_list = scene.object_list
|
|
287
|
+
self.angle = 0
|
|
288
|
+
self.rad = 0
|
|
289
|
+
self.ray_len = light.r
|
|
290
|
+
self.start_angle = 0
|
|
291
|
+
self.end_angle = 0
|
|
292
|
+
self.endX = 0
|
|
293
|
+
self.endY = 0
|
|
294
|
+
|
|
295
|
+
def ray_object_intersect(self):
|
|
296
|
+
closest_dist = self.light.r
|
|
297
|
+
for obj in self.object_list:
|
|
298
|
+
if obj.cast_shadow:
|
|
299
|
+
if isinstance(obj,Circle):
|
|
300
|
+
ob_x , ob_y , ob_r = 0 , 0 , 0
|
|
301
|
+
ob_x , ob_y , ob_r = obj.x , obj.y , obj.r
|
|
302
|
+
dx, dy = ob_x - self.light.x, ob_y - self.light.y
|
|
303
|
+
b = -2 * (dx * math.cos(self.rad) + dy * math.sin(self.rad))
|
|
304
|
+
c = dx * dx + dy * dy - ob_r * ob_r
|
|
305
|
+
val = b * b - 4 * c
|
|
306
|
+
if val >= 0:
|
|
307
|
+
val_sq = math.sqrt(val)
|
|
308
|
+
front_dist = (-b - val_sq) /2
|
|
309
|
+
back_dist = (-b + val_sq) /2
|
|
310
|
+
dist = (back_dist if front_dist < 0 else front_dist)
|
|
311
|
+
if dist >= 0 and dist <= closest_dist:
|
|
312
|
+
closest_dist = dist
|
|
313
|
+
|
|
314
|
+
if isinstance(obj,Line):
|
|
315
|
+
dx = obj.x2 - obj.x1
|
|
316
|
+
dy = obj.y2 - obj.y1
|
|
317
|
+
sin_r = math.sin(self.rad)
|
|
318
|
+
cos_r = math.cos(self.rad)
|
|
319
|
+
den = dy*cos_r-dx*sin_r
|
|
320
|
+
u = ((obj.x1-self.light.x)*sin_r-(obj.y1-self.light.y)*cos_r)/(den+0.0001)
|
|
321
|
+
t = ((obj.x1-self.light.x)*dy-(obj.y1-self.light.y)*dx)/(den+0.0001)
|
|
322
|
+
if u >= 0 and u <= 1 and t > 0 and t <= closest_dist:
|
|
323
|
+
closest_dist = t
|
|
324
|
+
return closest_dist
|
|
325
|
+
|
|
326
|
+
def raycast(self,renderer,start=0,end=360,step=1):
|
|
327
|
+
sdl2.SDL_SetRenderDrawColor(renderer,self.light.c.r , self.light.c.g , self.light.c.b , self.light.c.a)
|
|
328
|
+
self.angle = start
|
|
329
|
+
self.start_angle = start
|
|
330
|
+
self.end_angle = end
|
|
331
|
+
while self.angle < self.end_angle:
|
|
332
|
+
self.rad = math.radians(self.angle)
|
|
333
|
+
self.ray_len = self.light.r
|
|
334
|
+
val = self.ray_object_intersect()
|
|
335
|
+
if val != None:
|
|
336
|
+
self.ray_len = val
|
|
337
|
+
self.endX = self.light.x + self.ray_len * math.cos(self.rad)
|
|
338
|
+
self.endY = self.light.y + self.ray_len * math.sin(self.rad)
|
|
339
|
+
sdl2.SDL_RenderDrawLineF(renderer, self.light.x, self.light.y, self.endX, self.endY)
|
|
340
|
+
self.angle += step
|
|
341
|
+
|
|
342
|
+
def BreakObject2D(scene,raycaster,angle):
|
|
343
|
+
if abs(raycaster.angle+angle) > 1:
|
|
344
|
+
return
|
|
345
|
+
else:
|
|
346
|
+
to_remove = []
|
|
347
|
+
buffer = 2
|
|
348
|
+
for i in range(len(scene.object_list)):
|
|
349
|
+
if scene.object_list[i].breakable:
|
|
350
|
+
if isinstance(scene.object_list[i],Rect):
|
|
351
|
+
min_x = min(scene.object_list[i].x , scene.object_list[i].x + scene.object_list[i].w)
|
|
352
|
+
max_x = max(scene.object_list[i].x , scene.object_list[i].x + scene.object_list[i].w)
|
|
353
|
+
min_y = min(scene.object_list[i].y , scene.object_list[i].y + scene.object_list[i].h)
|
|
354
|
+
max_y = max(scene.object_list[i].y , scene.object_list[i].y + scene.object_list[i].h)
|
|
355
|
+
if (min_y - buffer <= raycaster.endY <= max_y + buffer ) and (min_x - buffer <= raycaster.endX <= max_x + buffer):
|
|
356
|
+
to_remove.append(scene.object_list[i])
|
|
357
|
+
if isinstance(scene.object_list[i],Line):
|
|
358
|
+
min_x = min(scene.object_list[i].x1,scene.object_list[i].x2)
|
|
359
|
+
max_x = max(scene.object_list[i].x1,scene.object_list[i].x2)
|
|
360
|
+
min_y = min(scene.object_list[i].y1,scene.object_list[i].y2)
|
|
361
|
+
max_y = max(scene.object_list[i].y1,scene.object_list[i].y2)
|
|
362
|
+
if (min_x - buffer <= raycaster.endX <= max_x + buffer) and (min_y - buffer <= raycaster.endY <= max_y + buffer):
|
|
363
|
+
to_remove.append(scene.object_list[i])
|
|
364
|
+
if isinstance(scene.object_list[i],Circle):
|
|
365
|
+
dx = (raycaster.endX - scene.object_list[i].x)
|
|
366
|
+
dy = (raycaster.endY - scene.object_list[i].y)
|
|
367
|
+
r = scene.object_list[i].r
|
|
368
|
+
if dx * dx + dy * dy <= r * r:
|
|
369
|
+
to_remove.append(scene.object_list[i])
|
|
370
|
+
for obj in to_remove:
|
|
371
|
+
if obj in scene.object_list:
|
|
372
|
+
scene.remove(obj)
|
|
373
|
+
|
|
374
|
+
def CreatePlatform2D(scene,map_data,w,h,space,x_offset,y_offset,cast_shadow=True):
|
|
375
|
+
row = len(map_data)
|
|
376
|
+
col = len(map_data[0])
|
|
377
|
+
current_color = None
|
|
378
|
+
for y in range(row):
|
|
379
|
+
x = 0
|
|
380
|
+
while x < col:
|
|
381
|
+
if map_data[y][x]==1:
|
|
382
|
+
start_c = x
|
|
383
|
+
current_color = RED
|
|
384
|
+
while x < col and map_data[y][x]==1:
|
|
385
|
+
x += 1
|
|
386
|
+
combined_w = (x-start_c)*w
|
|
387
|
+
new_rect = Rect(x_offset+start_c*(w+space),y_offset+y*(h+space),combined_w,h,current_color,scene,cast_shadow,False)
|
|
388
|
+
scene.add(new_rect)
|
|
389
|
+
elif map_data[y][x]==2:
|
|
390
|
+
current_color = YELLOW
|
|
391
|
+
new_rect = Rect(x_offset+x*(w+space),y_offset+y*(h+space),w,h,current_color,scene,cast_shadow,True)
|
|
392
|
+
scene.add(new_rect)
|
|
393
|
+
x += 1
|
|
394
|
+
else:
|
|
395
|
+
x += 1
|
simple2d_3d/setup.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import sdl2 , sys
|
|
2
|
+
def Init(title,w,h):
|
|
3
|
+
sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)
|
|
4
|
+
window = sdl2.SDL_CreateWindow(title,sdl2.SDL_WINDOWPOS_UNDEFINED,sdl2.SDL_WINDOWPOS_UNDEFINED, w , h , sdl2.SDL_WINDOW_SHOWN | sdl2.SDL_WINDOW_RESIZABLE)
|
|
5
|
+
if not window:
|
|
6
|
+
print("Error : ",sdl2.SDL_GetError())
|
|
7
|
+
sdl2.SDL_Quit()
|
|
8
|
+
sys.exit(0)
|
|
9
|
+
renderer = sdl2.SDL_CreateRenderer(window,-1,sdl2.SDL_RENDERER_ACCELERATED | sdl2.SDL_RENDERER_PRESENTVSYNC)
|
|
10
|
+
if not renderer:
|
|
11
|
+
print("Error : ",sdl2.SDL_GetError())
|
|
12
|
+
sdl2.SDL_Quit()
|
|
13
|
+
sys.exit(0)
|
|
14
|
+
sdl2.SDL_SetRenderDrawBlendMode(renderer, sdl2.SDL_BLENDMODE_BLEND);
|
|
15
|
+
sdl2.SDL_GetWindowSize(window,w,h)
|
|
16
|
+
return window , renderer
|
|
17
|
+
|
|
18
|
+
def CleanUp(window , renderer):
|
|
19
|
+
if renderer:
|
|
20
|
+
sdl2.SDL_DestroyRenderer(renderer)
|
|
21
|
+
if window:
|
|
22
|
+
sdl2.SDL_DestroyWindow(window)
|
|
23
|
+
sdl2.SDL_Quit()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: simple2d_3d
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A lightweight, hardware-accelerated 2D-3D layout and engine.
|
|
5
|
+
Author: ProdeeptoSundar Roy
|
|
6
|
+
Project-URL: Homepage, https://github.com/rtumpa099-gif/Simple2D_3D
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.7
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: pysdl2
|
|
14
|
+
Dynamic: license-file
|
|
15
|
+
|
|
16
|
+
# Simple2D_3D
|
|
17
|
+
A lightweight, hardware-accelerated 2D-3D layout and engine.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
simple2d_3d/__init__.py,sha256=xYdcK6tI184ZpLfC9DpbknT3MvkZeQVAQCK8p8me45I,592
|
|
2
|
+
simple2d_3d/colors.py,sha256=oa4TdMzN6QbZMg7oOVAULj-NRfnr--wLE98FJaLiXME,910
|
|
3
|
+
simple2d_3d/render.py,sha256=E_38TCrYBklElsp9wNvaZ0f8Ko-Y4Dz3maUmptp8EyM,13846
|
|
4
|
+
simple2d_3d/setup.py,sha256=bI7PkCKa6ejHbl6vn8WmJYKz1z9tAb6-oVF6PQs1dKk,797
|
|
5
|
+
simple2d_3d-0.1.0.dist-info/licenses/LICENSE,sha256=nImvLlK3J6DHaAeF9zZhAaPpex-FfCVsisr_6kpA1SE,1062
|
|
6
|
+
simple2d_3d-0.1.0.dist-info/METADATA,sha256=weOxIp0mR5j5GoD6XSsDKcwHKCzASeVAb_mvdmrOT7c,572
|
|
7
|
+
simple2d_3d-0.1.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
8
|
+
simple2d_3d-0.1.0.dist-info/top_level.txt,sha256=RSLeXzPvoYQcVyTPHZ-egVpv-QvnlURBL3eYNwGXMt0,12
|
|
9
|
+
simple2d_3d-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2026 ProdeeptoSundar Roy
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
simple2d_3d
|