AI先生のロボットキャラクター
第9章 - セクション4

スーパーマリオ風 ゲームウォッチローディングアニメーション

ドット絵のマリオがブロックを叩いてジャンプする、Game & Watch風のレトロなローディングアニメーション。CSS box-shadowでピクセルアートを描き、ゲーム機らしい雰囲気も作る

男子生徒のアイコン

マリオがジャンプしているローディング画面って、どうやって作るんですか?

AI先生のアイコン

CSSのbox-shadowを使えば、ピクセルアート風のキャラクターを描けるんだ。今回は1980年代のGame & Watch風の本体デザインも含めて、懐かしい雰囲気を出してみよう。

女子生徒のアイコン

本体のデザインまで作るんですか?

AI先生のアイコン

そうだね。十字キー、ボタン、液晶画面の質感まで、当時っぽい雰囲気を意識して作ってみよう。では実際に見てみよう。

作成したローディングアニメーション

Game & Watch風の本体に、マリオがブロックを叩いてジャンプし続けるローディングアニメーションです。CSS box-shadowを使って1ピクセルずつドット絵を描き、レトロゲーム機っぽい雰囲気を作ります。

HTML
<div class="gamewatch">
    <!-- 左サイド (十字キー) -->
    <div class="left-side">
        <div class="d-pad">
            <div class="dpad-part dpad-right dpad-shadow"></div>
            <div class="dpad-part dpad-down dpad-shadow"></div>
            <div class="dpad-part dpad-up"></div>
            <div class="dpad-part dpad-right"></div>
            <div class="dpad-part dpad-down"></div>
            <div class="dpad-part dpad-left"></div>
            <div class="dpad-part dpad-center"></div>
        </div>
    </div>

    <!-- 中央エリア (画面・ロゴ) -->
    <div class="center-area">
        <div class="screen-container">
            <div class="screen-display">
                <div class="scene">
                    <div class="block" id="block"></div>
                    <div class="loading-popup" id="popup">LOADING</div>
                    <div class="mario jump"></div>
                </div>
                <div class="ground"></div>
            </div>
        </div>
    </div>
    
    <!-- 左上ロゴプレート -->
    <div class="gw-logo-plate">
        <div class="gw-text">LOAD<br>&<br>WATCH</div>
    </div>

    <!-- 右サイド (ボタン) -->
    <div class="right-side">
        <div class="mode-buttons">
            <div class="mode-btn-group">
                <div class="mode-btn"></div>
                <div class="mode-label">GAME</div>
            </div>
            <div class="mode-btn-group">
                <div class="mode-btn"></div>
                <div class="mode-label">TIME</div>
            </div>
            <div class="mode-btn-group">
                <div class="mode-btn"></div>
                <div class="mode-label">PAUSE/RESET</div>
            </div>
        </div>

        <div class="action-btn-container">
            <div class="action-btn"></div>
            <div class="action-label">JUMP</div>
        </div>
    </div>
</div>
CSS(一部抜粋)
:root {
    --pixel-size: 3px;
    --bg-color: #5c94fc;
    --ground-height: 48px;
    --block-size: 24px;
    --question-block-size: calc(var(--pixel-size) * 16);
    --question-block-bottom: 95px;
    --gw-face-gradient-start: #e8e8e8;
    --gw-face-gradient-end: #bfbfbf;
    --gw-accent-border: #b0192b;
}

/* Game & Watch 本体 */
.gamewatch {
    width: 800px;
    height: 480px;
    background: linear-gradient(135deg, var(--gw-face-gradient-start) 0%, var(--gw-face-gradient-end) 100%);
    border-radius: 40px;
    border: 10px solid var(--gw-accent-border);
    box-shadow: 
        inset 3px 3px 6px rgba(255,255,255,0.4),
        inset -3px -3px 6px rgba(0,0,0,0.3),
        0 20px 50px rgba(0,0,0,0.6);
    /* ... */
}

/* マリオのピクセルアート(box-shadowで描画) */
.mario {
    width: var(--pixel-size);
    height: var(--pixel-size);
    background-color: transparent;
    position: absolute;
    bottom: calc(var(--pixel-size) * -1);
    left: 58%;
    margin-left: calc(var(--pixel-size) * -6);
    z-index: 10;
    transform: scaleX(-1);
    
    /* 通常時のスプライト */
    --mario-sprite-run:
        /* 帽子(赤) */
        calc(var(--pixel-size) * 3) calc(var(--pixel-size) * -11) 0 0 #d9001b,
        calc(var(--pixel-size) * 4) calc(var(--pixel-size) * -11) 0 0 #d9001b,
        /* 顔(肌色) */
        calc(var(--pixel-size) * 2) calc(var(--pixel-size) * -9) 0 0 #fca044,
        /* ... その他のピクセル ... */;
    
    /* ジャンプ時のスプライト */
    --mario-sprite-jump:
        /* 手の位置が変わる */
        calc(var(--pixel-size) * 1) calc(var(--pixel-size) * -8) 0 0 #fca044,
        /* ... その他のピクセル ... */;

    box-shadow: var(--mario-sprite-run);
    transform-origin: center bottom;
}

.mario.jump {
    animation: marioJump 1.2s cubic-bezier(0.35, 0, 0.45, 1) infinite;
}

@keyframes marioJump {
    0% { transform: translateY(0) scaleX(-1); box-shadow: var(--mario-sprite-run); }
    45% { transform: translateY(-60px) scaleX(-1); box-shadow: var(--mario-sprite-jump); }
    55% { transform: translateY(-60px) scaleX(-1); box-shadow: var(--mario-sprite-jump); }
    100% { transform: translateY(0) scaleX(-1); box-shadow: var(--mario-sprite-run); }
}
JavaScript
const block = document.getElementById('block');
const popup = document.getElementById('popup');

setInterval(() => {
    setTimeout(() => {
        hitBlock();
    }, 540);
}, 1200);

function hitBlock() {
    block.classList.remove('hit');
    void block.offsetWidth;
    block.classList.add('hit');

    popup.classList.remove('active');
    void popup.offsetWidth;
    popup.classList.add('active');
}

setTimeout(() => hitBlock(), 540);
男子生徒のアイコン

マリオのドット絵がCSSだけで描けるんですか?

AI先生のアイコン

box-shadowを使って1ピクセルずつ座標と色を指定することで、ドット絵を表現できるんだ。マリオの帽子は赤、顔は肌色、といった具合に色を配置していくんだよ。

AIへのプロンプト例

以下のようなプロンプトをAIに送信すると、このようなローディングアニメーションを作成できます:

1980年代のGame & Watch風の携帯ゲーム機を作成してください。

### 本体デザイン
- シルバーグレーのグラデーション背景
- 深めの赤い縁取り
- 角丸の筐体
- 内側の光沢と影で立体感を表現

### 左側:十字キー
- 黒い十字形のコントローラー
- 赤い縁取り
- 影付きで立体的に

### 中央:液晶画面エリア
- 黒い外枠に包まれた青い液晶画面
- 画面内にドット絵のマリオがジャンプ
- マリオの頭上に「?」ブロック
- ブロックを叩くと「LOADING」テキストがポップアップ
- 画面下部にレンガの地面

### 右側:ボタン類
- 上部:GAME、TIME、PAUSE/RESETの小さな楕円ボタン
- 下部:大きな赤い丸いJUMPボタン

### 左上:ロゴプレート
- 白い四角いプレート
- "LOAD & WATCH"のテキスト(イタリック体)

### アニメーション
- マリオが上下にジャンプ(一定の周期)
- ジャンプ時に手の位置が変わる
- ブロックが叩かれたタイミングで少し揺れる
- 「LOADING」テキストが浮き上がって消える演出

このアニメーションの特徴

  • box-shadowでピクセルアート CSSのbox-shadowだけで1ピクセルずつマリオのドット絵を描画
  • 本体の質感再現 グラデーション、insetシャドウ、光沢で立体的な筐体を表現
  • アニメーションの同期 マリオのジャンプとブロックの衝突、テキストポップアップのタイミングを合わせる
  • レトロゲーム機の雰囲気再現 十字キー、ボタン、液晶画面など、Game & Watch風の構成を参考に

コードのポイント

1. 外部フォントの読み込み

実装する際にHTMLファイルに組み込む場合は、<head>タグ内に以下を追加します:

<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Share+Tech+Mono&display=swap">

使用しているフォント:

  • Press Start 2P: ピクセルフォント(レトロゲーム風のテキスト表示)
  • Share Tech Mono: 等幅フォント(補助的に使用)

2. box-shadowによるピクセルアート描画

.mario {
    width: var(--pixel-size);
    height: var(--pixel-size);
    background-color: transparent;
    
    /* 各ピクセルをbox-shadowで配置 */
    --mario-sprite-run:
        /* X座標 Y座標 ぼかし スプレッド 色 */
        calc(var(--pixel-size) * 3) calc(var(--pixel-size) * -11) 0 0 #d9001b,
        calc(var(--pixel-size) * 4) calc(var(--pixel-size) * -11) 0 0 #d9001b,
        /* ... 各ピクセルの座標と色 ... */;
    
    box-shadow: var(--mario-sprite-run);
}

1つの要素に複数のbox-shadowを適用し、各ピクセルの位置と色を指定することで、ドット絵を描いています。--pixel-size変数で拡大縮小も可能です。

3. アニメーション中のスプライト切り替え

@keyframes marioJump {
    0% { 
        transform: translateY(0) scaleX(-1); 
        box-shadow: var(--mario-sprite-run); /* 通常時のスプライト */
    }
    45% { 
        transform: translateY(-60px) scaleX(-1); 
        box-shadow: var(--mario-sprite-jump); /* ジャンプ時のスプライト */
    }
    100% { 
        transform: translateY(0) scaleX(-1); 
        box-shadow: var(--mario-sprite-run); 
    }
}

ジャンプの高さ(translateY)と同時に、box-shadowの値を切り替えることで、手の位置が変わるスプライトアニメーションを実現しています。

4. 本体の立体感表現

.gamewatch {
    background: linear-gradient(135deg, 
        var(--gw-face-gradient-start) 0%, 
        var(--gw-face-gradient-end) 100%);
    box-shadow: 
        inset 3px 3px 6px rgba(255,255,255,0.4),  /* 内側の光沢 */
        inset -3px -3px 6px rgba(0,0,0,0.3),      /* 内側の影 */
        0 20px 50px rgba(0,0,0,0.6);              /* 外側の影 */
}

グラデーション背景と複数のbox-shadowinsetを使った内側の光と影)で、プラスチック筐体の質感を表現しています。

5. タイミング同期の仕組み

setInterval(() => {
    setTimeout(() => {
        hitBlock(); // ブロックを叩く
    }, 540); // マリオがジャンプして頂点に達するタイミング
}, 1200); // アニメーション1周期

function hitBlock() {
    // ブロックを揺らす
    block.classList.add('hit');
    // テキストをポップアップ
    popup.classList.add('active');
}

マリオのジャンプアニメーション(1.2秒)と、ブロックを叩くタイミング(0.54秒後)を揃えて、動きがズレないようにしています。

女子生徒のアイコン

box-shadowでこんなに複雑な絵が描けるんですね!

AI先生のアイコン

そうなんだ。CSS変数を使えば、ピクセルサイズの調整も簡単にできる。ただし、ピクセル数が多くなるとパフォーマンスに影響するから、適度な大きさに留めることが大切だよ。

男子生徒のアイコン

本体のデザインもそれっぽくて、ゲーム機みたいに見えます!

AI先生のアイコン

十字キーやボタンの立体感も、box-shadowborder-radiusの組み合わせで表現しているんだ。レトロなゲーム機の雰囲気を大切にしながら、Webサイトのローディング画面として使えるように工夫したよ。

まとめ

女子生徒のアイコン

今回は、CSSだけでゲーム機本体とピクセルアートを作ることができるって学びました!

男子生徒のアイコン

box-shadowを使ったドット絵の描き方と、アニメーションのタイミング調整が面白かったです。

AI先生のアイコン

そういうこと。Game & Watchのような懐かしいゲーム機の雰囲気を取り入れると、ローディング画面の印象を少し軽くできる。待ち時間が長いときでも、目が止まる要素になるんだ。

ピクセルアートローディングのポイント
  • box-shadowでドット絵 1ピクセルずつ座標と色を指定してキャラクターを描画
  • スプライト切り替え アニメーション中にbox-shadowの値を変更してキャラクターの動きを表現
  • CSS変数での拡大縮小 --pixel-size変数でピクセルサイズを一括調整可能
  • 立体感の演出 insetシャドウとグラデーションで本体の質感を再現
  • タイミング同期 JavaScriptでアニメーションとイベントのタイミングを調整

レトロなゲーム機風のデザインで、ローディング画面に遊び心を足す演出です。

学習チェック

このレッスンを理解できたら「完了」をクリックしてください。
後で見直したい場合は「未完了に戻す」で進捗をリセットできます。

レッスン完了!🎉

お疲れさまでした!