boats: Improve physics by implementing drag and friction forces
authorBartosz <gang65@users.noreply.github.com>
Thu, 24 Oct 2019 02:47:28 +0000 (04:47 +0200)
committerParamat <paramat@users.noreply.github.com>
Thu, 24 Oct 2019 02:47:28 +0000 (03:47 +0100)
Implement drag force according to the equation:
drag_force = drag_coefficient * speed ^2
Also add a small constant force to implement friction force.

.luacheckrc
mods/boats/init.lua

index c3df64be4954f481d90a63fd0f6616ccd896fff2..459912f114d58dc2db456e4ac2f36b0491e51dd4 100644 (file)
@@ -12,7 +12,9 @@ read_globals = {
        "Settings",
        "unpack",
        -- Silence errors about custom table methods.
-       table = { fields = { "copy", "indexof" } }
+       table = { fields = { "copy", "indexof" } },
+       -- Silence warnings about accessing undefined fields of global 'math'
+       math = { fields = { "sign" } }
 }
 
 -- Overwrites minetest.handle_node_drops
index a785bdc653a98b33f673e745b9ea71f862d21490..f9ae8e06659941b7e5b8fddbe824074731d3820b 100644 (file)
@@ -13,15 +13,6 @@ local function is_water(pos)
 end
 
 
-local function get_sign(i)
-       if i == 0 then
-               return 0
-       else
-               return i / math.abs(i)
-       end
-end
-
-
 local function get_velocity(v, yaw, y)
        local x = -math.sin(yaw) * v
        local z =  math.cos(yaw) * v
@@ -146,7 +137,7 @@ end
 
 
 function boat.on_step(self, dtime)
-       self.v = get_v(self.object:get_velocity()) * get_sign(self.v)
+       self.v = get_v(self.object:get_velocity()) * math.sign(self.v)
        if self.driver then
                local driver_objref = minetest.get_player_by_name(self.driver)
                if driver_objref then
@@ -157,13 +148,13 @@ function boat.on_step(self, dtime)
                                        minetest.chat_send_player(self.driver, S("Boat cruise mode on"))
                                end
                        elseif ctrl.down then
-                               self.v = self.v - dtime * 1.8
+                               self.v = self.v - dtime * 2.0
                                if self.auto then
                                        self.auto = false
                                        minetest.chat_send_player(self.driver, S("Boat cruise mode off"))
                                end
                        elseif ctrl.up or self.auto then
-                               self.v = self.v + dtime * 1.8
+                               self.v = self.v + dtime * 2.0
                        end
                        if ctrl.left then
                                if self.v < -0.001 then
@@ -185,15 +176,14 @@ function boat.on_step(self, dtime)
                self.object:set_pos(self.object:get_pos())
                return
        end
-       local s = get_sign(self.v)
-       self.v = self.v - dtime * 0.6 * s
-       if s ~= get_sign(self.v) then
-               self.object:set_velocity({x = 0, y = 0, z = 0})
+       -- We need to preserve velocity sign to properly apply drag force
+       -- while moving backward
+       local drag = dtime * math.sign(self.v) * (0.01 + 0.0796 * self.v * self.v)
+       -- If drag is larger than velocity, then stop horizontal movement
+       if math.abs(self.v) <= math.abs(drag) then
                self.v = 0
-               return
-       end
-       if math.abs(self.v) > 5 then
-               self.v = 5 * get_sign(self.v)
+       else
+               self.v = self.v - drag
        end
 
        local p = self.object:get_pos()