1. Let's have some fun with EuRaylib
- Posted by ChrisB (moderator) 2 days ago
- 139 views
Andys EuRaylib 6 ( even though it says 5). These are each separate programs, make sure you have raylib setup, Eu32 bit, everything else is standard Eu.
-- random_pixels.ex -- Draws random pixels in random colours on an 800x600 window -- Requires: 32-bit Euphoria 4.x and Euraylib 5 (Andy P / Icy Viking) include std/rand.e include raylib.e constant SCREEN_W = 800 constant SCREEN_H = 600 constant PIXELS_PER_FRAME = 10000 set_rand(time()) -- seed the random number generator InitWindow(SCREEN_W, SCREEN_H, "Euraylib 5 - Random Pixels") SetTargetFPS(60) while not WindowShouldClose() do BeginDrawing() ClearBackground(BLACK) for i = 1 to PIXELS_PER_FRAME do -- random position (raylib screen coords start at 0) integer x = rand(SCREEN_W) - 1 integer y = rand(SCREEN_H) - 1 -- random colour {r, g, b, a} sequence colour = {rand(256) - 1, rand(256) - 1, rand(256) - 1, 255} DrawPixel(x, y, colour) end for EndDrawing() end while CloseWindow()
-- lines.ex -- Lines screensaver: 1024x800 window, bouncing line with fading trail -- Requires: 32-bit Euphoria 4.x and Euraylib 5 (Andy P / Icy Viking) include std/rand.e include std/math.e include raylib.e constant SCREEN_W = 1024 constant SCREEN_H = 800 constant TRAIL_LENGTH = 80 -- how many old lines stay on screen constant MAX_SPEED = 7 set_rand(time()) -- p = {x1, y1, x2, y2} : the two endpoints of the current line sequence p = { rand(SCREEN_W) - 1, rand(SCREEN_H) - 1, rand(SCREEN_W) - 1, rand(SCREEN_H) - 1 } -- v = velocity of each coordinate, random speed and direction sequence v = repeat(0, 4) for i = 1 to 4 do v[i] = rand_range(2, MAX_SPEED) * (rand(2) * 2 - 3) -- (rand(2)*2-3) is -1 or +1 end for sequence history = {} -- each entry: {x1, y1, x2, y2, r, g, b} atom hue = 0 -- drives the colour cycling InitWindow(SCREEN_W, SCREEN_H, "Euraylib 5 - Lines") SetTargetFPS(60) while not WindowShouldClose() do -- move the endpoints, bouncing off the edges for i = 1 to 4 do integer limit if remainder(i, 2) = 1 then limit = SCREEN_W - 1 -- x coordinates else limit = SCREEN_H - 1 -- y coordinates end if p[i] += v[i] if p[i] < 0 then p[i] = 0 v[i] = -v[i] elsif p[i] > limit then p[i] = limit v[i] = -v[i] end if end for -- smoothly cycle the colour hue += 0.02 integer r = floor(127.5 + 127.5 * sin(hue)) integer g = floor(127.5 + 127.5 * sin(hue + 2.094)) integer b = floor(127.5 + 127.5 * sin(hue + 4.188)) -- add this frame's line to the trail, drop the oldest if it's full history = append(history, {p[1], p[2], p[3], p[4], r, g, b}) if length(history) > TRAIL_LENGTH then history = history[2..$] end if BeginDrawing() ClearBackground(BLACK) -- draw oldest to newest, with newer lines more opaque for i = 1 to length(history) do sequence ln = history[i] integer alpha = floor(255 * i / length(history)) DrawLine(ln[1], ln[2], ln[3], ln[4], {ln[5], ln[6], ln[7], alpha}) end for EndDrawing() end while CloseWindow()
-- cube.ex -- Rotating wireframe cube, 1024x800 window, colour-cycling edges -- Requires: 32-bit Euphoria 4.x and Euraylib 5 (Andy P / Icy Viking) include std/math.e include raylib.e constant SCREEN_W = 1024 constant SCREEN_H = 800 constant CENTRE_X = SCREEN_W / 2 constant CENTRE_Y = SCREEN_H / 2 constant CUBE_SIZE = 180 -- half the length of a cube edge, in pixels constant CAMERA_DIST = 700 -- distance from the "camera" to the cube centre constant FOCAL = 700 -- perspective strength -- the 8 corners of a cube centred on the origin constant verts = { {-1, -1, -1}, { 1, -1, -1}, { 1, 1, -1}, {-1, 1, -1}, {-1, -1, 1}, { 1, -1, 1}, { 1, 1, 1}, {-1, 1, 1} } -- the 12 edges, as pairs of indexes into verts constant edges = { {1, 2}, {2, 3}, {3, 4}, {4, 1}, -- back face {5, 6}, {6, 7}, {7, 8}, {8, 5}, -- front face {1, 5}, {2, 6}, {3, 7}, {4, 8} -- connecting edges } -- rotate a point around the X, then Y, then Z axis function rotate_point(sequence v, atom ax, atom ay, atom az) atom x = v[1] atom y = v[2] atom z = v[3] atom t -- around X t = y * cos(ax) - z * sin(ax) z = y * sin(ax) + z * cos(ax) y = t -- around Y t = x * cos(ay) + z * sin(ay) z = -x * sin(ay) + z * cos(ay) x = t -- around Z t = x * cos(az) - y * sin(az) y = x * sin(az) + y * cos(az) x = t return {x, y, z} end function -- project a 3D point onto the 2D screen, returns {screen_x, screen_y} function project_point(sequence v) atom scale = FOCAL / (CAMERA_DIST + v[3] * CUBE_SIZE) integer sx = floor(CENTRE_X + v[1] * CUBE_SIZE * scale) integer sy = floor(CENTRE_Y + v[2] * CUBE_SIZE * scale) return {sx, sy} end function -- turn a hue angle (radians) into an {r, g, b, a} colour function hue_colour(atom h) integer r = floor(127.5 + 127.5 * sin(h)) integer g = floor(127.5 + 127.5 * sin(h + 2.094)) integer b = floor(127.5 + 127.5 * sin(h + 4.188)) return {r, g, b, 255} end function atom ax = 0 atom ay = 0 atom az = 0 atom hue = 0 InitWindow(SCREEN_W, SCREEN_H, "Euraylib 5 - Rotating Cube") SetTargetFPS(60) while not WindowShouldClose() do -- advance the rotation angles (different speeds look more natural) ax += 0.011 ay += 0.017 az += 0.007 hue += 0.03 -- rotate and project all 8 corners sequence pts = repeat({0, 0}, length(verts)) for i = 1 to length(verts) do pts[i] = project_point(rotate_point(verts[i], ax, ay, az)) end for BeginDrawing() ClearBackground(BLACK) -- draw each edge, each with its own offset in the colour cycle for i = 1 to length(edges) do sequence a = pts[edges[i][1]] sequence b = pts[edges[i][2]] sequence col = hue_colour(hue + i * 0.5) -- draw each line three times with 1-pixel offsets to make it thicker DrawLine(a[1], a[2], b[1], b[2], col) DrawLine(a[1] + 1, a[2], b[1] + 1, b[2], col) DrawLine(a[1], a[2] + 1, b[1], b[2] + 1, col) end for EndDrawing() end while CloseWindow()
-- solid_cube.ex -- Rotating solid cube, 1024x800 window, six differently coloured opaque faces -- Requires: 32-bit Euphoria 4.x and Euraylib 5 (Andy P / Icy Viking) include std/math.e include raylib.e constant SCREEN_W = 1024 constant SCREEN_H = 800 constant CENTRE_X = SCREEN_W / 2 constant CENTRE_Y = SCREEN_H / 2 constant CUBE_SIZE = 180 -- half the length of a cube edge, in pixels constant CAMERA_DIST = 700 -- distance from the "camera" to the cube centre constant FOCAL = 700 -- perspective strength -- the 8 corners of a cube centred on the origin constant verts = { {-1, -1, -1}, { 1, -1, -1}, { 1, 1, -1}, {-1, 1, -1}, {-1, -1, 1}, { 1, -1, 1}, { 1, 1, 1}, {-1, 1, 1} } -- the 6 faces, each as 4 indexes into verts (in order around the face) constant faces = { {1, 2, 3, 4}, -- back {5, 6, 7, 8}, -- front {1, 4, 8, 5}, -- left {2, 3, 7, 6}, -- right {1, 2, 6, 5}, -- top {4, 3, 7, 8} -- bottom } -- one colour per face {r, g, b, a} constant face_colours = { {230, 40, 40, 255}, -- red { 40, 200, 60, 255}, -- green { 50, 90, 240, 255}, -- blue {245, 220, 40, 255}, -- yellow {220, 60, 220, 255}, -- magenta { 40, 220, 220, 255} -- cyan } -- rotate a point around the X, then Y, then Z axis function rotate_point(sequence v, atom ax, atom ay, atom az) atom x = v[1] atom y = v[2] atom z = v[3] atom t -- around X t = y * cos(ax) - z * sin(ax) z = y * sin(ax) + z * cos(ax) y = t -- around Y t = x * cos(ay) + z * sin(ay) z = -x * sin(ay) + z * cos(ay) x = t -- around Z t = x * cos(az) - y * sin(az) y = x * sin(az) + y * cos(az) x = t return {x, y, z} end function -- project a 3D point onto the 2D screen, returns {screen_x, screen_y} function project_point(sequence v) atom scale = FOCAL / (CAMERA_DIST + v[3] * CUBE_SIZE) integer sx = floor(CENTRE_X + v[1] * CUBE_SIZE * scale) integer sy = floor(CENTRE_Y + v[2] * CUBE_SIZE * scale) return {sx, sy} end function -- draw a filled triangle, fixing the vertex order so raylib always accepts it -- (raylib only draws triangles whose points run counter-clockwise on screen) procedure draw_tri(sequence a, sequence b, sequence c, sequence col) atom cross = (b[1] - a[1]) * (c[2] - a[2]) - (b[2] - a[2]) * (c[1] - a[1]) if cross > 0 then DrawTriangle(a, c, b, col) else DrawTriangle(a, b, c, col) end if end procedure atom ax = 0 atom ay = 0 atom az = 0 -- the camera sits on the negative Z side, in the same units as the cube corners constant cam_z = -CAMERA_DIST / CUBE_SIZE InitWindow(SCREEN_W, SCREEN_H, "Euraylib 5 - Solid Cube") SetTargetFPS(60) while not WindowShouldClose() do ax += 0.011 ay += 0.017 az += 0.007 -- rotate all 8 corners, then project them sequence rotated = repeat({0, 0, 0}, length(verts)) sequence pts = repeat({0, 0}, length(verts)) for i = 1 to length(verts) do rotated[i] = rotate_point(verts[i], ax, ay, az) pts[i] = project_point(rotated[i]) end for BeginDrawing() ClearBackground(BLACK) for f = 1 to length(faces) do sequence idx = faces[f] -- face centre = average of its 4 rotated corners. -- For a cube centred on the origin this is also the outward normal. atom cx = 0 atom cy = 0 atom cz = 0 for k = 1 to 4 do cx += rotated[idx[k]][1] cy += rotated[idx[k]][2] cz += rotated[idx[k]][3] end for cx /= 4 cy /= 4 cz /= 4 -- the face is visible if its normal points towards the camera: -- dot(normal, camera_position - face_centre) > 0 atom facing = cx * (0 - cx) + cy * (0 - cy) + cz * (cam_z - cz) if facing > 0 then sequence p1 = pts[idx[1]] sequence p2 = pts[idx[2]] sequence p3 = pts[idx[3]] sequence p4 = pts[idx[4]] -- a quad is two triangles draw_tri(p1, p2, p3, face_colours[f]) draw_tri(p1, p3, p4, face_colours[f]) -- thin black outline so the edges stand out DrawLine(p1[1], p1[2], p2[1], p2[2], BLACK) DrawLine(p2[1], p2[2], p3[1], p3[2], BLACK) DrawLine(p3[1], p3[2], p4[1], p4[2], BLACK) DrawLine(p4[1], p4[2], p1[1], p1[2], BLACK) end if end for EndDrawing() end while CloseWindow()
And finally, this blew my mind
-- enterprise.ex -- Rotating wireframe starship, 1024x800 window -- Requires: 32-bit Euphoria 4.x and Euraylib 5 (Andy P / Icy Viking) include raylib.e constant SCREEN_W = 1024 constant SCREEN_H = 800 constant CENTRE_X = SCREEN_W / 2 constant CENTRE_Y = SCREEN_H / 2 constant MODEL_SCALE = 150 -- pixels per model unit constant CAMERA_DIST = 1100 -- distance from the "camera" to the model centre constant FOCAL = 1100 -- perspective strength constant TWO_PI = 6.283185307179586 -- own constant, avoids clashing with PI in raylib.e ------------------------------------------------------------------ -- Model building helpers ------------------------------------------------------------------ sequence verts = {} -- each: {x, y, z} sequence edges = {} -- each: {vertex_a, vertex_b, {r, g, b}} sequence cur_col = {190, 205, 235} -- colour given to new edges function add_v(atom x, atom y, atom z) verts = append(verts, {x, y, z}) return length(verts) end function procedure add_e(integer a, integer b) edges = append(edges, {a, b, cur_col}) end procedure -- Spin a profile around an axis to make a ring-and-spoke surface. -- axis : 2 = spin around Y (vertical), 3 = spin around Z (lengthwise) -- shape : list of {radius, position_along_axis}, in order along the axis -- A radius of 0 makes a single point (a nose or tail tip). -- spoke_step: draw a lengthwise/radial line every N segments procedure add_lathe(integer axis, atom cx, atom cy, atom cz, sequence shape, integer segs, integer spoke_step) sequence prev = {} for p = 1 to length(shape) do atom r = shape[p][1] atom along = shape[p][2] sequence ring = repeat(0, segs) if r = 0 then if axis = 2 then ring = repeat(add_v(cx, cy + along, cz), segs) else ring = repeat(add_v(cx, cy, cz + along), segs) end if else for s = 1 to segs do atom a = TWO_PI * (s - 1) / segs atom u = r * cos(a) atom w = r * sin(a) if axis = 2 then ring[s] = add_v(cx + u, cy + along, cz + w) else ring[s] = add_v(cx + u, cy + w, cz + along) end if end for -- the ring itself for s = 1 to segs do add_e(ring[s], ring[remainder(s, segs) + 1]) end for end if -- spokes joining this ring to the previous one if p > 1 then for s = 1 to segs by spoke_step do if prev[s] != ring[s] then add_e(prev[s], ring[s]) end if end for end if prev = ring end for end procedure ------------------------------------------------------------------ -- Build the ship (nose points towards +Z) ------------------------------------------------------------------ -- Saucer section: {radius, height}, top to bottom cur_col = {190, 205, 235} add_lathe(2, 0, 0, 0.9, {{0.0, 0.17}, {0.25, 0.17}, {0.5, 0.13}, {0.8, 0.07}, {1.0, 0.0}, {0.8, -0.06}, {0.5, -0.09}, {0.25, -0.1}, {0.0, -0.1}}, 32, 2) -- Bridge dome on top of the saucer cur_col = {255, 230, 140} add_lathe(2, 0, 0.17, 0.9, {{0.0, 0.1}, {0.08, 0.07}, {0.12, 0.0}}, 12, 3) -- Secondary (engineering) hull: {radius, z} cur_col = {170, 185, 215} add_lathe(3, 0, -0.5, -0.4, {{0.0, -0.9}, {0.1, -0.85}, {0.17, -0.7}, {0.17, 0.3}, {0.12, 0.5}, {0.0, 0.6}}, 16, 4) -- Neck joining the secondary hull to the underside of the saucer integer n1 = add_v(-0.07, -0.345, -0.35) integer n2 = add_v( 0.07, -0.345, -0.35) integer n3 = add_v( 0.07, -0.345, -0.10) integer n4 = add_v(-0.07, -0.345, -0.10) integer t1 = add_v(-0.10, -0.07, 0.10) integer t2 = add_v( 0.10, -0.07, 0.10) integer t3 = add_v( 0.10, -0.095, 0.50) integer t4 = add_v(-0.10, -0.095, 0.50) add_e(n1, n2) add_e(n2, n3) add_e(n3, n4) add_e(n4, n1) add_e(t1, t2) add_e(t2, t3) add_e(t3, t4) add_e(t4, t1) add_e(n1, t1) add_e(n2, t2) add_e(n3, t3) add_e(n4, t4) -- Two nacelles with pylons (sx = -1 is one side, +1 is the other) for sx = -1 to 1 by 2 do -- nacelle body cur_col = {90, 170, 255} add_lathe(3, sx * 0.7, 0.12, -0.75, {{0.0, -0.78}, {0.08, -0.72}, {0.1, -0.6}, {0.1, 0.4}}, 12, 3) -- glowing red front dome cur_col = {255, 90, 70} add_lathe(3, sx * 0.7, 0.12, -0.35, {{0.1, 0.0}, {0.085, 0.12}, {0.05, 0.22}, {0.0, 0.3}}, 12, 3) -- pylon from the secondary hull up to the nacelle cur_col = {170, 185, 215} integer pa = add_v(sx * 0.1, -0.36, -1.05) integer pb = add_v(sx * 0.1, -0.36, -0.70) integer pc = add_v(sx * 0.7, 0.03, -1.05) integer pd = add_v(sx * 0.7, 0.03, -0.70) add_e(pa, pb) add_e(pc, pd) add_e(pa, pc) add_e(pb, pd) end for -- Centre the whole model on the origin so it spins about its middle sequence lo = {1e30, 1e30, 1e30} sequence hi = {-1e30, -1e30, -1e30} for i = 1 to length(verts) do for k = 1 to 3 do if verts[i][k] < lo[k] then lo[k] = verts[i][k] end if if verts[i][k] > hi[k] then hi[k] = verts[i][k] end if end for end for sequence mid = (lo + hi) / 2 for i = 1 to length(verts) do verts[i] -= mid end for ------------------------------------------------------------------ -- 3D maths ------------------------------------------------------------------ -- rotate a point around the X, then Y, then Z axis function rotate_point(sequence v, atom ax, atom ay, atom az) atom x = v[1] atom y = v[2] atom z = v[3] atom t -- around X t = y * cos(ax) - z * sin(ax) z = y * sin(ax) + z * cos(ax) y = t -- around Y t = x * cos(ay) + z * sin(ay) z = -x * sin(ay) + z * cos(ay) x = t -- around Z t = x * cos(az) - y * sin(az) y = x * sin(az) + y * cos(az) x = t return {x, y, z} end function -- project a 3D point onto the screen (model +Y is up, screen Y is down) function project_point(sequence v) atom scale = FOCAL / (CAMERA_DIST + v[3] * MODEL_SCALE) integer sx = floor(CENTRE_X + v[1] * MODEL_SCALE * scale) integer sy = floor(CENTRE_Y - v[2] * MODEL_SCALE * scale) return {sx, sy} end function ------------------------------------------------------------------ -- Main program ------------------------------------------------------------------ atom ax = 0.4 atom ay = 0 atom az = 0 InitWindow(SCREEN_W, SCREEN_H, "Euraylib 5 - Wireframe Starship") SetTargetFPS(60) while not WindowShouldClose() do -- spin on all three axes at different speeds ax += 0.011 ay += 0.017 az += 0.007 sequence rotated = repeat({0, 0, 0}, length(verts)) sequence pts = repeat({0, 0}, length(verts)) for i = 1 to length(verts) do rotated[i] = rotate_point(verts[i], ax, ay, az) pts[i] = project_point(rotated[i]) end for BeginDrawing() ClearBackground(BLACK) for i = 1 to length(edges) do integer ia = edges[i][1] integer ib = edges[i][2] sequence c = edges[i][3] -- dim edges that are further from the camera (+Z is away from us) atom zavg = (rotated[ia][3] + rotated[ib][3]) / 2 atom f = 0.65 - 0.35 * zavg / 1.9 if f < 0.25 then f = 0.25 end if if f > 1 then f = 1 end if DrawLine(pts[ia][1], pts[ia][2], pts[ib][1], pts[ib][2], {floor(c[1] * f), floor(c[2] * f), floor(c[3] * f), 255}) end for EndDrawing() end while CloseWindow()
All written with the help of claude in 1/2 an hours - it even corrected a mistake with duplicate PI in raylib.e and math.e.
Enjoy
Cheers
Chris
Edit - and then it made a suggestion which I couldn't resist
-- enterprise2.ex -- Wireframe starship (Constitution-class refit style) with starfield and keyboard control -- 1024x800 window -- Requires: 32-bit Euphoria 4.x and Euraylib 5 (Andy P / Icy Viking) -- -- Controls: -- Arrow keys : pitch (up/down) and yaw (left/right) -- Z / X : roll -- SPACE : turn the automatic spin on/off -- R : reset the orientation include std/rand.e include raylib.e constant SCREEN_W = 1024 constant SCREEN_H = 800 constant CENTRE_X = SCREEN_W / 2 constant CENTRE_Y = SCREEN_H / 2 constant MODEL_SCALE = 150 -- pixels per model unit constant CAMERA_DIST = 1100 -- distance from the "camera" to the model centre constant FOCAL = 1100 -- perspective strength constant TWO_PI = 6.283185307179586 -- own constant, avoids clashing with PI in raylib.e constant TURN_RATE = 0.03 -- radians per frame while a key is held -- starfield settings constant NUM_STARS = 300 constant STAR_FAR = 1000 -- how far away new stars appear constant STAR_NEAR = 20 -- stars closer than this are recycled constant STAR_SPEED = 3 -- how fast the stars fly past constant STAR_FOCAL = 500 set_rand(time()) ------------------------------------------------------------------ -- Model building helpers ------------------------------------------------------------------ sequence verts = {} -- each: {x, y, z} sequence edges = {} -- each: {vertex_a, vertex_b, {r, g, b}} sequence cur_col = {190, 205, 235} -- colour given to new edges function add_v(atom x, atom y, atom z) verts = append(verts, {x, y, z}) return length(verts) end function procedure add_e(integer a, integer b) edges = append(edges, {a, b, cur_col}) end procedure -- Spin a profile around an axis to make a ring-and-spoke surface. -- axis : 2 = spin around Y (vertical), 3 = spin around Z (lengthwise) -- shape : list of {radius, position_along_axis}, in order along the axis -- A radius of 0 makes a single point (a nose or tail tip). -- A shape with just one entry makes a single ring (used for accent lines). -- spoke_step: draw a lengthwise/radial line every N segments procedure add_lathe(integer axis, atom cx, atom cy, atom cz, sequence shape, integer segs, integer spoke_step) sequence prev = {} for p = 1 to length(shape) do atom r = shape[p][1] atom along = shape[p][2] sequence ring = repeat(0, segs) if r = 0 then if axis = 2 then ring = repeat(add_v(cx, cy + along, cz), segs) else ring = repeat(add_v(cx, cy, cz + along), segs) end if else for s = 1 to segs do atom a = TWO_PI * (s - 1) / segs atom u = r * cos(a) atom w = r * sin(a) if axis = 2 then ring[s] = add_v(cx + u, cy + along, cz + w) else ring[s] = add_v(cx + u, cy + w, cz + along) end if end for -- the ring itself for s = 1 to segs do add_e(ring[s], ring[remainder(s, segs) + 1]) end for end if -- spokes joining this ring to the previous one if p > 1 then for s = 1 to segs by spoke_step do if prev[s] != ring[s] then add_e(prev[s], ring[s]) end if end for end if prev = ring end for end procedure ------------------------------------------------------------------ -- Build the ship (nose points towards +Z) ------------------------------------------------------------------ -- Primary hull (saucer): {radius, height}, top to bottom cur_col = {190, 205, 235} add_lathe(2, 0, 0, 0.9, {{0.0, 0.20}, {0.15, 0.20}, {0.30, 0.17}, {0.45, 0.155}, {0.60, 0.12}, {0.80, 0.08}, {0.95, 0.03}, {1.0, 0.0}, {0.95, -0.03}, {0.80, -0.07}, {0.60, -0.09}, {0.40, -0.10}, {0.20, -0.11}, {0.0, -0.11}}, 40, 2) -- Window-light rings around the saucer edge cur_col = {255, 235, 150} add_lathe(2, 0, 0, 0.9, {{0.97, 0.025}}, 40, 1) add_lathe(2, 0, 0, 0.9, {{0.97, -0.025}}, 40, 1) -- Bridge dome on top of the saucer cur_col = {255, 230, 140} add_lathe(2, 0, 0.20, 0.9, {{0.0, 0.09}, {0.06, 0.085}, {0.10, 0.05}, {0.13, 0.0}}, 12, 3) -- Sensor dome underneath the saucer cur_col = {120, 220, 255} add_lathe(2, 0, -0.11, 0.9, {{0.12, 0.0}, {0.07, -0.05}, {0.0, -0.07}}, 12, 3) -- Secondary (engineering) hull: {radius, z} cur_col = {170, 185, 215} add_lathe(3, 0, -0.5, -0.4, {{0.0, -0.9}, {0.08, -0.88}, {0.14, -0.80}, {0.17, -0.70}, {0.18, -0.40}, {0.18, 0.0}, {0.17, 0.2}, {0.14, 0.35}, {0.10, 0.45}}, 16, 4) -- Hull accent rings cur_col = {255, 235, 150} add_lathe(3, 0, -0.5, -0.4, {{0.185, -0.55}}, 16, 1) add_lathe(3, 0, -0.5, -0.4, {{0.185, 0.15}}, 16, 1) -- Deflector dish at the front of the secondary hull cur_col = {120, 220, 255} add_lathe(3, 0, -0.5, -0.4, {{0.10, 0.45}, {0.07, 0.42}, {0.03, 0.40}, {0.0, 0.395}}, 12, 3) -- Neck joining the secondary hull to the underside of the saucer cur_col = {170, 185, 215} integer n1 = add_v(-0.07, -0.33, -0.35) integer n2 = add_v( 0.07, -0.33, -0.35) integer n3 = add_v( 0.07, -0.33, -0.10) integer n4 = add_v(-0.07, -0.33, -0.10) integer t1 = add_v(-0.10, -0.07, 0.10) integer t2 = add_v( 0.10, -0.07, 0.10) integer t3 = add_v( 0.10, -0.10, 0.50) integer t4 = add_v(-0.10, -0.10, 0.50) add_e(n1, n2) add_e(n2, n3) add_e(n3, n4) add_e(n4, n1) add_e(t1, t2) add_e(t2, t3) add_e(t3, t4) add_e(t4, t1) add_e(n1, t1) add_e(n2, t2) add_e(n3, t3) add_e(n4, t4) -- Two nacelles with pylons (sx = -1 is one side, +1 is the other) for sx = -1 to 1 by 2 do -- nacelle body cur_col = {90, 170, 255} add_lathe(3, sx * 0.7, 0.12, -0.75, {{0.0, -0.78}, {0.05, -0.76}, {0.085, -0.70}, {0.10, -0.60}, {0.10, 0.0}, {0.10, 0.40}}, 16, 4) -- blue accent rings along the nacelle cur_col = {120, 220, 255} add_lathe(3, sx * 0.7, 0.12, -0.75, {{0.104, -0.35}}, 16, 1) add_lathe(3, sx * 0.7, 0.12, -0.75, {{0.104, 0.05}}, 16, 1) -- glowing red front dome (Bussard collector) cur_col = {255, 90, 70} add_lathe(3, sx * 0.7, 0.12, -0.35, {{0.10, 0.0}, {0.09, 0.08}, {0.065, 0.17}, {0.035, 0.25}, {0.0, 0.30}}, 16, 4) -- pylon from the secondary hull up to the nacelle cur_col = {170, 185, 215} integer pa = add_v(sx * 0.1, -0.36, -1.05) integer pb = add_v(sx * 0.1, -0.36, -0.70) integer pc = add_v(sx * 0.7, 0.03, -1.05) integer pd = add_v(sx * 0.7, 0.03, -0.70) add_e(pa, pb) add_e(pc, pd) add_e(pa, pc) add_e(pb, pd) add_e(pa, pd) end for -- Centre the whole model on the origin so it spins about its middle sequence lo = {1e30, 1e30, 1e30} sequence hi = {-1e30, -1e30, -1e30} for i = 1 to length(verts) do for k = 1 to 3 do if verts[i][k] < lo[k] then lo[k] = verts[i][k] end if if verts[i][k] > hi[k] then hi[k] = verts[i][k] end if end for end for sequence mid = (lo + hi) / 2 for i = 1 to length(verts) do verts[i] -= mid end for ------------------------------------------------------------------ -- 3D maths (3x3 rotation matrices, so steering always feels the same -- no matter which way the ship is currently facing) ------------------------------------------------------------------ function m3_mul(sequence a, sequence b) sequence r = repeat(repeat(0, 3), 3) for i = 1 to 3 do for j = 1 to 3 do r[i][j] = a[i][1] * b[1][j] + a[i][2] * b[2][j] + a[i][3] * b[3][j] end for end for return r end function function m3_rotx(atom t) return {{1, 0, 0}, {0, cos(t), -sin(t)}, {0, sin(t), cos(t)}} end function function m3_roty(atom t) return {{cos(t), 0, sin(t)}, {0, 1, 0}, {-sin(t), 0, cos(t)}} end function function m3_rotz(atom t) return {{cos(t), -sin(t), 0}, {sin(t), cos(t), 0}, {0, 0, 1}} end function function m3_apply(sequence m, sequence v) return { m[1][1] * v[1] + m[1][2] * v[2] + m[1][3] * v[3], m[2][1] * v[1] + m[2][2] * v[2] + m[2][3] * v[3], m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3] } end function -- project a 3D point onto the screen (model +Y is up, screen Y is down) function project_point(sequence v) atom scale = FOCAL / (CAMERA_DIST + v[3] * MODEL_SCALE) integer sx = floor(CENTRE_X + v[1] * MODEL_SCALE * scale) integer sy = floor(CENTRE_Y - v[2] * MODEL_SCALE * scale) return {sx, sy} end function ------------------------------------------------------------------ -- Starfield ------------------------------------------------------------------ function new_star(integer at_far_end) integer z if at_far_end then z = STAR_FAR else z = rand_range(STAR_NEAR, STAR_FAR) end if return {rand_range(-1200, 1200), rand_range(-1000, 1000), z} end function sequence stars = repeat({0, 0, 0}, NUM_STARS) for i = 1 to NUM_STARS do stars[i] = new_star(0) end for procedure draw_stars() for i = 1 to NUM_STARS do stars[i][3] -= STAR_SPEED if stars[i][3] < STAR_NEAR then stars[i] = new_star(1) end if integer sx = floor(CENTRE_X + stars[i][1] * STAR_FOCAL / stars[i][3]) integer sy = floor(CENTRE_Y + stars[i][2] * STAR_FOCAL / stars[i][3]) if sx < 0 or sx >= SCREEN_W - 1 or sy < 0 or sy >= SCREEN_H - 1 then -- flew off the edge of the screen, send it back to the distance stars[i] = new_star(1) else -- nearer stars are brighter integer b = floor(255 * (1 - stars[i][3] / STAR_FAR)) if b < 40 then b = 40 end if sequence col = {b, b, b, 255} DrawPixel(sx, sy, col) if b > 170 then -- the nearest stars are drawn as little 2x2 squares DrawPixel(sx + 1, sy, col) DrawPixel(sx, sy + 1, col) DrawPixel(sx + 1, sy + 1, col) end if end if end for end procedure ------------------------------------------------------------------ -- Main program ------------------------------------------------------------------ sequence orient = m3_rotx(0.4) -- current orientation of the ship integer auto_spin = 1 InitWindow(SCREEN_W, SCREEN_H, "Euraylib 5 - Wireframe Starship") SetTargetFPS(60) while not WindowShouldClose() do -- ---- keyboard ---- if IsKeyPressed(KEY_SPACE) then auto_spin = not auto_spin end if if IsKeyPressed(KEY_R) then orient = m3_rotx(0.4) end if atom dx = 0 atom dy = 0 atom dz = 0 if auto_spin then dx = 0.011 dy = 0.017 dz = 0.007 end if if IsKeyDown(KEY_UP) then dx -= TURN_RATE end if if IsKeyDown(KEY_DOWN) then dx += TURN_RATE end if if IsKeyDown(KEY_LEFT) then dy -= TURN_RATE end if if IsKeyDown(KEY_RIGHT) then dy += TURN_RATE end if if IsKeyDown(KEY_Z) then dz += TURN_RATE end if if IsKeyDown(KEY_X) then dz -= TURN_RATE end if -- turn the ship a small step about the screen's X, Y and Z axes orient = m3_mul(m3_rotz(dz), m3_mul(m3_roty(dy), m3_mul(m3_rotx(dx), orient))) -- ---- transform the model ---- sequence rotated = repeat({0, 0, 0}, length(verts)) sequence pts = repeat({0, 0}, length(verts)) for i = 1 to length(verts) do rotated[i] = m3_apply(orient, verts[i]) pts[i] = project_point(rotated[i]) end for -- ---- draw ---- BeginDrawing() ClearBackground(BLACK) draw_stars() for i = 1 to length(edges) do integer ia = edges[i][1] integer ib = edges[i][2] sequence c = edges[i][3] -- dim edges that are further from the camera (+Z is away from us) atom zavg = (rotated[ia][3] + rotated[ib][3]) / 2 atom f = 0.65 - 0.35 * zavg / 1.9 if f < 0.25 then f = 0.25 end if if f > 1 then f = 1 end if DrawLine(pts[ia][1], pts[ia][2], pts[ib][1], pts[ib][2], {floor(c[1] * f), floor(c[2] * f), floor(c[3] * f), 255}) end for DrawText("Arrows: steer Z/X: roll SPACE: auto-spin R: reset", 10, 10, 18, {150, 160, 185, 255}) EndDrawing() end while CloseWindow()
Try stabilising the tumbling ship with the arrow keys
2. Re: Let's have some fun with EuRaylib
- Posted by Icy_Viking 2 days ago
- 127 views
Thanks Chris for using my mostly hand written code to train AI (slight sarcarsm). Regardless these are some cool programs.
3. Re: Let's have some fun with EuRaylib
- Posted by andreasWagner 1 day ago
- 123 views
Andys EuRaylib 6 ( even though it says 5). These are each separate programs, make sure you have raylib setup, Eu32 bit, everything else is standard Eu.
Hi, that's cool.
I quickly adapted it for my wrapper. It's just for Windows and 64-bit (but it supports Phix and Euphoria).
If you don't mind, I'll add it to my raylib example collection on github https://github.com/andizk4kx/raylib-playground/tree/main/examples. Let me know.
Yeah, I think it's a good idea to feed artificial intelligence with Euphoria code. Someone's got to remember Euphoria in the future.
Andreas
4. Re: Let's have some fun with EuRaylib
- Posted by ChrisB (moderator) 1 day ago
- 113 views
Thanks Chris for using my mostly hand written code to train AI (slight sarcarsm). Regardless these are some cool programs.
Haha
No, thankyou Andy for providing such a bloody good lib. You probably write code as fast as I prompt anyway!
I do think these highlight what raylib is capable of, and I for one vote for it's adoption into a general programming release.
Cheers Chris
5. Re: Let's have some fun with EuRaylib
- Posted by ChrisB (moderator) 1 day ago
- 113 views
Andys EuRaylib 6 ( even though it says 5). These are each separate programs, make sure you have raylib setup, Eu32 bit, everything else is standard Eu.
Hi, that's cool.
I quickly adapted it for my wrapper. It's just for Windows and 64-bit (but it supports Phix and Euphoria).
If you don't mind, I'll add it to my raylib example collection on github https://github.com/andizk4kx/raylib-playground/tree/main/examples. Let me know.
Yeah, I think it's a good idea to feed artificial intelligence with Euphoria code. Someone's got to remember Euphoria in the future.
Andreas
Absolutely - I can hardly claim they are my work anyway! Standing on the shoulders of giants as ever.
Perhaps you and Andy could agree on a common API to make translation between 32 and 64 bit trivial.
Cheers Chris
6. Re: Let's have some fun with EuRaylib
- Posted by Icy_Viking 1 day ago
- 107 views
Andys EuRaylib 6 ( even though it says 5). These are each separate programs, make sure you have raylib setup, Eu32 bit, everything else is standard Eu.
Hi, that's cool.
I quickly adapted it for my wrapper. It's just for Windows and 64-bit (but it supports Phix and Euphoria).
If you don't mind, I'll add it to my raylib example collection on github https://github.com/andizk4kx/raylib-playground/tree/main/examples. Let me know.
Yeah, I think it's a good idea to feed artificial intelligence with Euphoria code. Someone's got to remember Euphoria in the future.
Andreas
Absolutely - I can hardly claim they are my work anyway! Standing on the shoulders of giants as ever.
Perhaps you and Andy could agree on a common API to make translation between 32 and 64 bit trivial.
Cheers Chris
There's probably a way for the end-user to select if they wanna use 32-bit or 64-bit or way programming wise to make it so it can tell if the loaded DLL is 32 or 64-bit. I've kept it mostly 32-bit for compatibility reasons
7. Re: Let's have some fun with EuRaylib
- Posted by jmduro 1 day ago
- 71 views
I don't understand this thread. I ckecked EuRaylib6 with Linux Mint Debian x64. It works on Linux x64 and euc (4.2.0) already builds a 64-bit executable.
duro@hp-zbook15g2:~/Data/Euphoria/v4/EuRaylib6$ euc basic_win.ex Build directory: build-975579/ Translating code, pass: 1 2 3 4 5 6 7 generating Compiling with GCC Compiling 5% init-.c Compiling 21% basic_win.c Compiling 32% main-.c Compiling 42% raylib.c Compiling 53% ffi.c Compiling 63% machine.c Compiling 74% memory.c Compiling 84% dll.c Compiling 95% types.c Linking 100% ../basic_win duro@hp-zbook15g2:~/Data/Euphoria/v4/EuRaylib6$ file ./basic_win ./basic_win: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=9a172f96fcaac31a68f8467ba134dda9e8c7686a, for GNU/Linux 3.2.0, not stripped duro@hp-zbook15g2:~/Data/Euphoria/v4/EuRaylib6$ ./basic_win INFO: Initializing raylib 6.2 INFO: Platform backend: DESKTOP (GLFW) INFO: Supported raylib modules: INFO: > rcore:..... loaded (mandatory) INFO: > rlgl:...... loaded (mandatory) INFO: > rshapes:... loaded (optional) INFO: > rtextures:. loaded (optional) INFO: > rtext:..... loaded (optional) INFO: > rmodels:... loaded (optional) INFO: > raudio:.... loaded (optional) INFO: DISPLAY: Device initialized successfully INFO: > Display size: 1600 x 900 INFO: > Screen size: 800 x 600 INFO: > Render size: 800 x 600 INFO: > Viewport offsets: 0, 0 INFO: GLAD: OpenGL extensions loaded successfully INFO: GL: Supported extensions count: 216 INFO: GL: OpenGL device information: INFO: > Vendor: Mesa INFO: > Renderer: NVE6 INFO: > Version: 4.3 (Core Profile) Mesa 25.0.7-2+deb13u1 INFO: > GLSL: 4.30 INFO: GL: VAO extension detected, VAO functions loaded successfully INFO: GL: NPOT textures extension detected, full NPOT textures supported INFO: GL: DXT compressed textures supported INFO: GL: ETC2/EAC compressed textures supported INFO: PLATFORM: DESKTOP (GLFW - X11): Initialized successfully INFO: TEXTURE: [ID 1] Texture loaded successfully (1x1 | R8G8B8A8 | 1 mipmaps) INFO: TEXTURE: [ID 1] Default texture loaded successfully INFO: SHADER: [ID 1] Vertex shader compiled successfully INFO: SHADER: [ID 2] Fragment shader compiled successfully INFO: SHADER: [ID 3] Program shader loaded successfully INFO: SHADER: [ID 3] Default shader loaded successfully INFO: RLGL: Render batch vertex buffers loaded successfully in RAM (CPU) INFO: RLGL: Render batch vertex buffers loaded successfully in VRAM (GPU) INFO: RLGL: Default OpenGL state initialized successfully INFO: TEXTURE: [ID 2] Texture loaded successfully (128x128 | GRAY_ALPHA | 1 mipmaps) INFO: FONT: Default font loaded successfully (224 glyphs) INFO: SYSTEM: Working Directory: /home/duro/Data/Euphoria/v4/EuRaylib6 INFO: TIMER: Target time per frame: 16.667 milliseconds INFO: TEXTURE: [ID 2] Unloaded texture data from VRAM (GPU) INFO: SHADER: [ID 3] Default shader unloaded successfully INFO: TEXTURE: [ID 1] Default texture unloaded successfully INFO: Window closed successfully
So where is the need to get a multiarch version as the existing one, based on FFI, already is? Did I miss something ?
Jean-Marc
8. Re: Let's have some fun with EuRaylib
- Posted by ChrisB (moderator) 23 hours ago
- 58 views
I tried other AI engines (just for the hell of it), and claude trounced it. This is tonights promp
Using the euphoria programming, euraylib 5or 6 by Icy Viking (Andy P) on 1024 * 800 window, create a randomly generated maze that a player can walk through first person in a doom like fashion. Use a colour schem for the walls to enable easy visualisation. Use the keys wasd to control movement, and use the mouse to look around
and this is the result
-------------------------------------------------------------------------------- -- maze3d.ex : Doom-style first-person random maze (raycaster) -- Euphoria 4.1 (32-bit) + EuRayLib5 (Raylib wrapper by Andy P. / Icy Viking) -- -- Controls: W/A/S/D = move/strafe Mouse = look (left/right turns, up/down tilts) -- M = cycle map (local / full / off) R = new maze ESC = quit -- -- Wall colours (by the direction the wall FACES, so you always know which way -- you are heading, and darker with distance): -- North-facing = RED South-facing = BLUE -- East-facing = GREEN West-facing = YELLOW -------------------------------------------------------------------------------- include raylib.e include std/rand.e constant SW = 1024, SH = 800 -- window size constant COLW = 2 -- pixel width of each ray column (1 = sharper, slower) constant NUMCOLS = floor(SW / COLW) constant MZ_PI = 3.14159265358979 constant FOV = 0.66 -- camera plane length (~66 degree view) constant MOVE_SPEED = 3.2 -- cells per second constant MOUSE_SENS = 0.0025 -- radians per pixel constant PITCH_SENS = 1.0 -- pixels of horizon shift per pixel constant MAX_PITCH = 280 constant PLAYER_R = 0.22 -- collision radius constant mzDX = {1,-1,0,0}, mzDY = {0,0,1,-1} -- base colours: N, S, E, W constant mzFace = { {230,70,55}, {60,115,240}, {65,205,95}, {245,205,55} } -- ---------------------------------------------------------------- state ------ sequence mzGrid = {} integer mzG = 0, mzN = 8, mzLevel = 1 atom posX = 1.5, posY = 1.5, ang = 0, pitch = 0 atom goalX = 0, goalY = 0 atom msgTimer = 0 integer mapMode = 1 -- ------------------------------------------------------------- helpers ------- -- Colour helper: works whether the wrapper stores colours as {r,g,b,a} -- or as a packed 32-bit integer. If your colours break, edit only this. constant COLOR_IS_SEQ = sequence(RAYWHITE) function mzRGB(integer r, integer g, integer b, integer a = 255) if COLOR_IS_SEQ then return {r, g, b, a} end if return r + g * 256 + b * 65536 + a * 16777216 end function function mzAbs(atom x) if x < 0 then return -x end if return x end function function mzMax(integer a, integer b) if a > b then return a end if return b end function function mzMin(integer a, integer b) if a < b then return a end if return b end function -- ------------------------------------------------------ maze generation ------ -- Recursive backtracker on an (2n+1)x(2n+1) grid. 1 = wall, 0 = passage. -- Cells live on even 1-based indices (2,4,..,2n). procedure mzGenerate(integer n) sequence stack, cand, cur integer nx, ny, k mzG = 2 * n + 1 mzGrid = repeat(repeat(1, mzG), mzG) mzGrid[2][2] = 0 stack = {{2, 2}} while length(stack) > 0 do cur = stack[$] cand = {} for d = 1 to 4 do nx = cur[1] + mzDX[d] * 2 ny = cur[2] + mzDY[d] * 2 if nx >= 2 and nx <= mzG - 1 and ny >= 2 and ny <= mzG - 1 then if mzGrid[ny][nx] = 1 then cand = append(cand, d) end if end if end for if length(cand) = 0 then stack = stack[1..$-1] else k = cand[rand(length(cand))] nx = cur[1] + mzDX[k] * 2 ny = cur[2] + mzDY[k] * 2 mzGrid[cur[2] + mzDY[k]][cur[1] + mzDX[k]] = 0 -- knock out wall between mzGrid[ny][nx] = 0 stack = append(stack, {nx, ny}) end if end while end procedure procedure mzNewLevel() mzGenerate(mzN) posX = 1.5 posY = 1.5 if mzGrid[2][3] = 0 then ang = 0 -- face east if open else ang = MZ_PI / 2 -- otherwise face south end if pitch = 0 goalX = mzG - 1.5 -- centre of far corner cell goalY = mzG - 1.5 end procedure -- ------------------------------------------------------------ collision ------ function mzBlocked(atom x, atom y) integer gx, gy gx = floor(x) + 1 gy = floor(y) + 1 if gx < 1 or gy < 1 or gx > mzG or gy > mzG then return 1 end if return mzGrid[gy][gx] end function function mzCanStand(atom x, atom y) if mzBlocked(x - PLAYER_R, y - PLAYER_R) then return 0 end if if mzBlocked(x + PLAYER_R, y - PLAYER_R) then return 0 end if if mzBlocked(x - PLAYER_R, y + PLAYER_R) then return 0 end if if mzBlocked(x + PLAYER_R, y + PLAYER_R) then return 0 end if return 1 end function procedure mzMove(atom dx, atom dy) -- axis-separated => slide along walls if mzCanStand(posX + dx, posY) then posX += dx end if if mzCanStand(posX, posY + dy) then posY += dy end if end procedure -- ------------------------------------------------------------ 3D render ------- procedure mzRender() atom dirX, dirY, plX, plY, camX, rdx, rdy atom ddX, ddY, sdX, sdY, perp, wallX, shade integer mx, my, stepX, stepY, side, hit, face, top, h, horizon, lineH integer r, g, b, y0, y1 sequence base dirX = cos(ang) dirY = sin(ang) plX = -dirY * FOV plY = dirX * FOV horizon = floor(SH / 2 + pitch) -- ceiling (dark blue, brighter toward the horizon) for i = 0 to 9 do y0 = floor(horizon * i / 10) y1 = floor(horizon * (i + 1) / 10) DrawRectangle(0, y0, SW, y1 - y0 + 1, mzRGB(16 + i * 3, 18 + i * 3, 40 + i * 5)) end for -- floor (brown, brighter toward the player) for i = 0 to 9 do y0 = horizon + floor((SH - horizon) * i / 10) y1 = horizon + floor((SH - horizon) * (i + 1) / 10) DrawRectangle(0, y0, SW, y1 - y0 + 1, mzRGB(22 + i * 5, 20 + i * 4, 18 + i * 3)) end for -- walls: one DDA ray per column for col = 0 to NUMCOLS - 1 do camX = 2 * col / NUMCOLS - 1 rdx = dirX + plX * camX rdy = dirY + plY * camX mx = floor(posX) my = floor(posY) if rdx = 0 then ddX = 1e30 else ddX = mzAbs(1 / rdx) end if if rdy = 0 then ddY = 1e30 else ddY = mzAbs(1 / rdy) end if if rdx < 0 then stepX = -1 sdX = (posX - mx) * ddX else stepX = 1 sdX = (mx + 1 - posX) * ddX end if if rdy < 0 then stepY = -1 sdY = (posY - my) * ddY else stepY = 1 sdY = (my + 1 - posY) * ddY end if hit = 0 side = 0 while hit = 0 do if sdX < sdY then sdX += ddX mx += stepX side = 0 else sdY += ddY my += stepY side = 1 end if if mx < 0 or my < 0 or mx >= mzG or my >= mzG then hit = 1 elsif mzGrid[my + 1][mx + 1] = 1 then hit = 1 end if end while if side = 0 then perp = sdX - ddX wallX = posY + perp * rdy if stepX > 0 then face = 4 else face = 3 end if -- W / E face else perp = sdY - ddY wallX = posX + perp * rdx if stepY > 0 then face = 1 else face = 2 end if -- N / S face end if if perp < 0.05 then perp = 0.05 end if wallX -= floor(wallX) -- distance fog + dark edges between wall blocks shade = 1.2 / (1 + perp * 0.30) if shade > 1 then shade = 1 end if if shade < 0.10 then shade = 0.10 end if if wallX < 0.03 or wallX > 0.97 then shade *= 0.55 end if base = mzFace[face] r = floor(base[1] * shade) g = floor(base[2] * shade) b = floor(base[3] * shade) lineH = floor(SH / perp) top = horizon - floor(lineH / 2) h = lineH if top < 0 then h += top top = 0 end if if top + h > SH then h = SH - top end if if h > 0 then DrawRectangle(col * COLW, top, COLW, h, mzRGB(r, g, b)) end if end for end procedure -- --------------------------------------------------------------- map --------- procedure mzDrawMap(integer ox, integer oy, integer tile, integer x0, integer y0, integer x1, integer y1) integer lo, hi, rs, px, py, gcx, gcy sequence wallCol wallCol = mzRGB(120, 130, 170) DrawRectangle(ox - 3, oy - 3, (x1 - x0 + 1) * tile + 6, (y1 - y0 + 1) * tile + 6, mzRGB(0, 0, 0, 200)) DrawRectangle(ox, oy, (x1 - x0 + 1) * tile, (y1 - y0 + 1) * tile, mzRGB(18, 18, 28, 230)) lo = mzMax(x0, 1) hi = mzMin(x1, mzG) for gy = mzMax(y0, 1) to mzMin(y1, mzG) do rs = 0 for gx = lo to hi + 1 do if gx <= hi and mzGrid[gy][gx] = 1 then if rs = 0 then rs = gx end if elsif rs != 0 then DrawRectangle(ox + (rs - x0) * tile, oy + (gy - y0) * tile, (gx - rs) * tile, tile, wallCol) rs = 0 end if end for end for -- exit (green) gcx = floor(goalX) + 1 gcy = floor(goalY) + 1 if gcx >= x0 and gcx <= x1 and gcy >= y0 and gcy <= y1 then DrawRectangle(ox + (gcx - x0) * tile, oy + (gcy - y0) * tile, tile, tile, mzRGB(60, 255, 100)) end if -- player (red dot + heading line) px = ox + floor((posX - (x0 - 1)) * tile) py = oy + floor((posY - (y0 - 1)) * tile) DrawLine(px, py, px + floor(cos(ang) * tile * 1.6), py + floor(sin(ang) * tile * 1.6), mzRGB(255, 255, 255)) DrawCircle(px, py, tile * 0.35 + 1, mzRGB(255, 60, 60)) end procedure procedure mzDrawMapOverlay() integer cgx, cgy, tile, ox, oy if mapMode = 1 then cgx = floor(posX) + 1 cgy = floor(posY) + 1 tile = 9 ox = SW - 10 - 17 * tile oy = 10 mzDrawMap(ox, oy, tile, cgx - 8, cgy - 8, cgx + 8, cgy + 8) elsif mapMode = 2 then tile = floor(700 / mzG) if tile < 2 then tile = 2 end if ox = floor((SW - mzG * tile) / 2) oy = floor((SH - mzG * tile) / 2) mzDrawMap(ox, oy, tile, 1, 1, mzG, mzG) end if end procedure -- --------------------------------------------------------------- main -------- InitWindow(SW, SH, "Euphoria Maze - EuRayLib5 raycaster") SetTargetFPS(60) set_rand(time()) mzNewLevel() integer cx = floor(SW / 2), cy = floor(SH / 2) integer warm = 0, mxp, myp integer mvF, mvS atom dt, spd, ln, dx, dy, dist HideCursor() SetMousePosition(cx, cy) while not WindowShouldClose() do dt = GetFrameTime() if dt > 0.1 then dt = 0.1 end if -- ---- mouse look (re-centre the mouse every frame) ---- if IsWindowFocused() then mxp = GetMouseX() myp = GetMouseY() if warm > 5 then ang += (mxp - cx) * MOUSE_SENS pitch -= (myp - cy) * PITCH_SENS if pitch > MAX_PITCH then pitch = MAX_PITCH end if if pitch < -MAX_PITCH then pitch = -MAX_PITCH end if else warm += 1 end if SetMousePosition(cx, cy) end if -- ---- keyboard movement ---- mvF = 0 mvS = 0 if IsKeyDown(KEY_W) then mvF += 1 end if if IsKeyDown(KEY_S) then mvF -= 1 end if if IsKeyDown(KEY_D) then mvS += 1 end if if IsKeyDown(KEY_A) then mvS -= 1 end if if mvF != 0 or mvS != 0 then ln = sqrt(mvF * mvF + mvS * mvS) spd = MOVE_SPEED * dt dx = (cos(ang) * mvF - sin(ang) * mvS) / ln * spd dy = (sin(ang) * mvF + cos(ang) * mvS) / ln * spd mzMove(dx, dy) end if if IsKeyPressed(KEY_M) then mapMode = remainder(mapMode + 1, 3) end if if IsKeyPressed(KEY_R) then mzNewLevel() end if -- ---- reached the exit? ---- dist = sqrt((goalX - posX) * (goalX - posX) + (goalY - posY) * (goalY - posY)) if dist < 0.7 then mzLevel += 1 mzN = mzMin(8 + (mzLevel - 1) * 2, 24) mzNewLevel() msgTimer = 2.5 end if if msgTimer > 0 then msgTimer -= dt end if -- ---- draw ---- BeginDrawing() ClearBackground(mzRGB(0, 0, 0)) mzRender() mzDrawMapOverlay() -- crosshair DrawRectangle(cx - 8, cy - 1, 16, 2, mzRGB(255, 255, 255, 160)) DrawRectangle(cx - 1, cy - 8, 2, 16, mzRGB(255, 255, 255, 160)) DrawFPS(10, 10) DrawText(sprintf("Level %d Exit: %.1f m", {mzLevel, dist}), 10, 36, 20, mzRGB(255, 255, 255)) DrawText("WASD move | Mouse look | M map | R new maze | ESC quit", 10, SH - 28, 18, mzRGB(220, 220, 220)) if msgTimer > 0 then DrawText("You escaped! Next maze...", cx - 170, 90, 32, mzRGB(255, 230, 80)) end if EndDrawing() end while ShowCursor() CloseWindow()
I'm not bragging about my prompt writing skills, but just showing how good eu and raylib are together. I'm truly blown away.
Cheers Chris
9. Re: Let's have some fun with EuRaylib
- Posted by Icy_Viking 16 hours ago
- 42 views
I did recently upgrade my Raylib wrapper for Raylib 6.2 if I hadn't mentioned it before.
10. Re: Let's have some fun with EuRaylib
- Posted by ChrisB (moderator) 6 hours ago
- 18 views
Hi Andy
For handy ref, is there an EuRaylib constant to query which version is being run?
Cheers Chris

