|
| 1 | +/** |
| 2 | + * @title Infinite Circles |
| 3 | + * @author Jack B. Du |
| 4 | + * @github jackbdu |
| 5 | + * @created 2025-10-13 |
| 6 | + * @pull_request 162 |
| 7 | + * @thumbnail_start 33 |
| 8 | + */ |
| 9 | + |
| 10 | +/** |
| 11 | + * ============================================================================ |
| 12 | + * = Infinite Circles = |
| 13 | + * ============================================================================ |
| 14 | + */ |
| 15 | + |
| 16 | +const backgroundChars = '{------}'; |
| 17 | +const foregroundChars = '{CIRCLE}'; |
| 18 | + |
| 19 | +const circleFrequency = recho.number(4, {min: 1, max: 6, step: 1}); |
| 20 | +const animationRate = recho.number(1, {min: 1, max: 4, step: 1}); |
| 21 | + |
| 22 | +const cols = 75; |
| 23 | +const rows = 18; |
| 24 | +const aspectRatio = cols/rows*0.5; |
| 25 | + |
| 26 | +const frameRate = 60; |
| 27 | +const loopFrames = Math.floor(30/animationRate); |
| 28 | +const frameCount = recho.interval(1000/frameRate); |
| 29 | +const progress = (frameCount) => frameCount%loopFrames/loopFrames; |
| 30 | + |
| 31 | +const TAU = Math.PI*2; |
| 32 | + |
| 33 | +//➜ {---CLE}{------}{CIRC--}{---CLE}{CIRCLE}{CIRCLE}{------}{CIRC--}{--RCLE}{-- |
| 34 | +//➜ ---}{CIR---}{CIRCLE}{----LE}{CIRCLE}{CIRCLE}{CIRCLE}{----LE}{CI----}{CIRC-- |
| 35 | +//➜ {-IRCLE}{---CLE}{------}{CIRCL-}{------}{-----E}{CIRC--}{--RCLE}{----LE}{C- |
| 36 | +//➜ --E}{C-----}{CIR---}{-IRCLE}{------}{------}{---CLE}{C-----}{CIRC--}{-IRCL- |
| 37 | +//➜ {CIRCL-}{-IRCLE}{---CLE}{C-----}{CIRCLE}{CI----}{-IRCLE}{----LE}{C----E}{CI |
| 38 | +//➜ CLE}{-----E}{C-----}{CIR---}{-IRCLE}{CIRCLE}{C-----}{CIRC--}{-IRCL-}{--RCLE |
| 39 | +//➜ {CIRC--}{CIRCL-}{--RCLE}{---CLE}{CI----}{CIRCLE}{----LE}{-----E}{CI----}{CI |
| 40 | +//➜ CLE}{----LE}{-----E}{CI----}{CIR---}{------}{CIRC--}{CIRCL-}{--RCLE}{---CLE |
| 41 | +//➜ {CIR---}{CIRC--}{-IRCL-}{--RCLE}{----LE}{----LE}{-----E}{C-----}{CI----}{CI |
| 42 | +//➜ CLE}{----LE}{-----E}{C-----}{CI----}{CIR---}{CIRC--}{-IRCL-}{--RCLE}{---CLE |
| 43 | +//➜ {CIR---}{CIRC--}{-IRCL-}{--RCLE}{----LE}{----LE}{-----E}{C-----}{CI----}{CI |
| 44 | +//➜ CLE}{----LE}{-----E}{CI----}{CIR---}{------}{CIRC--}{CIRCL-}{--RCLE}{---CLE |
| 45 | +//➜ {CIRC--}{CIRCL-}{--RCLE}{---CLE}{CI----}{CIRCLE}{----LE}{-----E}{CI----}{CI |
| 46 | +//➜ CLE}{-----E}{C-----}{CIR---}{-IRCLE}{CIRCLE}{C-----}{CIRC--}{-IRCL-}{--RCLE |
| 47 | +//➜ {CIRCL-}{-IRCLE}{---CLE}{C-----}{CIRCLE}{CI----}{-IRCLE}{----LE}{C----E}{CI |
| 48 | +//➜ --E}{C-----}{CIR---}{-IRCLE}{------}{------}{---CLE}{C-----}{CIRC--}{-IRCL- |
| 49 | +//➜ {-IRCLE}{---CLE}{------}{CIRCL-}{------}{-----E}{CIRC--}{--RCLE}{----LE}{C- |
| 50 | +//➜ ---}{CIR---}{CIRCLE}{----LE}{CIRCLE}{CIRCLE}{CIRCLE}{----LE}{CI----}{CIRC-- |
| 51 | +{ |
| 52 | + const text = new Array(rows).fill(0).map((_,r,rowArray)=>{ |
| 53 | + |
| 54 | + return new Array(cols).fill(0).map((_,c,colArray)=>{ |
| 55 | + |
| 56 | + const t = progress(frameCount); |
| 57 | + const y = r/rowArray.length-0.5; |
| 58 | + const x = (c/colArray.length-0.5)*aspectRatio; |
| 59 | + |
| 60 | + const backgroundCharOffset = r*Math.floor(backgroundChars.length/2); |
| 61 | + const backgroundCharIndex = (c+backgroundCharOffset)%backgroundChars.length; |
| 62 | + const foregroundCharOffset = r*Math.floor(foregroundChars.length/2); |
| 63 | + const foregroundCharIndex = (c+foregroundCharOffset)%foregroundChars.length; |
| 64 | + |
| 65 | + const radius = Math.sqrt(x*x+y*y); |
| 66 | + const char = Math.sin(radius*TAU*circleFrequency+t*TAU) > 0 ? |
| 67 | + backgroundChars[backgroundCharIndex] : foregroundChars[foregroundCharIndex]; |
| 68 | + |
| 69 | + return char; |
| 70 | + |
| 71 | + }).join(''); |
| 72 | + |
| 73 | + }).join('\n'); |
| 74 | + |
| 75 | + echo(text); |
| 76 | +} |
0 commit comments