Can a timer be used for one part of a sketch?

I have modified a sketch that the original programmer is using a 30 sec delay. I have added 2 more sensors with led's and the dfplayer and I'm stuck with everything in the 30 sec delay. My question is it possible to set timers on sensors 1 & 2 sequences without affecting sensors 3 & 4. I have read thru a couple of tutorials but since I am still pretty new to writing code I am having trouble understanding it. Any help would be appreciated.

// Example Level Crossing Control Driving Common Cathode LEDs
// Version 1.4  Geoff Bunza 2018
// Uses software servo Library
//
#include <DFRobotDFPlayerMini.h>
#include <SoftwareSerial.h>
#include <Servo.h>

SoftwareSerial mySoftwareSerial(0, 1);
DFRobotDFPlayerMini myDFPlayer;

Servo gate1servo;  // create servo object to control crossing gate 1
                   //ASSUMPTION Gate is down at position 30 and up at position 120
Servo gate2servo;  // create servo object to control crossing gate 2
                   //ASSUMPTION Gate is down at position 30 and up at position 120
int sensor1 = 5;   // IR sensor pin Assumption== Pin goes LOW when train detected
int sensor2 = 6;   // IR sensor pin Assumption== Pin goes LOW when train detected
int sensor3 = 7;
int sensor4 = 8;
int led1 = 10;      // Led 1 pin first alternating flasher
int led2 = 11;      // Led 2 pin first alternating flasher
int led3 = 12;      // Led 3 pin second alternating flasher
int led4 = 13;     // Led 4 pin second alternating flasher
int led5 = A0;
int led6 = A1;
int gatelow = 30;        // variable to store the servo low gate stop position
int gatehigh = 120;    // variable to store the servo high gate stop position
int gateposition = 120;    // variable to store the servo gateposition
int entering_sensor = 5;       //this will tell which sensor was triggered first
int leaving_sensor = 6;        // this will tell which sensor shows train leaving
int gates_started = 0;         // this says if the crossing is active
int flash_state = 0;
long flash_time = 0;
long  flash_interval = 900;    // time in milliseconds between alternating flashes
int sensor_count = 0;
void setup()
{
  gate1servo.attach(3);  // attaches the servo on pin 3 to the servo object
  gate2servo.attach(4);  // attaches the servo on pin 4 to the servo object
  gate1servo.write(gateposition);  //start assuming no train
  gate2servo.write(gateposition);  //start assuming no train
  pinMode(sensor1, INPUT);  
  pinMode(sensor2, INPUT);
  pinMode(sensor3, INPUT);
  pinMode(sensor4, INPUT);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);  
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(led5, OUTPUT);
  pinMode(led6, OUTPUT);
  digitalWrite(led1, LOW);  // Start with all flashers off
  digitalWrite(led2, LOW);
  digitalWrite(led3, LOW);
  digitalWrite(led4, LOW);
  digitalWrite(led5, LOW);
  digitalWrite(led6, LOW);
  flash_time = millis();
  mySoftwareSerial.begin(9600);
  myDFPlayer.begin(mySoftwareSerial);
  myDFPlayer.setTimeOut(500);
  myDFPlayer.volume(15);
  myDFPlayer.EQ(DFPLAYER_EQ_BASS);
  myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);
}
void loop()
{
  if ((digitalRead (sensor3)==LOW)) {
    digitalWrite(led5, HIGH);
  }
  else if ((digitalRead (sensor3)==HIGH)) {
    digitalWrite(led5, LOW);
  }
  if ((digitalRead (sensor4)==LOW)) {
    digitalWrite(led6, HIGH);
  }
  else if ((digitalRead (sensor4)==HIGH)) {
    digitalWrite(led6, LOW);
  }
  if ((digitalRead (sensor1)==LOW)&& (gates_started==0)) {
    gates_started = 1;
    leaving_sensor = sensor2;
    starting_sequence();
  }
  if ((digitalRead (sensor2)==LOW)&& (gates_started==0)) {
    gates_started = 1;
    leaving_sensor = sensor1;
    starting_sequence();
  }
  if (gates_started) flash_leds();   //gates are down continue flashing
  if ((digitalRead(leaving_sensor)==LOW)&&(gates_started==1)) {   //train is starting to leave
   
  //as long as the leaving sensor is active the train is still in the crossing
  while (gates_started==1)  {   //now check if train is REALLY gone
    sensor_count = 0;
    for (int i=1; i<40; i++)  {
      if (digitalRead(leaving_sensor)==LOW) sensor_count++;
          delay (30);
                  flash_leds();
                  }
    if (sensor_count==0) gates_started=0;
    flash_leds();
    }
    // we only get here if the train has really left the crossing
                ending_sequence();
  }
}
void starting_sequence()  {
  myDFPlayer.play(1);
  long wait_time;
  flash_time = millis();
  wait_time = millis()+3000;
  while (wait_time > millis())  flash_leds();  //flash before dropping gates
  for(gateposition = gatehigh; gateposition>gatelow; gateposition-=1)  // goes from gatehigh degrees to gatelow degrees
  {                               
    gate1servo.write(gateposition);  // tell servo to go to gateposition in variable 'gateposition'
    gate2servo.write(gateposition);  // tell servo to go to gateposition in variable 'gateposition'
    flash_leds();                    // keep flashing leds
    delay(40);                       // waits 40ms to slow servo
  }
}
void ending_sequence()  {
    for(gateposition = gatelow; gateposition<gatehigh; gateposition++)   // goes from gatelow degrees to gatehigh degrees
  {                               
    gate1servo.write(gateposition);  // tell servo to go to gateposition in variable 'gateposition'
    gate2servo.write(gateposition);  // tell servo to go to gateposition in variable 'gateposition'
    flash_leds();                    // keep flashing leds
    delay(40);                       // waits 40ms to slow servo
  }
  myDFPlayer.pause();
  digitalWrite(led1, LOW);  //  flashers completely off
  digitalWrite(led3, LOW);
  digitalWrite(led2, LOW);
  digitalWrite(led4, LOW); 
  delay(30000);             // 30 second delay to account for the train passing the starting entry sensor
}
void flash_leds()  {
  if (flash_time > millis()) return;
  flash_state = ~flash_state;
  digitalWrite(led1, flash_state);  // Alternate flashers
  digitalWrite(led3, flash_state);
  digitalWrite(led2, ~flash_state);
  digitalWrite(led4, ~flash_state);
  flash_time = millis()+flash_interval;
}

By using the while loop and using the delay you stop your Arduino from doing anything else during that period. Read up on blink without delay and doing several things at once to get an idea of what is best practice as far as timing and delays are concerned.

I think it explains in the tutorials, but if not, the way comparisons are done regarding timing is by using subtraction

if(millis() - startTime >= timedPeriod)

and variables that are compared with millis are unsigned long, not long (since a time cannot be negative).

The only delay is at the end of ending_sequence(), right? Here's one idea.

First put the sensor 3 and 4 code in their own function.

void checkSensors()
{
  digitalWrite(led5, !digitalRead (sensor3));
  digitalWrite(led6, !digitalRead (sensor4));

}

Call the function at the start of loop().

void loop()
{
  checkSensors();

Remove the call to delay() at the end of ending_sequence().

Add the delay in loop() after the call to ending_sequence() using millis() so that you can continue to check the two sensors.

    // we only get here if the train has really left the crossing
    ending_sequence();

    // 30 second delay to account for the train passing the starting entry sensor
    unsigned long startDelay = millis();
    while ( (millis() - startDelay) < 30000 )
    {
      checkSensors();
    }

Unfortunately it doesn't work for just one part. All of the sketch must be re-written to use millis.

The way I read the requirement, there is a :30 delay and during that :30 sensors 3 and 4 need to be monitored. Based on that requirement, what doesn't work?

Thank You Blue Eyes, I will give that a try and thanks Metallor for the links. I appreciate the help