I’ve been playing about with raycasting recently, and thought I’d share a video and some code!

At the moment this is just a very basic straight port from a C++ untextured raycaster example I came across (http://lodev.org/cgtutor/raycasting.html). I’ve also tacked on some terrible touch controls for moving around. It certainly has a couple of bugs when viewing walls at particular angles, etc. It was very easy to port over though, and wouldn’t take much work to improve - I just haven’t found the time yet! :slight_smile:


Here’s the code: https://gist.github.com/1880241

@frosty - Nice job :slight_smile: Haven’t looked at your code, but just in case setRectTex doesn’t just scale the texture and actually displays what is specified in the coordinates, you could easily texture map the wall and it wouldn’t be much slower than colored lines since you’re using mesh(). Wolfenstein on Codea? :wink:

I totally would have never used this appoach. (which is why you have something that works and when I tried, I gave up :slight_smile: )

What is it with 3D things now and days? IT’S AWSOME! I might just turn it into a game with your permission (although I probably won’t).

Hey, cool. I was just in the middle of converting a similar bit of code, and now I don’t have to. :slight_smile:

Looks nice. As @Xavier said, texture draws on mesh surfaces are remarkably fast. Slip mesh.texture = “Planet Cute:Ramp South” in there just for fun.

Nice! I predict we’ll see many first person games in codea using this

Haha… Froggy 3d, snake 3d, breakout 3d… etc. Make the old games 3d!

Wow this is only 300 lines of lua?! How’s that possible…crazy

@Xavier @Mark Yeah, texture mapping shouldn’t be too tricky. You do however need to take into account the exact coordinate at which a ray intersects a wall so you know exactly which part of the texture needs to be displayed. The current untextured version above doesn’t do this, but there’s code for it in the article I linked in my original post.

I’m working on writing my own raycaster from scratch (just because I’d like to be able to), and I’m using this tutorial to help me learn: http://www.permadi.com/tutorial/raycast/index.html - it seems to be the tutorial that everyone follows for learning raycasting. It also looks like he addresses how to fix the ‘viewing walls at a particular angle causes them to be drawn incorrectly’ issue that the code I posted above has.

@frosty Ah, that’s a nice one. I’d been trying to make never height surfaces (voxel landscapes) and that original library has some issues when the camera is moved off the plane.

So I’ve been having a quick play with very roughly texture mapping this, but I’m having a problem which is probably due to my unfamiliarity with meshes - maybe someone can help…

I’m trying to texture the walls with the tall stone wall sprite. However, the sprite on its own isn’t tall enough (in pixels) to cover the whole height of the wall. Is there a way for me to stretch the sprite so it covers the whole of the mesh rect it’s applied to?

Frosty, yes with setRectTex which allows you do draw only a subregion of the sprite in that rectangle.

function setup()
    m = mesh()
    m.texture = "Planet Cute:Stone Block Tall"
    local idx = m:addRect(WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)

function draw()

Thanks, @ruilov - I was nearly there!

I’m still missing something though. So, I’ve updated my intialisation of themes meshes like so: (I realise this could be done with a single mesh, but I’m taking baby steps :slight_smile: )

idxs = {}

for i = 0, w do
        meshes[i] = mesh()
        meshes[i].vertices = tsq
        meshes[i].texture = "Planet Cute:Stone Block Tall"
        local idx =  meshes[i]:addRect(0, 0, SCALEF, 1)
        table.insert(idxs, i, idx)

And then I’ve altered the drawing code like so:

     translate(x, drawStart)
     --scale(1, drawEnd-drawStart)
     meshes[x]:setRect(idxs[x], 0, 0, SCALEF, drawEnd-drawStart)

This isn’t right, though! Without doing the scale(), each ray isn’t tall enough, and stops halfway up the screen. I figured I wouldn’t need to scale (and perhaps even not translate) if I could just position the rect through setRect, but I can’t quite work out how it should work exactly. Just doing the scale and translate I was doing before isnt right either.

Any advice? :confused:

Fixed! The main issue was that I hadn’t realised that setRect’s x and y parameters specify the center of the rect. I was treating them as a corner. I’ve also changed things so I’m using a single mesh, which results in much faster performance.


    rects = {}
    m = mesh()

    m.texture = "Planet Cute:Stone Block Tal
    for i = 0, w do
        local idx =  m:addRect(0, 0, SCALEF, 1)
        rects[i] = idx

And drawing is far simpler:

    m:setRectColor(rects[x], wcolor)
    m:setRect(rects[x], x, h/2, SCALEF, drawEnd-drawStart)

With one final call to m:draw() after the main loop.

Boom! Still needs much work, but I have some proper texture mapping going on!


Wow. You guys are racing ahead. Forget “will it play Doom?” I’m waiting for someone to take this ray caster and make a terrific rogue-like rpg.


With time, I would, but with Middle school, time is a thing of the past.

time is a thing of the past 

I see what you did there, @Zoyt :wink:

Working on better controllers and eventually being put in a class… But I’m barely anywhere. If you were thinking about doing it instead, please do.