振り子の支点を振り回す 3

--[[
とりあえず支点は固定したまま振り子を振ってみる。
スクリプトのフローは下の 3 行を繰り返すだけである。
★1. 「今の状態」を描画する。
★2. タイマーが tick したら「今の状態」を読み込んで「Δt 時間後の状態」を計算する。
★3. その「Δt 時間後の状態」を「今の状態」に置き換える。
--]]

timerTicking = false
screenW, screenH = platform.window:width(), platform.window:height()

unitLen     = screenW/4                         -- 1 メートルの、画面上での画素数
len         = 1                                 -- 振り子の棒の長さ〔m〕
ax          = 0                                 -- 振り子の支点の加速度 x〔m/sec^2〕
ay          = 0                                 -- 振り子の支点の加速度 y〔m/sec^2〕
angleIni    = 3.1                               -- 初期角度〔rad〕
velIni      = 0                                 -- 初期速度〔rad/sec〕
radiusPend  = screenW/30                        -- 分銅半径の描画画素数
x0          = screenW/2                         -- 支点の初期描画座標 x
y0          = screenH/2                         -- 支点の初期描画座標 y
xP          = x0+unitLen*len*math.sin(angleIni) -- 分銅の初期描画座標 x
yP          = y0+unitLen*len*math.cos(angleIni) -- 分銅の初期描画座標 y
step        = 0.01                              -- Δt〔sec〕
elapsedTime = 0                                 -- シム内の経過時間〔sec〕

function on.paint(gc)
   -- ★1.「今の状態」を描画する。
   drawPend(x0, y0, xP, yP, radiusPend, gc)
   gc:drawString(round(elapsedTime, 2), 1, 1)
   platform.window:invalidate()
end
function on.timer()
   -- ★2. タイマーが tick したら「今の状態」を読み込んで「Δt 時間後の状態」を計算する。
   var.store("len"     , len)
   var.store("ax"      , ax)
   var.store("ay"      , ay)
   var.store("angleini", angleIni)
   var.store("velini"  , velIni)
   var.store("step"    , step)   
   local temp = math.eval("pend(len, ax, ay, angleini, velini, step)")

   -- ★3. 「Δt 時間後の状態」を「今の状態」に置き換える。
   angleIni = temp[1]
   velIni   = temp[2]
   xP       = temp[3] * unitLen + x0
   yP       = temp[4] * unitLen + y0
   elapsedTime = elapsedTime + step
   platform.window:invalidate()
end
function on.enterKey()
   if     timerTicking == false then timer.start(step) timerTicking = true
   elseif timerTicking == true  then timer.stop()      timerTicking = false
   end
end
---------------------------------------------------
---------------------------------------------------
---------------------------------------------------
---------------------------------------------------
-- 振り子描画函数(支点描画座標, 分銅描画座標, 分銅描画半径, gc)
function drawPend(x0, y0, x1, y1, radius, gc)
   gc:drawLine(x0, y0, x1, y1)
   gc:fillArc(x1 - radius, y1 - radius, radius + radius, radius + radius, 0, 360)
end
-- 四捨五入函数(小数点数, 小数点以下の桁数)
function round(number, digits)
   return math.eval("round("..number..", "..digits..")")
   --[[return math.floor((number * 10^digits + 0.5))/10^digits--]]
end