Thursday, 22 December 2011

Bug Tunnel Defense: Levels

(originally posted 6 June 2011)
The missions in Bug Tunnel Defense started out a lines of code, describing the position and location of every wall, tunnel, entrance and exit. This became unwieldy very fast, and it was clear it would be unusable for the dozens of missions I wanted in the final game.

So I started making them as bitmaps, in particular PNGs, with black for the walls, blue and green for the entrances and exits, and red for the tunnel ends. This was done using a template with the flux points where starts, exits and tunnels have to go marked in grey. I then added code to the game to parse the loaded bitmap data:

for (iY = 0; iY < kGridSize; iY++) {
 for (iX = 0; iX < kGridSize; iX++) {

  // get pixel, split into RGB values
  iVal = bmp.getPixel(iX, iY);
  iR = (iVal >> 16) & 0xff;
  iG = (iVal >> 8) & 0xff;
  iB = iVal & 0xff;
  // mark black pixels
  if (iR < 16 && iG < 16 && iB < 16) {
   iVal = 0;
   bBlack = true;
  } else {
   // is it a hole ?
   iIndex = Grid.HoleIndex(iX, iY);
   if (iIndex >= 0) {
    // check for colour (any of RGB greatest)       
    iMin = Math.min(iR, Math.min(iG, iB));
    iMax = Math.max(iR, Math.max(iG, iB));
    if (iMax > iMin + 16) {
     // store based on colour
     if (iMax == iR) {
      aTunnels.push(new Vec2D(iVal, iIndex));
     } else if (iMax == iG) {
      aExits.push(new Vec2D(iVal, iIndex));
     }
     else {
      aStarts.push(new Vec2D(iVal, iIndex));
     }
    }
   }
   bBlack = false;
  }
  // check for transition, store length of run if it happened
  if (bBlack != bCurrBlack) {
   aRanges.push(iBlack);
   iBlack = 0;
   bCurrBlack = bBlack;
  }
  // update count
  iBlack++;

 } // end for
} // end for

The starts, exits and tunnels are put into arrays (actually using the Vector class), the walls are stored using run-length encoding as ranges of wall and no wall alternately.
This made it easy to create missions and also determine their order simply by looking at the files’ thumbnails, as seen in the above image of a close to final selection. They also became the first mission select interface:



The missions then were arranged in an 8 x 8 grid, and were unlocked when both across and down the screen by the mission immediately above and to the left, except the missions at the left and top edges which only depended on the mission immediately above or to the left. Unlocked missions are at 100% alpha, locked ones at 50%.
I abandoned this as it is easier to introduce new ideas, such as bugs and other challenges, if the missions are tackled in a fixed order. I also reduced the number from 64 to 40, to make the game a more reasonable length, removing some missions which were too similar to others or simply not as good. The interface was replaced with the current one which produces more representative thumbnails of the missions on the fly.
Eventually I replaced the bitmaps with strings generated from the bitmaps, but the above code stayed in the game in case so I could modify missions, until the editor was added so it was no longer needed.

No comments:

Post a Comment