forked from AdamCollins/Haskell-2048
-
Notifications
You must be signed in to change notification settings - Fork 0
/
render.hs
executable file
·123 lines (105 loc) · 4.72 KB
/
render.hs
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
-- The end of game images(cross/circle) are taken from this game:
-- https://gist.github.com/gallais/0d61677fe97aa01a12d5
module Render (windowIO, background, drawing, handleKeys) where
import Control.Monad.Reader
import Graphics.Gloss
import Graphics.Gloss.Interface.Pure.Game -- for Event
import State
squares_per_row = boardSize
numof_edges = squares_per_row + 1
square_to_edge_ratio = 7.6
scale_factor = 2600
background :: Color
background = makeColorI 187 173 160 255
windowIO :: Reader Float Display
windowIO = do
size <- ask
return ( InWindow "2048" (round size, round size) (10, 10) )
edge_sizeIO :: Reader Float Float
edge_sizeIO = do
window_size <- ask
return ( window_size / (numof_edges + squares_per_row * square_to_edge_ratio) )
square_sizeIO :: Reader Float Float
square_sizeIO = do
edge_size <- edge_sizeIO
return ( edge_size * square_to_edge_ratio )
posToLeft :: String -> Float
posToLeft tile = case move of
4 -> 3.8
3 -> 5
2 -> 8
1 -> 15
where move = foldl (\acc x -> 1 + acc) 0 tile
tileValueIO :: Tile -> Reader Float [Picture]
tileValueIO tile = do
window_size <- ask
square_size <- square_sizeIO
let amount = window_size / scale_factor
let posx = posToLeft $ show tile
let tileValue = if tile == 0
then []
else [translate (- square_size / posx) (- square_size / 10) $
Scale amount amount $ color black $ text $ show tile]
return tileValue
drawSquareIO :: Tile -> Index -> Reader Float Picture
drawSquareIO tile index = do
window_size <- ask
edge_size <- edge_sizeIO
square_size <- square_sizeIO
tileValue <- tileValueIO tile
return (
translate (-1/2 * window_size + edge_size * (index + 1) + square_size * index + 1/2 * square_size) 0 $
color (tileColor tile) $ pictures $ [rectangleSolid square_size square_size] ++ tileValue
)
drawRowIO :: Row -> Index -> Reader Float Picture
drawRowIO row index = do
window_size <- ask
drawSquares <- sequence [drawSquareIO tile tindex | (tile, tindex) <- zip row [0..squares_per_row - 1]]
edge_size <- edge_sizeIO
square_size <- square_sizeIO
return (translate 0
(1/2 * window_size - edge_size * (index + 1) - square_size * index - 1/2 * square_size)
$ pictures drawSquares)
doDrawing :: GameState -> Reader Float Picture
doDrawing gameState = do
winsize <- ask
drawRows <- sequence [drawRowIO row index | (row, index) <- zip (board gameState) [0..squares_per_row - 1]]
let gameOverDisplay = [drawGameOver winsize | status gameState == Lose]
let winDisplay = [drawWin winsize | status gameState == Win]
return ( pictures $ drawRows ++ gameOverDisplay ++ winDisplay )
drawing :: Float -> GameState -> Picture
drawing winsize gameState =
runReader (doDrawing gameState) winsize
resize :: Float -> Path -> Path
resize k = fmap (\ (x, y) -> (x * k, y * k))
drawWin :: Float -> Picture
drawWin winsize = color green $ translate 0 0 $ thickCircle (0.1 * k) (0.3 * k)
where k = winsize / 1.25
drawGameOver :: Float -> Picture
drawGameOver winsize = color red $ translate 0 0 $ pictures $ fmap (polygon . resize (winsize / 1.6))
[ [ (-0.35, -0.25), (-0.25, -0.35), (0.35,0.25), (0.25, 0.35) ]
, [ (0.35, -0.25), (0.25, -0.35), (-0.35,0.25), (-0.25, 0.35) ]
]
handleKeys :: Event -> GameState -> GameState
handleKeys (EventKey (SpecialKey KeyLeft) Down _ _) gs = shiftLeft gs
handleKeys (EventKey (SpecialKey KeyRight) Down _ _) gs = shiftRight gs
handleKeys (EventKey (SpecialKey KeyUp) Down _ _) gs = shiftUp gs
handleKeys (EventKey (SpecialKey KeyDown) Down _ _) gs = shiftDown gs
-- a special key to test win/lose display; to be deleted
-- handleKeys (EventKey (Char 'a') Down _ _) s = winBoard
handleKeys _ gs = gs
tileColor :: Tile -> Color
tileColor tile = case tile of
0 -> makeColorI 205 192 180 255
2 -> makeColorI 238 228 218 255
4 -> makeColorI 237 224 200 255
8 -> makeColorI 242 177 121 255
16 -> makeColorI 245 149 99 255
32 -> makeColorI 246 124 95 255
64 -> makeColorI 246 94 59 255
128 -> makeColorI 237 207 114 255
256 -> makeColorI 237 204 97 255
512 -> makeColorI 237 200 80 255
1024 -> makeColorI 237 197 63 255
2048 -> makeColorI 237 194 46 255
_ -> makeColorI 238 228 218 90