Mercurial > hg > index.fcgi > lj > lj046
comparison src/explode.c @ 0:c84446dfb3f5
initial add
author | paulo@localhost |
---|---|
date | Fri, 13 Mar 2009 00:39:12 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f9ab8104807b |
---|---|
1 /* | |
2 Bombl*ss extension for LOCKJAW Tetromino Game | |
3 Copr. 2007 Damian Yerrick | |
4 | |
5 */ | |
6 | |
7 | |
8 /* | |
9 | |
10 During falling, the auxiliary playfield p->c[][] contains a map of | |
11 individual regions used by the falling code. But during explosion, | |
12 it serves a different purpose: counting the number of frames before | |
13 a given block is erased. | |
14 | |
15 */ | |
16 | |
17 const char explodeWidth[nLines] = { | |
18 4, // megabomb | |
19 3, 3, 3, 3, 4, 5, 5, 6, 6, 7 // 1-10 lines | |
20 }; | |
21 const char explodeHeight[nLines] = { | |
22 3, // megabomb | |
23 0, 1, 2, 3, 4, 5, 5, 6, 6, 7 // 1-10 lines | |
24 }; | |
25 | |
26 | |
27 /** | |
28 * Sets the number of frames before a block is erased based on | |
29 * the explosion. | |
30 * @param p the playfield | |
31 * @param x the column where the bomb is centered | |
32 * @param y the row where the bomb is centered | |
33 * @param bombColor the color of the bomb | |
34 * @param nLines the number of lines cleared, which determines the explosion size | |
35 */ | |
36 void explodeAt(LJField *p, int x, int y, int bombColor, int nLines) { | |
37 int boom = nLines; | |
38 | |
39 if ((bombColor & COLOR_MASK) == BOMBCOLOR_SQUARE) { | |
40 boom = 4; | |
41 } else if (boom > 10) { | |
42 boom = 10; | |
43 } | |
44 | |
45 int boomLeft = x - explodeWidth[boom]; | |
46 if (boomLeft < p->leftWall) { | |
47 boomLeft = p->leftWall; | |
48 } | |
49 int boomRight = x + explodeWidth[boom]; | |
50 if (boomRight > p->rightWall - 1) { | |
51 boomLeft = p->rightWall - 1; | |
52 } | |
53 int boomBottom = y - explodeHeight[boom]; | |
54 if (boomLeft < 0) { | |
55 boomLeft = 0; | |
56 } | |
57 int boomTop = y + explodeHeight[boom]; | |
58 if (boomRight > LJ_PF_HT - 1) { | |
59 boomLeft = LJ_PF_HT - 1; | |
60 } | |
61 | |
62 for (by = boomBottom; bx < boomTop; ++bx) { | |
63 int dy = y - by; | |
64 int dy2 = dy * dy; | |
65 for (bx = boomLeft; bx < boomRight; ++bx) { | |
66 int dx = x - bx; | |
67 int dx2 = dx * dx; | |
68 unsigned int time = (dx2 + dy2) / EXPLODE_SPEED + 2; | |
69 if (p->c[y][x] > time) { | |
70 p->c[y][x] = time; | |
71 } | |
72 } | |
73 } | |
74 } | |
75 | |
76 static int blockIsBomb(unsigned int blk) { | |
77 return (blk & COLOR_MASK) == BOMBCOLOR_NORMAL | |
78 || (blk & COLOR_MASK) == BOMBCOLOR_SQUARE; | |
79 } | |
80 | |
81 /** | |
82 * Scans the exploding areas, erases blocks, and sets up bombs to explode. | |
83 * @param p the playfield | |
84 * @return the rows that were changed | |
85 */ | |
86 LJBits explodeFrame(LJField *p) { | |
87 LJBits changedRows = 0; | |
88 LJBits changeAny = 0; | |
89 | |
90 int nLines = countRows(p->tempRows); | |
91 | |
92 // first pass: destruction | |
93 for (int y = 0; y < LJ_PF_HT; ++y) { | |
94 for (int x = p->leftWall; x < p->rightWall; ++x) { | |
95 if (p->c[y][x] == 1) { | |
96 unsigned int blk = p->b[y][x]; | |
97 | |
98 if (blk) { | |
99 changedRows |= 1 << y; | |
100 p->b[y][x] = 0; | |
101 if (blockIsBomb(blk)) { | |
102 explodeAt(p, x, y, blk, nLines); | |
103 } | |
104 } | |
105 } | |
106 } | |
107 } | |
108 | |
109 // second pass: countdown timer per block | |
110 for (int y = 0; y < LJ_PF_HT; ++y) { | |
111 for (int x = p->leftWall; x < p->rightWall; ++x) { | |
112 if (p->c[y][x] > 0) { | |
113 --p->c[y][x] > 0; | |
114 changeAny = 1; | |
115 } | |
116 } | |
117 } | |
118 | |
119 return changeAny ? (1 << (LJ_PF_HT - 1)) : changedRows; | |
120 } | |
121 | |
122 /** | |
123 * Scans the cleared lines for bombs and marks c[] to trigger them. | |
124 * @param p the playfield, where tempRows holds the cleared lines | |
125 * @return the rows where bombs were triggered | |
126 */ | |
127 LJBits triggerBombs(LJField *p) { | |
128 LJBits bombRows = 0; | |
129 | |
130 for (int y = 0; y < LJ_PF_HT; ++y) { | |
131 if (p->tempRows & (1 << y)) { | |
132 for (int x = p->leftWall; x < p->rightWall; ++x) { | |
133 bool isBomb = blockIsBomb(p->b[y][x]); | |
134 p->c[y][x] = isBomb; | |
135 if (isBomb) { | |
136 bombRows |= 1 << y; | |
137 } | |
138 } | |
139 } | |
140 } | |
141 return bombRows; | |
142 } |