-
Notifications
You must be signed in to change notification settings - Fork 0
/
game-draw.sml
162 lines (149 loc) · 5.12 KB
/
game-draw.sml
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
structure GameDraw =
struct
open GameTypes
type block_build_result =
{lightBlocks: Real32.real vector list, darkBlocks: Real32.real vector list}
local
fun helpBuildBlocks (vec: block vector, pos: int, lightAcc, darkAcc) :
block_build_result =
if pos < 0 then
{lightBlocks = lightAcc, darkBlocks = darkAcc}
else
let
val {block = blockType, vertexData = blockVertex} =
Vector.sub (vec, pos)
(* Repeat case branch twice to avoid tuple allocation of
* (lightAcc, darkAcc) which I would guess is more expensive.*)
val lightAcc =
case blockType of
LIGHT => blockVertex :: lightAcc
| DARK => lightAcc
val darkAcc =
case blockType of
DARK => blockVertex :: darkAcc
| LIGHT => darkAcc
in
helpBuildBlocks (vec, pos - 1, lightAcc, darkAcc)
end
in
fun buildBlocks (vec, lightAcc, darkAcc) =
helpBuildBlocks (vec, Vector.length vec - 1, lightAcc, darkAcc)
end
local
fun helpDrawBlocksLine
(vec: block vector vector, pos: int, lightAcc, darkAcc) =
if pos < 0 then
{lightBlocks = lightAcc, darkBlocks = darkAcc}
else
let
val row = Vector.sub (vec, pos)
val {lightBlocks = lightAcc, darkBlocks = darkAcc} =
buildBlocks (row, lightAcc, darkAcc)
in
helpDrawBlocksLine (vec, pos - 1, lightAcc, darkAcc)
end
in
fun drawBlocksLine (vec: block vector vector) =
helpDrawBlocksLine (vec, Vector.length vec - 1, [], [])
end
fun drawBlocks (game: game_board) =
let
val {lightBlocks, darkBlocks} = drawBlocksLine (#blocks game)
(* Bind and draw light blocks. *)
val lightBlocks = Vector.concat lightBlocks
val dayVertexBuffer = #dayVertexBuffer game
val _ = Gles3.bindBuffer dayVertexBuffer
val _ =
Gles3.bufferData
(lightBlocks, Vector.length lightBlocks, Gles3.DYNAMIC_DRAW ())
val _ = Gles3.vertexAttribPointer (0, 2)
val _ = Gles3.enableVertexAttribArray 0
val dayProgram = #dayProgram game
val dayUniformLocation = Gles3.getUniformLocation (dayProgram, "col")
val _ = Gles3.useProgram dayProgram
val _ = Gles3.uniform4f
(dayUniformLocation, #dr game, #dg game, #db game, 1.0)
val _ = Gles3.drawArrays
(Gles3.TRIANGLES (), 0, Vector.length lightBlocks div 2)
val darkBlocks = Vector.concat darkBlocks
val nightVertexBuffer = #nightVertexBuffer game
val _ = Gles3.bindBuffer nightVertexBuffer
val _ =
Gles3.bufferData
(darkBlocks, Vector.length darkBlocks, Gles3.DYNAMIC_DRAW ())
val _ = Gles3.vertexAttribPointer (0, 2)
val _ = Gles3.enableVertexAttribArray 0
val nightProgram = #nightProgram game
val nightUniformLocation = Gles3.getUniformLocation (nightProgram, "col")
val _ = Gles3.useProgram (#nightProgram game)
val _ = Gles3.uniform4f
(nightUniformLocation, #nr game, #ng game, #nb game, 1.0)
val _ = Gles3.drawArrays
(Gles3.TRIANGLES (), 0, Vector.length darkBlocks div 2)
in
()
end
local
fun ballToVertexData ({xPos, yPos, ...}: ball) : Real32.real vector =
let
val left = Real32.fromInt xPos / 500.0
val right = left + 0.1
val top = Real32.fromInt yPos / 500.0
val bottom = top - 0.1
in
#[
right, bottom, (* bottom right *)
right, top, (* top right *)
left, top, (* top left *)
left, bottom (* bottom left *)
]
end
in
fun drawBalls (game: game_board) =
let
val
{ dayBall
, nightBall
, ballVertexBuffer
, ballVertexShader
, ballFragmentBuffer
, ballFragmentShader
, ballProgram
, dr
, dg
, db
, nr
, ng
, nb
, ...
} = game
val dayVertexData = ballToVertexData dayBall
val nightVertexData = ballToVertexData nightBall
(* Drawing code. *)
val _ = Gles3.bindBuffer ballVertexBuffer
val _ =
Gles3.bufferData
(dayVertexData, Vector.length dayVertexData, Gles3.DYNAMIC_DRAW ())
val _ = Gles3.vertexAttribPointer (0, 2)
val _ = Gles3.enableVertexAttribArray 0
val ballUniformLocation = Gles3.getUniformLocation (ballProgram, "col")
val _ = Gles3.useProgram ballProgram
val _ = Gles3.uniform4f (ballUniformLocation, nr, ng, nb, 1.0)
val _ = Gles3.drawArrays
(Gles3.TRIANGLE_FAN (), 0, Vector.length dayVertexData div 2)
val _ =
Gles3.bufferData
( nightVertexData
, Vector.length dayVertexData
, Gles3.DYNAMIC_DRAW ()
)
val _ = Gles3.uniform4f (ballUniformLocation, dr, dg, db, 1.0)
val _ = Gles3.drawArrays
(Gles3.TRIANGLE_FAN (), 0, Vector.length nightVertexData div 2)
in
()
end
end
fun draw (game: game_board) =
(drawBlocks game; drawBalls game)
end