Mercurial > hg > index.fcgi > lj > lj046
diff src/explode.c @ 0:c84446dfb3f5
initial add
author | paulo@localhost |
---|---|
date | Fri, 13 Mar 2009 00:39:12 -0700 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/explode.c Fri Mar 13 00:39:12 2009 -0700 1.3 @@ -0,0 +1,142 @@ 1.4 +/* 1.5 +Bombl*ss extension for LOCKJAW Tetromino Game 1.6 +Copr. 2007 Damian Yerrick 1.7 + 1.8 +*/ 1.9 + 1.10 + 1.11 +/* 1.12 + 1.13 +During falling, the auxiliary playfield p->c[][] contains a map of 1.14 +individual regions used by the falling code. But during explosion, 1.15 +it serves a different purpose: counting the number of frames before 1.16 +a given block is erased. 1.17 + 1.18 +*/ 1.19 + 1.20 +const char explodeWidth[nLines] = { 1.21 + 4, // megabomb 1.22 + 3, 3, 3, 3, 4, 5, 5, 6, 6, 7 // 1-10 lines 1.23 +}; 1.24 +const char explodeHeight[nLines] = { 1.25 + 3, // megabomb 1.26 + 0, 1, 2, 3, 4, 5, 5, 6, 6, 7 // 1-10 lines 1.27 +}; 1.28 + 1.29 + 1.30 +/** 1.31 + * Sets the number of frames before a block is erased based on 1.32 + * the explosion. 1.33 + * @param p the playfield 1.34 + * @param x the column where the bomb is centered 1.35 + * @param y the row where the bomb is centered 1.36 + * @param bombColor the color of the bomb 1.37 + * @param nLines the number of lines cleared, which determines the explosion size 1.38 + */ 1.39 +void explodeAt(LJField *p, int x, int y, int bombColor, int nLines) { 1.40 + int boom = nLines; 1.41 + 1.42 + if ((bombColor & COLOR_MASK) == BOMBCOLOR_SQUARE) { 1.43 + boom = 4; 1.44 + } else if (boom > 10) { 1.45 + boom = 10; 1.46 + } 1.47 + 1.48 + int boomLeft = x - explodeWidth[boom]; 1.49 + if (boomLeft < p->leftWall) { 1.50 + boomLeft = p->leftWall; 1.51 + } 1.52 + int boomRight = x + explodeWidth[boom]; 1.53 + if (boomRight > p->rightWall - 1) { 1.54 + boomLeft = p->rightWall - 1; 1.55 + } 1.56 + int boomBottom = y - explodeHeight[boom]; 1.57 + if (boomLeft < 0) { 1.58 + boomLeft = 0; 1.59 + } 1.60 + int boomTop = y + explodeHeight[boom]; 1.61 + if (boomRight > LJ_PF_HT - 1) { 1.62 + boomLeft = LJ_PF_HT - 1; 1.63 + } 1.64 + 1.65 + for (by = boomBottom; bx < boomTop; ++bx) { 1.66 + int dy = y - by; 1.67 + int dy2 = dy * dy; 1.68 + for (bx = boomLeft; bx < boomRight; ++bx) { 1.69 + int dx = x - bx; 1.70 + int dx2 = dx * dx; 1.71 + unsigned int time = (dx2 + dy2) / EXPLODE_SPEED + 2; 1.72 + if (p->c[y][x] > time) { 1.73 + p->c[y][x] = time; 1.74 + } 1.75 + } 1.76 + } 1.77 +} 1.78 + 1.79 +static int blockIsBomb(unsigned int blk) { 1.80 + return (blk & COLOR_MASK) == BOMBCOLOR_NORMAL 1.81 + || (blk & COLOR_MASK) == BOMBCOLOR_SQUARE; 1.82 +} 1.83 + 1.84 +/** 1.85 + * Scans the exploding areas, erases blocks, and sets up bombs to explode. 1.86 + * @param p the playfield 1.87 + * @return the rows that were changed 1.88 + */ 1.89 +LJBits explodeFrame(LJField *p) { 1.90 + LJBits changedRows = 0; 1.91 + LJBits changeAny = 0; 1.92 + 1.93 + int nLines = countRows(p->tempRows); 1.94 + 1.95 + // first pass: destruction 1.96 + for (int y = 0; y < LJ_PF_HT; ++y) { 1.97 + for (int x = p->leftWall; x < p->rightWall; ++x) { 1.98 + if (p->c[y][x] == 1) { 1.99 + unsigned int blk = p->b[y][x]; 1.100 + 1.101 + if (blk) { 1.102 + changedRows |= 1 << y; 1.103 + p->b[y][x] = 0; 1.104 + if (blockIsBomb(blk)) { 1.105 + explodeAt(p, x, y, blk, nLines); 1.106 + } 1.107 + } 1.108 + } 1.109 + } 1.110 + } 1.111 + 1.112 + // second pass: countdown timer per block 1.113 + for (int y = 0; y < LJ_PF_HT; ++y) { 1.114 + for (int x = p->leftWall; x < p->rightWall; ++x) { 1.115 + if (p->c[y][x] > 0) { 1.116 + --p->c[y][x] > 0; 1.117 + changeAny = 1; 1.118 + } 1.119 + } 1.120 + } 1.121 + 1.122 + return changeAny ? (1 << (LJ_PF_HT - 1)) : changedRows; 1.123 +} 1.124 + 1.125 +/** 1.126 + * Scans the cleared lines for bombs and marks c[] to trigger them. 1.127 + * @param p the playfield, where tempRows holds the cleared lines 1.128 + * @return the rows where bombs were triggered 1.129 + */ 1.130 +LJBits triggerBombs(LJField *p) { 1.131 + LJBits bombRows = 0; 1.132 + 1.133 + for (int y = 0; y < LJ_PF_HT; ++y) { 1.134 + if (p->tempRows & (1 << y)) { 1.135 + for (int x = p->leftWall; x < p->rightWall; ++x) { 1.136 + bool isBomb = blockIsBomb(p->b[y][x]); 1.137 + p->c[y][x] = isBomb; 1.138 + if (isBomb) { 1.139 + bombRows |= 1 << y; 1.140 + } 1.141 + } 1.142 + } 1.143 + } 1.144 + return bombRows; 1.145 +}