aboutsummaryrefslogtreecommitdiff
path: root/src/Chelleport.hs
blob: 536bba95daf712b0a250d80b9382578f0195f940 (plain) (blame)
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
module Chelleport where

import Control.Monad (foldM, unless)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import qualified Data.Text as Text
import Foreign (Ptr)
import Foreign.C (CInt)
import SDL (($=))
import qualified SDL
import qualified SDL.Font as TTF
import System.Exit (exitSuccess)

open :: IO ()
open = do
  -- Initialize SDL
  SDL.initializeAll
  TTF.initialize

  -- Create window
  window <-
    SDL.createWindow
      "My SDL Application"
      ( SDL.defaultWindow
          { -- SDL.windowMode = SDL.Fullscreen,
            SDL.windowInputGrabbed = True,
            SDL.windowBorder = False
          }
      )

  renderer <- SDL.createRenderer window (-1) SDL.defaultRenderer
  font <- TTF.load "Inter-Regular.ttf" 16

  SDL.windowOpacity window $= 0.6
  SDL.rendererDrawBlendMode renderer $= SDL.BlendAlphaBlend
  SDL.rendererDrawColor renderer $= SDL.V4 0 0 0 0

  appLoop renderer initState font

  SDL.destroyRenderer renderer
  SDL.destroyWindow window
  pure ()

data State = State
  { stateExit :: Bool,
    stateCount :: Int
  }

data Action = ActionQuit | ActionUpdateCount Int

initState :: State
initState = State {stateExit = False, stateCount = 0}

appLoop :: SDL.Renderer -> State -> TTF.Font -> IO ()
appLoop renderer state font = do
  events <- SDL.pollEvents

  SDL.clear renderer
  renderText renderer font $ Text.pack ("Hello, Haskell: " ++ show (stateCount state))
  SDL.present renderer

  newState <- evaluateEvents state events
  unless (stateExit newState) (appLoop renderer newState font)

evaluateEvents :: State -> [SDL.Event] -> IO State
evaluateEvents = foldM evaluate
  where
    evaluate :: State -> SDL.Event -> IO State
    evaluate st event = maybe (pure st) (update st) (eventToAction event)

update :: State -> Action -> IO State
update state ActionQuit = pure state {stateExit = True}
update state (ActionUpdateCount count) = pure state {stateCount = stateCount state + count}

eventToAction :: SDL.Event -> Maybe Action
eventToAction event =
  case SDL.eventPayload event of
    SDL.KeyboardEvent keyboardEvent
      | isKeyPress keyboardEvent SDL.KeycodeQ -> Just ActionQuit
    SDL.KeyboardEvent keyboardEvent
      | isKeyPress keyboardEvent SDL.KeycodeJ -> Just $ ActionUpdateCount (-1)
    SDL.KeyboardEvent keyboardEvent
      | isKeyPress keyboardEvent SDL.KeycodeK -> Just $ ActionUpdateCount 1
    _ -> Nothing

isKeyPress :: SDL.KeyboardEventData -> SDL.Keycode -> Bool
isKeyPress keyboardEvent keyCode =
  SDL.keyboardEventKeyMotion keyboardEvent == SDL.Pressed
    && SDL.keysymKeycode (SDL.keyboardEventKeysym keyboardEvent) == keyCode

-- Render text to the screen
renderText :: SDL.Renderer -> TTF.Font -> Text -> IO ()
renderText renderer font text = do
  -- Render text in white
  surface <- TTF.blended font (SDL.V4 255 255 255 255) text
  texture <- SDL.createTextureFromSurface renderer surface
  SDL.freeSurface surface

  -- Get text dimensions
  textureInfo <- SDL.queryTexture texture
  let textWidth = SDL.textureWidth textureInfo
      textHeight = SDL.textureHeight textureInfo
      position =
        SDL.P (SDL.V2 ((640 - textWidth) `div` 2) ((480 - textHeight) `div` 2))

  -- Render the texture
  SDL.copy renderer texture Nothing (Just (SDL.Rectangle position (SDL.V2 textWidth textHeight)))
  SDL.destroyTexture texture