定)
   -- P.S. 這裡的 renderer 是類似繪圖影擎的東西, 被稱為 *SDL rendering device*
   -- P.S. winConfig 和 rdrConfig 的定義寫在最下面
   window   <- SDL.createWindow "Hello!" winConfig
   renderer <- SDL.createRenderer window (-1) rdrConfig
   -- 創造一個 texture (相當於是畫布的東西)
   -- 然後把這個畫布貼到 renderer 之上
   texture  <- createCairoTexture renderer (V2 640 480)
   -- 設定初始玩家資訊
   let player = Player 50 10 15 15
   -- 這裡開始定義程式的 main loop
   -- mainLoop 是一個 a -> a 的 lambda function
   -- mainLoop 中定義程式邏輯的「執行一步」是要做什麼
   let mainLoop = \loop -> do
         threadDelay 20000
         -- 在 texture 上把東西畫出來
         -- 下述三個 functions 都定義在下面
         -- cairo 座標軸是左上為 (0,0) 往右是 +X 往下是 +Y
         showWindowBg   texture
         showPlayerInfo texture player
         showConcole    texture
         -- [顯示相關] 將 texture 目前的結果傳遞給 renderer
         SDL.copy renderer texture Nothing Nothing
         -- [顯示相關] 要求 renderer 顯示與更新畫面
         SDL.present renderer
         -- [鍵盤事件] 倒出目前所有的 events :: [Event]
         events <- SDL.pollEvents
         -- [鍵盤事件] 判斷是否 「有」 *ESC被按下去* 的事件
         -- P.S. null :: [a] -> Bool 會回傳一個 list 是否為 []
         let qPressed = not $ null $ filter eventIsESCPress events
         -- 利用鍵盤事件來中斷程式
         -- 也就是用 unless 來 break 出這個 mainLoop
         unless qPressed loop
   -- 利用 fix :: (a -> a) -> a 來無限地執行 mainLoop
   fix $ mainLoop
--
-- ########################################################
-- withCanvas :: Texture -> Canvas a -> IO a
showWindowBg :: SDL.Texture -> IO ()
showWindowBg tx = withCanvas tx $ do
   -- 重製背景
   background $ gray 220
   -- 繪製狀態列背景
   fill $ blue 255 !@ 64
   noStroke
   -- 繪製方塊, D 是 Dim 的 constructor
   -- 後面四個參數分別表示: X Y W H
   rect $ D 0 0 640 100
--
showPlayerInfo :: SDL.Texture -> Player -> IO ()
showPlayerInfo tx p = withCanvas tx $ do
   -- 設定 字體 大小 粗體 斜體
   textFont $ Font "Hiragino Maru Gothic ProN" 20 False False
   -- 設定顏色
   fill $ gray 0
   -- 繪製文字. P.S. (V2 30 40) 表示座標 (30,40)
   text ("HP:[" ++ (show $ hp p) ++ "]  MP:["++ (show $ mp p) ++"]")
      (V2 30 40)
   text ("X/Y:[" ++ (show $ lX p) ++ "/"++ (show $ lY p) ++"]")
      (V2
main :: IO ()
main = do
   -- SDL 初始化
   SDL.initialize [SDL.InitEverything]
   -- 從 SDL 中創造一個 window (用 winConfig 當做設定)
   -- 產生一個 renderer 並且將其崁入 window 上 (用 rdrConfig 為設定)
   -- P.S. 這裡的 renderer 是類似繪圖影擎的東西, 被稱為 *SDL rendering device*
   -- P.S. winConfig 和 rdrConfig 的定義寫在最下面
   window   <- SDL.createWindow "Hello!" winConfig
   renderer <- SDL.createRenderer window (-1) rdrConfig
   -- 創造一個 texture (相當於是畫布的東西)
   -- 然後把這個畫布貼到 renderer 之上
   texture  <- createCairoTexture renderer (V2 640 480)
   -- 設定初始玩家資訊
   let player = Player 50 10 15 15
   -- 這裡開始定義程式的 main loop
   -- mainLoop 是一個 a -> a 的 lambda function
   -- mainLoop 中定義程式邏輯的「執行一步」是要做什麼
   let mainLoop = \loop -> do
         threadDelay 20000
         -- 在 texture 上把東西畫出來
         -- 下述三個 functions 都定義在下面
         -- cairo 座標軸是左上為 (0,0) 往右是 +X 往下是 +Y
         showWindowBg   texture
         showPlayerInfo texture player
         showConcole    texture
         -- [顯示相關] 將 texture 目前的結果傳遞給 renderer
         SDL.copy renderer texture Nothing Nothing
         -- [顯示相關] 要求 renderer 顯示與更新畫面
         SDL.present renderer
         -- [鍵盤事件] 倒出目前所有的 events :: [Event]
         events <- SDL.pollEvents
         -- [鍵盤事件] 判斷是否 「有」 *ESC被按下去* 的事件
         -- P.S. null :: [a] -> Bool 會回傳一個 list 是否為 []
         let qPressed = not $ null $ filter eventIsESCPress events
         -- 利用鍵盤事件來中斷程式
         -- 也就是用 unless 來 break 出這個 mainLoop
         unless qPressed loop
   -- 利用 fix :: (a -> a) -> a 來無限地執行 mainLoop
   fix $ mainLoop
--
-- ########################################################
-- withCanvas :: Texture -> Canvas a -> IO a
main = do
   -- SDL 初始化
   SDL.initialize [SDL.InitEverything]
   -- 從 SDL 中創造一個 window (用 winConfig 當做設定)
   -- 產生一個 renderer 並且將其崁入 window 上 (用 rdrConfig 為設定)
   -- P.S. 這裡的 renderer 是類似繪圖影擎的東西, 被稱為 *SDL rendering device*
   -- P.S. winConfig 和 rdrConfig 的定義寫在最下面
   window   <- SDL.createWindow "Hello!" winConfig
   renderer <- SDL.createRenderer window (-1) rdrConfig
   -- 創造一個 texture (相當於是畫布的東西)
   -- 然後把這個畫布貼到 renderer 之上
   texture  <- createCairoTexture renderer (V2 640 480)
   -- 設定初始玩家資訊
   let player = Player 50 10 15 15
   -- 這裡開始定義程式的 main loop
   -- mainLoop 是一個 a -> a 的 lambda function
   -- mainLoop 中定義程式邏輯的「執行一步」是要做什麼
   let mainLoop = \loop -> do
         threadDelay 20000
         -- 在 texture 上把東西畫出來
         -- 下述三個 functions 都定義在下面
         -- cairo 座標軸是左上為 (0,0) 往右是 +X 往下是 +Y
         showWindowBg   texture
         showPlayerInfo texture player
         showConcole    texture
         -- [顯示相關] 將 texture 目前的結果傳遞給 renderer
         SDL.copy renderer texture Nothing Nothing
         -- [顯示相關] 要求 renderer 顯示與更新畫面
         SDL.present renderer
         -- [鍵盤事件] 倒出目前所有的 events :: [Event]
         events <- SDL.pollEvents
         -- [鍵盤事件] 判斷是否 「有」 *ESC被按下去* 的事件
         -- P.S. null :: [a] -> Bool 會回傳一個 list 是否為 []
         let qPressed = not $ null $ filter eventIsESCPress events
         -- 利用鍵盤事件來中斷程式
         -- 也就是用 unless 來 break 出這個 mainLoop
         unless qPressed loop
   -- 利用 fix :: (a -> a) -> a 來無限地執行 mainLoop
   fix $ mainLoop
--
-- ########################################################
-- withCanvas :: Texture -> Canvas a -> IO a