I am using the Windows lua SDK and I am having issues with the raycaster I've been trying to make as a test project. This is the first real project I am doing on the playdate without any tutorials. I have some amount of prior coding experience, but not with lua.
After shooting out the ray into a direction, it is supposed to give back the traveled distance after the first alpha collision with the map.
I used alpha collision so I can always edit the map without having to define the hitboxes of every single wall/object. The collisions didn't work as intended, and after adding a fillRect function for debugging that draws a rectangle on every collision of the ray and the map (I also removed the part that breaks out of the loop after the collision for a clearer image of what's wrong) it turns out that for some reason besides the regular collions, the raycaster detects two more collisions shifted to the right by some offset.
An image of what the map should look like next to what the raycaster sees. Everything is rendered two times more shifted to the right with some offset
This is the code for the raycaster in its current state:
local function raycast(playerX, playerY, playerAngle, FOV, RES, rayStep, rayLength)
for i = 0, RES do
local rayAngle = playerAngle - FOV / 2 + (i * FOV) / RES
local raydx = math.cos(math.rad(rayAngle)) * rayStep
local raydy = math.sin(math.rad(rayAngle)) * rayStep
local rayProgress = 0
local hit = false
raySprite:moveTo(playerX, playerY)
while (rayProgress <= rayLength) do
raySprite:moveBy(raydx,raydy)
if raySprite:alphaCollision(mapSprite) then
gfx.fillRect(raySprite.x - 1, raySprite.y - 1, 2, 2) --Draws boxes on collision for debugguing
--hit = true
--The traveled distance would just be rayProgress here
end
if (hit == true) then break end
rayProgress += rayStep
end
end
end
The weird thing is that I have used the same method to detect collisions between the player and the map, with the difference that they work just as intended.
playerSprite:moveBy(dx, dy)
if playerSprite:alphaCollision(mapSprite) then
playerSprite:moveBy(-dx, -dy)
end
Also this is the full code right now, if it helps
import "CoreLibs/object"
import "CoreLibs/graphics"
import "CoreLibs/sprites"
local pd <const> = playdate
local gfx <const> = pd.graphics
local mapSprite = nil
local playerSprite = nil
local raySprite = nil
local FOV = 70
local RES = 100
local rayStep = 3
local rayLength = 300
local playerSpeed = 4
local rotSpeed = 5
local playerAngle = 270
local function init()
local mapImage = gfx.image.new("images/map")
mapSprite = gfx.sprite.new(mapImage)
mapSprite:setCollideRect(0, 0, mapSprite:getSize())
mapSprite:moveTo(200,120)
mapSprite:add()
local playerImage = gfx.image.new("images/player")
playerSprite = gfx.sprite.new(playerImage)
playerSprite:setCollideRect(0, 0, playerSprite:getSize())
playerSprite:moveTo(200,120)
playerSprite:add()
local rayImage = gfx.image.new("images/ray")
raySprite = gfx.sprite.new(rayImage)
raySprite:setCollideRect(0, 0, raySprite:getSize())
raySprite:moveTo(200,120)
raySprite:add()
end
local function raycast(playerX, playerY, playerAngle, FOV, RES, rayStep, rayLength)
for i = 0, RES do
local rayAngle = playerAngle - FOV / 2 + (i * FOV) / RES
local raydx = math.cos(math.rad(rayAngle)) * rayStep
local raydy = math.sin(math.rad(rayAngle)) * rayStep
local rayProgress = 0
local hit = false
raySprite:moveTo(playerX, playerY)
while (rayProgress <= rayLength) do
raySprite:moveBy(raydx,raydy)
if raySprite:alphaCollision(mapSprite) then
gfx.fillRect(raySprite.x - 1, raySprite.y - 1, 2, 2) --Draws boxes on collision for debugguing
--hit = true
--The traveled distance would just be rayProgress here
end
if (hit == true) then break end
rayProgress += rayStep
end
end
end
init()
function pd.update()
if pd.buttonIsPressed(pd.kButtonUp) then
gfx.sprite.update()
local dx = math.cos(math.rad(playerAngle)) * playerSpeed
local dy = math.sin(math.rad(playerAngle)) * playerSpeed
playerSprite:moveBy(dx, dy)
if playerSprite:alphaCollision(mapSprite) then
playerSprite:moveBy(-dx, -dy)
end
raycast(playerSprite.x, playerSprite.y, playerAngle, FOV, RES, rayStep, rayLength)
end
if pd.buttonIsPressed(pd.kButtonLeft) then
gfx.sprite.update()
playerAngle -= rotSpeed
raycast(playerSprite.x, playerSprite.y, playerAngle, FOV, RES, rayStep, rayLength)
end
if pd.buttonIsPressed(pd.kButtonRight) then
gfx.sprite.update()
playerAngle += rotSpeed
raycast(playerSprite.x, playerSprite.y, playerAngle, FOV, RES, rayStep, rayLength)
end
end
I've tried many different things, but none of them did any help. If any more information is needed, let me know!