     // Check if button is still low after debounce.
     buttonNewState = digitalRead(BUTTON_PIN);
     if (buttonNewState == LOW) {
-      animationIndex++;
-      if (animationIndex >= (sizeof(animations) / sizeof(NeoPixelAnimation *))) {
-        animationIndex = 0;        
-      }
-      animations[animationIndex]->reset();
+      buttonPressed();
+      delay(20);
     }
   }
   buttonPreviousState = buttonNewState;
 }
 
+void buttonPressed() {
+  if(cycleAnimations) {
+    cycleAnimations = false;
+    return;
+  }
+  if (animationIndex == animationCount - 1) { //last animation
+    cycleAnimations = true;
+    timeForNextAnimation = millis() + ANIMATION_CYCLE_INTERVAL;
+  }
+  nextAnimation();
+}
+
+void checkTimeForNextAnimation() {
+  unsigned long currentTime = millis();
+  if (currentTime >= timeForNextAnimation) {
+    nextAnimation();
+    timeForNextAnimation = millis() + ANIMATION_CYCLE_INTERVAL;
+  }
+}
+
+void nextAnimation() {
+  animationIndex++;
+  if (animationIndex >= animationCount) {
+    animationIndex = 0;
+  }
+  animations[animationIndex]->reset();
+}
+

TheaterChaseAnimation theaterChaseAnimation(&strip);
RainbowCycleAnimation rainbowCycleAnimation(&strip);
NeoPixelAnimation *animations[] = {&rainbowAnimation, &fadeAnimation, &sparksAnimation, &theaterChaseAnimation, &rainbowCycleAnimation};

bool buttonPreviousState = HIGH;
byte animationIndex = 0;

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);

  strip.begin();
  strip.setBrightness(20);
  strip.show();

  timeForNextAnimation = millis() + ANIMATION_CYCLE_INTERVAL;
}

void loop() {
  if (cycleAnimations) {
    checkTimeForNextAnimation();
  }
  checkButton();
  animations[animationIndex]->nextFrame();
}
