mirror of
https://github.com/minetest/minetest_game.git
synced 2024-12-23 07:10:19 +01:00
Update carts from boost_cart
Better pathfinder algorithm, allows tuning the lag spike compensation. Smoother movement (when it's laggy). Set the player animation to stand on attach. Remove driver when they leave. Only update velocity when it's necessary.
This commit is contained in:
parent
59dbeebc2f
commit
ecea5364f1
@ -27,6 +27,10 @@ function cart_entity:on_rightclick(clicker)
|
|||||||
elseif not self.driver then
|
elseif not self.driver then
|
||||||
self.driver = player_name
|
self.driver = player_name
|
||||||
carts:manage_attachment(clicker, self.object)
|
carts:manage_attachment(clicker, self.object)
|
||||||
|
|
||||||
|
-- player_api does not update the animation
|
||||||
|
-- when the player is attached, reset to default animation
|
||||||
|
player_api.set_animation(clicker, "stand")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -36,7 +40,7 @@ function cart_entity:on_activate(staticdata, dtime_s)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
local data = minetest.deserialize(staticdata)
|
local data = minetest.deserialize(staticdata)
|
||||||
if not data or type(data) ~= "table" then
|
if type(data) ~= "table" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
self.railtype = data.railtype
|
self.railtype = data.railtype
|
||||||
@ -52,6 +56,13 @@ function cart_entity:get_staticdata()
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- 0.5.x and later: When the driver leaves
|
||||||
|
function cart_entity:on_detach_child(child)
|
||||||
|
if child and child:get_player_name() == self.driver then
|
||||||
|
self.driver = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
|
function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
|
||||||
local pos = self.object:get_pos()
|
local pos = self.object:get_pos()
|
||||||
local vel = self.object:get_velocity()
|
local vel = self.object:get_velocity()
|
||||||
@ -82,7 +93,7 @@ function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities,
|
|||||||
local player = minetest.get_player_by_name(self.driver)
|
local player = minetest.get_player_by_name(self.driver)
|
||||||
carts:manage_attachment(player, nil)
|
carts:manage_attachment(player, nil)
|
||||||
end
|
end
|
||||||
for _,obj_ in ipairs(self.attached_items) do
|
for _, obj_ in ipairs(self.attached_items) do
|
||||||
if obj_ then
|
if obj_ then
|
||||||
obj_:set_detach()
|
obj_:set_detach()
|
||||||
end
|
end
|
||||||
@ -165,6 +176,7 @@ local function get_railparams(pos)
|
|||||||
return carts.railparams[node.name] or {}
|
return carts.railparams[node.name] or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local v3_len = vector.length
|
||||||
local function rail_on_step(self, dtime)
|
local function rail_on_step(self, dtime)
|
||||||
local vel = self.object:get_velocity()
|
local vel = self.object:get_velocity()
|
||||||
if self.punched then
|
if self.punched then
|
||||||
@ -201,17 +213,23 @@ local function rail_on_step(self, dtime)
|
|||||||
|
|
||||||
local stop_wiggle = false
|
local stop_wiggle = false
|
||||||
if self.old_pos and same_dir then
|
if self.old_pos and same_dir then
|
||||||
-- Detection for "skipping" nodes
|
-- Detection for "skipping" nodes (perhaps use average dtime?)
|
||||||
local found_path = carts:pathfinder(
|
-- It's sophisticated enough to take the acceleration in account
|
||||||
pos, self.old_pos, self.old_dir, ctrl, self.old_switch, self.railtype
|
local acc = self.object:get_acceleration()
|
||||||
|
local distance = dtime * (v3_len(vel) + 0.5 * dtime * v3_len(acc))
|
||||||
|
|
||||||
|
local new_pos, new_dir = carts:pathfinder(
|
||||||
|
pos, self.old_pos, self.old_dir, distance, ctrl,
|
||||||
|
self.old_switch, self.railtype
|
||||||
)
|
)
|
||||||
|
|
||||||
if not found_path then
|
if new_pos then
|
||||||
-- No rail found: reset back to the expected position
|
-- No rail found: set to the expected position
|
||||||
pos = vector.new(self.old_pos)
|
pos = new_pos
|
||||||
update.pos = true
|
update.pos = true
|
||||||
|
cart_dir = new_dir
|
||||||
end
|
end
|
||||||
elseif self.old_pos and cart_dir.y ~= -1 and not self.punched then
|
elseif self.old_pos and self.old_dir.y ~= 1 and not self.punched then
|
||||||
-- Stop wiggle
|
-- Stop wiggle
|
||||||
stop_wiggle = true
|
stop_wiggle = true
|
||||||
end
|
end
|
||||||
@ -223,12 +241,14 @@ local function rail_on_step(self, dtime)
|
|||||||
local dir, switch_keys = carts:get_rail_direction(
|
local dir, switch_keys = carts:get_rail_direction(
|
||||||
pos, cart_dir, ctrl, self.old_switch, self.railtype
|
pos, cart_dir, ctrl, self.old_switch, self.railtype
|
||||||
)
|
)
|
||||||
|
local dir_changed = not vector.equals(dir, self.old_dir)
|
||||||
|
|
||||||
local new_acc = {x=0, y=0, z=0}
|
local new_acc = {x=0, y=0, z=0}
|
||||||
if stop_wiggle or vector.equals(dir, {x=0, y=0, z=0}) then
|
if stop_wiggle or vector.equals(dir, {x=0, y=0, z=0}) then
|
||||||
vel = {x = 0, y = 0, z = 0}
|
vel = {x = 0, y = 0, z = 0}
|
||||||
local pos_r = vector.round(pos)
|
local pos_r = vector.round(pos)
|
||||||
if not carts:is_rail(pos_r, self.railtype) then
|
if not carts:is_rail(pos_r, self.railtype)
|
||||||
|
and self.old_pos then
|
||||||
pos = self.old_pos
|
pos = self.old_pos
|
||||||
elseif not stop_wiggle then
|
elseif not stop_wiggle then
|
||||||
pos = pos_r
|
pos = pos_r
|
||||||
@ -239,7 +259,7 @@ local function rail_on_step(self, dtime)
|
|||||||
update.vel = true
|
update.vel = true
|
||||||
else
|
else
|
||||||
-- Direction change detected
|
-- Direction change detected
|
||||||
if not vector.equals(dir, self.old_dir) then
|
if dir_changed then
|
||||||
vel = vector.multiply(dir, math.abs(vel.x + vel.z))
|
vel = vector.multiply(dir, math.abs(vel.x + vel.z))
|
||||||
update.vel = true
|
update.vel = true
|
||||||
if dir.y ~= self.old_dir.y then
|
if dir.y ~= self.old_dir.y then
|
||||||
@ -291,7 +311,7 @@ local function rail_on_step(self, dtime)
|
|||||||
end
|
end
|
||||||
|
|
||||||
self.object:set_acceleration(new_acc)
|
self.object:set_acceleration(new_acc)
|
||||||
self.old_pos = vector.new(pos)
|
self.old_pos = vector.round(pos)
|
||||||
if not vector.equals(dir, {x=0, y=0, z=0}) and not stop_wiggle then
|
if not vector.equals(dir, {x=0, y=0, z=0}) and not stop_wiggle then
|
||||||
self.old_dir = vector.new(dir)
|
self.old_dir = vector.new(dir)
|
||||||
end
|
end
|
||||||
@ -338,9 +358,15 @@ local function rail_on_step(self, dtime)
|
|||||||
end
|
end
|
||||||
self.object:set_animation(anim, 1, 0)
|
self.object:set_animation(anim, 1, 0)
|
||||||
|
|
||||||
|
if update.vel then
|
||||||
self.object:set_velocity(vel)
|
self.object:set_velocity(vel)
|
||||||
|
end
|
||||||
if update.pos then
|
if update.pos then
|
||||||
|
if dir_changed then
|
||||||
self.object:set_pos(pos)
|
self.object:set_pos(pos)
|
||||||
|
else
|
||||||
|
self.object:move_to(pos)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- call event handler
|
-- call event handler
|
||||||
|
@ -99,6 +99,16 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
|
|||||||
right.z = -dir.x
|
right.z = -dir.x
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local straight_priority = ctrl and dir.y ~= 0
|
||||||
|
|
||||||
|
-- Normal, to disallow rail switching up- & downhill
|
||||||
|
if straight_priority then
|
||||||
|
cur = self:check_front_up_down(pos, dir, true, railtype)
|
||||||
|
if cur then
|
||||||
|
return cur
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if ctrl then
|
if ctrl then
|
||||||
if old_switch == 1 then
|
if old_switch == 1 then
|
||||||
left_check = false
|
left_check = false
|
||||||
@ -106,14 +116,14 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
|
|||||||
right_check = false
|
right_check = false
|
||||||
end
|
end
|
||||||
if ctrl.left and left_check then
|
if ctrl.left and left_check then
|
||||||
cur = carts:check_front_up_down(pos, left, false, railtype)
|
cur = self:check_front_up_down(pos, left, false, railtype)
|
||||||
if cur then
|
if cur then
|
||||||
return cur, 1
|
return cur, 1
|
||||||
end
|
end
|
||||||
left_check = false
|
left_check = false
|
||||||
end
|
end
|
||||||
if ctrl.right and right_check then
|
if ctrl.right and right_check then
|
||||||
cur = carts:check_front_up_down(pos, right, false, railtype)
|
cur = self:check_front_up_down(pos, right, false, railtype)
|
||||||
if cur then
|
if cur then
|
||||||
return cur, 2
|
return cur, 2
|
||||||
end
|
end
|
||||||
@ -122,10 +132,12 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Normal
|
-- Normal
|
||||||
cur = carts:check_front_up_down(pos, dir, true, railtype)
|
if not straight_priority then
|
||||||
|
cur = self:check_front_up_down(pos, dir, true, railtype)
|
||||||
if cur then
|
if cur then
|
||||||
return cur
|
return cur
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Left, if not already checked
|
-- Left, if not already checked
|
||||||
if left_check then
|
if left_check then
|
||||||
@ -158,33 +170,37 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
|
|||||||
return {x=0, y=0, z=0}
|
return {x=0, y=0, z=0}
|
||||||
end
|
end
|
||||||
|
|
||||||
function carts:pathfinder(pos_, old_pos, old_dir, ctrl, pf_switch, railtype)
|
function carts:pathfinder(pos_, old_pos, old_dir, distance, ctrl,
|
||||||
if vector.equals(old_pos, pos_) then
|
pf_switch, railtype)
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
local pos = vector.round(pos_)
|
local pos = vector.round(pos_)
|
||||||
|
if vector.equals(old_pos, pos) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local pf_pos = vector.round(old_pos)
|
local pf_pos = vector.round(old_pos)
|
||||||
local pf_dir = vector.new(old_dir)
|
local pf_dir = vector.new(old_dir)
|
||||||
|
distance = math.min(carts.path_distance_max,
|
||||||
|
math.floor(distance + 1))
|
||||||
|
|
||||||
for i = 1, 3 do
|
for i = 1, distance do
|
||||||
pf_dir, pf_switch = carts:get_rail_direction(
|
pf_dir, pf_switch = self:get_rail_direction(
|
||||||
pf_pos, pf_dir, ctrl, pf_switch, railtype)
|
pf_pos, pf_dir, ctrl, pf_switch or 0, railtype)
|
||||||
|
|
||||||
if vector.equals(pf_dir, {x=0, y=0, z=0}) then
|
if vector.equals(pf_dir, {x=0, y=0, z=0}) then
|
||||||
-- No way forwards
|
-- No way forwards
|
||||||
return false
|
return pf_pos, pf_dir
|
||||||
end
|
end
|
||||||
|
|
||||||
pf_pos = vector.add(pf_pos, pf_dir)
|
pf_pos = vector.add(pf_pos, pf_dir)
|
||||||
|
|
||||||
if vector.equals(pf_pos, pos) then
|
if vector.equals(pf_pos, pos) then
|
||||||
-- Success! Cart moved on correctly
|
-- Success! Cart moved on correctly
|
||||||
return true
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- Cart not found
|
-- Not found. Put cart to predicted position
|
||||||
return false
|
return pf_pos, pf_dir
|
||||||
end
|
end
|
||||||
|
|
||||||
function carts:register_rail(name, def_overwrite, railparams)
|
function carts:register_rail(name, def_overwrite, railparams)
|
||||||
|
@ -7,6 +7,8 @@ carts.railparams = {}
|
|||||||
carts.speed_max = 7
|
carts.speed_max = 7
|
||||||
-- Set to -1 to disable punching the cart from inside (min = -1)
|
-- Set to -1 to disable punching the cart from inside (min = -1)
|
||||||
carts.punch_speed_max = 5
|
carts.punch_speed_max = 5
|
||||||
|
-- Maximal distance for the path correction (for dtime peaks)
|
||||||
|
carts.path_distance_max = 3
|
||||||
|
|
||||||
|
|
||||||
dofile(carts.modpath.."/functions.lua")
|
dofile(carts.modpath.."/functions.lua")
|
||||||
|
Loading…
Reference in New Issue
Block a user