Skip to content

Commit 6515cc0

Browse files
committed
Add cone/triangle click flash, blurred background, and tracker void details (ref #7)
- Add red flash effect on cone click (main menu) and triangle click (void scene) - Blur checkerboard background slightly using pre-blurred texture - Add pink triangle (rare, 20% chance) and red object (rare, 15% chance) to tracker void - Make grey cone XYZ axis lines brighter and longer
1 parent 44eaff1 commit 6515cc0

2 files changed

Lines changed: 338 additions & 55 deletions

File tree

Sourcebox.py

Lines changed: 184 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ def __init__(self):
225225
self.diffuse = [1.0, 1.0, 1.0, 1.0]
226226
self.specular = [1.0, 1.0, 1.0, 1.0]
227227
self.setup_done = False
228-
228+
229229
def apply(self):
230230
if not self.setup_done:
231231
glLightfv(GL_LIGHT0, GL_AMBIENT, self.ambient)
@@ -244,41 +244,58 @@ def __init__(self):
244244
self.light_color = [0.0, 0.0, 0.0]
245245
self.brightness = 2
246246
self.display_list = None
247-
247+
self.texture = None
248+
248249
def create_display_list(self):
249250
if self.display_list is not None:
250251
return
251-
252+
253+
self._create_blurred_texture()
254+
252255
try:
253256
self.display_list = glGenLists(1)
254257
if self.display_list == 0:
255258
return
256-
259+
257260
glNewList(self.display_list, GL_COMPILE)
258-
261+
259262
size = self.size
260-
dark_r = self.dark_color[0] * self.brightness
261-
dark_g = self.dark_color[1] * self.brightness
262-
dark_b = self.dark_color[2] * self.brightness
263-
light_r = self.light_color[0] * self.brightness
264-
light_g = self.light_color[1] * self.brightness
265-
light_b = self.light_color[2] * self.brightness
266-
267-
glNormal3f(0, 1, 0)
268-
glBegin(GL_QUADS)
269-
for x in range(-size, size):
270-
for z in range(-size, size):
271-
if (x + z) & 1:
272-
glColor3f(light_r, light_g, light_b)
273-
else:
274-
glColor3f(dark_r, dark_g, dark_b)
275-
276-
glVertex3f(x, 0, z)
277-
glVertex3f(x, 0, z+1)
278-
glVertex3f(x+1, 0, z+1)
279-
glVertex3f(x+1, 0, z)
280-
glEnd()
281-
263+
264+
if self.texture:
265+
glEnable(GL_TEXTURE_2D)
266+
glBindTexture(GL_TEXTURE_2D, self.texture)
267+
glNormal3f(0, 1, 0)
268+
glColor3f(1, 1, 1)
269+
glBegin(GL_QUADS)
270+
glTexCoord2f(0, 0); glVertex3f(-size, 0, -size)
271+
glTexCoord2f(1, 0); glVertex3f(size, 0, -size)
272+
glTexCoord2f(1, 1); glVertex3f(size, 0, size)
273+
glTexCoord2f(0, 1); glVertex3f(-size, 0, size)
274+
glEnd()
275+
glDisable(GL_TEXTURE_2D)
276+
else:
277+
dark_r = self.dark_color[0] * self.brightness
278+
dark_g = self.dark_color[1] * self.brightness
279+
dark_b = self.dark_color[2] * self.brightness
280+
light_r = self.light_color[0] * self.brightness
281+
light_g = self.light_color[1] * self.brightness
282+
light_b = self.light_color[2] * self.brightness
283+
284+
glNormal3f(0, 1, 0)
285+
glBegin(GL_QUADS)
286+
for x in range(-size, size):
287+
for z in range(-size, size):
288+
if (x + z) & 1:
289+
glColor3f(light_r, light_g, light_b)
290+
else:
291+
glColor3f(dark_r, dark_g, dark_b)
292+
293+
glVertex3f(x, 0, z)
294+
glVertex3f(x, 0, z+1)
295+
glVertex3f(x+1, 0, z+1)
296+
glVertex3f(x+1, 0, z)
297+
glEnd()
298+
282299
glEndList()
283300
except Exception as e:
284301
print(f"Error creating checkerboard display list: {e}")
@@ -288,11 +305,69 @@ def create_display_list(self):
288305
except:
289306
pass
290307
self.display_list = None
291-
292-
def draw(self):
308+
309+
def _create_blurred_texture(self):
310+
"""generate a pre-blurred checkerboard texture"""
311+
try:
312+
tex_size = 1024
313+
tile_count = self.size * 2
314+
pixels_per_tile = tex_size / tile_count
315+
316+
dark_val = int(self.dark_color[0] * self.brightness * 255)
317+
light_val = int(self.light_color[0] * self.brightness * 255)
318+
319+
# generate sharp checkerboard
320+
data = bytearray(tex_size * tex_size * 3)
321+
for y in range(tex_size):
322+
for x in range(tex_size):
323+
tx = int(x / pixels_per_tile)
324+
ty = int(y / pixels_per_tile)
325+
val = light_val if (tx + ty) & 1 else dark_val
326+
idx = (y * tex_size + x) * 3
327+
data[idx] = val
328+
data[idx + 1] = val
329+
data[idx + 2] = val
330+
331+
# gentle blur: blend 20% blurred with 80% sharp
332+
sharp = bytes(data)
333+
blurred = bytearray(tex_size * tex_size * 3)
334+
radius = 1
335+
for y in range(tex_size):
336+
for x in range(tex_size):
337+
r_sum = 0
338+
count = 0
339+
for dy in range(-radius, radius + 1):
340+
for dx in range(-radius, radius + 1):
341+
nx = min(max(x + dx, 0), tex_size - 1)
342+
ny = min(max(y + dy, 0), tex_size - 1)
343+
r_sum += sharp[(ny * tex_size + nx) * 3]
344+
count += 1
345+
idx = (y * tex_size + x) * 3
346+
blur_val = r_sum // count
347+
sharp_val = sharp[idx]
348+
val = int(sharp_val * 0.9 + blur_val * 0.1)
349+
blurred[idx] = val
350+
blurred[idx + 1] = val
351+
blurred[idx + 2] = val
352+
data = blurred
353+
354+
self.texture = glGenTextures(1)
355+
glBindTexture(GL_TEXTURE_2D, self.texture)
356+
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_size, tex_size, 0,
357+
GL_RGB, GL_UNSIGNED_BYTE, bytes(data))
358+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
359+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
360+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
361+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
362+
glBindTexture(GL_TEXTURE_2D, 0)
363+
except Exception as e:
364+
print(f"Blur texture creation failed ({e}), using sharp checkerboard")
365+
self.texture = None
366+
367+
def draw(self, display_width=None, display_height=None):
293368
if self.display_list is None:
294369
return
295-
370+
296371
glPushMatrix()
297372
glTranslatef(*self.position)
298373
if self.rotation[0] or self.rotation[1] or self.rotation[2]:
@@ -302,14 +377,20 @@ def draw(self):
302377
glScalef(self.scale[0], self.scale[1], self.scale[2])
303378
glCallList(self.display_list)
304379
glPopMatrix()
305-
380+
306381
def cleanup(self):
307382
if self.display_list:
308383
try:
309384
glDeleteLists(self.display_list, 1)
310385
except:
311386
pass
312387
self.display_list = None
388+
if self.texture:
389+
try:
390+
glDeleteTextures([self.texture])
391+
except:
392+
pass
393+
self.texture = None
313394

314395
class MissingTextureScene:
315396
def __init__(self, sound_manager=None, display_scale=1.0):
@@ -1033,9 +1114,9 @@ def draw_object(obj):
10331114
brightness_map = {"cube": 0.6, "sphere": 0.7, "cone": 0.65}
10341115
b = brightness_map.get(obj.type, 0.6) * obj.brightness
10351116
glColor3f(b, b, b)
1036-
1117+
10371118
glCallList(obj.display_list)
1038-
1119+
10391120
if lighting_disabled:
10401121
glEnable(GL_LIGHTING)
10411122

@@ -1295,12 +1376,54 @@ def main():
12951376

12961377
elif clicked_obj and clicked_obj.type == "cone":
12971378
sound_manager.play_sound('cone_click')
1298-
1379+
1380+
# clear hover so cone shows normal color between flashes
1381+
clicked_obj.is_hovered = False
1382+
1383+
# red -> normal -> red -> normal -> red (fast)
1384+
flash_pattern = [True, False, True, False, True]
1385+
for is_red in flash_pattern:
1386+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
1387+
camera.apply()
1388+
light.apply()
1389+
board.draw(display[0], display[1])
1390+
glDisable(GL_TEXTURE_2D)
1391+
glBindTexture(GL_TEXTURE_2D, 0)
1392+
glEnable(GL_LIGHTING)
1393+
glEnable(GL_DEPTH_TEST)
1394+
glEnable(GL_COLOR_MATERIAL)
1395+
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
1396+
for o in objects:
1397+
if o == clicked_obj:
1398+
glPushMatrix()
1399+
glTranslatef(*o.position)
1400+
if o.base_rotation[0]: glRotatef(o.base_rotation[0], 1, 0, 0)
1401+
if o.base_rotation[1]: glRotatef(o.base_rotation[1], 0, 1, 0)
1402+
if o.base_rotation[2]: glRotatef(o.base_rotation[2], 0, 0, 1)
1403+
sx = o.scale * o.scale_xyz[0]
1404+
sy = o.scale * o.scale_xyz[1]
1405+
sz = o.scale * o.scale_xyz[2]
1406+
glScalef(sx, sy, sz)
1407+
if is_red:
1408+
glDisable(GL_LIGHTING)
1409+
glColor3f(1.0, 0.0, 0.0)
1410+
glCallList(o.display_list)
1411+
glEnable(GL_LIGHTING)
1412+
else:
1413+
b = 0.65 * o.brightness
1414+
glColor3f(b, b, b)
1415+
glCallList(o.display_list)
1416+
glPopMatrix()
1417+
else:
1418+
draw_object(o)
1419+
cursor_renderer.draw(mouse_pos, display[0], display[1])
1420+
pygame.display.flip()
1421+
pygame.time.wait(80)
1422+
12991423
cone_duration = sound_manager.get_sound_duration('cone_click')
1300-
if cone_duration > 0:
1301-
pygame.time.wait(int(cone_duration * 1000))
1302-
else:
1303-
pygame.time.wait(500)
1424+
remaining = int(cone_duration * 1000) - 400 if cone_duration > 0 else 100
1425+
if remaining > 0:
1426+
pygame.time.wait(remaining)
13041427

13051428
if hasattr(pygame.display, 'get_desktop_sizes'):
13061429
desktop_sizes = pygame.display.get_desktop_sizes()
@@ -1359,9 +1482,23 @@ def main():
13591482
# check triangle click in cone scene (LEFT-CLICK ONLY)
13601483
if cone_scene.check_triangle_click(mouse_pos, display[0], display[1]):
13611484
sound_manager.play_sound('cone_back')
1362-
1363-
# 3 second delay
1364-
pygame.time.wait(3000)
1485+
1486+
# clear hover so triangle shows normal color between flashes
1487+
cone_scene.triangle_hovered = False
1488+
1489+
# red -> grey -> red -> grey -> red
1490+
flash_pattern = ["red", "grey", "red", "grey", "red"]
1491+
for state in flash_pattern:
1492+
cone_scene.triangle_flash_red = state
1493+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
1494+
cone_scene.draw(display[0], display[1])
1495+
cursor_renderer.draw(mouse_pos, display[0], display[1])
1496+
pygame.display.flip()
1497+
pygame.time.wait(80)
1498+
cone_scene.triangle_flash_red = False
1499+
1500+
# 3 second delay (minus flash time)
1501+
pygame.time.wait(2600)
13651502

13661503
# return to main menu
13671504
current_scene = "main"
@@ -1410,12 +1547,14 @@ def main():
14101547
ray_caster.update_matrices()
14111548

14121549
check_object_hover(mouse_pos, ray_caster, objects, sound_manager)
1413-
1414-
board.draw()
1415-
1550+
1551+
board.draw(display[0], display[1])
1552+
glDisable(GL_TEXTURE_2D)
1553+
glBindTexture(GL_TEXTURE_2D, 0)
1554+
14161555
for obj in objects:
14171556
draw_object(obj)
1418-
1557+
14191558
cursor_renderer.draw(mouse_pos, display[0], display[1])
14201559

14211560
elif current_scene == "error":

0 commit comments

Comments
 (0)