forked from VoxeLibre/VoxeLibre
Modify do_movement_step to move to always move to the edge of the current rail segment before updating the direction to prevent oscillations at corners, fix end of track stop location with new movement behavior, disable experimental controls, swap code to detach the driver on float with a call to detach_driver()
This commit is contained in:
parent
fb9cdb145e
commit
ce83be4092
|
@ -7,6 +7,7 @@ mcl_minecarts = {}
|
||||||
mcl_minecarts.modpath = minetest.get_modpath(modname)
|
mcl_minecarts.modpath = minetest.get_modpath(modname)
|
||||||
mcl_minecarts.speed_max = 10
|
mcl_minecarts.speed_max = 10
|
||||||
mcl_minecarts.check_float_time = 15
|
mcl_minecarts.check_float_time = 15
|
||||||
|
local max_step_distance = 0.5
|
||||||
|
|
||||||
dofile(mcl_minecarts.modpath.."/functions.lua")
|
dofile(mcl_minecarts.modpath.."/functions.lua")
|
||||||
dofile(mcl_minecarts.modpath.."/rails.lua")
|
dofile(mcl_minecarts.modpath.."/rails.lua")
|
||||||
|
@ -192,6 +193,22 @@ local function make_staticdata( railtype, connected_at, dir )
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function to_dirstring(dir)
|
||||||
|
if dir.x == 0 then
|
||||||
|
if dir.z == 1 then
|
||||||
|
return "north"
|
||||||
|
else
|
||||||
|
return "south"
|
||||||
|
end
|
||||||
|
elseif dir.z == 0 then
|
||||||
|
if dir.x == 1 then
|
||||||
|
return " east"
|
||||||
|
else
|
||||||
|
return " west"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function register_entity(entity_id, mesh, textures, drop, on_rightclick, on_activate_by_rail)
|
local function register_entity(entity_id, mesh, textures, drop, on_rightclick, on_activate_by_rail)
|
||||||
local cart = {
|
local cart = {
|
||||||
initial_properties = {
|
initial_properties = {
|
||||||
|
@ -345,16 +362,51 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
||||||
|
|
||||||
local passenger_attach_position = vector.new(0, -1.75, 0)
|
local passenger_attach_position = vector.new(0, -1.75, 0)
|
||||||
|
|
||||||
local function do_movement_step(self, distance)
|
local function distance_to_next_block( dir, pos )
|
||||||
|
if dir.x == 1 then
|
||||||
|
return 1 - ( pos.x - math.floor(pos.x) )
|
||||||
|
elseif dir.x == -1 then
|
||||||
|
return pos.x - math.floor(pos.x)
|
||||||
|
elseif dir.z == 1 then
|
||||||
|
return 1 - ( pos.z - math.floor(pos.z) )
|
||||||
|
elseif dir.z == -1 then
|
||||||
|
return pos.z - math.floor(pos.z)
|
||||||
|
elseif dir.y == 1 then
|
||||||
|
return 1 - ( pos.y - math.floor(pos.z) )
|
||||||
|
else
|
||||||
|
return pos.y - math.floor(pos.y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function do_movement_step(self, remaining_distance)
|
||||||
local staticdata = self._staticdata
|
local staticdata = self._staticdata
|
||||||
local pos = self.object:get_pos()
|
local pos = self.object:get_pos()
|
||||||
local dir = staticdata.dir or vector.new(1,0,0)
|
local dir = staticdata.dir or vector.new(1,0,0)
|
||||||
dir = vector.new(dir)
|
dir = vector.new(dir)
|
||||||
|
|
||||||
-- Calculate raw location
|
-- Calculate the distance to the next block
|
||||||
local next_dir,last_switch = mcl_minecarts:get_rail_direction(pos, dir, nil, nil, staticdata.railtype)
|
-- This is just short of a full block to keep from jumping
|
||||||
next_dir = vector.new(next_dir) -- Needed to isolate the carts from one another
|
local distance_to_next = distance_to_next_block( dir, pos ) - 0.01
|
||||||
local next_pos = vector.new(pos + next_dir * distance)
|
local next_pos
|
||||||
|
local next_dir,last_switch
|
||||||
|
next_dir = dir
|
||||||
|
if distance_to_next < 0.01 then
|
||||||
|
distance_to_next = 0.5
|
||||||
|
|
||||||
|
-- Calculate next direction
|
||||||
|
next_dir,last_switch = mcl_minecarts:get_rail_direction(pos, dir, nil, nil, staticdata.railtype)
|
||||||
|
next_dir = vector.copy(next_dir) -- Needed to isolate the carts from one another
|
||||||
|
elseif distance_to_next > max_step_distance then
|
||||||
|
distance_to_next = max_step_distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local distance = remaining_distance
|
||||||
|
if distance > distance_to_next then
|
||||||
|
distance = distance_to_next
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculate next position
|
||||||
|
next_pos = vector.new(pos + next_dir * distance)
|
||||||
|
|
||||||
-- Fix up position
|
-- Fix up position
|
||||||
if next_dir.x == 0 then next_pos.x = math.floor(next_pos.x+0.5) end
|
if next_dir.x == 0 then next_pos.x = math.floor(next_pos.x+0.5) end
|
||||||
|
@ -363,10 +415,14 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
||||||
|
|
||||||
-- Direction flipped, stop
|
-- Direction flipped, stop
|
||||||
if next_dir == dir * -1 then
|
if next_dir == dir * -1 then
|
||||||
print("Stopping cart")
|
|
||||||
-- TODO: detach the cart if there isn't a stop after the rail
|
-- TODO: detach the cart if there isn't a stop after the rail
|
||||||
staticdata.velocity = 0
|
staticdata.velocity = 0
|
||||||
next_pos = vector.round(next_pos + dir)
|
next_pos = vector.round(next_pos)
|
||||||
|
|
||||||
|
if DEBUG and self._driver then
|
||||||
|
local node_name = minetest.get_node(next_pos).name
|
||||||
|
print("Stopping cart on "..node_name.." at "..tostring(next_pos))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Update cart orientation
|
-- Update cart orientation
|
||||||
|
@ -393,8 +449,8 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
||||||
end
|
end
|
||||||
print( prefix
|
print( prefix
|
||||||
.. "pos="..tostring(pos)
|
.. "pos="..tostring(pos)
|
||||||
..",dir="..tostring(dir)
|
..",dir="..to_dirstring(dir)
|
||||||
..",next_dir="..tostring(next_dir)
|
..",next_dir="..to_dirstring(next_dir)
|
||||||
..",next_pos="..tostring(next_pos)
|
..",next_pos="..tostring(next_pos)
|
||||||
..",velocity="..tostring(staticdata.velocity)
|
..",velocity="..tostring(staticdata.velocity)
|
||||||
..",distance="..tostring(distance)
|
..",distance="..tostring(distance)
|
||||||
|
@ -416,6 +472,9 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
||||||
new_node_def._mcl_minecarts_on_enter( next_pos_rounded, self )
|
new_node_def._mcl_minecarts_on_enter( next_pos_rounded, self )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Report distance traveled
|
||||||
|
return distance
|
||||||
end
|
end
|
||||||
|
|
||||||
local function process_acceleration(self, timestep)
|
local function process_acceleration(self, timestep)
|
||||||
|
@ -466,30 +525,15 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
||||||
-- causing large timesteps
|
-- causing large timesteps
|
||||||
local total_distance = dtime * ( staticdata.velocity or 0 )
|
local total_distance = dtime * ( staticdata.velocity or 0 )
|
||||||
local remaining_distance = total_distance
|
local remaining_distance = total_distance
|
||||||
local max_step_distance = 0.5
|
|
||||||
local steps = math.ceil(total_distance / max_step_distance )
|
|
||||||
|
|
||||||
process_acceleration(self,dtime * max_step_distance / total_distance)
|
process_acceleration(self,dtime * max_step_distance / total_distance)
|
||||||
|
|
||||||
for i = 1,steps do
|
while remaining_distance > 0.1 do
|
||||||
local step_distance = max_step_distance
|
local step_distance = do_movement_step(self, remaining_distance)
|
||||||
if remaining_distance < max_step_distance then
|
if step_distance > 0.1 then
|
||||||
step_distance = remaining_distance
|
|
||||||
remaining_distance = 0
|
|
||||||
else
|
|
||||||
remaining_distance = remaining_distance - max_step_distance
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Don't try to perform very small steps
|
|
||||||
if step_distance < 0.001 then break end
|
|
||||||
|
|
||||||
-- Handle acceleration on everything except the first step, as that was
|
|
||||||
-- done outside the loop
|
|
||||||
if i ~= 1 then
|
|
||||||
process_acceleration(self, dtime * step_distance / total_distance)
|
process_acceleration(self, dtime * step_distance / total_distance)
|
||||||
end
|
end
|
||||||
|
remaining_distance = remaining_distance - step_distance
|
||||||
do_movement_step(self, step_distance)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Clear punched flag now that movement for this step has been completed
|
-- Clear punched flag now that movement for this step has been completed
|
||||||
|
@ -521,8 +565,8 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Experimental controls
|
-- Experimental controls
|
||||||
self._go_forward = ctrl.up
|
--self._go_forward = ctrl.up
|
||||||
self._brake = ctrl.down
|
--self._brake = ctrl.down
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Give achievement when player reached a distance of 1000 nodes from the start position
|
-- Give achievement when player reached a distance of 1000 nodes from the start position
|
||||||
|
@ -583,14 +627,7 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
||||||
local g = minetest.get_item_group(node.name, "connect_to_raillike")
|
local g = minetest.get_item_group(node.name, "connect_to_raillike")
|
||||||
if g ~= self._staticdata.railtype and self._staticdata.railtype then
|
if g ~= self._staticdata.railtype and self._staticdata.railtype then
|
||||||
-- Detach driver
|
-- Detach driver
|
||||||
if player then
|
detach_driver(self)
|
||||||
if self._old_pos then
|
|
||||||
self.object:set_pos(self._old_pos)
|
|
||||||
end
|
|
||||||
mcl_player.player_attached[self._driver] = nil
|
|
||||||
player:set_detach()
|
|
||||||
player:set_eye_offset(vector.new(0,0,0),vector.new(0,0,0))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Explode if already ignited
|
-- Explode if already ignited
|
||||||
if self._boomtimer then
|
if self._boomtimer then
|
||||||
|
|
Loading…
Reference in New Issue