sanrio


Sanrio

In part a Mario parody, Sanrio is a multilevel sidescrolling platformer where the player aims to reach the end of a level, collecting coins for maximum points, while avoiding or defeating enemy obstacles.

As this project was intended to be built within 5 days, I used an image that I had drawn before as a base wireframe. Having an idea of what assets I needed and the functionality I wanted to create, organizing programming process was far more straightforward than starting from scratch.


I broke the game down into specific features I wanted implement:
  • Player creation and movement
  • Level generation
  • Enemy obstacles
  • Player shooting + variants on attacks
  • Items and powerups
  • Level map
  • Enemy projectiles + diversified attacks
  • Boss battles
I started off dedicating (probably too much) time towards dedicating a menu.
For the controls instruction, I wanted to do something a little different than a literal image diagram. By making an interactive keyboard that instantly reflected the result, I thought learning the controls would come much more intuitively than having to memorize and reference the menu.

I wanted to reflect changes in the keyboard without having to load multiple static images and so ended up generating one in JS. I was able to avoid hard-coding html for each key by creating an array of arrays that represented each row of keys, with each number reflecting a different type of key (ex. 1 = numbers, 2 = letters) and relying on styling to create the correct configuration.
generateControls() {
     let keyboard = 'QWERTYUIOPASDFGHJKLZXCVBNM';
     let nums = '1234567890';
     let number = 0;
     let letter = 0;
     let keyArray = [
         [4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 12],
         [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5],
         [0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 0],
         [8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 5, 5, 5],
         [6, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 6],
         [0, 0, 0, 0, 7, 0, 0, 9, 10, 11]
     ];
     
     for (let row = 0; row < keyArray.length; row++) {
         let list = document.getElementById(`row${row}`);
         keyArray[row].forEach(key => {
             let element = document.createElement('LI');
             switch (key) {
                 // number keys
                 case 1:
                     element.setAttribute("class", "keyboardKey");
                     element.setAttribute("id", `key${nums[number]}`);
                     let textnode = document.createElement('P');
                     let textContent = document.createTextNode(`${nums[number]}`);
                     textnode.setAttribute("class", "keyNumberContent");
                     textnode.appendChild(textContent);
                     element.appendChild(textnode);
                     list.appendChild(element);
                     number += 1;
                     break;
                 // letter keys
                 case 2:
                     element.setAttribute("class", "keyboardKey");
                     element.setAttribute("id", `key${keyboard[letter]}`);
                     let letternode = document.createElement('P');
                     let letterContent = document.createTextNode(`${keyboard[letter]}`);
                     letternode.setAttribute("class", "keyLetterContent");
                     letternode.appendChild(letterContent);
                     element.appendChild(letternode);
                     list.appendChild(element);
                     letter += 1;
                     break;
                 case 7:
                     element.setAttribute("id", "space");
                     list.appendChild(element);
                     break;
                     
                 // arrow keys
                 // blank keys

                 default:
                     break;
             }
         });
      }
   }
For scene generation, I wanted to be able to quickly generate multiple maps, without having to calculate the positions of each decorative element or platform. Using a text file where I could easily see layout provided a visual display for level creation.

The platforms themselves were built of 3 separate pieces- the round left and right edges and a middle piece that extended a given number of blocks and defined with a number of 1-5 that represented it's shade value.
By parsing a text file, I was able to use a simple switch case statement to create objects mapping different categories of elements that could be manipulated in the main game code. Keeping track of how many lines have been parsed in an independent variable, I was then able to instantiate elements at different 'depths' with respective colors.

    for (let i = 0; i < level.length; i++){
      switch (level[i]){
          case ' ':
              width += WIDTHSPAN;
              break;
          case '\n':
              height += HEIGHTSPAN;
              width = 0;
              break;
          case '\t':
              width += WIDTHSPAN*4;
              break;
                case 'c':
              items[itemCount] = (new Coin(width, height - HEIGHTSPAN, itemCount));
              itemCount += 1;
              width += WIDTHSPAN;
              break;
          case 'T':
              deco.push(new Tree(width, height + HEIGHTSPAN, 1.5));
              width += WIDTHSPAN;
              break;
          case 't':
              deco.push(new Tree(width, height + HEIGHTSPAN, 1));
              width += WIDTHSPAN;
              break;
          case 'b':
              deco.push(new Bush(width, height + HEIGHTSPAN, randomInt(0,5)));
              width += WIDTHSPAN;
              break;
          case 'x':
              blockCount += 1;
              break;
          case 'X':
              blockCount += 1;
              let depth = 5;
              switch (height > 0) {
                  case (height >= 0 && height < 100):
                      depth = 5;
                      break;
                  case (height >= 100 && height < 200):
                      depth = 4;
                      break;
                  case (height >= 200 && height < 300):
                      depth = 3;
                      break;
                  case (height >= 300 && height < 400):
                      depth = 2;
                      break;
                  case height >= 400:
                      depth = 1;
                      break;
              }
              sceneObjects.push(new PlatformBuilder(blockCount, width, height, depth));
              width += WIDTHSPAN*blockCount;
              blockCount = 0;
              break;
          default:
      }
  }