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! :)
Here's the code: https://gist.github.com/1880241
@frosty - Nice job :) 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? ;)
@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.
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)
m:setRectTex(idx,0,0,1,.94)
end
function draw()
background()
m:draw()
end
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 :) )
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)
meshes[i]:setRectTex(idx,0,0,1,.94)
table.insert(idxs, i, idx)
end
And then I've altered the drawing code like so:
pushMatrix()
meshes[x]:setColors(wcolor)
translate(x, drawStart)
--scale(1, drawEnd-drawStart)
meshes[x]:setRect(idxs[x], 0, 0, SCALEF, drawEnd-drawStart)
meshes[x]:draw()
popMatrix()
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? :/
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.
Initialisation:
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
m:setRectTex(idx,0,0,1,.94)
end
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.
It looks like you're new here. If you want to get involved, click one of these buttons!