Implemented engine

This commit is contained in:
Ivan Grachyov 2021-11-09 22:32:12 +05:00
parent e2c1c4bc88
commit 8a426a1d5c
7 changed files with 182 additions and 46 deletions

View File

@ -1,16 +1,39 @@
Clutch = class("Clutch") Clutch = class("Clutch")
function Clutch:initialize(options) function Clutch:initialize(options)
options = options or {} options = options or {}
self.stiffness = options.Stiffness or 0 self.stiffness = options.Stiffness or 0
self.capacity = options.Capacity or 0 self.capacity = options.Capacity or 0
self.damping = options.Damping or 0 self.damping = options.Damping or 0
self.maxTorque = options.MaxTorque or 0
self._engine = options.Engine self.press = 1
self._gearbox = options.Gearbox self.slip = 0
self.targetTorque = 0
self.torque = 0
self._engine = nil
self._gearbox = nil
end end
function Clutch:update() function Clutch:update()
local someConversionCoeff = 0.10472
local engRPM = self._engine and self._engine.rpm or 0
local gboxRPM = self._gearbox and self._gearbox.rpm or 0
local gboxRatio = self._gearbox and self._gearbox.ratio or 0
local gboxRatioNotZero = gboxRatio ~= 0 and 1 or 0
self.slip = (engRPM * someConversionCoeff - gboxRPM * someConversionCoeff) * gboxRatioNotZero / 2
self.targetTorque = math.clamp(self.slip * self.stiffness * (1 - self.press), -self.maxTorque, self.maxTorque)
self.torque = math.lerp(self.torque, self.targetTorque, self.damping)
end
function Clutch:linkEngine(engine)
self._engine = engine
end
function Clutch:linkGearbox(gbox)
self._gearbox = gbox
end end

View File

@ -1,20 +1,73 @@
-- @include ../libs/constants.txt
require("../libs/constants.txt")
Engine = class("Engine") Engine = class("Engine")
function Engine:initialize(options) function Engine:initialize(options)
options = options or {} options = options or {}
self.idleRPM = options.IdleRPM or 800 self.idleRPM = options.IdleRPM or 800
self.maxRPM = options.MaxRPM or 8000 self.maxRPM = options.MaxRPM or 8000
self.flywheelMass = options.FlywheelMass or 4 self.flywheelMass = options.FlywheelMass or 4
self.flywheelRadius = options.FlywheelRadius or 0.3 self.flywheelRadius = options.FlywheelRadius or 0.3
self.startFriction = options.StartFriction or -30 self.startFriction = options.StartFriction or -30
self.frictionCoeff = options.FrictionCoeff or 0.02 self.frictionCoeff = options.FrictionCoeff or 0.02
self.limiterDuration = options.LimiterDuration or 0.05 self.limiterDuration = options.LimiterDuration or 0.05
self.torqueMap = options.TorqueMap or {} self.torqueMap = options.TorqueMap or {}
self.throttle = 0 self.throttle = 0
self.torque = 0
self.rpmFrac = 0
self.rpm = self.idleRPM
self.friction = 0
self._fwInertia = self.flywheelMass * self.flywheelRadius ^ 2 / 2
self._limiterTime = 0
self._clutch = nil
end
function Engine:setThrottle(throttle)
self.throttle = throttle
end
function Engine:linkClutch(clutch)
self._clutch = clutch
clutch:linkEngine(self)
end
function Engine:update()
self.rpmFrac = math.clamp((self.rpm - self.idleRPM) / (self.maxRPM - self.idleRPM), 0, 1)
self.friction = self.startFriction - self.rpm * self.frictionCoeff
local tqIdx = math.clamp(math.floor(self.rpmFrac * #self.torqueMap), 1, #self.torqueMap)
local maxInitialTorque = self.torqueMap[tqIdx] - self.friction
local idleFadeStart = math.clamp(math.remap(self.rpm, self.idleRPM - 300, self.idleRPM, 1, 0), 0, 1)
local idleFadeEnd = math.clamp(math.remap(self.rpm, self.idleRPM, self.idleRPM + 600, 1, 0), 0, 1)
local additionalEnergySupply = idleFadeEnd * (-self.friction / maxInitialTorque) + idleFadeStart
if self.rpm > self.maxRPM then
self.throttle = 0
self._limiterTime = os.time()
else
self.throttle = os.time() >= self._limiterTime + self.limiterDuration and self.throttle or 0
end
local masterThrottle = math.clamp(additionalEnergySupply + self.throttle, 0, 1)
local realInitialTorque = maxInitialTorque * masterThrottle
local loadTorque = self._clutch and self._clutch.torque or 0
self.torque = realInitialTorque + self.friction
self.rpm = self.rpm + (self.torque - loadTorque) / self._fwInertia * RAD_TO_RPM * TICK_INTERVAL
self.rpm = math.max(self.rpm, 0)
end end

View File

@ -1,18 +1,20 @@
Gearbox = class("Gearbox") Gearbox = class("Gearbox")
function Gearbox:initialize(options) function Gearbox:initialize(options)
options = options or {} options = options or {}
self.ratios = options.ratios self.ratios = options.Ratios
self.finalDrive = options.finalDrive self.finalDrive = options.FinalDrive
self.reverse = options.Reverse
self._linkedDiffs = {} self.gear = 0
self.gear = 0 self._linkedDiffs = {}
self._clutch = nil
end end
function Gearbox:linkDiff(diff) function Gearbox:linkDiff(diff)
table.insert(self._linkedDiffs, diff) table.insert(self._linkedDiffs, diff)
end end
function Gearbox:shift(dir) function Gearbox:shift(dir)
@ -20,7 +22,14 @@ function Gearbox:shift(dir)
end end
function Gearbox:setGear(gear) function Gearbox:setGear(gear)
self.gear = gear if gear >= -1 and gear <= #self.ratios then
self.gear = gear
end
end
function Gearbox:linkClutch(clutch)
self._clutch = clutch
clutch:linkGearbox(self)
end end
function Gearbox:update() function Gearbox:update()

View File

@ -2,3 +2,9 @@
require("./base.txt") require("./base.txt")
CVT = class("CVT") CVT = class("CVT")
function CVT:initialize(options)
options = options or {}
self.base = Gearbox:new(options)
end

View File

@ -4,7 +4,14 @@ require("./base.txt")
ManualGearbox = class("ManualGearbox") ManualGearbox = class("ManualGearbox")
function ManualGearbox:initialize(options) function ManualGearbox:initialize(options)
-- create base gearbox inside options = options or {}
-- might want to segregate construction options for base gearbox
self.base = Gearbox:new(options)
end
function ManualGearbox:linkClutch(clutch)
return self.base:linkClutch(clutch)
end end
-- proxy the methods here -- proxy the methods here

View File

@ -1,9 +1,11 @@
-- @name Koptilnya Engine -- @name Koptilnya Engine
-- @author Koptilnya1337 -- @author Koptilnya1337
-- @shared -- @server
-- --
-- @include ./engine.txt -- @include ./engine.txt
-- --
-- @include ./clutch.txt
--
-- @include ./gearboxes/manual.txt -- @include ./gearboxes/manual.txt
-- @include ./gearboxes/cvt.txt -- @include ./gearboxes/cvt.txt
-- @include ./gearboxes/auto.txt -- @include ./gearboxes/auto.txt
@ -13,6 +15,8 @@
-- @include ./configs/audi_tt.txt -- @include ./configs/audi_tt.txt
require("./engine.txt") require("./engine.txt")
-- --
require("./clutch.txt")
--
require("./gearboxes/manual.txt") require("./gearboxes/manual.txt")
require("./gearboxes/cvt.txt") require("./gearboxes/cvt.txt")
require("./gearboxes/auto.txt") require("./gearboxes/auto.txt")
@ -21,22 +25,54 @@ require("./differential.txt")
-- --
require("./configs/audi_tt.txt") require("./configs/audi_tt.txt")
if SERVER then ECU = class("ECU")
function adjustPorts()
wire.adjustPorts({
Input = "table"
}, {
RPM = "number"
})
end
function setupHooks() function ECU:initialize(options)
options = options or {}
end self.engine = options.Engine
self.clutch = options.Clutch
self.gearbox = options.Gearbox
self.differentials = options.Differentials
self.input = {}
adjustPorts() self:adjustPorts()
-- printTable(config)
else
hook.add('tick', 'ecu_update', function()
self:update()
end)
end end
function ECU:adjustPorts()
wire.adjustPorts({
Input = "table"
}, {
RPM = "number",
Torque = "number"
})
end
function ECU:update()
wire.ports.RPM = self.engine.rpm
wire.ports.Torque = self.engine.torque
self.input = wire.ports.Input
self.engine:setThrottle(self.input.Throttle.Value)
self.engine:update()
end
local clutch = Clutch:new(config.Clutch)
local engine = Engine:new(config.Engine)
engine:linkClutch(clutch)
local gearbox = ManualGearbox:new(config.Gearbox)
gearbox:linkClutch(clutch)
local ecu = ECU:new({
Engine = engine,
Clutch = clutch
-- Gearbox = gearbox
})
-- printTable(config)

View File

@ -1,3 +1,5 @@
NULL_ENTITY = entity(0) NULL_ENTITY = entity(0)
CURRENT_PLAYER = player() CURRENT_PLAYER = player()
OWNER = owner() OWNER = owner()
TICK_INTERVAL = game.getTickInterval()
RAD_TO_RPM = 9.5493