0

I am trying to make a game where there are arrows going towards an object (in this case I printed x) and you have to evade the arrows. When you press the button it is supposed to print x on the top row and clear the bottom row with printing nothing and if you don't press the button its supposed to print x on the bottom row and nothing on the top. Then the for loop is supposed to print arrows randomly going from right to left.

Problem: When I actually run the code I only see the x every time the arrow hits the (0,1) or (0,0) position.

I want the x to be there all the time.

#include <LiquidCrystal.h>
// init the lcd display according to the circuit
LiquidCrystal lcd(12, 11, 6, 5, 4, 3);

String line2 = " x ";
int xPosition;
int yPosition;
int yConstant;

void setup()  {
  lcd.begin(16, 2);
  // put your setup code here, to run once:
  int switchState = 0;
  pinMode(7, INPUT);
  int leftjump = 0;
  pinMode(8, INPUT);
}

void loop() {
  ///////////////////////////////
  //supose tp print arrow randomly going from right to left
  xPosition = 15;
  yPosition = random(0, 10);
  if (yPosition > 5) {
    yConstant = 1;
  }
  else yConstant = 0;
  lcd.setCursor(xPosition, yConstant);
  for (int xPosition = 15; xPosition > 1; xPosition--) {
    lcd.print("<-");
    delay(100);
    lcd.clear();
    lcd.setCursor((xPosition), yConstant);
  }
  ////////////////////////////
  // suppose to print x on the top row and print nothing on buttom row
  //and otherwise when button is not pressed print x on bottom and
  //print nothing on top row
  int rightjump = 0;
  rightjump = digitalRead(7);
  if (rightjump == 1 ) {
    lcd.setCursor(0, 0);
    //delay(10);
    lcd.print(line2);
    //delay(200);
    lcd.setCursor(0, 1);
    lcd.print("  ");
  }
  else if ( rightjump == 0 ) {
    lcd.setCursor(0, 1);
    //delay(10);
    lcd.print(line2);
    //delay(200);
    lcd.setCursor(0, 0);
    lcd.print("  ");
  }
}

3 Answers 3

-1

There is one big problem with your program, and it is here:

delay(100);

Using delay() is bad practice. The Arduino does nothing useful while delaying. Quite importantly, it cannot respond to user input. And to make matters worse, you have this delay inside a loop. This means your program will be stuck inside the loop for 1.4 seconds. And during this time it will not take care of reading the button, nor drawing the player on the screen.

The solution is to use millis() to manage your timings, and never block your program while waiting for something. The approach is well explained in the Blink Without Delay Arduino tutorial. In a nutshell: on every loop iteration, you check the clock and, if it's time to do some particular task, you do it. If it's not time, well, you simply don't do it. Most importantly: you don't wait. If you don't do something on this loop iteration, no worries, you will do it on some other iteration.

With this approach, there are some pieces of information (e.g. arrow position) that will have to be remembered from one loop iteration to the next. This can be done by storing that in global variables. I prefer to to use static local variables though, to keep the information confined to where it belongs.

Here is my try at your loop(). Notice that both the arrow and the player are managed through the same pattern: if (it needs to be updated right now) { update it; }

void loop() {
    static uint32_t last_arrow_move;  // last time the arrow moved
    static int arrow_x, arrow_y;
    const int player_x = 0;
    static int player_y;

    // Update the arrow position every 100 ms.
    if (millis() - last_arrow_move >= 100) {
        last_arrow_move += 100;

        // Erase the arrow at its old position.
        lcd.setCursor(arrow_x, arrow_y);
        lcd.print("  ");

        // Move one cell to the left.
        arrow_x--;

        // If too far left, then send a brand new arrow.
        if (arrow_x < 2) {
            arrow_x = 15;
            arrow_y = random(0, 2);
        }

        // Draw the arrow at its new position.
        lcd.setCursor(arrow_x, arrow_y);
        lcd.print("<-");
    }

    // Get the updated player position.
    int new_player_y;
    if (digitalRead(7) == HIGH) {  // "jump" button pressed
        new_player_y = 0;
    } else {
        new_player_y = 1;
    }

    // Update the player if he moved.
    if (new_player_y != player_y) {

        // Erase the player at its old position.
        lcd.setCursor(player_x, player_y);
        lcd.print(" ");

        // Move.
        player_y = new_player_y;

        // Redraw at the updated position.
        lcd.setCursor(player_x, player_y);
        lcd.print("x");
    }
}
0
0

You have a nested loop. When your for loop is finished moving the arrow to column 0 then, and only then, the " x " is displayed, exactly as predicted. You can start by drawing the x from inside the for loop (before the delay) that will make it visible all the time. It's a start anyways.

-1

Combing two codes to make it work on the same time but not effecting the other code?

the simplest would be to have two arduino and run each piece on one of them.

4
  • is there a way to it with one arduino because i need it on one lcd, the only problem is that i need the x to be there all the time. Dec 5, 2017 at 0:54
  • technically, no. arduino has one execution unit so at any given point in time, it is either running code A, nothing else. for you to run both pieces on one arduino, you have to relax your constraints. no other way around that.
    – dannyf
    Dec 5, 2017 at 0:57
  • it runs on both but i just need the x to show all the time. Dec 5, 2017 at 0:59
  • Is there a way to show the x all the time, without having it clear with the for loop. Dec 5, 2017 at 1:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.