Working Raycasting example! WolfenLöve 3D if you will...

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
Jasoco
Inner party member
Posts: 3641
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Working Raycasting example! WolfenLöve 3D if you will...

Post by Jasoco » Fri Jan 06, 2012 5:40 am

Edit: Click this link to see where the actual progress begins:
viewtopic.php?f=4&t=6834&start=10#p45793

----Original post starts here----

I would really love to see a working Raycasting example that worked in Löve. I've tried converting numerous JavaScript versions with no luck at all. It's always just out of reach. Surely it can't be hard.

There was an example in the "What are you working on" thread a while ago but it was a bit buggy. I just tried the code now and it just looks and works wrong. I'm not talking about the fisheye, rather some other glitches. This is the code that was posted there:

Code: Select all

-------------------------------------------------------------------
--Raycasting sample code (written by Roland Yonaba)
-- Credits to :http://lodev.org/cgtutor/raycasting.html
-------------------------------------------------------------------
local map = {
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1},
  {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1},
  {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
}

local map_height,map_width = #map,#map[1]

local posX,posY = 22,12
local dirX,dirY = -1,0
local planeX,planeY = 0,0.66
local time,oldtime = 0,0
local w = love.graphics.getWidth()
local h = love.graphics.getHeight()

local moveSpeed, rotSpeed = 0,0

function love.update(dt)
   moveSpeed = dt*3
   rotSpeed = dt
   
   if love.keyboard.isDown('up') then
      if map[math.floor(posX+dirX*moveSpeed)][math.floor(posY)] == 0 then
      posX = posX + dirX*moveSpeed
      end
      if map[math.floor(posX)][math.floor(posY+dirY*moveSpeed)] == 0 then
      posY = posY + dirY*moveSpeed
      end
   end
   
   if love.keyboard.isDown('down') then
      if map[math.floor(posX-dirX*moveSpeed)][math.floor(posY)] == 0 then
      posX = posX - dirX*moveSpeed
      end
      if map[math.floor(posX)][math.floor(posY-dirY*moveSpeed)] == 0 then
      posY = posY - dirY*moveSpeed
      end
   end   
   
   if love.keyboard.isDown('left') then
   local oldDirX = dirX
   dirX = dirX * math.cos(rotSpeed)- dirY*math.sin(rotSpeed)
   dirY = oldDirX * math.sin(rotSpeed)+ dirY*math.cos(rotSpeed)
   local oldPlaneX = planeX
   planeX = planeX * math.cos(rotSpeed) - planeY*math.sin(rotSpeed)
   planeY = oldPlaneX * math.sin(rotSpeed) + planeY*math.cos(rotSpeed)
   end
   
   if love.keyboard.isDown('right') then
   local oldDirX = dirX
   dirX = dirX * math.cos(-rotSpeed)- dirY*math.sin(-rotSpeed)
   dirY = oldDirX * math.sin(-rotSpeed)+ dirY*math.cos(-rotSpeed)
   local oldPlaneX = planeX
   planeX = planeX * math.cos(-rotSpeed) - planeY*math.sin(-rotSpeed)
   planeY = oldPlaneX * math.sin(-rotSpeed) + planeY*math.cos(-rotSpeed)
   end   
   
end


function love.draw()
   love.graphics.clear({0,0,0})   
   for x = 0,w do
   local camX = 2*(x/w)-1
   local rayPosX = posX
   local rayPosY = posY
   local rayDirX = dirX + planeX*camX
   local rayDirY = dirY + planeY*camX
   local mapX = math.floor(rayPosX)
   local mapY = math.floor(rayPosY)
   local sideDistX,sideDistY
   
   local deltaDistX = math.sqrt(1+(rayDirY^2)/(rayDirX^2))
   local deltaDistY = math.sqrt(1+(rayDirX^2)/(rayDirY^2))
   local perpWallDist
   
   local stepX,stepY
   
   local hit = 0
   local side
   
      if rayDirX<0 then
      stepX = -1
      sideDistX = (rayPosX - mapX)*deltaDistX
      else
      stepX = 1
      sideDistX = (mapX+1-rayPosX)*deltaDistX
      end
      
      if rayDirY <0 then
      stepY = -1
      sideDistY = (rayPosY - mapY) * deltaDistY
      else
      stepY =  1
      sideDistY = (rayPosY +1-rayPosY)*deltaDistY
      end
      
      while (hit==0) do
         if (sideDistX < sideDistY) then
         sideDistX = sideDistX + deltaDistX
         mapX = mapX+stepX
         side = 0
         else
         sideDistY = sideDistY + deltaDistY
         mapY = mapY + stepY
         side = 1
         end
         
         if map[mapX][mapY] > 0 then hit = 1 end
      end
      
      if side==0 then
      perpWallDist = math.abs((mapX - rayPosX+(1-stepX)/2)/rayDirX)
      else
      perpWallDist = math.abs((mapY - rayPosY+(1-stepY)/2)/rayDirY)
      end
      
      local lineHeight = math.abs(math.floor(h/perpWallDist))
      local drawStart = -lineHeight/2 + h/2
         if drawStart < 0 then drawStart = 0 end
      local drawEnd = lineHeight/2 + h/2
         if drawEnd >= h then drawEnd = h-1 end
         
      local color = {}
      local square = map[mapX][mapY]
         if square == 1 then color = {255,0,0} 
         elseif square == 2 then color = {0,255,0}
         elseif square == 3 then color = {0,0,255}
         elseif square == 4 then color = {255,255,255}
         else color = {255,255,0}
         end
         
      if side == 1 then 
         for k,v in ipairs(color) do v = v/2 end 
      end
      love.graphics.setColor(color)
      love.graphics.line(x,drawStart,x,drawEnd)
   end

end
From Roland_Yonaba's post here: http://love2d.org/forums/viewtopic.php? ... ing#p33899

Surely if it could be done so perfectly in 1992, it can be done right now. I'm not even concerned about image textures yet. I just want the shapes. The textures would come later based on where along the wall tile a ray is touching and dividing the texture into a quad per horizontal pixel unit. Blah blah blah.
Last edited by Jasoco on Thu Feb 02, 2012 8:08 am, edited 2 times in total.

Erniecz
Prole
Posts: 2
Joined: Fri Jan 06, 2012 9:07 am

Re: Working Raycasting example?

Post by Erniecz » Fri Jan 06, 2012 9:21 am

Hello everybody,
I wrote a very simple (only 144 lines!) raycasting example (I used this toturial: http://www.permadi.com/tutorial/raycast/, it is really good). I just changed one thing - when finding walls, I used very simple and VERY slow algorithm. So if you want to use it, you have to rewrite it to the algorithm in tutorial.
Obviously, it should run in smaller window (320 x 200), it uses bigger window for map and some info.

Here it is:
http://dl.dropbox.com/u/6534785/simple3D.love
(i can't upload attachment, I click button and nothing happens).

User avatar
SimonLarsen
Party member
Posts: 100
Joined: Thu Mar 31, 2011 4:47 pm
Location: Denmark
Contact:

Re: Working Raycasting example?

Post by SimonLarsen » Fri Jan 06, 2012 10:29 am

I did a quick test some time ago. Did the math myself so it's not very optimized.
Attachments
ray.love
(1.32 KiB) Downloaded 665 times

User avatar
T-Bone
Inner party member
Posts: 1492
Joined: Thu Jun 09, 2011 9:03 am

Re: Working Raycasting example?

Post by T-Bone » Fri Jan 06, 2012 3:02 pm

SimonLarsen wrote:I did a quick test some time ago. Did the math myself so it's not very optimized.
Hey, that's awesome! And it runs well even on my netbook.

jfroco
Prole
Posts: 24
Joined: Fri Jan 06, 2012 5:14 pm

Re: Working Raycasting example?

Post by jfroco » Fri Jan 06, 2012 5:20 pm

Hi,

This is my first post!!!!

I took this: http://dev.opera.com/articles/view/crea ... l-5-can-1/

and implemented a texture-less Love2d version...

Image

http://dl.dropbox.com/u/4281970/love2d/raycast.love

Move using arrows...

Hope this helps.

JF

User avatar
T-Bone
Inner party member
Posts: 1492
Joined: Thu Jun 09, 2011 9:03 am

Re: Working Raycasting example?

Post by T-Bone » Fri Jan 06, 2012 6:13 pm

So when will we see the first FPS made in LÖVE?

User avatar
MarekkPie
Inner party member
Posts: 587
Joined: Wed Dec 28, 2011 4:48 pm
Contact:

Re: Working Raycasting example?

Post by MarekkPie » Fri Jan 06, 2012 6:26 pm

I really like jfroco's version. Much cleaner walls.

User avatar
Jasoco
Inner party member
Posts: 3641
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Working Raycasting example?

Post by Jasoco » Fri Jan 06, 2012 8:35 pm

jfroco wrote:Hi,

This is my first post!!!!

I took this: http://dev.opera.com/articles/view/crea ... l-5-can-1/

and implemented a texture-less Love2d version...

http://dl.dropbox.com/u/4281970/love2d/raycast.png

http://dl.dropbox.com/u/4281970/love2d/raycast.love

Move using arrows...

Hope this helps.

JF
I am impressed. That's the exact same code I was trying to port myself all yesterday with no avail. I am going to have to compare your port to the original and my half-assed failure and see if I can learn more.

I want to try and get a real working Wolf-style game engine going. I even downloaded that Prelude of the Chambered (Notch's Ludum Dare game from the previous LD) and couldn't make heads nor tails of the code to figure out which stuff was the actual math calculations or if it was even raycasting or simply warping 2D images in 3D space like MineCraft does.

Thanks for this. It'll be a good testing ground to start with. You even accounted for the fisheye. Now if you could get texturing in, it would be even better. Then I'd have to figure out how to do sprites with clipping and z-indexing.

Everyone's examples are great. But jfroco somehow reached into my brain and figured out what I was trying to do all day yesterday. Don't know how.

I'd really like to up the resolution on how many lines of ray are drawn across the screen up to 320 so I can have a true 320x200 game.

User avatar
bartbes
Sex machine
Posts: 4944
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: Working Raycasting example?

Post by bartbes » Fri Jan 06, 2012 8:45 pm

It's probably because your name are alike.. are you the same person? :P

User avatar
Jasoco
Inner party member
Posts: 3641
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Working Raycasting example?

Post by Jasoco » Fri Jan 06, 2012 10:58 pm

Not unless jfroco's the me from the future come back in time to secretly help me become the master of the universe.

Post Reply

Who is online

Users browsing this forum: Google [Bot] and 6 guests