module Game.Toaster ( Toaster, mkToaster, add, update, render, ) where import Data.Foldable (traverse_) import qualified Game.BitmapFont as BM import qualified SDL 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