How to make delay with millis()

So I am making a LCD video game. Which actually works almost how I want it to be.
The only thing is I use in "void Schieten()" a couple delays of 150ms. I want those gone because they also delay the rest of my code.

So I want to replace them with the millis function but I don't know really how. This is my first time working with millis(). So maybe this is very easy but I don't know how to succeed.

Here is half my code:

#include <Wire.h> // Bibliotheek voor communicatie met I2C
#include <LiquidCrystal_I2C.h> // Bibliotheek voor communicatie met LCD

LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4); // LCD heeft als adressering 0x27 en heeft 20 kolommen en 4 rijen

byte KnopPin1 = 3; // Pin van drukknop1
byte LaatsteKnopStatus1 = 0; // De laast gelezen toestand van de drukknop
byte KnopStatus1; // Huidige toestand van de drukknop 

byte KnopPin2 = 4; // Pin van drukknop2
byte LaatsteKnopStatus2 = 0; // De laast gelezen toestand van de drukknop
byte KnopStatus2; // Huidige toestand van de drukknop 

byte KnopPin3 = 5; // Pin van drukknop3
byte LaatsteKnopStatus3 = 0; // De laast gelezen toestand van de drukknop
byte KnopStatus3; // Huidige toestand van de drukknop 

byte KnopPin4 = 9; // Pin van drukknop4
byte LaatsteKnopStatus4 = 0; // De laast gelezen toestand van de drukknop
byte KnopStatus4; // Huidige toestand van de drukknop 

byte KnopPin5 = 10; // Pin van drukknop5
byte LaatsteKnopStatus5 = 0; // De laast gelezen toestand van de drukknop
byte KnopStatus5; // Huidige toestand van de drukknop 

byte KnopPin6 = 11; // Pin van drukknop6
byte LaatsteKnopStatus6 = 0; // De laast gelezen toestand van de drukknop
byte KnopStatus6; // Huidige toestand van de drukknop 

byte KnopPin12 = 12; // Pin van drukknop12
byte LaatsteKnopStatus12 = 0; // De laast gelezen toestand van de drukknop
byte KnopStatus12; // Huidige toestand van de drukknop 

byte Xschip = 10; // Positie van het ruimteschip op de X-as
byte Yschip = 3; // Positie van het ruimteschip op de Y-as


byte Xvijand = 10; // Positie van de alien op de X-as
byte Yvijand = 0; // Positie van de alien op de Y-as

unsigned long lastDebounceTime = 0;  // De laatste keer dat de toestand van de drukknop is veranderd, dit gebruiken we om de tijd te checken
unsigned long debounceDelay = 50;   // Wacht tijd van 50ms om te kijken of de status van de drukknop(pen) echt hoog was

unsigned long lastDebounceTime12 = 0;  // De laatste keer dat de toestand van de drukknop is veranderd, dit gebruiken we om de tijd te checken
unsigned long debounceDelay12 = 50; // Wacht tijd van 50ms om te kijken of de status van de drukknop(pen) echt hoog was

byte AantalHartjesVijand = 3; // Aantal hartjes (levens) van de alien
byte AantalHartjesSchip = 3; // Aantal hartjes (levens) van het ruimteschip

bool HitAlien; // Als deze waar is dan is de alien geraakt 
bool HitSchip; // Als deze waar is dan is het ruimteschip geraakt

bool start; // Als deze waar is dan is het spel gestart

byte Arno = 0; // Deze leg ik later uit
byte Lucky = 0; // Deze leg ik later uit

byte Ruimteschip[8] = // Ruimteschip
{
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00100,
  B01110,
  B11111
};

byte Kogel1[8] = // Kogel1
{
  B00000,
  B00100,
  B00100,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};

byte Kogel2[8] = // Kogel2
{
  B00100,
  B00000,
  B00000,
  B00000,
  B00000,
  B00100,
  B00100,
  B00000
};

byte Kogel3[8] = // Kogel 3
{
  B00000,
  B00100,
  B00100,
  B00000,
  B00000,
  B00000,
  B00000,
  B00100
};

byte Alien[8] = // Alien
{
  B01110,
  B10101,
  B11111,
  B00100,
  B01010,
  B10001,
  B00000,
  B00000
};

byte Kogel4[8] = // Kogel 4
{
  B01110,
  B10101,
  B11111,
  B00100,
  B01010,
  B10001,
  B00100,
  B00100
};

byte Levens[8] = // Hartjes (levens)
{
  B00000,
  B01010,
  B10101,
  B10001,
  B10001,
  B01010,
  B00100,
  B00000
};

byte Kogel5[8] = // Kogel 5
{
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00100,
  B00100
};

void setup() // void setup
{
 
  lcd.init(); // Initialiseert het lcd scherm
  lcd.begin(20,4); // Zorgt ervoor dat het lcd scherm opspringt met de juiste afmetingen
  lcd.backlight(); // Zorgt ervoor dat het lampje achter het lcd display aan gaat (zodat je beter kan zien)
  lcd.home(); // Zorgt ervoor dat de cursor van het lcd scherm in de linkerboven hoek begint
  lcd.createChar(0, Ruimteschip); // karakter 0 is het ruimteschip
  lcd.createChar(1, Kogel1); // karakter 1 is Kogel1
  lcd.createChar(2, Kogel2); // karakter 2 is Kogel2
  lcd.createChar(3, Kogel3); // karakter 3 is Kogel3
  lcd.createChar(4, Alien); // karakter 4 is de alien
  lcd.createChar(5, Kogel4); // karakter 5 is Kogel4
  lcd.createChar(6, Levens); // karakter 6 is een hartje
  lcd.createChar(7, Kogel5); // karakter 7 is Kogel5
  pinMode(KnopPin1,INPUT); // Pin 3 declareren als INPUT
  pinMode(KnopPin2,INPUT); // Pin 4 declareren als INPUT
  pinMode(KnopPin3,INPUT); // Pin 5 declareren als INPUT
  pinMode(KnopPin4,INPUT); // Pin 9 declareren als INPUT
  pinMode(KnopPin5,INPUT); // Pin 10 declareren als INPUT
  pinMode(KnopPin6,INPUT); // Pin 11 declareren als INPUT
  pinMode(KnopPin12,INPUT); // Pin 12 declareren als INPUT
  Serial.begin(9600); // Snelheid waarmee er word gecommuniceerd tussen de arduino en seriele monitor
}

void loop() // void loop
{
 Begin(); // Hier word de functie "Begin" opgeroepen
 Hartjes();  // Hier word de functie "Hartjes" opgeroepen
 Links(); // Hier word de functie "Links" opgeroepen
 Rechts(); // Hier word de functie "Rechts" opgeroepen 
 MaxPos(); // Hier word de functie "MaxPos" opgeroepen 
 Schieten(); // Hier word de functie "Schieten" opgeroepen 
 Vijand(); // Hier word de functie "Vijand" opgeroepen
 VijandRechts(); // Hier word de functie "VijandRechts" opgeroepen
 VijandLinks(); // Hier word de functie "VijandLinks" opgeroepen 
 AlienSchieten(); // Hier word de functie "AlienSchieten" opgeroepen 
 HitAlien1(); // Hier word de functie "HitAlien1" opgeroepen
 HitSchip1(); // Hier word de functie "HitSchip1" opgeroepen
 SchipWint(); // Hier word de functie "SchipWint" opgeroepen
 AlienWint(); // Hier word de functie "AlienWint" opgeroepen
}

void Links() // functie Links
{
 int lezing = digitalRead(KnopPin1); // Pin 3 word digitaal binnen gelezen, als er dan word gedrukt op de knop dan word de toestand HOOG anders blijft die LAAG 
  if (lezing != LaatsteKnopStatus1) // Als de lezing niet gelijk is aan de LaatsteKnopStatus dan:
  {
    lastDebounceTime = millis(); // Word de lastDebounceTime gelijk aan de tijd dat het programma al bezig is 
  }

  if ((millis() - lastDebounceTime) > debounceDelay) // Als dan de huidige tijd dat het programma bezig is - de tijd die we net aan de lastDebounceTime hebben gegeven groter is dan 50ms dan:
  {
    if (lezing != KnopStatus1) // Als de lezing niet gelijk is aan de status van de drukknop dan:
    {
      KnopStatus1 = lezing; // Word die status van de drukknop wel gelijk aan de lezing

      if (KnopStatus1 == HIGH && start == true) // Als dan de KnopStatus HOOG is en start is waar dan:
      {
        lcd.setCursor(Xschip,Yschip); // Het ruimteschip verdwijnt op de huidige positie waar staat
        lcd.print(" ");
      
         Xschip = Xschip - 1; // En dan word de positie op de X-as van het schip - 1 gedaan --> ruimteschip verplaats naar links
      }
    }
  }
      
    LaatsteKnopStatus1 = lezing;  // Hier word de lezing van net opgeslagen, de lezing is gelijk aan de LaatsteKnopStatus
  
}

void Rechts() // functie Rechts
{
 int lezing3 = digitalRead(KnopPin3); // Pin 5 word digitaal binnen gelezen, als er dan word gedrukt op de knop dan word de toestand HOOG anders blijft die LAAG 
  if (lezing3 != LaatsteKnopStatus3) // Als de lezing niet gelijk is aan de LaatsteKnopStatus dan:
  {
   lastDebounceTime = millis(); // Word de lastDebounceTime gelijk aan de tijd dat het programma al bezig is
  }

  if ((millis() - lastDebounceTime) > debounceDelay) // Als dan de huidige tijd dat het programma bezig is - de tijd die we net aan de lastDebounceTime hebben gegeven groter is dan 50ms dan:
  {
   
   if (lezing3 != KnopStatus3) // Als de lezing niet gelijk is aan de status van de drukknop dan:
    {
      KnopStatus3 = lezing3; // Word die status van de drukknop wel gelijk aan de lezing

     if (KnopStatus3 == HIGH && start == true) // Als dan de KnopStatus HOOG is en start is waar dan:
      {
        lcd.setCursor(Xschip,Yschip); // Het ruimteschip verdwijnt op de huidige positie waar staat
        lcd.print(" ");
      
         Xschip = Xschip + 1; // Dan word de positie op de X-as van het schip + 1 gedaan --> ruimteschip verplaats naar rechts
      }
    }
  }
      
    LaatsteKnopStatus3 = lezing3; // Hier word de lezing van net opgeslagen, de lezing is gelijk aan de LaatsteKnopStatus
}

void Schieten() // functie Schieten
{
  int lezing2 = digitalRead(KnopPin2); // Pin 4 word digitaal binnen gelezen, als er dan word gedrukt op de knop dan word de toestand HOOG anders blijft die LAAG 
  if (lezing2 != LaatsteKnopStatus2) // Als de lezing niet gelijk is aan de LaatsteKnopStatus dan:
  {
    lastDebounceTime = millis(); // Word de lastDebounceTime gelijk aan de tijd dat het programma al bezig is
  }

  if ((millis() - lastDebounceTime) > debounceDelay) // Als dan de huidige tijd dat het programma bezig is - de tijd die we net aan de lastDebounceTime hebben gegeven groter is dan 50ms dan:
  {
    if (lezing2 != KnopStatus2) // Als de lezing niet gelijk is aan de status van de drukknop dan:
    {
      KnopStatus2 = lezing2; // Word die status van de drukknop wel gelijk aan de lezing
      
      if (KnopStatus2 == HIGH && start == true) // Als dan de KnopStatus HOOG is en start is waar dan:
      {
        lcd.setCursor(Xschip, Yschip); // Op de plaats waar het ruimteschip zich bevind verschijnt het eerste deel van de kogel 
        lcd.write(byte(1));
        delay(150); // Vertraging van 150ms
        lcd.setCursor(Xschip, Yschip); // Op de plaats waar het ruimteschip zich bevind word verwijnd het eerste deel van de kogel
        lcd.write(byte(0));
        lcd.setCursor(Xschip, 2); // Een rij hoger komt het tweede deel van de kogel te voorschijn
        lcd.write(byte(2));
        delay(150); // Vertraging van 150ms
        lcd.setCursor(Xschip, 1); // Een rij hoger komt het derde deel van de kogel te voorschijn
        lcd.write(byte(3));
        lcd.setCursor(Xschip, 2); // Het tweede deel van de kogel verwijnt
        lcd.print(" ");
        delay(150); // Vertraging van 150ms
        lcd.setCursor(Xschip, 1); // Het derde deel van de kogel verwijnt
        lcd.print(" "); 
        lcd.setCursor(Xschip,0); // Het laatste deel van de kogel verschijnt
        lcd.write(byte(7));
        HitAlien = true; // HitAlien is waar --> Alien is mogelijk geraakt 
        delay(150); // Vertraging van 150ms
        lcd.setCursor(Xschip,0); // Het laatste deel van de kogel verwijnt
        lcd.print(" "); 
      }
    }
  }
      
    LaatsteKnopStatus2 = lezing2; // Hier word de lezing van net opgeslagen, de lezing is gelijk aan de LaatsteKnopStatus 
}
   
void MaxPos() // functie MaxPos
{
  if(Xschip < 1) // Als de positie van het ruimteschip op de X-as kleiner dan 1 wilt gaan
  {
    Xschip = 1; // Dan blijft die positie 1
  
  }

   if(Xschip > 18) // Als de positie van het ruimteschip op de X-as groter dan 18 wilt gaan
  {
    Xschip = 18; // Dan blijft die positie 18
   
  }
 }

void Vijand() // void Vijand
{
  if(Xvijand > 18) // Als de positie van het alien op de X-as groter dan 18 wilt gaan
  {

    Xvijand = 18; // Dan blijft die positie 18
    lcd.setCursor(19,0); // De alien die zou willen komen op de X-as bij 19 verdwijnt
    lcd.print(" ");
  
  }

  if(Xvijand < 1) // // Als de positie van het alien op de X-as kleiner dan 1 wilt gaan
  {

    Xvijand = 1; // Dan blijft die positie 1
    lcd.setCursor(0,0); // De alien die zou willen komen op de X-as bij 0 verdwijnt 
    lcd.print(" ");
  }
 
}

What is so very hard about the concept of using code tags?

Yeah I am sorry this is my first post. I fixed it now.

it's more that just using millis(). you need to re-organize your code to monitor several inputs without waiting forever while also checking if a time measured using millis() has expired

Sadly, as @gcjr points out… only in the ver simplest cases is millis() a drop-in solution.

Your program structure needs to be aware of its non-blocking functionality and may need a significant rethink.

The challenge is that you need to think about functionality being ‘time’ driven, rather than purely linear /sequential.

it looks like the bulk of the posted code deals with button presses with individual routines

consider the following code, that demonstrates the use of a single function to monitor a number of buttons and how loop() handles button and timed events. one button event controls a timed event

// check multiple buttons and toggle LEDs

enum { Off = HIGH, On = LOW };

byte pinsLed [] = { 10, 11, 12 };
byte pinsBut [] = { A1, A2, A3 };
#define N_BUT   sizeof(pinsBut)

byte butState [N_BUT];

// -----------------------------------------------------------------------------
int
chkButtons ()
{
    for (unsigned n = 0; n < sizeof(pinsBut); n++)  {
        byte but = digitalRead (pinsBut [n]);

        if (butState [n] != but)  {
            butState [n] = but;

            delay (10);     // debounce

            if (On == but)
                return n;
        }
    }
    return -1;
}

// -----------------------------------------------------------------------------
#define OneSecond  1000

unsigned long interval = 0;
unsigned long msecLst  = 0;

void
loop ()
{
    // timed events
    unsigned long msec = millis ();
    if (interval && msec - msecLst > interval)  {
        msecLst = msec;
        digitalWrite (pinsLed [0], ! digitalRead (pinsLed [0]));
    }

    // button events
    switch (chkButtons ())  {
    case 2:
        digitalWrite (pinsLed [2], ! digitalRead (pinsLed [2]));
        break;

    case 1:
        digitalWrite (pinsLed [1], ! digitalRead (pinsLed [1]));
        break;

    case 0:
        if (interval)  {
            interval = 0;
            digitalWrite (pinsLed [0], Off);
        }
        else {
            msecLst  = msec;
            interval = OneSecond / 4;
        }
        break;
    }
}

// -----------------------------------------------------------------------------
void
setup ()
{
    Serial.begin (9600);

    for (unsigned n = 0; n < sizeof(pinsBut); n++)  {
        pinMode (pinsBut [n], INPUT_PULLUP);
        butState [n] = digitalRead (pinsBut [n]);
    }

    for (unsigned n = 0; n < sizeof(pinsLed); n++)  {
        digitalWrite (pinsLed [n], Off);
        pinMode      (pinsLed [n], OUTPUT);
    }
}

This tutorial covers millis delays/timers
How to write Timers and Delays in Arduino
To get the best effect you should combine that with a tasked based coding approach
see Multi-tasking in Arduino
For debouncing see this tutorial Debouncing Switches in Arduino

multitaskingDiagramSmall