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 }