Zenn
📚

shアニメーションでも生成させてみるか

に公開

cursorを初めて使ったので、まずはchatしながら形作ることにした。
エディタと一体化しているのはやはり便利ですね~

テーマは、蠟燭の火。結局アスキーアートはいいのが生成させられず、自作しました.

コード

#!/bin/bash

# 画面をクリアする関数
clear_screen() {
    clear
}

fire_slices=(
"                    ##                 "
"                   ####                "
"                 ###**###              "
"               ###**##**###            "
"              ###**####**###           "
"             ###**##||##**###          "
"           ####**##||||##**####        "
"          ####**##||||||##**####       "
"          ###**##||||||||##**###       "
"          ###**##||||||||##**###       "
"           ###**##||||||##**###        "
"            ###**##||||##**###         "
"             ###**#||||#**###          "
"                ##**||**##             "
)

# 行数を計算
num_lines=${#fire_slices[@]}

# 各行の最大シフト量を計算
declare -a max_shifts
for i in $(seq 0 $((num_lines-1))); do
    line="${fire_slices[$i]}"
    # 左側のスペースの数を数える
    left_spaces=$(echo "$line" | grep -o '^ *' | wc -c)
    left_spaces=$((left_spaces - 1))  # 末尾の改行を除く
    # 右側のスペースの数を数える
    right_spaces=$(echo "$line" | grep -o ' *$' | wc -c)
    right_spaces=$((right_spaces - 1))  # 末尾の改行を除く
    # 左右の小さい方を最大シフト量とする
    max_shifts[$i]=$((left_spaces < right_spaces ? left_spaces : right_spaces))
done

# 各行の前回のシフト量を保持する配列
declare -a prev_shifts
for i in $(seq 0 $((num_lines-1))); do
    prev_shifts[$i]=0
done

# 一行目の動きの制御用変数
direction=1  # 1: 右向き, -1: 左向き
target_pos=10  # 目標位置(左右の端)

# メインループ
while true; do
    clear_screen
    
    # 一行目の動きを制御
    # 現在の位置が目標位置に達したら向きを反転
    if [ ${prev_shifts[0]} -ge $target_pos ]; then
        direction=-1
    elif [ ${prev_shifts[0]} -le -$target_pos ]; then
        direction=1
    fi
    
    # 1-4文字のランダムな移動量を決定
    move_amount=$((RANDOM % 4 + 1))
    
    # 一行目の新しいシフト量を計算
    new_shift=$((prev_shifts[0] + direction * move_amount))
    # シフト量の範囲を制限
    if [ $new_shift -gt $target_pos ]; then
        new_shift=$target_pos
        direction=-1
    elif [ $new_shift -lt -$target_pos ]; then
        new_shift=-$target_pos
        direction=1
    fi
    prev_shifts[0]=$new_shift
    
    # 各行を表示
    for i in $(seq 0 $((num_lines-1))); do
        if [ $i -gt 0 ]; then
            # 2行目以降は上の行の動きに追従
            # 上の行の前回のシフト量に近づくように調整
            prev_line=$((i-1))
            diff=$((prev_shifts[prev_line] - prev_shifts[i]))
            # diffの絶対値を取得
            abs_diff=${diff#-}
            # abs_diffが0の場合は小さなランダムな動きを生成
            if [ $abs_diff -eq 0 ]; then
                random_step=$((RANDOM % 3 - 1))  # -1, 0, 1のいずれか
            else
                # 1からabs_diffまでのランダムな値を生成
                random_step=$((RANDOM % abs_diff + 1))
                # diffの符号に応じてrandom_stepを加算または減算
                if [ $diff -lt 0 ]; then
                    random_step=$((random_step * -1))
                fi
            fi
            new_shift=$((prev_shifts[i] + random_step))
            # シフト量の範囲を制限
            if [ $new_shift -gt ${max_shifts[$i]} ]; then
                new_shift=${max_shifts[$i]}
            elif [ $new_shift -lt -${max_shifts[$i]} ]; then
                new_shift=-${max_shifts[$i]}
            fi
            prev_shifts[$i]=$new_shift
        fi
        
        # 行をシフトして表示
        line="${fire_slices[$i]}"
        shift=${prev_shifts[$i]}
        if [ $shift -gt 0 ]; then
            # 右にシフト
            echo -e "\033[33m$(printf "%*s%s" $shift "" "$line")\033[0m"
        else
            # 左にシフト
            shift=${shift#-}  # 絶対値を取る
            echo -e "\033[33m${line:$shift}\033[0m"
        fi
    done
    echo -e "        |========================|        "
    echo -e "        |========================|        "
    echo -e "        |========================|        "
    echo -e "        |========================|        "
    echo -e "        |========================|        "
    echo -e "        |========================|        "
    sleep 0.05
done

生成AIのパワーを感じたところ

別にcursrorだからということではありませんが。

まず、

黄色で表示されるため、より本物の炎に近い見た目になります

こんなメッセージを最初の生成時に返してきたところ。確かにね。ありがとう。

次に、下記の指示を出したときのこと。

一行目のshiftをランダムウォーク的に決定し、それ以降の行は、自分の一個上の行の前回のシフト量をもとに少し変化する形で決定できますか

これで、

        if [ $i -gt 0 ]; then
            # 2行目以降は上の行の動きに追従
            # 上の行の前回のシフト量に近づくように調整
            diff=$((prev_shifts[$((i-1))] - prev_shifts[$i]))
            new_shift=$((prev_shifts[$i] + diff/2))
            # シフト量の範囲を制限(以下略)

を出してきたところ。特殊な指示ではないにしろ、ふわっとしたのでそこそこのコード乃至アルゴリズムを出してこられると感心してしまう。

その後、下記の指示を出した

一行目は単純なランダムウォークではなく、決まった数字まで左右どちらかに進み続け、その数字分進んだら向きを変える、ということを繰り返す方式にしてください。

これぐらいの指示レベルで行けちゃうのはえらい

Discussion

ログインするとコメントできます