Add clearance check for spawning, Improved obstacle avoidance

This commit is contained in:
ElCeejo 2022-08-03 02:03:05 -07:00
parent da15c361cf
commit b41924d4cb
4 changed files with 53 additions and 36 deletions

View File

@ -135,7 +135,8 @@ function creatura.get_node_def(node) -- Node can be name or pos
return def
end
function creatura.get_ground_level(pos2, max_diff)
function creatura.get_ground_level(pos, max_diff)
local pos2 = pos -- Prevent modifying table that shouldn't be changed
pos2.y = math.floor(pos2.y - 0.49)
local node = minetest.get_node(pos2)
local node_under = minetest.get_node({

View File

@ -38,7 +38,7 @@ local dir2yaw = minetest.dir_to_yaw
texture = tex or "creatura_particle_red.png",
expirationtime = time or 3,
glow = 6,
size = 12
size = 1
})
end]]
@ -59,20 +59,17 @@ local function raycast(pos1, pos2, liquid)
end
local function get_collision(self, yaw)
local width = self.width + 0.5
local height = self.height + 0.5
local width = self.width
local height = self.height
local total_height = height + self.stepheight
local pos = self.object:get_pos()
if not pos then return end
local ground = creatura.get_ground_level(pos, (self.stepheight or 2))
if ground.y > pos.y then
pos = ground
end
local pos2 = vec_add(pos, vec_multi(yaw2dir(yaw), width + 3))
ground = creatura.get_ground_level(pos2, (self.stepheight or 2))
if ground.y > pos2.y then
pos2 = ground
end
pos.y = pos.y + 0.1
local speed = abs(vec_len(self.object:get_velocity()))
local pos2 = vec_add(pos, vec_multi(yaw2dir(yaw), (width + 0.5) * ((speed > 1 and speed) or 1)))
-- Localize for performance
local pos_x, pos_z = pos.x, pos.z
local pos2_x, pos2_z = pos2.x, pos2.z
for x = -width, width, width / ceil(width) do
local step_flag = false
for y = 0, total_height, total_height / ceil(total_height) do
@ -81,14 +78,14 @@ local function get_collision(self, yaw)
break
end
local vec1 = {
x = cos(yaw) * ((pos.x + x) - pos.x) + pos.x,
x = cos(yaw) * ((pos_x + x) - pos_x) + pos_x,
y = pos.y + y,
z = sin(yaw) * ((pos.x + x) - pos.x) + pos.z
z = sin(yaw) * ((pos_x + x) - pos_x) + pos_z
}
local vec2 = {
x = cos(yaw) * ((pos2.x + x) - pos2.x) + pos2.x,
x = cos(yaw) * ((pos2_x + x) - pos2_x) + pos2_x,
y = vec1.y,
z = sin(yaw) * ((pos2.x + x) - pos2.x) + pos2.z
z = sin(yaw) * ((pos2_x + x) - pos2_x) + pos2_z
}
local ray = raycast(vec1, vec2, true)
if ray then
@ -101,6 +98,14 @@ local function get_collision(self, yaw)
end
end
end
--[[if width > 0.5
and height > 0.5 then
else
local ray = raycast(pos, pos2, true)
if ray then
return true, ray.intersection_point
end
end]]
return false
end
@ -112,7 +117,9 @@ local function get_avoidance_dir(self)
local vel = self.object:get_velocity()
local ahead = vec_add(pos, vec_normal(self.object:get_velocity()))
local avoidance_force = vector.subtract(ahead, col_pos)
avoidance_force = vec_multi(vec_normal(avoidance_force), vec_len(vel))
avoidance_force.y = 0
local vel_len = vec_len(vel)
avoidance_force = vec_multi(vec_normal(avoidance_force), (vel_len > 1 and vel_len) or 1)
return vec_dir(pos, vec_add(ahead, avoidance_force))
end
end
@ -201,6 +208,7 @@ local function trim_path(pos, path)
local trim = false
local closest
for i = #path, 1, -1 do
if not path[i] then break end
if (closest
and vec_dist(pos, path[i]) > vec_dist(pos, path[closest]))
or trim then
@ -327,6 +335,8 @@ end)
creatura.register_movement_method("creatura:obstacle_avoidance", function(self)
local box = clamp(self.width, 0.5, 1.5)
self:set_gravity(-9.8)
local steer_to
local steer_timer = 0.25
local function func(_self, goal, speed_factor)
local pos = _self.object:get_pos()
if not pos then return end
@ -337,7 +347,10 @@ creatura.register_movement_method("creatura:obstacle_avoidance", function(self)
_self:halt()
return true
end
local steer_to = get_avoidance_dir(_self, goal)
steer_timer = steer_timer - self.dtime
if steer_timer <= 0 then
steer_to = get_avoidance_dir(_self)
end
-- Get movement direction
local goal_dir = vec_dir(pos, goal)
if steer_to then
@ -355,9 +368,7 @@ creatura.register_movement_method("creatura:obstacle_avoidance", function(self)
else
_self:set_forward_velocity(speed * 0.33)
end
if yaw_diff > 0.1 then
_self:turn_to(goal_yaw, turn_rate)
end
_self:turn_to(goal_yaw, turn_rate)
end
return func
end)
end)

View File

@ -67,25 +67,23 @@ minetest.register_globalstep(function(dtime)
step_tick = step_tick - dtime
end)
-- A metatable is used to avoid issues
-- With mobs performing functions outside
-- their own scope
local mob = {
-- Stats
max_health = 20,
armor_groups = {fleshy = 100},
damage = 2,
speed = 4,
tracking_range = 16,
despawn_after = nil,
-- Physics
max_fall = 3,
stepheight = 1.1,
hitbox = {
width = 0.5,
height = 1
},
follow = {},
fancy_collide = false,
bouyancy_multiplier = 1,
hydrodynamics_multiplier = 1
}
local mob_meta = {__index = mob}
@ -159,7 +157,7 @@ end
-- Turn to specified yaw
local function lerp_rad(a, b, w)
local function interp_rad(a, b, w)
local cs = (1 - w) * cos(a) + w * cos(b)
local sn = (1 - w) * sin(a) + w * sin(b)
return atan2(sn, cs)
@ -170,7 +168,7 @@ function mob:turn_to(tyaw, rate)
rate = rate or 5
local yaw = self.object:get_yaw()
local step = math.min(self.dtime * rate, abs(diff(yaw, tyaw)) % (pi2))
self.object:set_yaw(lerp_rad(yaw, tyaw, step))
self.object:set_yaw(interp_rad(yaw, tyaw, step))
end
-- Set Gravity (default of -9.8)
@ -1093,7 +1091,6 @@ function mob:_execute_utilities()
}
self:clear_action()
end
--local us_time = minetest.get_us_time()
local action = self._action
if action
and type(action) ~= "table" then
@ -1101,7 +1098,6 @@ function mob:_execute_utilities()
self:clear_action()
end
end
--minetest.chat_send_all(minetest.get_us_time() - us_time)
end
end

View File

@ -57,7 +57,7 @@ function creatura.register_spawn_egg(name, col1, col2, inventory_image) -- depre
local mobdef = minetest.registered_entities[name]
local spawn_offset = abs(mobdef.collisionbox[2])
local pos = minetest.get_pointed_thing_position(pointed_thing, true)
pos.y = (pos.y - 0.49) + spawn_offset
pos.y = (pos.y - 0.4) + spawn_offset
local object = minetest.add_entity(pos, name)
if object then
object:set_yaw(random(1, 6))
@ -245,6 +245,14 @@ local function execute_spawns(player)
return
end
local mob_def = minetest.registered_entities[mob]
local mob_width = mob_def.collisionbox[4]
local mob_height = math.max(0, mob_def.collisionbox[5] - mob_def.collisionbox[2])
if not creatura.is_pos_moveable(spawn_pos, mob_width, mob_height) then
return
end
local group_size = random(spawn.min_group or 1, spawn.max_group or 1)
if spawn.spawn_cluster then
@ -290,7 +298,8 @@ end)
minetest.register_node("creatura:spawn_node", {
drawtype = "airlike",
groups = {not_in_creative_inventory = 1}
groups = {not_in_creative_inventory = 1},
walkable = false
})
local spawn_interval = tonumber(minetest.settings:get("creatura_spawn_interval")) or 10
@ -351,4 +360,4 @@ minetest.register_abm({
end
end
end,
})]]
})]]