Rewind rect() x position for endless movement



  • Hi!

    I am struggling to think of a way to endlessly move a rect() along X axis and "rewind" back to 0 once it moves past page bounds – essentially creating a smooth movement.

    Here‘s my code: it kind of works, but it starts to break as soon the cycle runs repeatedly.

    I know there must be a mistake sowewhere and my terrible math skills only got me so far:

    Variable([
        dict(name="progress", ui="Slider",
                args=dict(
                    value=0,
                    minValue=0,
                    maxValue=1,
                    )),
        ], globals())
    
    # Use page dimensions as frame for debugging
    pageW, pageH = (500, 500)
    
    # Arbitrary backgrounds to tell them apart
    backgrounds = [(0.5, 1, 0.5), (0.5, 1, 1), (0.5, 0, 0), (1, 1, 0), (0.5, 0, 1), (0.5, 0.5, 0.5), (0, 1, 0)]
    
    newPage(900, 900)
    
    itemCount = 6
    itemW = 100
    itemH = pageH
    
    translate(200, 200)
    offsetX = (progress * pageW) * 4 # Speed up 4x
    
    for item in range(itemCount):
        # Position on init
        startingX = item * itemW
        
        # Move in time
        currentX = startingX + offsetX
        
        # How many times whole cycle elapsed
        fullProgressCount = offsetX // pageW
        
        # How many times this item elapsed
        elapsedCount = (currentX) // pageW
        
        # Rewind to beginning
        rewind = (elapsedCount * pageW) + itemW if elapsedCount else 0
        
        # Real X position
        realX = currentX - rewind
    
        # Fill and draw
        fill(*backgrounds[item])
        rect(realX, 0, itemW, itemH)
        
        # Debug item
        fill(0)
        text(f'{str(item)}\nReal: {round(realX)}\ncX: {round(currentX)}\nEl: {elapsedCount}\n{rewind}', (currentX - rewind, 560))
    
    # Debug status
    fill(0)
    text(f'{str(progress)}\n{offsetX}\n{fullProgressCount}', (-100, -100))
    
    # Draw debugging page frame
    with savedState():
        fill(None)
        stroke(0)
        rect(0, 0, pageW, pageH)
    

    Thanks so much for any pointers.


  • admin

    I guess you made it to difficult...

    
    Variable([
        dict(name="progress", ui="Slider",
                args=dict(
                    value=0,
                    minValue=0,
                    maxValue=1,
                    )),
        ], globals())
        
    backgroundColors = [
        (0.5, 1, 0.5), 
        (0.5, 1, 1), 
        (0.5, 0, 0), 
        (1, 1, 0), 
        (0.5, 0, 1), 
        (0.5, 0.5, 0.5), 
        (0, 1, 0)
    ]
    
    # pageW, pageH = (500, 500)
    pageW, pageH = width(), height()
    
    
    advance = pageW * progress
    
    itemCount = len(backgroundColors)
    itemWidth = pageW / (itemCount)
    
    moveIndex = int(advance * progress // itemWidth)
    backgroundColors = backgroundColors[-moveIndex:] + backgroundColors
    
    for i in range(0, itemCount + 1):
        color = backgroundColors[i]
        fill(*color)    
        rect(itemWidth * (i-moveIndex) - itemWidth + advance * progress, 0, itemWidth, pageH)
    
    fill(None)
    stroke(0)
    strokeWidth(10)
    rect(0, 0, pageW, pageH)
    
    


  • Hello @frederik, thanks so much for your input.

    Wow, works just as I described. The problem is I failed to mention I will want to use those rect() as a clipMask() for text, creating a sort of a parallax effect – something like https://dailydrawbot.tumblr.com/post/135907707375/how-now-brown-cow-references-in-this-thread-on.

    Thus I need rect() to maintaint its order/index. Here‘s my (faulty) code that I made initially but gave up and thought I will try to fix the endless move across X axis first:

    The "optical" effect is more of less how I want it, but the loop breaks as before.

    import math
    
    Variable([
        dict(name="progress", ui="Slider",
                args=dict(
                    value=0,
                    minValue=0,
                    maxValue=1,
                    )),
        ], globals())
    
    pageW, pageH = 500, 500
    steps = 5
    stepW = int(pageW/steps)
    
    # Canvas with one step more
    extendedW = pageW + stepW
    
    textString = "O"
    oneside = math.floor(steps/2)
    fs = 300
    pushX = progress * pageW
    
    newPage(pageW, pageH)
    
    text(str(pushX), (5, 5))
    
    # Draw one extra step
    for i, stepStartX in enumerate(range(0, extendedW, stepW)):
        elapsed = (stepStartX+pushX)//(pageW+stepW)
    
        if elapsed:    
            stepStartX -= (elapsed * pageW) + stepW
            
        x1 = stepStartX + pushX
        x2 = x1 + stepW
        
        mask = BezierPath()
        mask.moveTo((x1, 0))
        mask.lineTo((x2, 0))
        mask.lineTo((x2, pageH))
        mask.lineTo((x1, pageH))
        mask.closePath()
        
        stroke(None)
        fill(0)
        fontSize(fs)
        textW, textH = textSize(textString)
        stepCenter = x1+(stepW-textW)/2
        
        offset = (x1-(oneside*stepW))*-0.5
        
        # Draw mask
        with savedState():
            fill(None)
            stroke(random())
            drawPath(mask)
        
        with savedState():
            fontSize(8)
            text(f'{i}\nStepStartX: {stepStartX}\nx1: {x1}\nelapsed: {elapsed}', (x1, pageH-10))
        
        with savedState():
            clipPath(mask)
            translate(offset, 0)
            textBox(textString, (stepCenter, (pageH-textH)/2, textW, textH))
    

    Any chance you could tell me what I am doing wrong please?

    Thanks for your time :—)


Log in to reply