Last active 1693212965

A mini 2.5D engine in python

Millefeuille revised this gist 1693212965. Go to revision

1 file changed, 239 insertions

cubEngine.py(file created)

@@ -0,0 +1,239 @@
1 + import math
2 + from kandinsky import *
3 +
4 +
5 + def shade_color(intensity, dist, way, color):
6 + if color >= 255 - 20:
7 + color = 255 - 20
8 + if way:
9 + ret = ((color / 255.0) + 0.1) * (intensity * (dist / 255.0))
10 + else:
11 + ret = ((color / 255.0) + 0.1) * (intensity * (255.0 / dist))
12 +
13 + ret = color + 20 if ret > color + 20 else ret
14 + ret = 0 if ret < 0 else ret
15 +
16 + return int(ret)
17 +
18 +
19 + class CubColor:
20 + def __init__(self, r, g, b):
21 + self.r = r
22 + self.g = g
23 + self.b = b
24 + self.shadedR = 0
25 + self.shadedG = 0
26 + self.shadedB = 0
27 +
28 + def shade(self, intensity, dist, way):
29 + self.shadedR = shade_color(intensity, dist, way, self.r)
30 + self.shadedG = shade_color(intensity, dist, way, self.g)
31 + self.shadedB = shade_color(intensity, dist, way, self.b)
32 + return [self.shadedR, self.shadedG, self.shadedB]
33 +
34 + def get_color(self):
35 + return [self.r, self.g, self.b]
36 +
37 +
38 + class CubVector:
39 + def __init__(self, x, y):
40 + self.x = x
41 + self.y = y
42 +
43 + def translate(self, x, y):
44 + self.x += x
45 + self.y += y
46 +
47 + def rotate(self, angle):
48 + old = CubVector(self.x, self.y)
49 + self.x = old.x * math.cos(math.radians(angle)) - old.y * math.sin(math.radians(angle))
50 + self.y = old.x * math.sin(math.radians(angle)) + old.y * math.cos(math.radians(angle))
51 +
52 +
53 + class CubPlayer:
54 + def __init__(self, pos, prov_dir):
55 + self.pos = pos
56 + self.dir = prov_dir
57 + self.plan = CubVector(0, 0.66)
58 + self.view_offset = 0
59 +
60 + def move(self, angle, speed, prov_map):
61 + dire = CubVector(self.dir.x, self.dir.y)
62 +
63 + dire.rotate(angle)
64 + n_pos = CubVector(
65 + self.pos.x + dire.x / speed,
66 + self.pos.y + dire.y / speed
67 + )
68 +
69 + if prov_map[int(n_pos.y + dire.y / (speed / 2))][int(n_pos.x + dire.x / (speed / 2))] == 1:
70 + return
71 + self.pos.x = n_pos.x
72 + self.pos.y = n_pos.y
73 +
74 + def look_sides(self, angle):
75 + self.dir.rotate(angle)
76 + self.plan.rotate(angle)
77 +
78 + def look_up(self, speed):
79 + if self.view_offset < 100:
80 + self.view_offset += speed
81 +
82 + def look_down(self, speed):
83 + if self.view_offset > -100:
84 + self.view_offset -= speed
85 +
86 +
87 + class CubRay:
88 + def __init__(self, cam):
89 + self.origin = CubVector(player.pos.x, player.pos.y)
90 + self.dir = CubVector(
91 + player.dir.x + player.plan.x * cam,
92 + player.dir.y + player.plan.y * cam
93 + )
94 + self.mpos = CubVector(int(player.pos.x), int(player.pos.y))
95 + self.dist = CubVector(
96 + 1 if self.dir.x == 0 else 0,
97 + 1 if self.dir.y == 0 else 0
98 + )
99 + if self.dir.x != 0 and self.dir.y != 0:
100 + self.dist.x = abs(1 / self.dir.x)
101 + self.dist.y = abs(1 / self.dir.y)
102 + self.step = CubVector(1, 1)
103 + self.sdist = CubVector(
104 + (self.mpos.x + 1.0 - player.pos.x) * self.dist.x,
105 + (self.mpos.y + 1.0 - player.pos.y) * self.dist.y
106 + )
107 + if self.dir.x < 0:
108 + self.step.x = -1
109 + self.sdist.x = (player.pos.x - self.mpos.x) * self.dist.x
110 + if self.dir.y < 0:
111 + self.step.y = -1
112 + self.sdist.y = (player.pos.y - self.mpos.y) * self.dist.y
113 + self.hit = 0
114 + self.side = 0
115 +
116 + def cast(self):
117 + while self.hit == 0:
118 + if self.sdist.x < self.sdist.y:
119 + self.side = 0
120 + self.sdist.x += self.dist.x
121 + self.mpos.x += self.step.x
122 + else:
123 + self.side = 1
124 + self.sdist.y += self.dist.y
125 + self.mpos.y += self.step.y
126 + if prov_map[int(self.mpos.y)][int(self.mpos.x)] == 1:
127 + self.hit = 1
128 +
129 + def calc(self, x):
130 + wall = CubColor(255, 55, 0)
131 +
132 + if self.side == 0:
133 + dist = (self.mpos.x - player.pos.x + (1 - self.step.x) / 2) / self.dir.x
134 + else:
135 + dist = (self.mpos.y - player.pos.y + (1 - self.step.y) / 2) / self.dir.y
136 +
137 + if dist == 0:
138 + line_height = 0
139 + else:
140 + line_height = int(height / dist)
141 +
142 + start = int(-line_height / 2 + height / 2 + player.view_offset)
143 + end = int(line_height / 2 + height / 2 + player.view_offset)
144 +
145 + return [wall.shade(5, dist, False), x, start, end]
146 +
147 +
148 + prov_map = [
149 + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
150 + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
151 + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
152 + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
153 + [1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1],
154 + [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
155 + [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
156 + [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
157 + [1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1],
158 + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
159 + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
160 + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
161 + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
162 + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
163 + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
164 + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
165 + [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
166 + [1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
167 + [1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
168 + [1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
169 + [1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
170 + [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
171 + [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
172 + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
173 + ]
174 +
175 + width = 320
176 + height = 222
177 +
178 + player = CubPlayer(CubVector(12.5, 10.5), CubVector(1, 0))
179 + ceil = CubColor(50, 50, 50)
180 + floor = CubColor(20, 20, 20)
181 + running = True
182 +
183 +
184 + def draw_line(sc_x, sc_y, color):
185 + for i in range(sc_y[0], sc_y[1]):
186 + set_pixel(sc_x, i, color)
187 +
188 +
189 + def render():
190 + ceil = CubColor(50, 50, 50)
191 + floor = CubColor(20, 20, 20)
192 +
193 + #for x in range(width):
194 + # draw_line(x, (0, height), (0,0,0))
195 +
196 + for x in range(width):
197 + cam = 2 * x / width - 1
198 + ray = CubRay(cam)
199 + ray.cast()
200 + lst = ray.calc(x)
201 + draw_line(lst[1], (0, lst[2]), ceil.get_color())
202 + draw_line(lst[1], (lst[2], lst[3]), lst[0])
203 + draw_line(lst[1], (lst[3], height), floor.get_color())
204 +
205 +
206 + def update(keys):
207 + global running
208 +
209 + tm = 4
210 + if "right" in keys:
211 + player.move(90, int(10 / tm), prov_map)
212 + elif "left" in keys:
213 + player.move(-90, int(10 / tm), prov_map)
214 + if "down" in keys:
215 + player.move(180, int(10 / tm), prov_map)
216 + elif "up" in keys:
217 + player.move(0, int(10 / tm), prov_map)
218 + if "8" in keys:
219 + player.look_up(int((height / 100)) * tm)
220 + elif "5" in keys:
221 + player.look_down(int((height / 100)) * tm)
222 + if "4" in keys:
223 + player.look_sides(int(width / -200) * tm)
224 + elif "6" in keys:
225 + player.look_sides(int(width / 200) * tm)
226 + if "0" in keys:
227 + running = False
228 +
229 +
230 + def game():
231 + global running
232 +
233 + #render()
234 + running = True
235 + while running:
236 + keys = get_keys()
237 + if keys != set():
238 + update(keys)
239 + render()
Newer Older

Powered by Opengist ⋅ Load: 39ms