mirror of
https://github.com/ElCeejo/creatura.git
synced 2025-04-30 13:51:41 -04:00
Add clearance check for spawning, Improved obstacle avoidance
This commit is contained in:
parent
da15c361cf
commit
b41924d4cb
4 changed files with 53 additions and 36 deletions
3
api.lua
3
api.lua
|
@ -135,7 +135,8 @@ function creatura.get_node_def(node) -- Node can be name or pos
|
||||||
return def
|
return def
|
||||||
end
|
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)
|
pos2.y = math.floor(pos2.y - 0.49)
|
||||||
local node = minetest.get_node(pos2)
|
local node = minetest.get_node(pos2)
|
||||||
local node_under = minetest.get_node({
|
local node_under = minetest.get_node({
|
||||||
|
|
51
methods.lua
51
methods.lua
|
@ -38,7 +38,7 @@ local dir2yaw = minetest.dir_to_yaw
|
||||||
texture = tex or "creatura_particle_red.png",
|
texture = tex or "creatura_particle_red.png",
|
||||||
expirationtime = time or 3,
|
expirationtime = time or 3,
|
||||||
glow = 6,
|
glow = 6,
|
||||||
size = 12
|
size = 1
|
||||||
})
|
})
|
||||||
end]]
|
end]]
|
||||||
|
|
||||||
|
@ -59,20 +59,17 @@ local function raycast(pos1, pos2, liquid)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_collision(self, yaw)
|
local function get_collision(self, yaw)
|
||||||
local width = self.width + 0.5
|
local width = self.width
|
||||||
local height = self.height + 0.5
|
local height = self.height
|
||||||
local total_height = height + self.stepheight
|
local total_height = height + self.stepheight
|
||||||
local pos = self.object:get_pos()
|
local pos = self.object:get_pos()
|
||||||
if not pos then return end
|
if not pos then return end
|
||||||
local ground = creatura.get_ground_level(pos, (self.stepheight or 2))
|
pos.y = pos.y + 0.1
|
||||||
if ground.y > pos.y then
|
local speed = abs(vec_len(self.object:get_velocity()))
|
||||||
pos = ground
|
local pos2 = vec_add(pos, vec_multi(yaw2dir(yaw), (width + 0.5) * ((speed > 1 and speed) or 1)))
|
||||||
end
|
-- Localize for performance
|
||||||
local pos2 = vec_add(pos, vec_multi(yaw2dir(yaw), width + 3))
|
local pos_x, pos_z = pos.x, pos.z
|
||||||
ground = creatura.get_ground_level(pos2, (self.stepheight or 2))
|
local pos2_x, pos2_z = pos2.x, pos2.z
|
||||||
if ground.y > pos2.y then
|
|
||||||
pos2 = ground
|
|
||||||
end
|
|
||||||
for x = -width, width, width / ceil(width) do
|
for x = -width, width, width / ceil(width) do
|
||||||
local step_flag = false
|
local step_flag = false
|
||||||
for y = 0, total_height, total_height / ceil(total_height) do
|
for y = 0, total_height, total_height / ceil(total_height) do
|
||||||
|
@ -81,14 +78,14 @@ local function get_collision(self, yaw)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
local vec1 = {
|
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,
|
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 = {
|
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,
|
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)
|
local ray = raycast(vec1, vec2, true)
|
||||||
if ray then
|
if ray then
|
||||||
|
@ -101,6 +98,14 @@ local function get_collision(self, yaw)
|
||||||
end
|
end
|
||||||
end
|
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
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -112,7 +117,9 @@ local function get_avoidance_dir(self)
|
||||||
local vel = self.object:get_velocity()
|
local vel = self.object:get_velocity()
|
||||||
local ahead = vec_add(pos, vec_normal(self.object:get_velocity()))
|
local ahead = vec_add(pos, vec_normal(self.object:get_velocity()))
|
||||||
local avoidance_force = vector.subtract(ahead, col_pos)
|
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))
|
return vec_dir(pos, vec_add(ahead, avoidance_force))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -201,6 +208,7 @@ local function trim_path(pos, path)
|
||||||
local trim = false
|
local trim = false
|
||||||
local closest
|
local closest
|
||||||
for i = #path, 1, -1 do
|
for i = #path, 1, -1 do
|
||||||
|
if not path[i] then break end
|
||||||
if (closest
|
if (closest
|
||||||
and vec_dist(pos, path[i]) > vec_dist(pos, path[closest]))
|
and vec_dist(pos, path[i]) > vec_dist(pos, path[closest]))
|
||||||
or trim then
|
or trim then
|
||||||
|
@ -327,6 +335,8 @@ end)
|
||||||
creatura.register_movement_method("creatura:obstacle_avoidance", function(self)
|
creatura.register_movement_method("creatura:obstacle_avoidance", function(self)
|
||||||
local box = clamp(self.width, 0.5, 1.5)
|
local box = clamp(self.width, 0.5, 1.5)
|
||||||
self:set_gravity(-9.8)
|
self:set_gravity(-9.8)
|
||||||
|
local steer_to
|
||||||
|
local steer_timer = 0.25
|
||||||
local function func(_self, goal, speed_factor)
|
local function func(_self, goal, speed_factor)
|
||||||
local pos = _self.object:get_pos()
|
local pos = _self.object:get_pos()
|
||||||
if not pos then return end
|
if not pos then return end
|
||||||
|
@ -337,7 +347,10 @@ creatura.register_movement_method("creatura:obstacle_avoidance", function(self)
|
||||||
_self:halt()
|
_self:halt()
|
||||||
return true
|
return true
|
||||||
end
|
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
|
-- Get movement direction
|
||||||
local goal_dir = vec_dir(pos, goal)
|
local goal_dir = vec_dir(pos, goal)
|
||||||
if steer_to then
|
if steer_to then
|
||||||
|
@ -355,9 +368,7 @@ creatura.register_movement_method("creatura:obstacle_avoidance", function(self)
|
||||||
else
|
else
|
||||||
_self:set_forward_velocity(speed * 0.33)
|
_self:set_forward_velocity(speed * 0.33)
|
||||||
end
|
end
|
||||||
if yaw_diff > 0.1 then
|
|
||||||
_self:turn_to(goal_yaw, turn_rate)
|
_self:turn_to(goal_yaw, turn_rate)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
return func
|
return func
|
||||||
end)
|
end)
|
16
mob_meta.lua
16
mob_meta.lua
|
@ -67,25 +67,23 @@ minetest.register_globalstep(function(dtime)
|
||||||
step_tick = step_tick - dtime
|
step_tick = step_tick - dtime
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- A metatable is used to avoid issues
|
|
||||||
-- With mobs performing functions outside
|
|
||||||
-- their own scope
|
|
||||||
|
|
||||||
local mob = {
|
local mob = {
|
||||||
-- Stats
|
|
||||||
max_health = 20,
|
max_health = 20,
|
||||||
armor_groups = {fleshy = 100},
|
armor_groups = {fleshy = 100},
|
||||||
damage = 2,
|
damage = 2,
|
||||||
speed = 4,
|
speed = 4,
|
||||||
tracking_range = 16,
|
tracking_range = 16,
|
||||||
despawn_after = nil,
|
despawn_after = nil,
|
||||||
-- Physics
|
|
||||||
max_fall = 3,
|
max_fall = 3,
|
||||||
stepheight = 1.1,
|
stepheight = 1.1,
|
||||||
hitbox = {
|
hitbox = {
|
||||||
width = 0.5,
|
width = 0.5,
|
||||||
height = 1
|
height = 1
|
||||||
},
|
},
|
||||||
|
follow = {},
|
||||||
|
fancy_collide = false,
|
||||||
|
bouyancy_multiplier = 1,
|
||||||
|
hydrodynamics_multiplier = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
local mob_meta = {__index = mob}
|
local mob_meta = {__index = mob}
|
||||||
|
@ -159,7 +157,7 @@ end
|
||||||
|
|
||||||
-- Turn to specified yaw
|
-- 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 cs = (1 - w) * cos(a) + w * cos(b)
|
||||||
local sn = (1 - w) * sin(a) + w * sin(b)
|
local sn = (1 - w) * sin(a) + w * sin(b)
|
||||||
return atan2(sn, cs)
|
return atan2(sn, cs)
|
||||||
|
@ -170,7 +168,7 @@ function mob:turn_to(tyaw, rate)
|
||||||
rate = rate or 5
|
rate = rate or 5
|
||||||
local yaw = self.object:get_yaw()
|
local yaw = self.object:get_yaw()
|
||||||
local step = math.min(self.dtime * rate, abs(diff(yaw, tyaw)) % (pi2))
|
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
|
end
|
||||||
|
|
||||||
-- Set Gravity (default of -9.8)
|
-- Set Gravity (default of -9.8)
|
||||||
|
@ -1093,7 +1091,6 @@ function mob:_execute_utilities()
|
||||||
}
|
}
|
||||||
self:clear_action()
|
self:clear_action()
|
||||||
end
|
end
|
||||||
--local us_time = minetest.get_us_time()
|
|
||||||
local action = self._action
|
local action = self._action
|
||||||
if action
|
if action
|
||||||
and type(action) ~= "table" then
|
and type(action) ~= "table" then
|
||||||
|
@ -1101,7 +1098,6 @@ function mob:_execute_utilities()
|
||||||
self:clear_action()
|
self:clear_action()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
--minetest.chat_send_all(minetest.get_us_time() - us_time)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
13
spawning.lua
13
spawning.lua
|
@ -57,7 +57,7 @@ function creatura.register_spawn_egg(name, col1, col2, inventory_image) -- depre
|
||||||
local mobdef = minetest.registered_entities[name]
|
local mobdef = minetest.registered_entities[name]
|
||||||
local spawn_offset = abs(mobdef.collisionbox[2])
|
local spawn_offset = abs(mobdef.collisionbox[2])
|
||||||
local pos = minetest.get_pointed_thing_position(pointed_thing, true)
|
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)
|
local object = minetest.add_entity(pos, name)
|
||||||
if object then
|
if object then
|
||||||
object:set_yaw(random(1, 6))
|
object:set_yaw(random(1, 6))
|
||||||
|
@ -245,6 +245,14 @@ local function execute_spawns(player)
|
||||||
return
|
return
|
||||||
end
|
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)
|
local group_size = random(spawn.min_group or 1, spawn.max_group or 1)
|
||||||
|
|
||||||
if spawn.spawn_cluster then
|
if spawn.spawn_cluster then
|
||||||
|
@ -290,7 +298,8 @@ end)
|
||||||
|
|
||||||
minetest.register_node("creatura:spawn_node", {
|
minetest.register_node("creatura:spawn_node", {
|
||||||
drawtype = "airlike",
|
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
|
local spawn_interval = tonumber(minetest.settings:get("creatura_spawn_interval")) or 10
|
||||||
|
|
Loading…
Add table
Reference in a new issue