piyo-0.1.0.0: src/Piyo/Draw.hs
-- | Draw functions.
-- Last two arguments -> X -> Y is the drawing origin.
module Piyo.Draw
( cls
, dot
, line
, rect
, rectfill
, circ
, circfill
, tri
, trifill
, spr
, sprn
, sprc
, txt
, txtb
, mp
)
where
import Control.Monad.IO.Class ( MonadIO )
import Control.Monad
import Foreign.C.Types ( CInt )
import SDL ( ($=) )
import qualified SDL
import qualified SDL.Primitive
import qualified SDL.Image
import qualified SDL.Font
import Piyo.Internal.Types
import Piyo.Internal.Constants
import Data.Word ( Word8 )
import Data.Text ( pack )
-- | Clear the screen with given color.
cls :: MonadIO m => Color -> DrawOp m
cls c ra = setColor c ra >> SDL.clear (renderer ra)
-- | Draw rectangle with given color.
-- Origin is left-top.
rect :: MonadIO m => Color -> Width -> Height -> X -> Y -> DrawOp m
rect = rectF SDL.Primitive.rectangle
rectfill :: MonadIO m => Color -> Width -> Height -> X -> Y -> DrawOp m
rectfill = rectF SDL.Primitive.fillRectangle
rectF f c w h x y = \ra -> f (renderer ra) pa pb col
where
pa = makePos x y
pb = makePos (x + w) (y + h)
col = colorCode c
dot :: MonadIO m => Color -> X -> Y -> DrawOp m
dot c x y = \ra -> SDL.Primitive.pixel (renderer ra) p col
where
p = makePos x y
col = colorCode c
line :: MonadIO m => Color -> X -> Y -> X -> Y -> DrawOp m
line c xa ya xb yb = \ra -> SDL.Primitive.line (renderer ra) pa pb col
where
pa = makePos xa ya
pb = makePos xb yb
col = colorCode c
-- | Draw circle with given color.
-- Origin is center.
circ :: MonadIO m => Color -> Radius -> X -> Y -> DrawOp m
circ = circF SDL.Primitive.circle
circfill :: MonadIO m => Color -> Radius -> X -> Y -> DrawOp m
circfill = circF SDL.Primitive.fillCircle
circF f c r x y = \ra -> f (renderer ra) p r' col
where
p = makePos x y
r' = fromIntegral r
col = colorCode c
tri :: MonadIO m => Color -> X -> Y -> X -> Y -> X -> Y -> DrawOp m
tri = triF SDL.Primitive.triangle
trifill :: MonadIO m => Color -> X -> Y -> X -> Y -> X -> Y -> DrawOp m
trifill = triF SDL.Primitive.fillTriangle
triF f c xa ya xb yb xc yc = \ra -> f (renderer ra) pa pb pc col
where
pa = makePos xa ya
pb = makePos xb yb
pc = makePos xc yc
col = colorCode c
-- | Draw sprite.
-- Origin is left-top.
spr :: MonadIO m => IdX -> IdY -> X -> Y -> DrawOp m
spr xId yId = sprn xId yId 1 1
-- | Draw sprite for large size.
sprn :: MonadIO m => IdX -> IdY -> CntX -> CntY -> X -> Y -> DrawOp m
sprn xId yId bw bh = sprc x' y' w h
where
x' = boxSize * xId
y' = boxSize * yId
w = boxSize * bw
h = boxSize * bh
-- | Draw sprite for any size.
sprc :: MonadIO m => X -> Y -> Width -> Height -> X -> Y -> DrawOp m
sprc xs ys w h xt yt ra = case mTxtr of
Just txtr -> SDL.copy rdr txtr (Just rs) (Just rt)
Nothing -> return ()
where
mTxtr = mImage ra
rdr = renderer ra
rs = makeRect xs ys w h
rt = makeRect xt yt w h
-- | Draw text with given color.
-- Font is JF-Dot-K12.
-- Origin is left-top.
txt :: MonadIO m => Color -> String -> X -> Y -> DrawOp m
txt = txtF plain
-- | Draw bold text with given color.
-- Font is JF-Dot-K12B.
-- Origin is left-top.
txtb :: MonadIO m => Color -> String -> X -> Y -> DrawOp m
txtb = txtF bold
txtF f c t x y ra = do
sfc <- SDL.Font.solid font' col t'
txtr <- SDL.createTextureFromSurface rdr sfc
(w, h) <- SDL.Font.size font' t'
let rt = makeRect x y w h in SDL.copy rdr txtr Nothing (Just rt)
SDL.freeSurface sfc
SDL.destroyTexture txtr
where
t' = pack t
font' = f $ font ra
rdr = renderer ra
col = colorCode c
-- | Draw map (a set of sprites).
-- Origin is left-top.
mp :: MonadIO m => IdX -> IdY -> CntX -> CntY -> X -> Y -> DrawOp m
mp mx my mw mh x y ra = forM_
im
(\(vrt, il) -> forM_
il
(\(hr, (nx, ny)) -> do
let w = boxSize
h = boxSize
xs = w * nx
ys = h * ny
xt = x + w * (mx + hr)
yt = y + h * (my + vrt)
unless (hr > mw || vrt > mh) $ sprc xs ys w h xt yt ra
)
)
where
m = imageMap ra
l = zip [0 ..]
im = l $ (map l) m
setColor :: MonadIO m => Color -> DrawOp m
setColor c ra = SDL.rendererDrawColor (renderer ra) $= colorCode c
colorCode :: Color -> SDL.V4 Word8
colorCode Black = SDL.V4 0 0 0 maxBound
colorCode DarkBlue = SDL.V4 29 43 83 maxBound
colorCode DarkPurple = SDL.V4 126 37 83 maxBound
colorCode DarkGreen = SDL.V4 0 135 81 maxBound
colorCode Brown = SDL.V4 171 82 54 maxBound
colorCode DarkGray = SDL.V4 95 87 79 maxBound
colorCode LightGray = SDL.V4 194 195 199 maxBound
colorCode White = SDL.V4 maxBound 241 232 maxBound
colorCode Red = SDL.V4 maxBound 0 77 maxBound
colorCode Orange = SDL.V4 maxBound 163 0 maxBound
colorCode Yellow = SDL.V4 maxBound 236 39 maxBound
colorCode Green = SDL.V4 0 228 54 maxBound
colorCode Blue = SDL.V4 41 173 maxBound maxBound
colorCode Indigo = SDL.V4 131 118 156 maxBound
colorCode Pink = SDL.V4 maxBound 119 168 maxBound
colorCode Peach = SDL.V4 maxBound 204 170 maxBound
makePos :: Int -> Int -> SDL.V2 CInt
makePos x y = SDL.V2 x' y' where (x', y') = (fromIntegral x, fromIntegral y)
makeRect :: Int -> Int -> Int -> Int -> SDL.Rectangle CInt
makeRect x y w h = SDL.Rectangle o z
where
(x', y', w', h') =
(fromIntegral x, fromIntegral y, fromIntegral w, fromIntegral h)
o = SDL.P (SDL.V2 x' y')
z = SDL.V2 w' h'