正弦波ASCIIアートアニメーションテキスト


11

コンピューターがi3、i5、i7の代わりにx86と呼ばれたときのコンピューターの機能を示す古いデモを見逃しています。386で最初に見たものの1つは、現在25周年を迎えているFuture CrewのUnrealデモでした。午前043分にデモの最初の部分が開始され、正弦波のパスに沿ってスクロールテキストが表示されます。ASCIIアートでその効果を模倣してみましょう!

チャレンジ

このパスが与えられた場合:

***                                ***
   ***                          ***
      **                      **
        *                    *
         *                  *
         *                  *
          *                *
           **            **
             ***      ***
                ******

そして、入力テキスト、このパスに続くテキストを次のように描画します。

Thi                                Golf! 
   s i                          de       Yay
      s                       Co            !
        P                     
         r                  d
         o                  n
          g                a
           ra            s 
             mmi      zle
                ng Puz

スペースはパス内の文字としてカウントされ、テキストがサンプルよりも長い場合はパスが繰り返されることに注意してください。

アニメーション部分

テキストを描画したら、100 ms待機して(約10 fpsのアニメーションを作成する)、テキストを再度描画しますが、パスの次の位置から開始します。したがって、frameの#n場合n modulo 40、パスの次の位置で計算し、描画を開始します。テキストは常にキャンバスの左側に配置されます。

***                                ***
|  ***                          ***  |
|     **                      **     |
|       *                    *       |
|        *                  *        |
|        *                  *        |
|         *                *         |
|          **            **          |
|            ***      ***            |
|               ******               |
Position 0                 Position 39

したがって、フレーム10には次のものがあります。

                           and Co
                        es       de 
                      zl            Go
                     z                l
                    u                  f
T                   P                  !
 h                                       
  is             ng                       Ya
     is       mmi                           y!
        Progra

ノート

  • 入力は、アニメーション化するテキストを含む単一string(またはchar配列)であり、常に少なくとも1文字が含まれます。
  • アニメートする有効な文字は、印刷可能なASCIIセット内の文字です
  • フォローするパスは、指定されたとおりになります。
  • テキストは常にキャンバスの左側に配置されるため、効果は、テキストの移動なしで、旗のように手を振るテキストになります。そして、キャンバスとは、スクリーンまたはテキストを表示するために使用するものを意味します。;-)
  • 文字/ピクセルが両方のフレームで同じでない限り、フレームは前のフレームの文字/ピクセルをクリアする必要があります。
  • アニメーションの速度は、スムーズに実行される限り、またはデバイスができる限り高速である限り重要ではありません(最低5 fpsを設定できますが、これは要件ではありません)。速度を調整するだけで滑らかになり、待ち時間がまったく同じであるかどうか心配する必要はありません。
  • アニメーションは無限にループします。

これはなので、テキストをアニメーション化できる最短のプログラムまたは機能が勝つかもしれません!



1
私は38列ではなく、40カウントすることができます
アルノー

1
@Arnauldは、カウントするのは列ではなくパス内の位置だからです。
チャーリー

ああなるほど。理にかなっています。
アーナウド

これは出力として大丈夫ですか?入力を正弦波の形で表示し、無限にループします。もちろん、ビデオはグラフィックス交換形式であるため、実際にはより高速です。
R. Kap

回答:


9

HTML + ES6、241の 244 237バイト

壊す:

  • HTML:16バイト
  • JS関数:221バイト

let f =

s=>setInterval(_=>o.innerHTML=[...s].map((c,i)=>([j,y]=[...Array(40)].map((_,k)=>[j=k%20,y,y+=77732>>j&1?k<20||-1:0],y=0)[(i+p)%40],a[y]=a[y]||[...s].fill` `)[x]=(x+=j!=9,c),x=0,a=[],p++)&&a.map(r=>r.join``).join`
`,p=30)

f("This is Programming Puzzles and Code Golf! Yay!")
<pre id=o></pre>

どうやって?

パスを構築する

次のコードはパスを作成します。

[...Array(40)].map((_, k) =>
  [
    j = k % 20,
    y,
    y += 77732 >> j & 1 ? k < 20 || -1 : 0
  ],
  y = 0
)

これは配列の配列与えるjは位置モジュロ20であるが、yはこの位置でy座標であり、Zは、(それだけでいくつかのバイトを節約するためにここで計算されることを起こる)後は使用されません。[j, y, z]

パスは対称であるため、最初の20の位置のみをエンコードする必要があります。各1ビットがyを更新する必要があることを意味する2進数を使用して、これを行います(前半に+1、後半に-1)。

001
   001
      01
        1
         1
         1
          1
           01
             001
                000

最初の位置が最下位ビットにマッピングされると、次のようになります。

00010010111110100100 as binary = 77732 as decimal

この2進数自体も対称であるため、後半についても同じ順序で読み取ることができます。

したがって、式:

y += (77732 >> j) & 1 ? (k < 20 ? 1 : -1) : 0

次のように書くこともできます。

y += (77732 >> j) & 1 ? k < 20 || -1 : 0

ここで、kは位置、jは20を法とする位置です。

xの更新は非常に簡単です。20を法とする位置を9と比較することで検出する特別なケースが1つあります。

テキストを描く

次のコードでは、上記のパス構築コードpathが読みやすいように変数に置き換えられています。

s => setInterval(                       // set a periodic timer:
  _ =>                                  //   with an anonymous callback
    o.innerHTML =                       //   which updates the content of 'o'
      [...s].map((c, i) => (            //   for each character c of the string s
          [j, y] = path[(i + p) % 40],  //     retrieve j and y from the path
          a[y] = a[y] || [...s].fill` ` //     initialize a[y] if it's undefined
        )[x] = (x += j! = 9, c),        //     update a[y][x] / update x
        x = 0,                          //     initialize x
        a = [],                         //     initialize a[]
        p++                             //     increment the phase
      ) &&                              //   end of map()
      a.map(r => r.join``).join`\n`,    //   join everything together
  p = 30                                //   initial phase = interval period = 30
)                                       // end of timer definition

これは素晴らしく、質問されたパスに非常に近いものですが、パスは正確には私が描いたものではありません。*垂直方向に2を含む2つの列は(同じ高さで)位置合わせされておらず、別の小さなニッチがあります。しかし、あなたのコードがどのように波の効果を作成するのかまだわからないと言わなければなりません(何をしy+=155464ますか?)。おめでとう!
チャーリー

@CarlosAlejoパスを修正する必要があると思います。再確認していただけますか?使用する方法の説明を追加します。
アーナウド

1
パスが確認されました。説明をありがとうございます。
チャーリー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.