(Sidenote: the thread is not linked to the puzzle, if a moderator could edit that it would be great.)
I recently started to learn ursina engine for Python and I thought it could be funny to implement a playable version of this 2.5D maze.
So here it is. All you need is Python 3.6+, install ursina (https://www.ursinaengine.org/) with ‘pip install ursina’ in the terminal, and launch the script:
from ursina import *
from ursina.shaders import basic_lighting_shader
from ursina.prefabs.first_person_controller import FirstPersonController
start, end, _, *G = """1 4
9 5
16 16
################
#....#....#....#
#.++++.++++.++.#
#.+..+.+..X.+..#
#.|.++X+.++++++#
#....X.+.#.....#
#.++++.+X+++++.#
#....+...+.....#
##+++++-.+++++##
#.....#...|....#
#.+++++++...++##
#.+.+.+...+.+..#
#.+X+...+.+.++.#
#.|.++++++-..+.#
#..........#...#
################""".split("\n")
i_start, j_start = map(int, start.split())
i_end, j_end = map(int, end.split())
h, w = len(G), len(G[0])
app = Ursina()
SKY = color.rgb(180, 230, 240)
GOLD = color.rgb(255, 215, 0)
BROWN = color.rgb(140, 70, 20)
NONE = color.rgba(255, 255, 255, 0)
GREEN, RED = color.green, color.red
window.color = SKY
window.fps_counter.enabled = False
window.exit_button.visible = False
window.fullscreen = True
YYSCALE = dict(zip("+#|-XO", [(2,8), (6,16), (0,4), (0,4), (5.5,1), (9.5,9)]))
for i in range(h):
for j in range(w):
c = RED if (i, j) == (i_start, j_start) else GREEN if (i, j) == (i_end, j_end) else BROWN
Entity(model='cube', position=(4*i, -4, 4*j), collider='box', scale=(4, 4, 4),
color=c, shader=basic_lighting_shader)
if G[i][j] == ".": continue
y, y_scale = YYSCALE[G[i][j]]
Entity(model='cube', position=(4*i, y, 4*j), collider='box', scale=(4, y_scale, 4),
color=GOLD, shader=basic_lighting_shader)
if G[i][j] in "+X":
if G[i][j-1] in ".|":
Entity(model='cube', position=(4*i, 10, 4*j-1.75), collider='box', scale=(4, 8, 0.5),
color=NONE)
if G[i][j+1] in ".|":
Entity(model='cube', position=(4*i, 10, 4*j+1.75), collider='box', scale=(4, 8, 0.5),
color=NONE)
if G[i-1][j] in ".-":
Entity(model='cube', position=(4*i-1.75, 10, 4*j), collider='box', scale=(0.5, 8, 4),
color=NONE)
if G[i+1][j] in ".-":
Entity(model='cube', position=(4*i+1.75, 10, 4*j), collider='box', scale=(0.5, 8, 4),
color=NONE)
elif G[i][j] == "|":
Entity(model='cube', position=(4*i, 8, 4*j-1.75), collider='box', scale=(4, 8, 0.5),
color=NONE)
Entity(model='cube', position=(4*i, 8, 4*j+1.75), collider='box', scale=(4, 8, 0.5),
color=NONE)
Entity(model='cube', position=(4*i, 3, 4*j-1.75), collider='box', scale=(4, 2, 0.5),
color=GOLD, shader=basic_lighting_shader)
Entity(model='cube', position=(4*i, 3, 4*j+1.75), collider='box', scale=(4, 2, 0.5),
color=GOLD, shader=basic_lighting_shader)
elif G[i][j] == "-":
Entity(model='cube', position=(4*i-1.75, 8, 4*j), collider='box', scale=(0.5, 8, 4),
color=NONE)
Entity(model='cube', position=(4*i+1.75, 8, 4*j), collider='box', scale=(0.5, 8, 4),
color=NONE)
Entity(model='cube', position=(4*i-1.75, 3, 4*j), collider='box', scale=(0.5, 2, 4),
color=GOLD, shader=basic_lighting_shader)
Entity(model='cube', position=(4*i+1.75, 3, 4*j), collider='box', scale=(0.5, 2, 4),
color=GOLD, shader=basic_lighting_shader)
player = FirstPersonController(position=(4*i_start, 8, 4*j_start), collider='box', jump_height=4, speed=10)
player.cursor.color = color.black
player.cursor.rotation = (0, 0, 0)
player.cursor.scale = 0.005
app.run()
Controls are the basic wasd + mouse and space for jump.
To change the map, just replace the string in """ """
with the testcase you want to try or you can invent your own map. I implemented the "O"
tunnel thing even if it’s not present in testcases.
There are invisible walls in the map to prevent forbidden moves, you can visualize them by changing the alpha of the color NONE, use 40 instead of 0 for example.
I didn’t use textures to make it a standalone script but you can easily add some.
Just put jpg files named wall.jpg, floor.jpg, sky.jpg in the folder of the script, add those lines in the script:
sky = load_texture('sky.jpg')
wall = load_texture('wall.jpg')
floor = load_texture('floor.jpg')
Entity(model='sphere', position=(0, -200, 0), rotation=(0, 0, -90), texture=sky, scale=800, double_sided=True)
and add the option texture=floor in the BROWN/GREEN/RED Entities and texture=wall in the GOLD Entities.