From d972017f5762bcbd95bc2f235b5dbb8234777058 Mon Sep 17 00:00:00 2001 From: fnicon Date: Sat, 21 Mar 2026 10:10:59 +0900 Subject: [PATCH] add inertia and fix physics --- game/love_src/src/system/racing_phy.lua | 51 ++++---- .../world/top_down_race/component/race.lua | 9 +- .../love_src/src/world/top_down_race/init.lua | 15 +-- .../world/top_down_race/system/velocity.lua | 115 +++++++++++++----- .../world/top_down_race/template/racer.lua | 10 +- 5 files changed, 129 insertions(+), 71 deletions(-) diff --git a/game/love_src/src/system/racing_phy.lua b/game/love_src/src/system/racing_phy.lua index 56b75fc..25f482d 100644 --- a/game/love_src/src/system/racing_phy.lua +++ b/game/love_src/src/system/racing_phy.lua @@ -13,51 +13,46 @@ local function accelerate(dt, gas_input, speed, max_speed, accel, min_speed) return new_speed end -local function centrifugal_force(dt, speed, max_speed) +local function centrifugal_force(dt, mass, speed, max_speed) local speed_percent = (speed/max_speed) local dx = dt * 2 * speed_percent local dy = dt * 2 * speed_percent - -- assume mass is 1 - return 1 * dy * speed * speed + return mass * dy * speed * speed end -local function drift(dt, pos_x, pos_y, speed, max_speed, angle, centrifugal) +local function drift(dt, pos_x, pos_y, speed, max_speed, angle, scale_x, scale_y) local speed_percent = (speed/max_speed) - local dx = dt * 2 * speed_percent -- at top speed, should be able to cross from left to right (-1 to 1) in 1 second - local dy = dt * 2 * speed_percent + local dx = dt * 2.0 * speed_percent -- at top speed, should be able to cross from left to right (-1 to 1) in 1 second + local dy = dt * 2.0 * speed_percent cos = math.cos(angle) sin = math.sin(angle) - return pos_x + (dx * speed_percent * cos * centrifugal), - pos_y + (dy * speed_percent * sin * centrifugal) + return pos_x + (dx * speed_percent * cos) * (scale_x or 1), + pos_y + (dy * speed_percent * sin) * (scale_y or 1) end -local function gas(accel, drag, friction) - friction = friction or 0 - return accel - drag - friction -end +-- local function gas(accel, drag, friction) +-- friction = friction or 0 +-- return accel - drag - friction +-- end -local function brake(decel, drag, grip, friction) - friction = friction or 0 - return - decel - drag - grip - friction -end +-- local function brake(decel, drag, grip, friction) +-- friction = friction or 0 +-- return - decel - drag - grip - friction +-- end -local function roam(decel, drag, friction) - friction = friction or 0 - return - decel - drag - friction -end +-- local function roam(decel, drag, friction) +-- friction = friction or 0 +-- return - decel - drag - friction +-- end -local function steer(_steer, grip, drag, velocity, friction) - friction = friction or 0 - return _steer + grip + drag - velocity + friction -end +-- local function steer(_steer, grip, drag, velocity, friction) +-- friction = friction or 0 +-- return _steer + grip + drag - velocity + friction +-- end return { accelerate = accelerate, drift = drift, - gas = gas, - brake = brake, - steer = steer, - roam = roam, centrifugal_force = centrifugal_force } diff --git a/game/love_src/src/world/top_down_race/component/race.lua b/game/love_src/src/world/top_down_race/component/race.lua index afbd402..7166826 100644 --- a/game/love_src/src/world/top_down_race/component/race.lua +++ b/game/love_src/src/world/top_down_race/component/race.lua @@ -9,7 +9,8 @@ components.dict = { brake = "race.brake", decel = "race.decel", drag = "race.drag", - direction = "race.direction" + mass = "race.mass", + inertia = "race.inertia" } function components.velocity (c, x) @@ -44,8 +45,12 @@ function components.drag (c, x) c.data = x end -function components.direction (c, x) +function components.mass (c, x) c.data = x end +function components.inertia (c, x, y) + c.data = {x, y} +end + return components diff --git a/game/love_src/src/world/top_down_race/init.lua b/game/love_src/src/world/top_down_race/init.lua index 34e4441..b770e51 100644 --- a/game/love_src/src/world/top_down_race/init.lua +++ b/game/love_src/src/world/top_down_race/init.lua @@ -32,13 +32,14 @@ function wrapper:load(_args) assemblage = racer.assemble, data = { accel = 20.0, - brake = 10.0, - grip = 2.0, - max_speed = 100.0, - steer = 2.0, - velocity = 10.0, - decel = 10.0, - drag = 2.0 + brake = 1.0, + grip = 1.0, + max_speed = 50.0, + steer = 1.0, + velocity = 0.0, + inertia = {0.0, 0.0}, + drag = 1.0, + mass = 1.0 } } }) diff --git a/game/love_src/src/world/top_down_race/system/velocity.lua b/game/love_src/src/world/top_down_race/system/velocity.lua index ed26db2..f40bb10 100644 --- a/game/love_src/src/world/top_down_race/system/velocity.lua +++ b/game/love_src/src/world/top_down_race/system/velocity.lua @@ -18,8 +18,9 @@ system.pool = { race.dict.max_speed, race.dict.steer, race.dict.velocity, - race.dict.decel, - race.dict.drag + race.dict.inertia, + race.dict.drag, + race.dict.mass } } @@ -30,8 +31,9 @@ system.components = { [race.dict.max_speed] = race.max_speed, [race.dict.steer] = race.steer, [race.dict.velocity] = race.velocity, - [race.dict.decel] = race.decel, - [race.dict.drag] = race.drag + [race.dict.inertia] = race.inertia, + [race.dict.drag] = race.drag, + [race.dict.mass] = race.mass } function system.new() @@ -55,7 +57,8 @@ local function get(e) e[race.dict.steer].data, e[race.dict.velocity].data, e[race.dict.drag].data, - e[race.dict.decel].data + e[race.dict.inertia].data, + e[race.dict.mass].data end local function draw(text, x, y, sx, sy, angle, image, origin) @@ -101,7 +104,7 @@ local frictions = { 0, 0, lw/2, lh }, color = {0, 255/255, 0}, - friction = 5 + friction = 2 }, { name = "pavement", @@ -110,32 +113,70 @@ local frictions = { lw/2, 0, lw/2, lh }, color = {0, 255/255, 255/255}, - friction = 0 + friction = 1 } } -local function get_velocity(dt, up, down, accel, drag, decel, grip, velocity, max_speed, friction) - local new_accel - local new_min_speed = 0 +local function accel_force(up, down, accel, brake, inertia) + local force if (up) then - new_accel = racing_phy.gas(accel, drag, friction) + force = accel - inertia elseif(down) then - new_accel = racing_phy.brake(decel, drag, grip, friction) - new_min_speed = -max_speed + force = - brake + inertia else - new_accel = racing_phy.roam(decel, drag, friction) + force = inertia end - return racing_phy.accelerate(dt, 1, velocity, max_speed, new_accel, new_min_speed) + return force end -local function get_angle(dt, left, right, steer, grip, drag, velocity, max_speed, friction) - local new_angle = 0 +local function steer_force(left, right, steer, inertia) if (left) then - new_angle = - 1 * racing_phy.steer(steer, grip, drag, velocity / max_speed, friction) * dt - elseif (right) then - new_angle = 1 * racing_phy.steer(steer, grip, drag, velocity / max_speed, friction) * dt + force = -steer + inertia + elseif(right) then + force = steer - inertia + else + force = inertia end - return new_angle + return force +end + +local function grip_force(grip, friction) + return friction * grip +end + +local function add_friction(force, grip, friction, tire_c, floor_c) + local f_grip = grip_force(grip, friction) + if (force > 0) then + -- tire - floor + force = force + tire_c * f_grip - floor_c * f_grip + elseif (force < 0) then + force = force - tire_c * f_grip + floor_c * f_grip + else + force = force + end + return force +end + +local function add_drag(force, drag) + if (force > 0) then + force = force - drag + elseif (force < 0) then + force = force + drag + else + force = force + end + return force +end + +local function add_centrifugal(force, centrifugal) + if (force > 0) then + force = force - centrifugal + elseif (force < 0) then + force = force + centrifugal + else + force = force + end + return force end -- x1 y1 -- (x1 + w1) y1 @@ -162,7 +203,7 @@ end function system:update(dt) for _, e in ipairs(self.pool) do - local accel, brake, grip, max_speed, steer, velocity, drag, decel = get(e) + local accel, brake, grip, max_speed, steer, velocity, drag, inertia, mass = get(e) local up = love.keyboard.isDown("up") local down = love.keyboard.isDown("down") @@ -173,17 +214,31 @@ function system:update(dt) local friction = get_friction(pos_x, pos_y, frictions) - e[race.dict.velocity].data = get_velocity(dt, up, down, accel, drag, decel, grip, velocity, max_speed, friction) + local f_forward = accel_force(up, down, accel, brake, inertia[1]) + local f_lateral = steer_force(left, right, steer, inertia[2]) - local angle = e["race.angle"].data - local new_angle = get_angle(dt, left, right, steer, grip, drag,velocity, max_speed, friction) - e["race.angle"].data = angle + new_angle + f_forward = add_friction(f_forward, grip, friction, 1.0, 0.5) + f_lateral = add_friction(f_lateral, grip, friction, 1.0, 0.5) - velocity = e[race.dict.velocity].data - angle = e["race.angle"].data + f_forward = add_drag(f_forward, drag) + f_lateral = add_drag(f_lateral, drag) - local centrifugal = racing_phy.centrifugal_force(dt, velocity, max_speed) - local goal_x, goal_y = racing_phy.drift(dt, pos_x, pos_y, velocity, max_speed, angle, centrifugal) + if (mass == 0) then + mass = 1 + end + + local new_velocity = racing_phy.accelerate(dt, 1, velocity, max_speed, f_forward*dt/mass, 0) + local centrifugal = racing_phy.centrifugal_force(dt, mass, new_velocity, max_speed) + f_lateral = add_centrifugal(f_lateral, centrifugal) + + e[race.dict.inertia].data = {f_forward * dt, f_lateral * dt} + + local new_angle = e["race.angle"].data + f_lateral * dt/mass + e["race.angle"].data = new_angle + e[race.dict.velocity].data = new_velocity + + local goal_x, goal_y = racing_phy.drift(dt, pos_x, pos_y, new_velocity, max_speed, new_angle, 100000, 100000) + -- print("force_forward", f_forward, "f_lateral", f_lateral, "velocity", new_velocity, "angle", new_angle, "goal_x", goal_x, "goal_y", goal_y) e["race.pos"].data[1] = goal_x e["race.pos"].data[2] = goal_y diff --git a/game/love_src/src/world/top_down_race/template/racer.lua b/game/love_src/src/world/top_down_race/template/racer.lua index c7fc621..1abe821 100644 --- a/game/love_src/src/world/top_down_race/template/racer.lua +++ b/game/love_src/src/world/top_down_race/template/racer.lua @@ -8,9 +8,10 @@ template.default_data = { grip = 10.0, max_speed = 10.0, steer = 10.0, - velocity = 10.0, - decel = 5.0, - drag = 2.0 + velocity = 0.0, + inertia = {0.0, 0.0}, + drag = 2.0, + mass = 10.0 } function template.assemble(e, data) e:give(race.dict.accel, data.accel) @@ -19,8 +20,9 @@ function template.assemble(e, data) e:give(race.dict.max_speed, data.max_speed) e:give(race.dict.steer, data.steer) e:give(race.dict.velocity, data.velocity) - e:give(race.dict.decel, data.decel) + e:give(race.dict.inertia, data.inertia[1], data.inertia[2]) e:give(race.dict.drag, data.drag) + e:give(race.dict.mass, data.mass) end return template