1 | // |
---|
2 | // Monsterz |
---|
3 | // |
---|
4 | // Copyright: (c) 2005-2011 Sam Hocevar <sam@hocevar.net> |
---|
5 | // This program is free software; you can redistribute it and/or |
---|
6 | // modify it under the terms of the Do What The Fuck You Want To |
---|
7 | // Public License, Version 2, as published by Sam Hocevar. See |
---|
8 | // http://sam.zoy.org/projects/COPYING.WTFPL for more details. |
---|
9 | // |
---|
10 | |
---|
11 | #if defined HAVE_CONFIG_H |
---|
12 | # include "config.h" |
---|
13 | #endif |
---|
14 | |
---|
15 | #include <cstdio> |
---|
16 | #include <cmath> |
---|
17 | #include <cstdlib> |
---|
18 | #include <ctime> |
---|
19 | |
---|
20 | #include "core.h" |
---|
21 | #include "board.h" |
---|
22 | #include "piece.h" |
---|
23 | #include "thumbs.h" |
---|
24 | #include "mash.h" |
---|
25 | #include "monsterz.h" |
---|
26 | |
---|
27 | /* |
---|
28 | * Board implementation class |
---|
29 | */ |
---|
30 | |
---|
31 | class BoardData |
---|
32 | { |
---|
33 | friend class Board; |
---|
34 | |
---|
35 | private: |
---|
36 | int2 dim; |
---|
37 | int npieces; |
---|
38 | int board, tiles; |
---|
39 | int click, whip; |
---|
40 | |
---|
41 | struct Pair |
---|
42 | { |
---|
43 | int id; |
---|
44 | Piece *piece; |
---|
45 | } |
---|
46 | pairs[MAX_WIDTH][MAX_HEIGHT], grabbed; |
---|
47 | int nmoves; |
---|
48 | |
---|
49 | Text *scoretext; |
---|
50 | int score; |
---|
51 | |
---|
52 | Mash *mashes; |
---|
53 | Emitter *emitter; |
---|
54 | Thumbs *thumbs; |
---|
55 | int2 src_cell, dst_cell; |
---|
56 | |
---|
57 | int2 oldmouse; |
---|
58 | int3 oldbuttons; |
---|
59 | float nextblink, whipdelay; |
---|
60 | |
---|
61 | enum |
---|
62 | { |
---|
63 | IDLE, |
---|
64 | BADCLICK, |
---|
65 | GRAB, |
---|
66 | } |
---|
67 | state; |
---|
68 | }; |
---|
69 | |
---|
70 | /* |
---|
71 | * Public Board class |
---|
72 | */ |
---|
73 | |
---|
74 | Board::Board(int2 dim, int npieces) |
---|
75 | : data(new BoardData()) |
---|
76 | { |
---|
77 | data->dim = dim; |
---|
78 | data->npieces = npieces; |
---|
79 | data->board = Tiler::Register(PNG_BOARD, 384, 384, 1.0f); |
---|
80 | data->tiles = Tiler::Register(PNG_TILES, 48, 48, 1.0f); |
---|
81 | data->click = Sampler::Register(WAV_CLICK); |
---|
82 | data->whip = Sampler::Register(WAV_WHIP); |
---|
83 | |
---|
84 | data->emitter = new Emitter(data->tiles, float3(0, -0.0006f, 0)); |
---|
85 | Ticker::Ref(data->emitter); |
---|
86 | |
---|
87 | Fill(); |
---|
88 | |
---|
89 | data->mashes = NULL; |
---|
90 | data->nextblink = 0.0f; |
---|
91 | data->whipdelay = 0.0f; |
---|
92 | data->state = BoardData::IDLE; |
---|
93 | |
---|
94 | data->thumbs = new Thumbs(MAX_PIECES); |
---|
95 | Ticker::Ref(data->thumbs); |
---|
96 | |
---|
97 | data->scoretext = new Text(NULL, "monsterz/gfx/font2.png"); |
---|
98 | data->scoretext->SetAlign(Text::ALIGN_RIGHT); |
---|
99 | data->scoretext->SetPos(int3(624, 432, 1)); |
---|
100 | Ticker::Ref(data->scoretext); |
---|
101 | data->score = 0; |
---|
102 | |
---|
103 | position = int3(24, 72, 1); |
---|
104 | bbox[0] = position; |
---|
105 | bbox[1] = bbox[0] + int3(384, 384, 0); |
---|
106 | |
---|
107 | Input::TrackMouse(this); |
---|
108 | } |
---|
109 | |
---|
110 | void Board::TickGame(float deltams) |
---|
111 | { |
---|
112 | Entity::TickGame(deltams); |
---|
113 | |
---|
114 | int3 buttons = Input::GetMouseButtons(); |
---|
115 | |
---|
116 | /* If possible, make a random monster blink */ |
---|
117 | if ((data->nextblink -= deltams) < 0.0f) |
---|
118 | { |
---|
119 | data->pairs[rand() % data->dim.i] |
---|
120 | [rand() % data->dim.j].piece->Blink(); |
---|
121 | data->nextblink = (float)(200 + rand() % 500); |
---|
122 | } |
---|
123 | |
---|
124 | /* Do not whip too often, the sound may become annoying */ |
---|
125 | data->whipdelay -= deltams; |
---|
126 | |
---|
127 | /* Get rid of finished mashes */ |
---|
128 | for (Mash **it = &data->mashes; *it; ) |
---|
129 | { |
---|
130 | if ((*it)->IsDead()) |
---|
131 | { |
---|
132 | Ticker::Unref(*it); |
---|
133 | *it = (*it)->nextmash; |
---|
134 | } |
---|
135 | else |
---|
136 | it = &(*it)->nextmash; |
---|
137 | } |
---|
138 | |
---|
139 | /* Update score */ |
---|
140 | data->scoretext->SetInt(data->score); |
---|
141 | |
---|
142 | switch (data->state) |
---|
143 | { |
---|
144 | case BoardData::IDLE: |
---|
145 | /* Should we start dragging something? */ |
---|
146 | if (buttons[0] && !data->oldbuttons[0] && mousepos.x != -1) |
---|
147 | { |
---|
148 | int2 cell = mousepos / 48; |
---|
149 | if (data->pairs[cell.x][cell.y].piece->Grab(int2(0, 0))) |
---|
150 | { |
---|
151 | Sampler::PlaySample(data->click); |
---|
152 | data->grabbed = data->pairs[cell.x][cell.y]; |
---|
153 | data->src_cell = mousepos / 48; |
---|
154 | data->dst_cell = int2(-1); |
---|
155 | data->state = BoardData::GRAB; |
---|
156 | } |
---|
157 | else |
---|
158 | data->state = BoardData::BADCLICK; |
---|
159 | } |
---|
160 | break; |
---|
161 | case BoardData::GRAB: |
---|
162 | if (mousepos.x != -1) |
---|
163 | { |
---|
164 | /* Mouse is still in the window, keep grabbing */ |
---|
165 | data->grabbed.piece->Grab(mousepos - data->oldmouse); |
---|
166 | int2 cur_pos = data->grabbed.piece->GetPos(); |
---|
167 | int2 cur_cell = (cur_pos + 24) / 48; |
---|
168 | if (cur_cell.i < 0 || cur_cell.i >= data->dim.i |
---|
169 | || cur_cell.j < 0 || cur_cell.j >= data->dim.j |
---|
170 | || (cur_pos - cur_cell * 48).sqlen() > 24 * 24 |
---|
171 | || (cur_cell - data->src_cell).sqlen() != 1) |
---|
172 | cur_cell = int2(-1); |
---|
173 | /* If potential target changed, update our cache. */ |
---|
174 | if (cur_cell != data->dst_cell) |
---|
175 | { |
---|
176 | if (data->whipdelay < 0.0f) |
---|
177 | { |
---|
178 | Sampler::PlaySample(data->whip); |
---|
179 | data->whipdelay = DELAY_WHIP; |
---|
180 | } |
---|
181 | if (data->dst_cell != int2(-1)) |
---|
182 | data->pairs[data->dst_cell.i] |
---|
183 | [data->dst_cell.j].piece->Ungrab(data->dst_cell * 48); |
---|
184 | if (cur_cell != int2(-1)) |
---|
185 | data->pairs[cur_cell.i] |
---|
186 | [cur_cell.j].piece->Ungrab(data->src_cell * 48); |
---|
187 | data->dst_cell = cur_cell; |
---|
188 | } |
---|
189 | } |
---|
190 | if (!buttons[0] || mousepos.x == -1 |
---|
191 | || (data->src_cell * 48 |
---|
192 | - data->grabbed.piece->GetPos()).sqlen() > 100 * 100) |
---|
193 | { |
---|
194 | /* Mouse released, or exited window, or dragged too far. */ |
---|
195 | data->grabbed.piece->Ungrab(data->grabbed.piece->GetCell() * 48); |
---|
196 | if (data->dst_cell != int2(-1)) |
---|
197 | Switch(data->src_cell, data->dst_cell); |
---|
198 | data->state = BoardData::IDLE; |
---|
199 | } |
---|
200 | break; |
---|
201 | case BoardData::BADCLICK: |
---|
202 | if (!buttons[0]) |
---|
203 | data->state = BoardData::IDLE; |
---|
204 | break; |
---|
205 | } |
---|
206 | |
---|
207 | data->oldmouse = mousepos; |
---|
208 | data->oldbuttons = buttons; |
---|
209 | } |
---|
210 | |
---|
211 | void Board::TickDraw(float deltams) |
---|
212 | { |
---|
213 | Entity::TickDraw(deltams); |
---|
214 | |
---|
215 | Scene::GetDefault()->AddTile((data->board << 16) | 0, |
---|
216 | position.x, position.y, 1, 0); |
---|
217 | } |
---|
218 | |
---|
219 | /* Fill the board with an initial position. We ensure no pieces are |
---|
220 | * aligned and at least one move is possible. */ |
---|
221 | void Board::Fill() |
---|
222 | { |
---|
223 | srand(rand() ^ time(NULL)); |
---|
224 | |
---|
225 | int list[MAX_WIDTH][MAX_HEIGHT]; |
---|
226 | do |
---|
227 | { |
---|
228 | for (int j = 0; j < data->dim.j; j++) |
---|
229 | for (int i = 0; i < data->dim.i; i++) |
---|
230 | data->pairs[i][j].id = 1 + rand() % data->npieces; |
---|
231 | } while (ListMashes(list) || !(data->nmoves = ListMoves(list))); |
---|
232 | |
---|
233 | /* Spawn pieces */ |
---|
234 | for (int j = 0; j < data->dim.j; j++) |
---|
235 | for (int i = 0; i < data->dim.i; i++) |
---|
236 | { |
---|
237 | int2 newpos = int2(i, j + data->dim.j) * 48; |
---|
238 | int id = 80 + 20 * data->pairs[i][j].id; |
---|
239 | data->pairs[i][j].piece = new Piece(data->emitter, int2(i, j), id); |
---|
240 | data->pairs[i][j].piece->SetPos(newpos); |
---|
241 | data->pairs[i][j].piece->Move(int2(i, j) * 48); |
---|
242 | if (j) |
---|
243 | data->pairs[i][j].piece->SetBelow(data->pairs[i][j - 1].piece); |
---|
244 | Ticker::Ref(data->pairs[i][j].piece); |
---|
245 | } |
---|
246 | } |
---|
247 | |
---|
248 | void Board::Switch(int2 cell_a, int2 cell_b) |
---|
249 | { |
---|
250 | BoardData::Pair a = data->pairs[cell_a.i][cell_a.j]; |
---|
251 | BoardData::Pair b = data->pairs[cell_b.i][cell_b.j]; |
---|
252 | data->pairs[cell_a.i][cell_a.j] = b; |
---|
253 | data->pairs[cell_b.i][cell_b.j] = a; |
---|
254 | |
---|
255 | /* Check whether this is a valid move by testing all patterns. |
---|
256 | * If the move is invalid, cancel the swap and bail out */ |
---|
257 | int list[MAX_WIDTH][MAX_HEIGHT]; |
---|
258 | |
---|
259 | if (!ListMashes(list)) |
---|
260 | { |
---|
261 | data->pairs[cell_a.i][cell_a.j] = a; |
---|
262 | data->pairs[cell_b.i][cell_b.j] = b; |
---|
263 | a.piece->Ungrab(cell_a * 48); |
---|
264 | b.piece->Ungrab(cell_b * 48); |
---|
265 | return; |
---|
266 | } |
---|
267 | |
---|
268 | /* Perform the swap */ |
---|
269 | a.piece->SetCell(cell_b); |
---|
270 | a.piece->Ungrab(cell_b * 48); |
---|
271 | b.piece->SetCell(cell_a); |
---|
272 | b.piece->Ungrab(cell_a * 48); |
---|
273 | |
---|
274 | /* Swap above and below cells */ |
---|
275 | if (cell_a.i == cell_b.i) |
---|
276 | { |
---|
277 | Piece *tmpa = a.piece->GetAbove(); |
---|
278 | Piece *tmpb = b.piece->GetAbove(); |
---|
279 | if (tmpb == a.piece) |
---|
280 | { |
---|
281 | tmpb = b.piece->GetBelow(); |
---|
282 | b.piece->SetAbove(tmpa); |
---|
283 | b.piece->SetBelow(a.piece); |
---|
284 | a.piece->SetBelow(tmpb); |
---|
285 | } |
---|
286 | else /* tmpa == b.piece */ |
---|
287 | { |
---|
288 | tmpa = a.piece->GetBelow(); |
---|
289 | a.piece->SetAbove(tmpb); |
---|
290 | a.piece->SetBelow(b.piece); |
---|
291 | b.piece->SetBelow(tmpa); |
---|
292 | } |
---|
293 | } |
---|
294 | else |
---|
295 | { |
---|
296 | Piece *tmpa = a.piece->GetAbove(); |
---|
297 | Piece *tmpb = b.piece->GetAbove(); |
---|
298 | a.piece->SetAbove(tmpb); |
---|
299 | b.piece->SetAbove(tmpa); |
---|
300 | tmpa = a.piece->GetBelow(); |
---|
301 | tmpb = b.piece->GetBelow(); |
---|
302 | a.piece->SetBelow(tmpb); |
---|
303 | b.piece->SetBelow(tmpa); |
---|
304 | } |
---|
305 | |
---|
306 | /* Remove matching pieces and store them in Mash objects */ |
---|
307 | do |
---|
308 | { |
---|
309 | Mash *mash = new Mash(data->emitter); |
---|
310 | Ticker::Ref(mash); |
---|
311 | |
---|
312 | for (int j = data->dim.j; j--;) for (int i = 0; i < data->dim.i; i++) |
---|
313 | { |
---|
314 | if (!list[i][j]) |
---|
315 | continue; |
---|
316 | |
---|
317 | /* The mash becomes the new owner of the disappearing piece */ |
---|
318 | mash->AddPiece(data->pairs[i][j].piece); |
---|
319 | data->thumbs->AddCount(data->pairs[i][j].id, 1); |
---|
320 | |
---|
321 | #if 0 // Test for piece creation |
---|
322 | if (list[i][j] >= 2) |
---|
323 | { |
---|
324 | Piece *old = data->pairs[i][j].piece; |
---|
325 | int id = 1 + rand() % data->npieces; |
---|
326 | data->pairs[i][j].id = id; |
---|
327 | data->pairs[i][j].piece = new Piece(data->emitter, int2(i, j), 80 + 20 * id); |
---|
328 | data->pairs[i][j].piece->SetBelow(old->GetBelow()); |
---|
329 | data->pairs[i][j].piece->SetAbove(old->GetAbove()); |
---|
330 | Ticker::Ref(data->pieces[i][j].piece); |
---|
331 | list[i][j] = 0; |
---|
332 | } |
---|
333 | else |
---|
334 | #endif |
---|
335 | { |
---|
336 | Piece *below = data->pairs[i][data->dim.j - 1].piece; |
---|
337 | |
---|
338 | /* Change coordinates for the whole column above */ |
---|
339 | for (int j2 = j + 1; j2 < data->dim.j; j2++) |
---|
340 | { |
---|
341 | data->pairs[i][j2 - 1] = data->pairs[i][j2]; |
---|
342 | data->pairs[i][j2 - 1].piece->SetCell(int2(i, j2 - 1)); |
---|
343 | data->pairs[i][j2 - 1].piece->Move(int2(i, j2 - 1) * 48); |
---|
344 | list[i][j2 - 1] = list[i][j2]; |
---|
345 | } |
---|
346 | |
---|
347 | /* Spawn a new piece above all the others and attach it to |
---|
348 | * the board. */ |
---|
349 | int2 newpos = int2(i * 48, below->GetPos().y + 48); |
---|
350 | int2 newcell = int2(i, data->dim.j - 1); |
---|
351 | int id = 1 + rand() % data->npieces; |
---|
352 | Piece *tmp = new Piece(data->emitter, newcell, 80 + 20 * id); |
---|
353 | tmp->SetBelow(below); |
---|
354 | tmp->SetPos(newpos); |
---|
355 | tmp->Move(newcell * 48); |
---|
356 | Ticker::Ref(tmp); |
---|
357 | data->pairs[i][data->dim.j - 1].id = id; |
---|
358 | data->pairs[i][data->dim.j - 1].piece = tmp; |
---|
359 | list[i][data->dim.j - 1] = 0; |
---|
360 | } |
---|
361 | } |
---|
362 | |
---|
363 | mash->nextmash = data->mashes; |
---|
364 | data->mashes = mash; |
---|
365 | } |
---|
366 | while(ListMashes(list)); |
---|
367 | |
---|
368 | data->nmoves = ListMoves(list); |
---|
369 | |
---|
370 | if (data->nmoves == 0) |
---|
371 | { |
---|
372 | Mash *mash = new Mash(data->emitter); |
---|
373 | Ticker::Ref(mash); |
---|
374 | |
---|
375 | for (int j = data->dim.j; j--;) for (int i = 0; i < data->dim.i; i++) |
---|
376 | mash->AddPiece(data->pairs[i][j].piece); |
---|
377 | |
---|
378 | mash->nextmash = data->mashes; |
---|
379 | data->mashes = mash; |
---|
380 | |
---|
381 | Piece *below[MAX_WIDTH]; |
---|
382 | for (int i = 0; i < data->dim.i; i++) |
---|
383 | below[i] = data->pairs[i][data->dim.j - 1].piece; |
---|
384 | |
---|
385 | Fill(); |
---|
386 | |
---|
387 | for (int i = 0; i < data->dim.i; i++) |
---|
388 | data->pairs[i][0].piece->SetBelow(below[i]); |
---|
389 | } |
---|
390 | } |
---|
391 | |
---|
392 | /* Fill an array with the list of pieces that should disappear due to |
---|
393 | * 3-piece or more alignments. */ |
---|
394 | int Board::ListMashes(int list[MAX_WIDTH][MAX_HEIGHT]) |
---|
395 | { |
---|
396 | int ret = 0; |
---|
397 | |
---|
398 | for (int j = 0; j < data->dim.j; j++) |
---|
399 | for (int i = 0; i < data->dim.i; i++) |
---|
400 | list[i][j] = 0; |
---|
401 | |
---|
402 | for (int j = 0; j < data->dim.j; j++) |
---|
403 | for (int i = 0; i < data->dim.i; i++) |
---|
404 | { |
---|
405 | int id = data->pairs[i][j].id; |
---|
406 | |
---|
407 | if (i + 2 < data->dim.i && data->pairs[i + 1][j].id == id |
---|
408 | && data->pairs[i + 2][j].id == id) |
---|
409 | { |
---|
410 | list[i][j]++; |
---|
411 | list[i + 1][j] += 2; |
---|
412 | list[i + 2][j]++; |
---|
413 | ret = 1; |
---|
414 | } |
---|
415 | |
---|
416 | if (j + 2 < data->dim.j && data->pairs[i][j + 1].id == id |
---|
417 | && data->pairs[i][j + 2].id == id) |
---|
418 | { |
---|
419 | list[i][j]++; |
---|
420 | list[i][j + 1] += 2; |
---|
421 | list[i][j + 2]++; |
---|
422 | ret = 1; |
---|
423 | } |
---|
424 | } |
---|
425 | |
---|
426 | return ret; |
---|
427 | } |
---|
428 | |
---|
429 | /* Fill an array with the list of pieces that can be moved. A value of 1 |
---|
430 | * indicates the piece can be moved right. A value of 2 means it can be |
---|
431 | * moved up, and a value of 3 means both moves are possible. The number |
---|
432 | * of possible moves is returned. */ |
---|
433 | int Board::ListMoves(int moves[MAX_WIDTH][MAX_HEIGHT]) |
---|
434 | { |
---|
435 | int ret = 0; |
---|
436 | |
---|
437 | for (int j = 0; j < data->dim.j; j++) |
---|
438 | for (int i = 0; i < data->dim.i; i++) |
---|
439 | moves[i][j] = 0; |
---|
440 | |
---|
441 | for (int j = 0; j < data->dim.j; j++) |
---|
442 | for (int i = 0; i < data->dim.i; i++) |
---|
443 | { |
---|
444 | /* Copy neighbourhood to a local buffer */ |
---|
445 | int tmp[6][6]; |
---|
446 | |
---|
447 | for (int dj = -2; dj <= 3; dj++) |
---|
448 | for (int di = -2; di <= 3; di++) |
---|
449 | if (j + dj >= 0 && j + dj < data->dim.j |
---|
450 | && i + di >= 0 && i + di < data->dim.i) |
---|
451 | tmp[2 + di][2 + dj] = data->pairs[i + di][j + dj].id; |
---|
452 | else |
---|
453 | tmp[2 + di][2 + dj] = 0; |
---|
454 | |
---|
455 | /* +--+--+--+--+--+--+ |
---|
456 | * | | |25| | | | |
---|
457 | * +--+--+--+--+--+--+ |
---|
458 | * | | |24|34| | | |
---|
459 | * +--+--+--+--+--+--+ |
---|
460 | * |03|13|c |33|43| | |
---|
461 | * +--+--+--+--+--+--+ |
---|
462 | * |02|12|a |b |42|52| |
---|
463 | * +--+--+--+--+--+--+ |
---|
464 | * | |11|21|31| | | |
---|
465 | * +--+--+--+--+--+--+ |
---|
466 | * | | |20|30| | | |
---|
467 | * +--+--+--+--+--+--+ */ |
---|
468 | int a = tmp[2][2]; |
---|
469 | int b = tmp[3][2] ? tmp[3][2] : -1; |
---|
470 | int c = tmp[2][3] ? tmp[2][3] : -1; |
---|
471 | |
---|
472 | /* Try moving right */ |
---|
473 | if ((a == tmp[3][0] && a == tmp[3][1]) || |
---|
474 | (a == tmp[3][1] && a == tmp[3][3]) || |
---|
475 | (a == tmp[3][3] && a == tmp[3][4]) || |
---|
476 | (a == tmp[4][2] && a == tmp[5][2]) || |
---|
477 | (b == tmp[2][0] && b == tmp[2][1]) || |
---|
478 | (b == tmp[2][1] && b == tmp[2][3]) || |
---|
479 | (b == tmp[2][3] && b == tmp[2][4]) || |
---|
480 | (b == tmp[0][2] && b == tmp[1][2])) |
---|
481 | { |
---|
482 | moves[i][j] |= 1; |
---|
483 | ret++; |
---|
484 | } |
---|
485 | |
---|
486 | /* Try moving up */ |
---|
487 | if ((a == tmp[0][3] && a == tmp[1][3]) || |
---|
488 | (a == tmp[1][3] && a == tmp[3][3]) || |
---|
489 | (a == tmp[3][3] && a == tmp[4][3]) || |
---|
490 | (a == tmp[2][4] && a == tmp[2][5]) || |
---|
491 | (c == tmp[0][2] && c == tmp[1][2]) || |
---|
492 | (c == tmp[1][2] && c == tmp[3][2]) || |
---|
493 | (c == tmp[3][2] && c == tmp[4][2]) || |
---|
494 | (c == tmp[2][0] && c == tmp[2][1])) |
---|
495 | { |
---|
496 | moves[i][j] |= 2; |
---|
497 | ret++; |
---|
498 | } |
---|
499 | } |
---|
500 | |
---|
501 | return ret; |
---|
502 | } |
---|
503 | |
---|
504 | Board::~Board() |
---|
505 | { |
---|
506 | Input::UntrackMouse(this); |
---|
507 | |
---|
508 | for (int j = 0; j < data->dim.j; j++) |
---|
509 | for (int i = 0; i < data->dim.i; i++) |
---|
510 | { |
---|
511 | data->pairs[i][j].piece->SetBelow(NULL); |
---|
512 | Ticker::Unref(data->pairs[i][j].piece); |
---|
513 | } |
---|
514 | Ticker::Unref(data->thumbs); |
---|
515 | Ticker::Unref(data->scoretext); |
---|
516 | while (data->mashes) |
---|
517 | { |
---|
518 | Ticker::Unref(data->mashes); |
---|
519 | data->mashes = data->mashes->nextmash; |
---|
520 | } |
---|
521 | /* FIXME: the emitter may be destroyed after the Tiler is removed, |
---|
522 | * because the last Tiler tick may be done just after the emitter |
---|
523 | * scheduled its sprites! */ |
---|
524 | Ticker::Unref(data->emitter); |
---|
525 | Tiler::Deregister(data->board); |
---|
526 | Tiler::Deregister(data->tiles); |
---|
527 | Sampler::Deregister(data->click); |
---|
528 | Sampler::Deregister(data->whip); |
---|
529 | delete data; |
---|
530 | } |
---|
531 | |
---|