GODRICH
#cssアニメーション#ボタン#ローディング#トランジション#スクロール#ダッシュボード#実用ui#デザイントレンド

歩くアニメーション 作り方 9種 — 計算で歩かせるサイクル

歩行は前へ倒れる体を脚が交互に支える計算です — 02番は接地から持ち上げまで五つの局面で足の裏が床に張り付く時間を作り、03番は歩幅を開く角度で速さを決め、07番は下り坂で体を前に傾けて脚が体勢を立て直す時間を稼ぎます。

キャラクターの歩くアニメーションは、ポーズを順にめくる再生ではなく、前傾する体を二本の脚が交互に床へ押す角度を毎フレーム計算して歩いているように見せるものです — 歩くアニメーションの作り方はサイクル位相から始まります

自動再生 · タイルを押すとその項目へ · すべて1つのzip

九つの場面は同じ歩きの時計と同じ脚の解き方を使い、場面ごとに違うのは見る値ひとつだけです。キャラクターは画面の中央で足踏みの位置のまま歩き、床の目盛りと背景の丘や雲が groundV の速さで後ろへ流れます。

歩きの状態は歩行周期の計算からだけ作ります

時計は二つです。歩きの時計 walkT は歩きの位相を決め、場面の時計 sceneT は向きの転換や斜面の切り替えのような時間表を回します。脚の角度・足の位置・腕の振りは (walkT * STEP_HZ) % 1 から解いて出し、保存した歩きの絵はありません。

    function advance(dt) {
        sceneT += dt;
        walkT += dt;
        if (!manual) {
            while (evAt < script.length && script[evAt].t <= sceneT) {
                const ev = script[evAt];
                evAt += 1;
                ev.f();
            }
            if (sceneT >= LAP_S) {
                lap += 1;
                begin();
                return;
            }
        }
        update(dt);
    }

begin() が一判ごとに二つの時計を0に戻すので、同じ時間表は同じ歩きを出します。9つの index.html のどこにも Math.random・Date・performance・fetch はありません。

一歩は1/60秒で固定して消化します

フレームの間隔は DT_MAX の0.05秒で切って acc に積み、while (acc >= STEP_S) で STEP_S の1/60秒ずつ advance に渡します。タブが隠れるあいだはループを止め、戻ったら acc を空にして最初のフレームの dt を捨てるので、数秒が一フレームに集まって歩きが跳ぶことはありません。

歩きのサイクル 9種 — 位相のつなぎ・接地を含む五つの局面・歩幅の角度・頭の上下と視線・肘の逆振れ・胴の揺れ・斜面への対応・足の移動弧の補正・足裏の固定

九つの場面を描画して測った面積とフレーム

場面 累積面積 動いたフレーム 強さの平均
01 位相のつなぎ 21.4% 23/23 78.4
02 五つの局面 20.3% 23/23 62.0
03 歩幅の角度 13.5% 23/23 62.6
04 頭と視線 14.3% 23/23 70.5
05 肘 15.6% 23/23 78.9
06 胴のねじれ 14.9% 23/23 73.3
07 斜面への対応 20.2% 23/23 63.1
08 弧の補正 14.1% 23/23 64.9
09 足の固定の完成 16.1% 23/23 115.8

累積面積が最も広いのは01の21.4%で、最も狭いのは03の13.5%です。九つの場面はどれも23/23フレーム動き、強さの平均は09の115.8が最高で、最も低いのは02の62.0です。

01切れ目なくつながるサイクル位相

歩きを二歩でひと回りと見て、cyclePhase() は (walkT * STEP_HZ) % 2 を返し、legPhase() は右脚にだけ半歩を足して二本の脚を半歩ずらします。剰余で位相を切るので、最後のポーズと最初のポーズの間に歩くたび跳ぶ段差は生まれません。右のパネルの「つなぎの跳び」は一フレームで sin の値が0.35を超えて跳んだ回数で、同じ式をノードで3.75秒(225フレーム)回した値は0回でした。

継ぎ目なくつながるサイクル位相
新しいタブで開く

01 · 継ぎ目なくつながるサイクル位相 — 計測 累積面積 21.353% · 動いたフレーム 23/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

cyclePhaselegPhaseSTEP_HZwalkT
    const GAIT = { stepHz: STEP_HZ, strideDeg: STRIDE_DEG, legPx: LEG_PX, legRatio: LEG_RATIO, contactShare: CONTACT_SHARE };
    // walkT は歩きの時間だけで進む時計(秒)。phase は一歩の位相0〜1、cyclePhase は二歩の位相0〜2
    let walkT = 0;
    function stepPhase() { return (walkT * GAIT.stepHz) % 1; }
    function cyclePhase() { return (walkT * GAIT.stepHz) % 2; }
    function stepIndex() { return Math.floor(walkT * GAIT.stepHz); }
    // 脚ごとの一歩の位相 — 左脚が整数の歩、右脚が半歩ずれる
    function legPhase(right) { return ((walkT * GAIT.stepHz) + (right ? 0.5 : 0)) % 1; }

02接地から押し出しまで足の裏が張り付く五つの局面

一歩を接地12%・抵抗18%・中間15%・押し出し15%・持ち上げ40%に分け、CONTACT_SHARE の0.6の内側(inStance)では solveFoot が足首を床の高さに固定します。足首は接地で-14度で触れて0度に寝たあと、0.45歩を過ぎてからつま先で押しながら16度まで転がります。一歩0.63秒のうち接地が0.37秒、スイングが0.25秒です。

接地から蹴り出しまで足裏が張り付く五つの局面
新しいタブで開く

02 · 接地から蹴り出しまで足裏が張り付く五つの局面 — 計測 累積面積 20.344% · 動いたフレーム 23/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

PH5inStanceCONTACT_SHAREsolveFoot
    function drawStanceFoot(hipX, hipY, ph) {
        const fs = solveFoot(hipX, hipY, ph, plantXOf(0, hipX), 0, GROUND_Y);
        // 接地の局面: 足裏を床に付けたまま転がす — ankleDeg を ph で補間(かかとの接地 → つま先の押し出し)
        const roll = ph < 0.12 ? lerp(-14, 0, ph / 0.12) : (ph > 0.45 ? lerp(0, 16, (ph - 0.45) / (GAIT.contactShare - 0.45)) : 0);
        footShape(fs.ax, fs.ay, fs.planted ? roll : fs.ankleDeg, MINT);
        return roll;
    }

03歩幅の角度で歩く速さを決める

STRIDE_DEG の28度で一歩が押し出す距離は 2 * LEG_PX * sin(28度) の84.5pxで、これに STEP_HZ の1.6を掛けた135.2px/sが groundV に入り、床の目盛りがその速さで流れます。下の合わない判は体の速さを0.82倍の110.9px/sにして、接地した足が drift の分だけ這う軌跡を描いて見せます。接地の0.37秒に体が進む距離は50.7pxです。

歩幅の角度で歩みの速さを決める
新しいタブで開く

03 · 歩幅の角度で歩みの速さを決める — 計測 累積面積 13.483% · 動いたフレーム 23/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

STRIDE_DEGstepDistMISMATCHgroundV
    function build() {
        stepDist = 0;
        vOk = 0;
    }
    function update(dt) {
        if (dt <= 0) {
            return;
        }
        // 一歩の距離 — 前足の到達(前への開き)と後ろ足の押し出し(後ろへの開き)の合計
        stepDist = Math.sin(rad(GAIT.strideDeg)) * GAIT.legPx * 2;
        vOk = stepDist * GAIT.stepHz;
        groundV = vOk;
    }

04歩くたびに上下する頭と定まる視線

hipHeight が作る体の高さの揺れは振幅7.20pxで、頭は headY でその揺れの82%を逆に引くので目の振幅は1.3pxまで減り、目の高さがほぼ一定に見えます。向きが変わる2.4秒より0.4秒早く、視線 gazeX が320から120へ先に動いて次の向きを知らせます。

歩みごとに浮く頭と固定される視線
新しいタブで開く

04 · 歩みごとに浮く頭と固定される視線 — 計測 累積面積 14.278% · 動いたフレーム 23/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

hipHeightbobNowgazeXdirChangeAt
        const ph = legPhase(false);
        // 体の上下 — hipHeight がすでに ph のサイン。頭は半周ずれた位相で打ち消す
        bobNow = hipHeight(ph);
        headY = bobNow - 0.82 * (hipHeight(ph) - GAIT.legPx * 0.93);
        // 歩く向きの転換 — 転換の0.4秒前に視線が先に目標へ動く
        if (dirChangeAt > 0 && sceneT > dirChangeAt - 0.4 && sceneT < dirChangeAt) {
            const k = (sceneT - (dirChangeAt - 0.4)) / 0.4;
            gazeX = lerp(320, 120, k);
        }
        if (dirChangeAt > 0 && sceneT >= dirChangeAt) {
            gazeX = 120;
            dirChangeAt = -1;
        }

05脚と逆に振れる肘

solveArm は同じ側の脚から半歩ずれた armPh で肩を STRIDE_DEG * 0.6 の分、つまり最大16.8度振り、肘は 70 * (0.4 + LEG_RATIO) の大きさで最大61.6度曲げます。LEG_RATIO を0.42に下げると同じ式が57.4度を返すので、脚の比率を変えると腕の感じも一緒に動きます。

脚と逆に振れる肘
新しいタブで開く

05 · 脚と逆に振れる肘 — 計測 累積面積 15.59% · 動いたフレーム 23/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

solveArmLEG_RATIOARM_LbendBase
    // 腕の解き方 — 肩の角度(脚に比例・逆位相)と肘の曲がり(前のスイングで最大)。曲がりの尺度は LEG_RATIO
    function solveArm(shoulderX, shoulderY, side) {
        const ph = legPhase(side === 1);
        const armPh = (ph + 0.5) % 1;
        const swing = Math.sin(armPh * TAU);
        const deg = swing * GAIT.strideDeg * 0.6;
        const bendBase = Math.max(0, Math.sin(armPh * Math.PI)) * 70;
        const bend = bendBase * (0.4 + GAIT.legRatio);
        const a = rad(deg);
        const ex = shoulderX + Math.sin(a) * ARM_L;
        const ey = shoulderY + Math.cos(a) * ARM_L;
        const fa = a + rad(bend) * (Math.sin(a) >= 0 ? 1 : 0.6);
        const hx = ex + Math.sin(fa) * FORE_L;
        const hy = ey + Math.cos(fa) * FORE_L;
        return { ex: ex, ey: ey, hx: hx, hy: hy, bend: bend, deg: deg };
    }

06歩くたびに左右へ回る胴と骨盤

骨盤は hipTwist = sin(ph * TAU) * amp で回り、肩は逆向きに1.2倍(shTwist)回ります。amp は 6 * (STEP_HZ / 1.6) なので、1.6Hzで骨盤±6度・肩±7.2度になり、歩数が2.4Hzに上がると±9度・±10.8度に大きくなって、速く歩くほど胴がよくねじれます。

歩みごとに左右へ回る胴と骨盤
新しいタブで開く

06 · 歩みごとに左右へ回る胴と骨盤 — 計測 累積面積 14.933% · 動いたフレーム 23/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

hipTwistshTwistSTEP_HZlegPhase
    function update(dt) {
        if (dt <= 0) {
            return;
        }
        // 骨盤・肩の回転 — 歩きの位相のサインに比例し、大きさは歩く速さに比例(1.6Hzで±6度)
        const ph = legPhase(false);
        const amp = 6 * (GAIT.stepHz / 1.6);
        hipTwist = Math.sin(ph * TAU) * amp;
        shTwist = -Math.sin(ph * TAU) * amp * 1.2;
        if (Math.floor(sceneT * 30) % 2 === 0) {
            hipHist.push(hipTwist);
            shHist.push(shTwist);
            if (hipHist.length > 90) {
                hipHist.shift();
                shHist.shift();
            }
        }
    }

07斜面で体が傾く適応の歩き

leanDeg は下りの傾きに0.5、上りに0.25を掛けて体を傾け、下り-14度では体が7度前に倒れて baseStepHz + max(0, -lean) * 0.06 の式で歩数が1.6Hzから約2.02Hzに上がります。上り+10度では体が2.5度後ろに傾き、歩数は1.6Hzのままです。接地した足の高さは groundYAt の斜面の式で求め、足首は斜面の角度だけ曲げます。

斜面で体が傾く適応の歩き
新しいタブで開く

07 · 斜面で体が傾く適応の歩き — 計測 累積面積 20.211% · 動いたフレーム 23/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

leanDeggroundYAtsolveFootSlopeSLOPES
    function update(dt) {
        if (dt <= 0) {
            return;
        }
        slopeNow = slopeAt();
        // 下りで歩数を上げる — 前への傾き(-lean)が大きいほど stepHz が増える
        const lean = leanDeg(slopeNow);
        GAIT.stepHz = clamp(baseStepHz + Math.max(0, -lean) * 0.06, 0.8, 2.8);
    }

08足が通る弧を削らない移動の補正

ankleY の補正なしの判は GROUND_Y - sin(PI * k) * LEG_PX * 0.09 の低い弧を描き、補正ありの判は ARC_MIN_PX * clamp(1.6 / STEP_HZ, 0.5, 2) の最小の高さをkが0.85まで保ち、最後の15%でだけ下ろします。最小の高さは1.6Hzで20px、2.4Hzで13.3px、0.8Hzで40pxです。スイング区間を100点でサンプルした近似では、床から4px以内の区間の割合がおよそ34%からおよそ3%に減り、画面の scuffRaw・scuffFix はこれとは別にフレームを直接数えた値です。

足の通る弧を削る移動の補正
新しいタブで開く

08 · 足の通る弧を削る移動の補正 — 計測 累積面積 14.109% · 動いたフレーム 23/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

ARC_MIN_PXankleYswingKscuffRaw
    function swingK() {
        const ph = legPhase(true);
        if (inStance(ph)) {
            return -1;
        }
        return (ph - GAIT.contactShare) / (1 - GAIT.contactShare);
    }
    // 足首の y — raw(円弧のまま)と corrected(最小の高さ)
    function ankleY(k, corrected) {
        const half = rad(GAIT.strideDeg);
        const ang = lerp(half, -half, k);
        const rawY = GROUND_Y - Math.sin(Math.PI * k) * GAIT.legPx * 0.09;
        if (!corrected) {
            return rawY;
        }
        const minH = ARC_MIN_PX * clamp(1.6 / GAIT.stepHz, 0.5, 2);
        const drop = k > 0.85 ? (k - 0.85) / 0.15 : 0;
        const lift = Math.max(minH * (1 - drop), Math.sin(Math.PI * Math.min(k / 0.85, 1)) * minH * 1.2);
        return rawY - lift;
    }

09床に固定される足裏と完成の場面

三人の歩き手は28度・1.6Hz、18度・2.0Hz、40度・1.2Hzで、一歩の距離は84.5・55.6・115.7px、速さは135.2・111.3・138.8px/sになります。接地した足は位相と固定した体のxから解いた画面座標なので、体が sin(sceneT * 3.1) * 3 px揺れても足は動かず、maxSlip は、座標を解き直していた場合に体の速さの±12%の揺れが一フレームで足を押したはずの最大量を、式で見積もった0.27px前後の近似値です。

床に固定される足裏と完成場面
新しいタブで開く

09 · 床に固定される足裏と完成場面 — 計測 累積面積 16.135% · 動いたフレーム 23/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

lockPlantsplantXOfWALKERSmaxSlip
    function update(dt) {
        if (dt <= 0) {
            return;
        }
        // 接地中の足の画面上の移動量を測る — plant を保存すれば0、解き直せば揺れの分だけ動く
        maxSlip = 0;
        for (let i = 0; i < WALKERS.length; i += 1) {
            const wk = WALKERS[i];
            for (let r = 0; r < 2; r += 1) {
                const ph = ((walkT * wk.hz) + (r === 1 ? 0.5 : 0)) % 1;
                if (ph < 0.6) {
                    const noSave = Math.sin(rad(wk.stride)) * GAIT.legPx * 2 * wk.hz * Math.cos(sceneT * 3.1) * 0.12 * (1 / 60);
                    maxSlip = Math.max(maxSlip, Math.abs(noSave));
                }
            }
        }
    }

歩くキャラクターをコードで作ると、一歩はどんな値がいくつで決まるのでしょうか。

五つの値が一歩を決めます。ほかの数値はこの五つから計算で出てきます。

ソースの定数五つで決まります

定数 値 決めるもの
STEP_HZ 1.6 一秒あたりの歩数。一歩0.63秒、二歩のサイクル1.25秒
STRIDE_DEG 28 脚が前後に開く半分の角度
LEG_PX 90 脚の長さ。股関節から足首まで
LEG_RATIO 0.48 すねと太ももの比率
CONTACT_SHARE 0.6 一歩のうち接地が占める割合

一歩の中の時間配分

CONTACT_SHARE の0.6は接地0.37秒とスイング0.25秒に分かれ、二本の脚が半歩ずれているので、両足が同時に床にある区間が0.2歩、0.13秒できます。体の高さ hipHeight は LEG_PX * (0.93 + 0.04 * bob) の形で80.10pxから87.30pxの間を行き来します。

サイクル位相を時間で進め、脚の角度を三角関数で解き、関節を画面の座標へ移して描く — 歩くアニメーションの一歩が処理される順番

位相が先で、絵はあとから付いてきます

advance が walkT を進めると legPhase が二本の脚の位相を出し、inStance が接地かスイングかを分けます。そのあとで solveFoot が足の位置を決め、limb が関節の間を結ぶ線をキャンバスに引きます。

余弦定理で膝を解きます

脚は太もも L1 の60.81pxとすね L2 の29.19pxの二つのリンクで、合計は LEG_PX の90pxです。股関節と足首の距離 d を求めて L1 + L2 - 0.01 で切り、余弦定理で膝の角度を解き、曲がり方が二通り出る解のうち base - elbow 側のひとつだけを使います。

歩くキャラクターを実際の画面に付けるとき — ライブラリなしの作り方・向きの転換と歩数の調整・体が低くなる場面

キャラクターのアニメーションやゲームの移動の演出、読み込み中のマスコットに付けるときは、groundV をキャラクターの移動の速さに、STEP_HZ を進み具合に結び付ければ足ります。歩くアニメーションを横から見せるなら、この九つの場面のように床の目盛りを後ろへ流すだけで、描き方は変わりません。ドット絵の歩く素材は描いておいたフレームを繰り返しますが、このコードは STEP_HZ を変えた瞬間に別の歩きが出ます。

ライブラリなしの作り方

キャンバスは内部を480×300に固定し、devicePixelRatio は Math.min で2までしか掛けません。ライブラリ・WebGL・CDN・外部の画像がないので、このファイルひとつを静的なページに貼れば動き、キャラクターは円と丸い棒で描いた自前の図形です。「歩くアニメーション フリー 素材」を探す人も、素材を取り込まずにこのページの上で動かして確かめられます。

向きの転換と歩数の調整

速さは STEP_HZ で変え、向きが変わるときは04のように視線を先に回します。07は下りで STEP_HZ を自分で上げるので、地形が歩きを変える仕組みも同じ式から出てきます。キー操作では左右の矢印が STEP_HZ を0.4ずつ0.8〜2.8の間で動かします。

体が低くなる場面

hipHeight は一歩の中で、歩き始めの点の80.10pxがいちばん低くなります。07はここに Math.cos(rad(slopeNow)) を掛けて、斜面で体の高さをさらに下げます。

このデモのまま使えない場面

足は一つの平面の上の二つのリンクによる近似です。地形の高低ごとに足の位置を解き直す場合は07の groundYAt を地形の関数に置き換え、脚が三つ以上のリンクか足首の関節を持つ場合は余弦定理一回では解けないので反復の解法が要り、歩きから立ち止まりへの切り替えは一定のサイクルの外なので位相を止める規則を別に決める必要があります。

カーソル生物の編との違い

カーソル生物の編 は目標の点を追って脚が付いていき、この編は歩きの時計が位相を進めて脚が決まります。一枚ずつ絵を描いてめくる側が気になるなら パラパラ漫画の編 を見てください。

歩くアニメーションが壊れる落とし穴 — 足裏が床をすべって見えること・両脚が同じ位相で跳ぶこと・斜面で足が地面にめり込むこと

足裏が床をすべります

03の合わない判がその実物です。体の速さ110.9px/sが式の求める135.2px/sに届かないと、接地した足が drift の分だけ這って床に線が引かれます。このソースは接地した足を画面の座標に固定して目盛りだけを groundV で流しますが、世界が動く実際の場面では、接地の位置を世界の座標で保存してカメラで移す必要があります。

両脚が同じ位相で跳びます

右脚に足す0.5歩がないと、01の二本の曲線が重なって両脚が一緒に接地して一緒に浮きます。legPhase(right) の一行がこの違いを作ります。

斜面で足が地面にめり込みます

接地した足の高さを平地の値のままにすると、斜面の上で足が地面の中に入ったり浮いて見えたりします。07は接地した足の y を groundYAt(x, BASE_Y, slope) で、足首の角度を -slopeNow で解くことでこの問題を避けています。

この記事の九つの場面のソース一式と編集用のファイルは、下の箱のzipで受け取れます。開くための圧縮パスワードは yts6py5y です。

歩幅の速さと開き角度と脚の長さの比率を変えると感じはどれだけ変わるか — STEP_HZ・STRIDE_DEG・LEG_RATIOを変えた違い

名前 変えた値 感じ
歩きをもっと速く 01 STEP_HZ 1.6 → 2.4 一歩が0.63秒から0.42秒に、接地が0.37秒から0.25秒に短くなり、体の移動の速さが135.2px/sから202.8px/sに増えて、走るような慌ただしさが付きます。骨盤のねじれは±6度から±9度に、弧の最小の高さは20pxから13.3pxに変わります
歩幅をもっと狭く 03 STRIDE_DEG 28 → 14 一歩の距離が84.5pxから43.5pxで基本の51.5%になり、1.6Hzでの速さも135.2px/sから69.7px/sに下がって小刻みな歩きになります
すねをもっと短く 05 LEG_RATIO 0.48 → 0.42 すねが29.2pxから26.6pxに短くなり、太ももが60.8pxから63.4pxに長くなって、05の肘の最大の曲がりが61.6度から57.4度に減ります

ひとつの値が複数の場面に広がります。STEP_HZ は06の骨盤のねじれと08の最小の高さまで、STRIDE_DEG は05の肩の角度と groundV まで、LEG_RATIO は膝の位置と05の肘まで触れるので、一度にひとつずつ変えて見るのがよいでしょう。

動きを減らす設定では歩みの止まった立ち姿勢一枚 — サイクルの局面と今の歩数を文で読み上げるアクセシビリティ

キーボードで歩きを触ります

九つの場面の舞台は role="application" に tabindex="0" を付けています。左右の矢印は STEP_HZ を0.4ずつ0.8〜2.8で動かし、03では STRIDE_DEG を10〜44で2ずつ、05では上下が LEG_RATIO を0.40〜0.56で0.02ずつ、09では左右が三人の歩き手の速さを×1.15・×0.87に変えます。Enter・Space・Pは一時停止、Nは時間表の次の出来事を一つ進め、Rは最初からで、触れると時間表が止まって計算だけが流れます。

読み上げはモードが変わるときだけです

画面の状態の行は aria-live="off" なので、値が変わっても読まれません。role="status" の欄には speakText() が、触った直後と場面のモードが変わるときだけ文を書き、自動のデモが流れるあいだは書きません。キャンバスの aria-label には、場面に見える文言と主な値を書いてあります。

動きを減らす設定と隠れたタブ

prefers-reduced-motion が有効なときはループを回さず、showRest() が walkT と sceneT を REST_S に置いて歩みの止まった静止の一枚を描きます。入力のあとは afterInput() がすぐに描き直し、舞台には touch-action: none が付いているので、タッチで画面が引きずられません。

    // 動きを減らす設定 — ループなしで時間表の REST_S 秒までを一度に済ませた場面の一コマ。キャラクターは歩みの補間なしでその時点の位置にすぐ立つ
    function showRest() {
        stopLoop();
        lap = 0;
        begin();
        walkT = REST_S;
        while (evAt < script.length && script[evAt].t <= REST_S) {
            const ev = script[evAt];
            evAt += 1;
            sceneT = ev.t;
            ev.f();
        }
        sceneT = REST_S;
        update(0);
        showNow();
    }

歩くアニメーションのFAQ — フレームは何枚が適切か・足がすべって見えるとき直す値・歩きと走りを分ける基準

歩くアニメーションのフレームは何枚が適切ですか

この編は枚数の代わりに連続した位相を使います。1.6Hzで二歩のサイクルが1.25秒なので60fpsで75回描かれ、絵数枚に移したいときは接地12%・抵抗18%・中間15%・押し出し15%・持ち上げ40%の割合で一歩の枚数を分ければ足ります。

足がすべって見えるとき直す値は何ですか

体の速さを 2 * LEG_PX * sin(STRIDE_DEG) * STEP_HZ に合わせます。03で135.2px/sと0.82倍の110.9px/sを並べると差がすぐ見え、接地区間の足の座標を一度解いて保存すれば体の速さが揺れても足は動きません。

歩きと走りは何で分けますか

この編の CONTACT_SHARE の0.6は、両足が同時に付く区間が0.2歩残る値です。二本の脚の位相差が0.5なので、接地の割合が0.5を下回ると両足が浮く瞬間ができる計算になりますが、この編では0.6ひとつだけを回して試し、0.5を下回る値は確かめていません。この「歩くアニメーション 横」の見せ方のまま、走りに切り替える場合は別の確認が要ります。

出典: CanvasRenderingContext2D.lineTo・requestAnimationFrame・prefers-reduced-motion

解凍パスワードを入力してください

パスワードはこの記事の本文の中にあります。読み進めると出てきます。