In the previous tutorial we learned how to make the “man” of the WALLED game and how to move it.

Today we start to build the descending walls and its gates that will be crossed by our man!

Let’s start inserting the walls variable.

Step 1: Make the walls

First we insert a variable called wallYPosition that is used to change the Y position – ROW – of the wall that falls down.

Insert the wallYPosition after the MAN VARIABLES

//MAN VARIABLES
byte manXPosition = 2;//the position of the man
byte keySensibility = 70; //the sensibility of the two touch buttons.
//WALL VARIABLES
byte wallYPosition = 0; //Y value of the wall

Now we can create the function, that will be fired by the Timer1 interrupt, used to increase the wallYPosition in order to pull down the wall.

We increase the wallYposition becasue the top of the LEDs matrix has ROW index 0. So the bottom has index MATRIX_ROW - 1 = 4

Let’s create the updateWallPosition(), after the function updateManPosition(), in this way:

void updateWallPosition() {
  int wallOldYPosition = wallYPosition; //store the old wall position

  if (wallYPosition < MATRIX_ROW - 1) { //if wall position isn't the bottom
    wallYPosition++; //increase Y position - go down
  } else { //else, if the wall touch the bottom
    wallYPosition = 0; //reset its position
  }

  //delete previous wall position
  for (byte x = 0; x < MATRIX_COL; x++) {
    matrixState[wallOldYPosition][x] = 0;
  }
  //show new wall position
  for (byte x = 0; x < MATRIX_COL; x++) {
    matrixState[wallYPosition][x] = 1;
  }
}

Well, in this function first we store the current wallYPosition in the wallOldYPosition variable.

Next we check if the wall hasn’t reached the bottom position: MATRIX_ROW - 1.

If it is, we increase its Y position. Otherwise, if the wall has reached the bottom position – index 4 – we reset the wall position to 0 – top of the LEDs matrix.

After that we clear the previous position of the wall by clearing every LEDs in the same ROW of the OLD wallYPosition.

Next we set the new wall position by turning on all the LEDs in the new ROW.

 

Now we put this function inside the timer 1 overflow interrupt function – aka ISR(TIM1_OVF_vect) – because we want to update the wall position in the background without interference – like the delay() inside the updateManPosition().

So we insert this function inside the ISR(TIM1_OVF_vect) function after this declaration: TCNT1 = 65406; and before the charlieplexing functions.

ISR(TIM1_OVF_vect) {  // timer1 overflow interrupt service routine
  cli(); //disable interrupt
  TCNT1 = 65406;
  //THIS PART IS USED TO UPDATE THE WALL POSITION
  updateWallPosition();
  
  // THIS PART IS USED TO UPDATE THE CHARLIEPLEXING LEDS MATRIX
  // YOU CAN JUST DON'T CARE ABOUT THIS PART
  // BECAUSE YOU CAN CODE LIKE A STANDARD MATRIX BY MANIPULATING THE
  // VALUE OF THE matrixState MATRIX
  ...

But if we upload the sketch now we notice that the wall go down too fast.

This because the timer 1 overflow occur every 1/60 seconds = 0,0167 seconds. Too fast for us!

So we need to decrease the speed of the wall. How?

Just creating a counter and increasing it. After it reach our desired value, we fire the updateWallPosition() function.

Now add the following variables at the top of the sketch, after the wallYPosition variable declaration:

//WALL VARIABLES
byte wallYPosition = 0; //Y value of the wall
const byte wallSpeed = 15; 
byte wallUpdatePositionCounter = 0; //it is a counter to update wall position
byte wallUpdatePositionSpeed = wallSpeed; //the actual speed of the wall

Well, our counter is the wallUpdatePositionCounter. We increase this counter until it reaches the wallUpdatePositionSpeed‘s value.

This last variable have the same value of the wallSpeed variable. The value of this function is inversely proportional to the speed of the wall.

Now we adjust the firing of the updateWallPosition() in the ISR(TIM1_OVF_vect) function in this way:

  ...
  wallUpdatePositionCounter++;
  if (wallUpdatePositionCounter > wallUpdatePositionSpeed) {
    updateWallPosition();
    wallUpdatePositionCounter = 0;
  }
  ...

Now we can upload the sketch and, after that, we can see the walls that go down.

The first thing that you have certainly noticed is that the walls doesn’t have the gates! Right!

The second thing, that maybe you haven’t noticed, is that, at the first start of the game, the wall doesn’t start at the 0 position.

Let’s fix it!

Step 2: Create wall’s gate!

The gates are only a turned OFF LED in a specific X position – COL – of the wall.

This position can’t be the same for all the walls – Or do you like to win easily? 🙂

So we need to randomise the gate position.

Insert the wallGateXPosition variable at the end of the WALL’S VARIABLES and before the ISR(TIM1_OVF_vect) function:

//WALL VARIABLES
byte wallYPosition = 0; //Y value of the wall
const byte wallSpeed = 15; 
byte wallUpdatePositionCounter = 0; //it is a counter to update wall position
byte wallUpdatePositionSpeed = wallSpeed; //the actual speed of the wall
byte wallGateXPosition = random(0, MATRIX_COL); //randomized wall's gate
ISR(TIM1_OVF_vect) {
... 

We randomise the wallGateXPosition between 0 and MATRIX_COL - 1

NOTE:
The random() function randomize a number between two values in this way:
int x = random(min_value, max_value + 1);

Now we change the wallUpdateFunction() to show up the wall’s gate:

void updateWallPosition() {
  int wallOldYPosition = wallYPosition; //store the old wall position
  if (wallYPosition < MATRIX_ROW - 1) { //if wall position isn't the bottom
    wallYPosition++; //increase Y position - go down
  } else { //else, if the wall touch the bottom
    wallYPosition = 0; //reset its position
    wallGateXPosition = random(0, MATRIX_COL); //randomize another gate
  }
  //delete previous wall position
  for (byte x = 0; x < MATRIX_COL; x++) {
    matrixState[wallOldYPosition][x] = 0;
  }
  //show new wall position
  for (byte x = 0; x < MATRIX_COL; x++) {
    if (x != wallGateXPosition) {
      matrixState[wallYPosition][x] = 1;
    }
  }
}

We have randomised another wallGateXPosition after the previous wall touches the bottom of the screen.

After we have modified the last for cycle used to show the new wall in the matrixState.

We have declared that if the x position of the wall dot, that we are going to set in the matrixState, isn’t in the same position of the gate, we set the bit in that position.

Else, if we are in the same position of the gate, we don’t set the bit in the matrixState and so we don’t turn ON the LED in that position.

Now we can fix the fact that, at the first start, the wall starts at index 1 and not 0, by adding the following lines at the end of the setup() function.

  ...
  // enable global interrupts:
  sei();
  clearMatrix(); //clear the Matrix
  //show wall
  for (byte x = 0; x < MATRIX_COL; x++) {
    if (x != wallGateXPosition) {
      matrixState[wallYPosition][x] = 1;
    }
  }
}

This because, at the first declaration of the wallYPosition we set it to zero. When the function updateWallPosition() is fired, it immediately increases this variable and then it shows the wall in the new position with index 1.

Inserting the previously lines in the setup() function, we immediately show the wall in its first position with index 0.

Now we can upload the sketch and see the randomised gates in the walls!

Download the complete sketch for this second tutorial here.

You can actually play, but you never die because we need to implement the collision between the walls and the man.

After that we need to create the score and, to make the game more funny,  we can increase the speed of the walls automatically.

All these things in the next tutorial!

Stay Tuned!

{"cart_token":"","hash":"","cart_data":""}