From e3688b5380241970b7e198ae97ab9b576124d92a Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Mon, 9 Oct 2017 10:58:11 +0200 Subject: [PATCH] Pathfinder: Auto-correct position on failure (smoother) Dynamic pathfinder distance, depending on speed and dtime Replace various deprecated function names --- cart_entity.lua | 48 +++++++++++++++++++++++++++--------------------- functions.lua | 22 +++++++++++++--------- init.lua | 12 +++++++++--- 3 files changed, 49 insertions(+), 33 deletions(-) diff --git a/cart_entity.lua b/cart_entity.lua index 858b92d..08fa118 100644 --- a/cart_entity.lua +++ b/cart_entity.lua @@ -82,8 +82,8 @@ function cart_entity:get_staticdata() end function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction) - local pos = self.object:getpos() - local vel = self.object:getvelocity() + local pos = self.object:get_pos() + local vel = self.object:get_velocity() if not self.railtype or vector.equals(vel, {x=0, y=0, z=0}) then local node = minetest.get_node(pos).name self.railtype = minetest.get_item_group(node, "connect_to_raillike") @@ -103,7 +103,7 @@ function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, -- Pick up cart: Drop all attachments if self.driver then if self.old_pos then - self.object:setpos(self.old_pos) + self.object:set_pos(self.old_pos) end local player = minetest.get_player_by_name(self.driver) boost_cart:manage_attachment(player, nil) @@ -150,16 +150,16 @@ function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, end function cart_entity:on_step(dtime) - local vel = self.object:getvelocity() + local vel = self.object:get_velocity() if self.punched then vel = vector.add(vel, self.velocity) - self.object:setvelocity(vel) + self.object:set_velocity(vel) self.old_dir.y = 0 elseif vector.equals(vel, {x=0, y=0, z=0}) then return end - local pos = self.object:getpos() + local pos = self.object:get_pos() local update = {} if self.old_pos and not self.punched then @@ -181,21 +181,27 @@ function cart_entity:on_step(dtime) end end - if self.old_pos then - -- Detection for "skipping" nodes - local found_path = boost_cart:pathfinder( - pos, self.old_pos, self.old_dir, ctrl, self.old_switch, self.railtype + local cart_dir = boost_cart:velocity_to_dir(vel) + if self.old_pos and vector.equals(cart_dir, self.old_dir) then + -- Detection for "skipping" nodes (perhaps use average dtime?) + -- It's sophisticated enough to take the acceleration in account + local acc = self.object:get_acceleration() + local distance = dtime * (vector.length(vel) + + 0.5 * dtime * vector.length(acc)) + + local new_pos, new_dir = boost_cart:pathfinder( + pos, self.old_pos, self.old_dir, distance, ctrl, + self.old_switch, self.railtype ) - if not found_path then - -- No rail found: reset back to the expected position - pos = vector.new(self.old_pos) + if new_pos then + -- No rail found: set to the expected position + pos = new_pos update.pos = true + cart_dir = new_dir end end - local cart_dir = boost_cart:velocity_to_dir(vel) - -- dir: New moving direction of the cart -- switch_keys: Currently pressed L/R key, used to ignore the key on the next rail node local dir, switch_keys = boost_cart:get_rail_direction( @@ -211,7 +217,7 @@ function cart_entity:on_step(dtime) else -- Direction change detected if not vector.equals(dir, self.old_dir) then - vel = vector.multiply(dir, math.abs(vel.x + vel.z)) + vel = vector.multiply(dir, vector.length(vel)) update.vel = true if dir.y ~= self.old_dir.y then pos = vector.round(pos) @@ -300,8 +306,8 @@ function cart_entity:on_step(dtime) end end - self.object:setacceleration(new_acc) - self.old_pos = pos + self.object:set_acceleration(new_acc) + self.old_pos = vector.round(pos) if not vector.equals(dir, {x=0, y=0, z=0}) then self.old_dir = dir end @@ -336,7 +342,7 @@ function cart_entity:on_step(dtime) elseif self.old_dir.z < 0 then yaw = 1 end - self.object:setyaw(yaw * math.pi) + self.object:set_yaw(yaw * math.pi) local anim = {x=0, y=0} if dir.y == -1 then @@ -346,9 +352,9 @@ function cart_entity:on_step(dtime) end self.object:set_animation(anim, 1, 0) - self.object:setvelocity(vel) + self.object:set_velocity(vel) if update.pos then - self.object:setpos(pos) + self.object:set_pos(pos) end end diff --git a/functions.lua b/functions.lua index 86f8535..13b6087 100644 --- a/functions.lua +++ b/functions.lua @@ -160,33 +160,37 @@ function boost_cart:get_rail_direction(pos_, dir, ctrl, old_switch, railtype) return {x=0, y=0, z=0} end -function boost_cart:pathfinder(pos_, old_pos, old_dir, ctrl, pf_switch, railtype) - if vector.equals(old_pos, pos_) then - return true - end +function boost_cart:pathfinder(pos_, old_pos, old_dir, distance, ctrl, + pf_switch, railtype) local pos = vector.round(pos_) + if vector.equals(old_pos, pos) then + return + end + local pf_pos = vector.round(old_pos) local pf_dir = vector.new(old_dir) + distance = math.min(boost_cart.path_distance_max, + math.floor(distance + 1)) - for i = 1, 3 do + for i = 1, distance do pf_dir, pf_switch = boost_cart:get_rail_direction( pf_pos, pf_dir, ctrl, pf_switch, railtype) if vector.equals(pf_dir, {x=0, y=0, z=0}) then -- No way forwards - return false + return pf_pos, pf_dir end pf_pos = vector.add(pf_pos, pf_dir) if vector.equals(pf_pos, pos) then -- Success! Cart moved on correctly - return true + return end end - -- Cart not found - return false + -- Not found. Put cart to predicted position + return pf_pos, pf_dir end function boost_cart:boost_rail(pos, amount) diff --git a/init.lua b/init.lua index ff53f92..1b2afa2 100644 --- a/init.lua +++ b/init.lua @@ -8,11 +8,17 @@ if not minetest.settings then .. " (Version <= 0.4.15)") end +local function getNum(setting) + return tonumber(minetest.settings:get(setting)) +end + -- Maximal speed of the cart in m/s -boost_cart.speed_max = tonumber(minetest.settings:get("boost_cart.speed_max")) or 10 +boost_cart.speed_max = getNum("boost_cart.speed_max") or 10 -- Set to -1 to disable punching the cart from inside -boost_cart.punch_speed_max = - tonumber(minetest.settings:get("boost_cart.punch_speed_max")) or 7 +boost_cart.punch_speed_max = getNum("boost_cart.punch_speed_max") or 7 +-- Maximal distance for the path correction (for dtime peaks) +boost_cart.path_distance_max = 3 + -- Support for non-default games if not default.player_attached then