Things used in this project

Hardware components:
Maker Board Let's Start Coding Ultimate Kit
×1

Code

Jump Man CodeC/C++
#include "MakerScreenXVI.h"

MakerScreenXVI lcd;

byte run0[8] = { //legs in partial stride
  0b00000,
  0b01100,
  0b01100,
  0b01100,
  0b01110,
  0b01100,
  0b01010,
  0b01010
};

byte run1[8] = { //legs in full stride
  0b00000,
  0b01100,
  0b01100,
  0b01111,
  0b01100,
  0b01100,
  0b01010,
  0b10001
};

/*
 * The same custom character will work for both walls
 */
byte wall[8] = { //wall obstacle
  0b11111,
  0b10101,
  0b11111,
  0b10001,
  0b11111,
  0b10101,
  0b11111,
  0b10001
};

byte crash[8] = { //crashed JumpMan
  0b00000,
  0b00011,
  0b01011,
  0b00111,
  0b00011,
  0b00011,
  0b00001,
  0b00001
};

byte jump[8] = { //mid-jump icon
  0b00110,
  0b10110,
  0b01100,
  0b01111,
  0b01110,
  0b01011,
  0b10000,
  0b00000
};

// Make an icon for the heart object, just like the others
byte heart[8] = {//heart for extra life
  0b00000,
  0b01010,
  0b10101,
  0b10001,
  0b01010,
  0b00100,
  0b00000,
  0b00000
};

int position = 0;  //holds the changing position of the cursor
bool runState = 0; //which running animation to draw (0 or 1).
int jumpState = 0; //0 ='pre-jump', 1 ='mid jump', 2='post jump'
bool buttonState = 0; //will equal 1 after press, 0 after jump completed
int wallPosition = 14; //wall can be placed from 0 to 15


int wall2Position = 10; //position of the second wall

bool heartState = 0;//0 = no heart available, 1 = heart available
int heartPosition; //which column is the heart in?
int lives = 3; //starting number of lives

int animationDuration = 300; //ms between animations of JumpMan's legs
int runDuration = 600; //ms between moving JumpMan's position on the screen

//Timers to update for each 'level'
long animationTimer;
long runTimer;

void setup() {

  lcd.begin();
  
  lcd.backlightOn();

  lcd.createChar(0, run0); //partial stride character
  lcd.createChar(1, run1); //full stride character
  lcd.createChar(2, wall); //wall character in 'slot' 2 of custom characters
  lcd.createChar(3, crash); //splatted character against the wall
  lcd.createChar(4, jump);  //mid-jump icon
  lcd.createChar(5, heart); //heart for extra lives

  pinMode(6,INPUT_PULLUP); //button to trigger jump

  startScreen();//run function for welcome screen

  //Start both timers equal to millis() so that the difference between
  //millis and the variables is 0.
  animationTimer = millis();
  runTimer = millis();

  randomSeed(analogRead(A0));//take a reading from A0 to get a random number

}

void loop() {
 
  lcd.setCursor(0,0);
  lcd.write(4); //Show the jump icon alongside the lives counter
  lcd.print(lives);

   //Set the cursor depending on the state of the character
  if (jumpState == 0){
    lcd.setCursor(position,1);
  }
  else if (jumpState == 1){
    lcd.setCursor(position,0);
  }
  else if (jumpState == 2){
    lcd.setCursor(position,1);
  }

  if (jumpState == 1){ //if jump has been activated..
    lcd.write(4); //draw JumpMan mid-air
  }
  else{
    lcd.write(runState); //draw the run0 or run1 animation
  }

  lcd.setCursor(wallPosition,1);
  lcd.write(2); //draw wall

  /*
   * Draw your second wall the same way you drew the other
   */
  lcd.setCursor(wall2Position,1);
  lcd.write(2);//draw wall 2

  if (heartState == 1){//if a heart is available, draw it
    lcd.setCursor(heartPosition,0);
    lcd.write(5);
  }
  if ((digitalRead(6) == LOW)&&(jumpState == 0)){
    buttonState = 1; //1 means a press is recorded
  }
  
   //Button is unpressed and a jump has been completed
  if ((digitalRead(6) == HIGH)&&(jumpState == 2)){
    jumpState = 0;
  }

  if (millis() - animationTimer > animationDuration){
    runState = 1 - runState; //draw the next JumpMan animation
    animationTimer = millis();
    lcd.clear(); //clear the LCD to draw a new character
  }

  if (millis() - runTimer > runDuration){//update position after runDuration
    position = position + 1;

   if (position == 16){
      heartState = 0; //by default there is no heart available
      
      if (random(0,10) < 3){//30% of the time...
        heartState = 1; //signal that a heart will be available
        heartPosition = random(3,16); // Place the heart randomly
      }

      wallPosition = random(3,16);//place wall 1 in column 3 through 15

      /*
       * Wall 2 should always be at least 3 spaces away from wall 1 because
       * JumpMan can only jump one wall at a time. Without the added space,
       * the walls could appear back-to-back and create an impossible level.
       * 
       * You may notice that if wallPosition is 15, then wall2Position can 
       * be a random number between 18 and 16. That means sometimes you'll have
       * only one wall. You could ensure you'll always have two walls by
       * limiting how far to the right wall 1 is allowed to be placed.
       */
      wall2Position = random((wallPosition+3),16);
      
      position = 0;//reset JumpMan to the left of the screen after a level
    }

  //if button has been pressed and a jump hasn't been initiated...
    if ((buttonState == 1)&&(jumpState == 0)){
      jumpState = 1; //signal a jump
      buttonState = 0; //reset button to 'unpressed' in the code
    }
    else if (jumpState == 1){ //true if jumpState set to one in the last loop
      jumpState = 2; //jump is marked as complete
    }

    //check for heart collision
    if ((position == heartPosition)&&(jumpState == 1)){
      // heartState gets set to 0 so the player doesn't get it
      // more than once.
      if (heartState == 1){
        lives = lives + 1; //add a life
        heartState = 0; //reset the heart variable
      }
    }
    
    /*
     * You will now use logic to check for a collision with the
     * second wall. The || operator checks if either or both of two
     * conditions is true. The check below says "Run the code if 
     * position equals wallPosition OR wall2Position AND the jumpState
     * is not equal to one.
     * To type the Boolean "OR", you will hold 'shift' and press the \ 
     * key, usually under the backspace or delete key
     */

    //Check to see if either jump has been missed
    if (((position == wallPosition)||(position == wall2Position))&&(jumpState != 1)){
      drawCrash();
      
      lives = lives - 1;//decrease lives by one with each crash

      if (lives == 0){ //if out of lives...
        // Clear the LCD and write "Game Over" to it
        lcd.clear();
        lcd.setCursor(4,0);
        lcd.print("Game Over");

        delay(2000);//wait two seconds to restart the game

        //Reset all state variables:
        lives = 3;
        position = 0;
        buttonState = 0;
        runState = 0;

        //Reset speeds to 'level one'
        runDuration = 600; 
        animationDuration = 300;

        /*
         * Show the start screen after the 'game over' is shown so that the 
         * next game won't start until the button is pressed again
         */
        startScreen();
      } 
    }

    //if either wall is cleared
    else if ((position == wallPosition)||(position == wall2Position)){
      runDuration = runDuration - 50; //speed each position up by 50 ms
      
      if (runDuration < 100){//keep runDuration at a minimum of 100
        runDuration = 100;
      }
    
      animationDuration = runDuration/2; //Move legs twice per position change
    }

    lcd.clear();
        
    runTimer = millis();
  }
}

void drawCrash(){
  lcd.clear();

  lcd.setCursor(position-1,1); //move cursor one position left of the collision
  lcd.write(3);//draw 'splatted' JumpMan

  lcd.setCursor(wallPosition,1);
  lcd.write(2); //draw the wall
  
  lcd.setCursor(wall2Position,1);
  lcd.write(2); //draw the second wall

  delay(1000);

  // Reset the variables to put the JumpMan back at the starting point
  position = 0;
  buttonState = 0;
  jumpState = 0;
}

void startScreen(){

  lcd.clear();

  lcd.setCursor(2,0);//place cursor near the middle of Maker Screen
  lcd.print("Press button 6");
  lcd.setCursor(4,1);//Move to the next line and complete the message
  lcd.print("to play!");

  while (digitalRead(6) == HIGH){//while the button isn't pressed...
    delay(10); //wait 10 ms and check the 'while' again
  }
  
  while (digitalRead(6) == LOW){ //while the button is pressed...
    delay(10); //wait 10 ms and check the 'while' again
  }
  
  //After both 'while' loops have completed, clear the screen and complete
  //the function
  
  lcd.clear();
  
}

 
  
 //(c) 2017 Let's Start Coding. License: www.letsstartcoding.com/bsdlicense

Credits

00874890dc60012517e93740a51e1b75
Zachary Haslam
0 projects • 12 followers
My name is Zach, and I am 13! I love making! I've been developing for a little over a year. I specialize in Python, Windows, Arduino.
Contact

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Sign up / LoginProjectsPlatformsTopicsContestsLiveAppsBetaBlog