Homing in on you
- Tanks now launch Homing Missiles
- changeable wall color
- menu is back
- lots of ROM savings
Menu's back in place. All options should be functional, so let me know if something doesn't work as expected.
A couple Tanks launched Homing Missiles. They're shaped differently than the normal shots. The menu option sets the number of redirects each Homing Missile can make. Values range from 0-3 (0=no redirect). The "remove brick" routine needs to be updated to cope with the homing missiles. If it lines up with 2 bricks it only takes 1 out. If the tank keeps shooting, the same brick is taken out so the tank won't be able to create an opening it can shoot thru.
The wall color used to be hard coded. I've seen purple and red walls in Frenzy, so I've added the ability for the C code to control the wall color. At the moment it only uses blue for Berzerk and purple for Frenzy.
Found over 800 bytes worth of savings!
First savings was 172 bytes by changing how I divide by 5 for dealing with the playfield pixels (each "brick" is 5 scanlines tall). The ARM supports multiplication, but not division, so I had been using a 185 byte table.
const unsigned char div_5[] = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,... 35, 35, 35, 35, 35, 36, 36, 36, 36, 36 }; if (y < 36*5) y5 = div_5[y]; else y5 = 36;
Omegamatrix's first(!) blog entry referenced reciprocal multiplication which is basically using x * 0.2 to get the result. We only have integers, so we use an implied decimal point like when doing subpixel positioning.
#define DIV_BY_5 0xCCCD #define DIV_BY_5_SHIFT 18 y5 = (y * DIV_BY_5) >> DIV_BY_5_SHIFT;
My next find was spotting this in the "player shoots" routine:
switch (direction) { case 0: gMissileX[0] = gSpriteX[0] + 7; gMissileY[0] = gSpriteY[0] + 3; gMissileControl[0] |= 0; break; case 1: gMissileX[0] = gSpriteX[0] + 6; gMissileY[0] = gSpriteY[0] + 9; gMissileControl[0] |= 1; break; case 2: gMissileX[0] = gSpriteX[0] + 3; gMissileY[0] = gSpriteY[0] + 16; gMissileControl[0] |= 2; break; case 3: gMissileX[0] = gSpriteX[0] - 3; gMissileY[0] = gSpriteY[0] + 9; gMissileControl[0] |= 1; break; case 4: gMissileX[0] = gSpriteX[0] - 4; gMissileY[0] = gSpriteY[0] + 3; gMissileControl[0] |= 0; break; case 5: gMissileX[0] = gSpriteX[0] - 4; gMissileY[0] = gSpriteY[0] + 1; gMissileControl[0] |= 1; break; case 6: gMissileX[0] = gSpriteX[0] + 3; gMissileY[0] = gSpriteY[0] - 5; gMissileControl[0] |= 2; break; case 7: gMissileX[0] = gSpriteX[0] + 7; gMissileY[0] = gSpriteY[0] + 1; gMissileControl[0] |= 1; break; default: break; }
and realizing I could change it (and the corresponding "robot/tank shoots") to use a few tables:
const signed char missile_x_offset[] = { 7, 6, 3,-1,-4,-2, 3, 7, // humanoid 7, 6, 3, 0,-4, 0, 3, 7 // robot and tank }; const signed char missile_y_offset[] = { 3, 9,16, 9, 3, 1,-5, 1, // humanoid 6,13,13,13, 6,-3,-4,-3, // robot and tank }; const char missile_shape[] = { 0, 1, 2, 1, 0, 1, 2, 1 // humanoid and robot (tank is always 3) }; ... gMissileX[i] = gSpriteX[0] + missile_x_offset[direction]; gMissileY[i] = gSpriteY[0] + missile_y_offset[direction]; gMissileControl[i] |= missile_shape[direction];
That saved 188 bytes. I bet it's also faster.
The next was realizing I had similar switch/case logic for the humanoid movement:
switch (direction) { case 0: gSpriteX[0]++; break; case 1: gSpriteX[0]++; gSpriteY[0]++; break; case 2: gSpriteY[0]++; break; case 3: gSpriteX[0]--; gSpriteY[0]++; break; case 4: gSpriteX[0]--; break; case 5: gSpriteX[0]--; gSpriteY[0]--; break; case 6: gSpriteY[0]--; break; case 7: gSpriteX[0]++; gSpriteY[0]--; break; default: break; }
And changed it to this:
const signed char dir_x[] = { 1, 1, 0,-1,-1,-1, 0, 1 }; const signed char dir_y[] = { 0, 1, 1, 1, 0,-1,-1,-1 }; ... gSpriteX[0] += dir_x[direction]; gSpriteY[0] += dir_y[direction];
The same logic was used for moving Otto, the robots, shots, and doing tests of "can the robot safely move here". I changed all of those to use the tables for 376 bytes of savings.
Finally, when I added back the menu I decided to make the Continue feature always enabled. Removing the menu logic saved another 68 bytes.
Note: the continue feature has not been added back yet.
Controls
- RESET = start game
- SELECT = return to menu
- Right Difficulty, Test Mode*: B = Off, A = On
* Test Mode is infinite lives and max robots. Score will be red when active.
ROM
Source
- 2
7 Comments
Recommended Comments