Bug Race in a Single Tween

// the entire game engine is in a single GSAP tween!
gsap.to(".bug", {
  x:function() {
    return "+=" + gsap.utils.random(0, 75) // make the 50 bigger to go faster
  },
  repeat:-1,
  repeatRefresh:true,
  onUpdate: function() {
    let finishPos = document.querySelector(".finishLine").getBoundingClientRect().left
    this.targets().forEach(function(el){
      if(gsap.getProperty(el, "x") > finishPos) {
        gsap.to(el, {filter:"brightness(2)", repeat:6, yoyo:true, duration:0.1})
        gsap.getTweensOf(el)[0].pause()
      }
    })
  }
})

Bug Race #2

// BUG test #2 --------------------------------
let bugs = gsap.utils.toArray(".bugs-2 .bug")
let jerkLevel = 0.2
function moveMe(bug) {
    let endX = (Power4.easeIn(Math.random())*200)+25 // gsap.utils.random(10,100)
    let delay = Power4.easeIn(Math.random())
    let rotation = 0
    if(Math.random() < jerkLevel) { endX = -endX rotation = 180 } gsap.to(bug, {rotation:rotation, duration:0.05}) gsap.to(bug, { duration:gsap.utils.random(0.5, 1.5), x:"+=" + endX, delay:delay, ease:"power3", onComplete:moveMe, onCompleteParams:[bug] }) } bugs.forEach( (el) => moveMe(el) )

document.addEventListener("click", () =>
  gsap.globalTimeline.paused(!gsap.globalTimeline.paused()))
    
gsap.ticker.add(checkWinner)  // ticker - every 1/60s checked  

function checkWinner() {
    let finishPos = document.querySelector(".finishLine2").getBoundingClientRect().left
    bugs.forEach(function(el) {
        if(gsap.getProperty(el,"x") > finishPos) {
            gsap.killTweensOf(".bugs-2 .bug")
            gsap.to(el, {filter:"brightness(2)", repeat:6, yoyo:true, duration:0.1, delay:0.001})
            gsap.ticker.remove(checkWinner)
        }
    })
}