Problem with creating a timed action in arduino code

Hey all, I am trying to recreate the chrome dino game using an arduino, 16x2 lcd display and a push button. The wiring isn't really an issue here so I didn't include a schematic (hope that isn't a problem).

The problem I am facing and have been facing for a while is trying to get the jump() function to have the dino move to the top column and then drop back down after a set time which I chose to be 600ms.

My code has gone through alot of changes in the past week and I've relied heavily on using this forum to figure out how to work around millis();

I have figured out how to get millis() to incrementaly move the cacti but doing the same with the jumping has posed to be a challenge to me. I will have to admit (and you may have already caught on to it) I haven't really done much programming in my life.

Here is the code:

#include <LiquidCrystal_I2C.h>

#define NOT_JUMPING 0
#define JUMPING 1

int dinoState = NOT_JUMPING;

LiquidCrystal_I2C lcd(0x27, 16, 2);
int buttonPin = 2;
int buttonVal;
int cactusPosition = 15;
int dinoPosition = 3;  // Initial position of the Dino
int oldCactusPos;
int line = 1;
const unsigned long interval = 300;
static unsigned long lastExecutionTime = 0;
const unsigned long jumpInterval = 600;
static unsigned long lastJumpTime = 0;

byte amogus[] = {
  B01111,
  B01111,
  B11001,
  B11111,
  B11111,
  B01111,
  B01001,
  B01001
};

byte cactus[] = {
  B01100,
  B01100,
  B01101,
  B11110,
  B01100,
  B01100,
  B01100,
  B01100
};

void setup() {
  pinMode(buttonPin, INPUT);
  digitalWrite(buttonPin, HIGH);
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.backlight();
  lcd.clear();
  lcd.createChar(0, amogus);
  lcd.createChar(1, cactus);
  lcd.setCursor(dinoPosition, 1);
  lcd.write(0);
}

void loop() {
  unsigned long currentTime = millis();
  readButton();
  if (dinoState == JUMPING) {
    if (currentTime - lastJumpTime >= jumpInterval) {
      Jump();
      lastExecutionTime = currentTime;
    }
  } else {
    Down();
  }
  if (currentTime - lastExecutionTime >= interval) {
    spawnCactus();
    lastExecutionTime = currentTime;
  }
}

int readButton() {
  // Read button
  buttonVal = digitalRead(buttonPin);
  // Check if button is pressed
  // If button is pressed return line as 0
  if (buttonVal == 0) {
    dinoState = JUMPING;
  } else {
    dinoState = NOT_JUMPING;
    Serial.println("NOT JUMPING!");
    return dinoState;
  }
}

void Down() {
  lcd.setCursor(dinoPosition, 1);
  lcd.write(0);
  lcd.setCursor(dinoPosition, 0);
  lcd.write(' ');
}

void Jump() {
  // Dino is still jumping, update the display
  lcd.setCursor(dinoPosition, 0);
  lcd.write(0);
  lcd.setCursor(dinoPosition, 1);
  lcd.write(' ');
}

void spawnCactus() {
  // Spawn a cactus
  if (cactusPosition == 0) {
    lcd.setCursor(0, 1);
    lcd.write(' ');
    cactusPosition = 15;
  }
  // Update oldCactusPos with cactusPosition
  oldCactusPos = cactusPosition;
  // Update cactusPosition to move one block
  cactusPosition -= 1;
  // Move the cactus incrementaly to the left
  lcd.setCursor((oldCactusPos), 1);
  lcd.write(' ');
  // Clear the block the cactus was on previously
  lcd.setCursor(cactusPosition, 1);
  lcd.write(1);
  checkCollision();
}

void checkCollision() {
  // Check if the Dino collides with the cactus
  if (cactusPosition == dinoPosition && dinoState == NOT_JUMPING) {
    // Implement your collision action here (e.g., game over)
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Game Over!");
    delay(2000);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Press button");
    lcd.setCursor(0, 1);
    lcd.print("to Restart");
    while (true) {
      // Game over loop
      buttonVal = digitalRead(buttonPin);
      if (buttonVal == 0) {
        lcd.clear();
        break;
      }
    }
  }
}

The variable in the if-condition and the updating must be the same

  //                same variable here 
  if (currentTime - lastExecutionTime >= interval) {
    spawnCactus();
    // and HERE
    lastExecutionTime = currentTime;
  }

This is happening continioulsy. This is the reason why it is sufficient to have only these three lines of code.

Jumping occurs only from time to time.

When the jump starts you store the actual snapshot of time in a variable
I would name it "jumpStartTime"

And then you check

  //                same variable here 
  if (currentTime - jumpStartTime >= jumpInterval) {
    // finish jump
  }

So where in your code are you detecting "jump" ?
this is the place where you store

jumpStartTime = currentTime;

best regards Stefan

And in order to detect when your jump starts, you need to know when the button was pressed, not if the button is pressed.

This is done by keeping track of the previous buttons state. Look at the Debounce example in the IDE (File->examles->02. Digital->Debounce)

Those changes need to be in your readButton() function.

Ha! I didn’t notice that thanks

Thanks, I’ll check it out. That’s what I’ve been trying to figure out this whole time.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.