52700.fb2 Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 332

Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 332

data Event = Touch Ball | UserClick H.Position

data Sense = Sense

{ senseHero

:: HeroBall

, senseBalls

:: [Ball]

}

Через Query чистые данные могут рассказать грязным о том, что необходимо удалить шар из игры, об-

новить скорость шара игрока или создать новый шар (Freq отвечает за параметры создания шара). Грязные

данные могут рассказать чистым на языке Event и Sense о том, что один из шаров коснулся до шара иг-

рока, или игрок кликнул мышкой в определённой точке. Также мы сообщаем все обновлённые положения

параметры шаров в типе Sense. Тип Event отвечает за события, которые происходят иногда, а тип Sense за

те параметры, которые мы наблюдаем непрерывно (это типы глазарук), Query – это язык действий (это тип

руконог). Нам понадобится ещё один маленький язык, на котором мы будем объясняться с OpenGL.

data Picture = Prim Color Primitive

| Join Picture Picture

data Primitive = Line Point Point | Circle Point Radius

data Point

= Point Double Double

type Radius = Double

data Color = Color Double Double Double

Эти три языка станут барьером, которым мы ограничим влияние IO. У нас будут функции:

percept

:: Dirty -> IO (Sense, [Event])

updatePure

:: Sense -> [Event] -> Pure -> (Pure, [Query])

react

:: [Query] -> Dirty -> IO Dirty

updateDirty :: Dirty -> IO Dirty

picture

:: Pure -> Picture

draw

:: Picture -> IO ()

Вся логика игры будет происходить в чистой функции updatePure, обновлять модель мира мы будем в

updateDirty. Давайте опять начнём проектироваание сверху-вниз. С этими функциями мы уже можем напи-

сать основную функцию цикла игры:

loop :: IORef World -> IO ()

loop worldRef = do

world <- get worldRef

300 | Глава 20: Императивное программирование

drawWorld world

(world, dt) <- updateWorld world

worldRef $= world

G. addTimerCallback (max 0 $ frameTime - dt) $ loop worldRef

updateWorld :: World -> IO (World, Time)

updateWorld world = do

t0 <- get G. elapsedTime

(sense, events) <- percept dirty

let (pure’, queries) = updatePure sense events pure

dirty’ <- updateDirty =<< react queries dirty