-
Notifications
You must be signed in to change notification settings - Fork 1
/
GUI.oz
337 lines (309 loc) · 11.3 KB
/
GUI.oz
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
functor
import
QTk at 'x-oz://system/wp/QTk.ozf'
Input
Browser
Projet2019util
System
export
portWindow:StartWindow
windowBuilt:WindowBuilt
define
WindowBuilt
StartWindow
TreatStream
InitPlayer
UpdateValue
BuildWindow
Squares
Items
DrawMap
PrepareMap
Spawn
Hide
Move
ApplyTo
ApplyToHandle
ApplyToHandle2
StateModification
% Images definition :
ObsiWall = {QTk.newImage photo(file:'./img/obsidian.gif' height:50 width:50)}
Chest = {QTk.newImage photo(file:'./img/normalchest.gif' height:30 width:30)}
SpecialChest = {QTk.newImage photo(file:'./img/netherchest.gif' height:30 width:30)}
PointIcon = {QTk.newImage photo(file:'./img/gold.gif' height:30 width:30)}
BonusIcon = {QTk.newImage photo(file:'./img/diamond.gif' height:30 width:30)}
Grass = {QTk.newImage photo(file:'./img/grass.gif' height:50 width:50)}
Glass = {QTk.newImage photo(file:'./img/glass.gif' height:50 width:50)}
BombIcon = {QTk.newImage photo(file:'./img/creeper.gif' height:30 width:30)}
Lava = {QTk.newImage photo(file:'./img/lava.gif' height:30 width:30)}
in
%%%%% Build the initial window and set it up (call only once)
fun{BuildWindow}
Grid GridLife GridScore Toolbar Desc DescLife DescScore Window GridItems
in
Toolbar=lr(glue:we tbbutton(text:"Quit" glue:w action:toplevel#close))
Desc=grid(handle:Grid height:50*Input.nbRow width:50*Input.nbColumn)
DescLife=grid(handle:GridLife height:100 width:50*Input.nbBombers)
DescScore=grid(handle:GridScore height:100 width:50*Input.nbBombers)
Window={QTk.build td(Toolbar Desc DescLife DescScore)}
{Window show}
% configure rows and set headers
for N in 1..Input.nbRow do
{Grid rowconfigure(N minsize:50 weight:0 pad:5)}
end
% configure columns and set headers
for N in 1..Input.nbColumn do
{Grid columnconfigure(N minsize:50 weight:0 pad:5)}
end
% configure lifeboard
{GridLife rowconfigure(1 minsize:50 weight:0 pad:5)}
{GridLife columnconfigure(1 minsize:50 weight:0 pad:5)}
{GridLife configure(label(text:"life" width:1 height:1) row:1 column:1 sticky:wesn)}
for N in 1..(Input.nbBombers) do
{GridLife columnconfigure(N+1 minsize:50 weight:0 pad:5)}
end
% configure scoreboard
{GridScore rowconfigure(1 minsize:50 weight:0 pad:5)}
{GridScore columnconfigure(1 minsize:50 weight:0 pad:5)}
{GridScore configure(label(text:"score" width:1 height:1) row:1 column:1 sticky:wesn)}
for N in 1..(Input.nbBombers) do
{GridScore columnconfigure(N+1 minsize:50 weight:0 pad:5)}
end
{DrawMap Grid}
GridItems = {PrepareMap Grid}
% Here the map was built so we bind the value to let Main.oz know that the game can start
WindowBuilt = true
handle(grid:Grid items:GridItems life:GridLife score:GridScore)
end
%%%%% Squares of path and wall
Squares = square(0:label(image:Grass width:1 height:1 bg:c(0 204 120))
1:label(image:ObsiWall borderwidth:5 relief:raised width:1 height:1 bg:c(0 0 0))
2:label(image:Grass width:1 height:1 bg:c(0 204 0))
3:label(image:Grass width:1 height:1 bg:c(0 204 0))
4:label(image:Glass width:1 height:1 bg:c(255 255 255))
)
Items = items(boxpoint:fun{$ Handle} label(image:Chest borderwidth:2 relief:raised width:30 height:30 bg:c(139 69 19) handle:Handle) end
boxbonus:fun{$ Handle} label(image:SpecialChest borderwidth:2 relief:raised width:30 height:30 bg:c(210 105 30) handle:Handle) end
point:fun{$ Handle} label(image:PointIcon height:30 width:30 handle:Handle bg:green) end
bonus:fun{$ Handle} label(image:BonusIcon height:30 width:30 handle:Handle bg:green) end
bomb:fun{$ Handle} label(image:BombIcon height:30 width:30 handle:Handle bg:black) end
fire:fun{$ Handle} label(image:Lava height:30 width:30 handle:Handle bg:green) end
)
%%%%% Function to draw the map
proc{DrawMap Grid}
proc{DrawColumn Column M N}
case Column
of nil then skip
[] T|End then
{Grid configure(Squares.T row:M column:N sticky:wesn)}
{DrawColumn End M N+1}
end
end
proc{DrawRow Row M}
case Row
of nil then skip
[] T|End then
{DrawColumn T M 1}
{DrawRow End M+1}
end
end
in
{DrawRow Input.map 1}
end
fun{PrepareMap GridHandle}
Res
proc{CreateRemove Label Row Col Remove}
{GridHandle configure(Label row:Row column:Col)}
if (Remove) then
{GridHandle remove(Label.handle)}
else
{Label.handle 'raise'()}
end
end
proc{PrepareColumn Column M N}
case Column
of nil then skip
[] 0|End then BombH FireH in
{CreateRemove {Items.bomb BombH} M N true}
{CreateRemove {Items.fire FireH} M N true}
Res.M.N = items(box:null bonus:null point:null bomb:BombH fire:FireH)
{PrepareColumn End M N+1}
[] 1|End then
Res.M.N = items(box:null bonus:null point:null bomb:null fire:null)
{PrepareColumn End M N+1}
[] 2|End then BoxH PointH BombH FireH in
{CreateRemove {Items.boxpoint BoxH} M N false}
{CreateRemove {Items.point PointH} M N true}
{CreateRemove {Items.bomb BombH} M N true}
{CreateRemove {Items.fire FireH} M N true}
Res.M.N = items(box:BoxH bonus:null point:PointH bomb:BombH fire:FireH)
{PrepareColumn End M N+1}
[] 3|End then BoxH BonusH BombH FireH in
{CreateRemove {Items.boxbonus BoxH} M N false}
{CreateRemove {Items.bonus BonusH} M N true}
{CreateRemove {Items.bomb BombH} M N true}
{CreateRemove {Items.fire FireH} M N true}
Res.M.N = items(box:BoxH bonus:BonusH point:null bomb:BombH fire:FireH)
{PrepareColumn End M N+1}
[] 4|End then BombH FireH in
{CreateRemove {Items.bomb BombH} M N true}
{CreateRemove {Items.fire FireH} M N true}
Res.M.N = items(box:null bonus:null point:null bomb:BombH fire:FireH)
{PrepareColumn End M N+1}
end
end
proc{PrepareRow Row M}
case Row
of nil then skip
[] T|End then
Res.M = {Tuple.make items Input.nbColumn}
{PrepareColumn T M 1}
{PrepareRow End M+1}
end
end
in
Res = {Tuple.make items Input.nbRow}
{PrepareRow Input.map 1}
Res
end
%%%%% Init the Player
fun{InitPlayer Grid ID}
Handle HandleLife HandleScore Id Color LabelPlayer LabelLife LabelScore
in
bomber(id:Id color:Color name:_) = ID
LabelPlayer = label(text:"P" handle:Handle borderwidth:5 relief:raised bg:Color ipadx:4 ipady:4)
LabelLife = label(text:Input.nbLives borderwidth:5 handle:HandleLife relief:solid bg:Color ipadx:5 ipady:5)
LabelScore = label(text:0 borderwidth:5 handle:HandleScore relief:solid bg:Color ipadx:5 ipady:5)
{Grid.grid configure(LabelPlayer row:0 column:0 sticky:wesn)}
{Grid.grid remove(Handle)}
{Grid.life configure(LabelLife row:1 column:Id+1 sticky:wesn)}
{Grid.score configure(LabelScore row:1 column:Id+1 sticky:wesn)}
{HandleLife 'raise'()}
{HandleScore 'raise'()}
guiPlayer(id:ID life:HandleLife score:HandleScore player:Handle)
end
proc{UpdateValue Handle Life}
{Handle set(Life)}
end
proc{ApplyTo Grid Pos Label Fun}
Row Col Square
in
Pos = pt(x:Col y:Row)
Square = Grid.items.Row.Col.Label
if (Square \= null) then
{Fun Grid Square Row Col}
end
end
proc{ApplyToHandle Grid Handle Pos Fun}
Row Col
in
Pos = pt(x:Col y:Row)
{System.show 'GUI : Before Fun Grid Handle Row Col'}
{Fun Grid Handle Row Col}
{System.show 'GUI : After Fun Grid Handle Row Col'}
end
proc{ApplyToHandle2 Grid Handle Fun}
{Fun Grid Handle _ _}
end
proc{Spawn Grid Handle Row Col}
{Grid.grid configure(Handle row:Row column:Col)}
{Handle 'raise'()}
end
proc{Hide Grid Handle Row Col}
{Grid.grid remove(Handle)}
end
proc{Move Grid Handle Row Col}
{Hide Grid Handle Row Col}
{Spawn Grid Handle Row Col}
end
fun{StateModification Grid Wanted State Fun}
case State
of nil then nil
[] guiPlayer(id:ID life:_ score:_ player:_)|Next then
if (ID == Wanted) then
{Fun Grid State.1}|Next
else
State.1|{StateModification Grid Wanted Next Fun}
end
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
fun{StartWindow}
Stream
OutputStream
Port
in
{NewPort Stream Port}
thread
OutputStream = {Projet2019util.portWindowChecker Stream}
end
thread
{TreatStream OutputStream nil nil}
end
Port
end
proc{TreatStream Stream Grid Players}
{Browser.browse Stream.1}
case Stream
of nil then skip
[] H|T then
{System.show 'GUI : TreatStream : H : '#H}
case H
of buildWindow then NewGrid in
NewGrid = {BuildWindow}
{TreatStream T NewGrid {Tuple.make players Input.nbBombers}}
[] initPlayer(ID) then
Players.(ID.id) = {InitPlayer Grid ID}
{TreatStream T Grid Players}
[] spawnPlayer(ID Pos) then
{ApplyToHandle Grid Players.(ID.id).player Pos Spawn}
{TreatStream T Grid Players}
[] movePlayer(ID Pos) then
{ApplyToHandle Grid Players.(ID.id).player Pos Move}
{TreatStream T Grid Players}
[] hidePlayer(ID) then
{ApplyToHandle2 Grid Players.(ID.id).player Hide}
{TreatStream T Grid Players}
[] lifeUpdate(ID Life) then
{UpdateValue Players.(ID.id).life Life}
{TreatStream T Grid Players}
[] scoreUpdate(ID Score) then
{UpdateValue Players.(ID.id).score Score}
{TreatStream T Grid Players}
[] spawnBonus(Pos) then
{ApplyTo Grid Pos bonus Spawn}
{TreatStream T Grid Players}
[] hideBonus(Pos) then
{ApplyTo Grid Pos bonus Hide}
{TreatStream T Grid Players}
[] spawnPoint(Pos) then
{ApplyTo Grid Pos point Spawn}
{TreatStream T Grid Players}
[] hidePoint(Pos) then
{ApplyTo Grid Pos point Hide}
{TreatStream T Grid Players}
[] spawnFire(Pos) then
{ApplyTo Grid Pos fire Spawn}
{TreatStream T Grid Players}
[] hideFire(Pos) then
{ApplyTo Grid Pos fire Hide}
{TreatStream T Grid Players}
[] spawnBomb(Pos) then
{ApplyTo Grid Pos bomb Spawn}
{TreatStream T Grid Players}
[] hideBomb(Pos) then
{ApplyTo Grid Pos bomb Hide}
{TreatStream T Grid Players}
[] hideBox(Pos) then
{ApplyTo Grid Pos box Hide}
{TreatStream T Grid Players}
[] displayWinner(ID) then
{Browser.browse 'the winner is '#ID}
{TreatStream T Grid Players}
else
{Browser.browse 'unsupported message'#H}
{TreatStream T Grid Players}
end
end
end
end