aboutsummaryrefslogtreecommitdiff
path: root/src/Game/Toaster.hs
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