52700.fb2
getClick
:: Sensor H.Position -> IO (Maybe Event)
Далее мы не будем каждый раз выписывать новые неопределённые функции, мы будем просто оставлять
объявления типов без определений. Итак мы написали одну функцию, и получили ещё четыре новых.
Мы сделаем предположение о том, что сначала мы реагируем на непрерывные события, а затем на дис-
кретные. Причём к запросам на реакции могут привести только дискретные события:
updatePure :: Sense -> [Event] -> Pure -> (Pure, [Query])
updatePure s evts = updateEvents evts . updateSenses s
-- в Pure.hs
updateSenses :: Sense -> Pure -> Pure
updateEvents :: [Event] -> Pure -> (Pure, [Query])
В функции react мы предполагаем, что реакции мира на события независимы друг от друга. foldQuery~–
функция свёртки для типа Query.
import Control.Monad
...
react :: [Query] -> Dirty -> IO Dirty
react = foldr (<=< ) return
. fmap (foldQuery removeBall heroVelocity makeBall)
-- в Dirty.hs
removeBall
:: Ball
-> Dirty -> IO Dirty
heroVelocity
:: H.Velocity
-> Dirty -> IO Dirty
makeBall
:: Freq
-> Dirty -> IO Dirty
Обратите внимание на то, как мы воспользовались функциями foldr, return и <=< для того чтобы нани-
зать друг на друга функции типа Dirty -> IO Dirty. Напомню, что функция <=< ~– это аналог композиции
для монадных функций.
Обновление модели:
updateDirty :: Dirty -> IO Dirty
updateDirty = stepDirty dt
-- в Dirty.hs
Детализируем функции обновления состояния игры | 303
stepDirty :: H.Time -> Dirty -> IO Dirty
-- в Inits.hs
dt :: H.Time
dt = 0.5
Функции рисования поместим в отдельный модуль Graphics. hs
-- переместим из Loop.hs в World.hs
drawWorld :: World -> IO ()
drawWorld = draw . picture . worldPure
-- в Graphics.hs
draw :: Picture -> IO ()
-- в Pure.hs
picture
:: Pure -> Picture