blob: 671473b3e641d867e530bd4a31148b987bcf433f (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
module Game.Toaster
( Toaster,
mkToaster,
add,
update,
render,
)
where
import Data.Foldable (traverse_)
import Game.BitmapFont qualified as BM
import SDL qualified
toastDelay :: Int
toastDelay = 128
data Toast = Toast
{ message :: String,
y :: Int,
delay :: Int
}
data Toaster = Toaster
{ font :: BM.BitmapFont,
gameHeight :: Int,
queue :: [String],
current :: Maybe Toast
}
-- | Make a "toast" notification manager.
--
-- The toast notifications appear on the bottom left of the screen and disappear after some seconds.
mkToaster :: BM.BitmapFont -> Int -> IO Toaster
mkToaster font height = do
pure $ Toaster font height [] Nothing
add :: Toaster -> String -> Toaster
add t message =
t {queue = t.queue ++ [message]}
-- | Update the current notification or activate the next one if there is no notification active.
update :: Toaster -> Toaster
update t = case t.current of
Nothing -> case t.queue of
[] -> t
(next : _) -> t {current = Just $ Toast next t.gameHeight toastDelay, queue = tail t.queue}
-- FIXME: magic number
Just toast -> t {current = updateToast (t.gameHeight - 14) toast}
where
updateToast :: Int -> Toast -> Maybe Toast
updateToast height toast
| toast.y > height && toast.delay > 0 = Just toast {y = toast.y - 1}
| toast.delay > 0 = Just toast {delay = toast.delay - 1}
| toast.y < t.gameHeight = Just toast {y = toast.y + 1}
| otherwise = Nothing
-- | Render current notification (if there's one active).
render :: SDL.Renderer -> Toaster -> IO ()
render renderer t =
traverse_ (\toast -> BM.renderTextSolid renderer t.font 4 toast.y toast.message) t.current
|