Raycasting

This commit is contained in:
MaddoScientisto 2024-04-29 23:32:40 +02:00
commit a352a671b9
3 changed files with 184 additions and 49 deletions

View file

@ -58,6 +58,7 @@ local weapons_manager = require(make_path("weapons"))
local Barrel = require(make_path("barrel"))
local Strawberry = require(make_path("strawberry"))
local Box = require(make_path("box"))
local NPC = require(make_path("npc"))
include(make_path("pgui" .. ".lua"))
@ -115,7 +116,8 @@ actors_db = {
{name="player",sprite=65,actor=nil},
{name="box",sprite=4,actor=Box},
{name="alarm",sprite=19,actor=nil},
{name="fan",sprite=16,actor=nil}
{name="fan",sprite=16,actor=nil},
{name="NPC",sprite=69,actor=NPC}
}
@ -307,3 +309,66 @@ function check_collisions()
end
function raycast(x1, y1, x2, y2, max_distance)
local dx = x2 - x1
local dy = y2 - y1
local step_x = dx > 0 and 1 or -1
local step_y = dy > 0 and 1 or -1
dx = dx < 0 and -dx or dx
dy = dy < 0 and -dy or dy
local fraction = dx - dy
local x = x1
local y = y1
-- calculate the distance between start and end point
local distance = (math.sqrt((x2-x1)^2 + (y2-y1)^2))\1
local scale = max_distance / distance
local px = x1 + (x2 - x1) * scale
local py = y1 + (y2 - y1) * scale
-- limit the maximum distance
if distance > max_distance then
--return x2, y2, false
return px, py, false
end
-- checking the start point
--if map_manager.is_tile_shoot_solid(flr(x / tile_width), flr(y / tile_height)) then
if map_manager.is_tile_shoot_solid(x, y) then
return x1, y1, false
end
local distance_traveled = 0
while distance_traveled <= max_distance and (x ~= x2 or y ~= y2) do
local prevX = x -- store previous positions for distance calculation
local prevY = y
if fraction >= 0 then
x += step_x
fraction -= dy
else
y += step_y
fraction += dx
end
-- calculate distance traveled
distance_traveled += math.sqrt((x - prevX) ^ 2 + (y - prevY) ^ 2)\1
-- return false as soon as a solid tile is hit
if map_manager.is_tile_shoot_solid(x, y) then
if x==x2 and y==y2 then -- return true only if hit tile is destination tile
return x, y, true
else
return x, y, false
end
end
end
-- if the loop is done without hitting a solid tile, return false
return x2, y2, true
end

69
src/npc.lua Normal file
View file

@ -0,0 +1,69 @@
local Actor = require(make_path("actor2"))
local NPC = Actor:new()
function NPC:new(x,y)
local n = Actor:new(x,y)
n.spriteIndex = 69
n.range = 64 + 16
n.found = false
n.enemy_x_debug = 0
n.enemy_x_debug = 0
--n.dir_vec_debug_x = 0
--n.dir_vec_debug_y = 0
n.hit_x = 0
n.hit_y = 0
n.raycast_frames = 0
n.raycast_frames_to_wait = 120
return setmetatable(n, {__index=self})
end
function NPC:update()
local enemy_x = cirnoInstance.x + 8
local enemy_y = cirnoInstance.y + 8
self.enemy_x_debug = enemy_x
self.enemy_y_debug = enemy_y
--local dir_vec = get_direction_vector(self.x, self.y, enemy_x, enemy_y)
--self.dir_vec_debug_x = dir_vec.dir_x
--self.dir_vec_debug_y = dir_vec.dir_y
self.raycast_frames += 1
if (self.raycast_frames % self.raycast_frames_to_wait == 0) then
local hit_x, hit_y, hit_status = raycast(self.x, self.y, enemy_x, enemy_y, self.range, 2)
--if (raycast_hit) then
self.hit_x = hit_x
self.hit_y = hit_y
--end
self.found = hit_status == true
end
end
function NPC:draw()
--circfill(self.x,self.y,self.range,18)
local col = 30
spr(self.spriteIndex,self.x,self.y)
print(string.format("Found: %s", tostring(self.found)),self.x,self.y-16,col)
--print(string.format("dir_x: %.2f dir_y: %.2f",self.dir_vec_debug_x, self.dir_vec_debug_y),self.x,self.y-8,28)
--print(string.format("hit_x: %.2f dir_y: %.2f", self.hit_x, self.hit_y),self.x, self.y,28)
--line(self.x,self.y, self.enemy_x_debug, self.enemy_y_debug, 14)
line(self.x,self.y, self.hit_x, self.hit_y, col)
end
return NPC