初めてのプログラミングで生み出した最高に可愛いカービィを紹介したい(Processing)

:::note 
この記事は[DeNA 25 新卒 Advent Calendar 2024](https://qiita.com/advent-calendar/2024/dena-25-newgrad)の13日目の記事です！他の記事もぜひチェックしてみてください！
:::

# はじめに
初めまして、立命館大学4回生の藤堂ゆうかです。

大学1回生の頃に授業で制作したカービィがあまりにも可愛いので、この記事でご紹介したいと思います。

この作品は、私にとって**初めてのプログラミング**でした。
それでも、基本的な操作に少し工夫を加えるだけで、今の自分でも誇れるほどのクオリティの作品を完成させることができました。この経験から、「**工夫次第でいろんなことが可能になる**」ということを強く感じ、この楽しさを胸に4年間プログラミングに興じてきました。

とっても可愛いので、ぜひ最後までお楽しみください！

# 作ったカービィの紹介

#### ぷかぷか浮くカービィ
実行すると、自動でぷかぷか浮く仕様になっています。この記事では、ここに至るまでの処理をいくつか紹介します。

<iframe width="560" height="315" src="https://www.youtube.com/embed/WXHOliQWGCk?si=VTabLDFZeSp1Hdxr" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

#### ハートを投げるカービィ
今回は紹介しませんが、マウスクリックでハートを投げる仕様も実装しています。

<iframe width="560" height="315" src="https://www.youtube.com/embed/IZeTsHCm82w?si=OrW8PZt6yJGXVeIW" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

参考にしたアニメーションは次の動画の 0:00 ~ 0:05 です。

<iframe width="560" height="315" src="https://www.youtube.com/embed/1vNmTih9IXI?si=wxJ2S0XdJaeZxGak" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

#### 実際にこのカービィを触ってみたい方へ
Vercelにデプロイしています。レスポンシブ対応などはできていませんが、ぜひ触ってみてください。

https://kirby-animation.vercel.app/

# 使用技術
- [Processing](https://processing.org/) [Java]

# 実装方法

## カービィの顔を単純な図形の組み合わせで再現する
この作品は、**円・楕円とその扇形・枠線、四角形のみで構成**されています。(背景等も含む)
カービィができるまでの過程をイラストにまとめました。

![カービィのつくりかた](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984887/d2fe360a-29ee-abf6-f0ae-506f896fab1e.png)

課題として何か作るとなったとき、簡単な図形で作りやすそうだったので「カービィ」を選びました。構想通り、目やほっぺなどの全てのパーツを単純な図形のみで表現することができました。
口や手などの少し複雑そうに見えるパーツも、円や楕円の扇形を組み合わせることで他のパーツと統一感のある丸みがかったフォルムになっています。

### Processingのさまざまな図形の描き方
Processingでは、さまざまな図形を描く方法が用意されています。
当時の私は、目を円と長方形で表現していましたが、後日、丸みのある四角形の描き方を紹介している記事を見つけました。
Processingで絵を描いている方は、こちらの記事もぜひ参考にしてみてください！

https://qiita.com/reona396/items/5fa4babc8243c4ed4914

## 工夫したアニメーション
カービィを制作する際、より自然な動きを目指して、さまざまなアニメーションを取り入れました。この記事では、その中からいくつかをピックアップしてご紹介します。

### ぷかぷか浮遊モーション
カービィは、時間の経過に合わせて左右に移動しながら、上下運動を繰り返します。
正確な物理運動を再現するためには運動方程式を用いるべきかもしれませんが、今回の制作は学校の課題作品であり、厳密な再現性は求められていませんでした。

そのため、上下運動には正弦関数を利用しました。インクリメント変数 `x` を用いることで時間に応じた波状の動きを簡単に実現しています。

``` main.pde
    // 1. y座標の変位を正弦関数から計算
    y = 130 * sin(x) + 160;
    
    // 2. 座標を移動
    translate(50 * x + 500, y);
```

イメージ図を描きました。軌道は次の画像のようになります。
![浮遊時の機動イメージ図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984887/a3462d91-83b9-e2a3-a88c-209fe480090c.png)


#### 1. 直線運動
`y` の座標を固定で、`x` の座標のみを変換させた状態
<iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/Xn_OdtwdAxc?si=WRco4Ahgw8glp3m5&loop=1&playlist=Xn_OdtwdAxc" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" 
    allowfullscreen>
</iframe>


#### 2. 正弦関数によるy軸方向の浮遊
`y` の座標を最終的な実装通り正弦関数を用いて変換させた状態
<iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/lblX6Boxy60?si=ZSLhVp7P8MbmvIWq&loop=1&playlist=lblX6Boxy60" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" 
    allowfullscreen>
</iframe>



### カービィの膨らみ
カービィは前述の上下運動に合わせて体を膨張・収縮させています。それを表現すべく、ここでも正弦関数を利用しました。
同じ正弦関数を利用することで、上下運動に合わせて体の大きさが変化するようになっています。

``` main.pde
    // 1. 拡大・縮小
    scale(0.8 + 1.1 * (sin(x + PI * 5 / 6 + (1 - X) * PI / 6) / 25));

    // 2. 円の描画
    ellipse(0, 0, 255, 255);
```

<iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/GTOZA2xa0HE?si=Lf0eTImpS-5zrGyI&loop=1&playlist=GTOZA2xa0HE" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" 
    allowfullscreen>
</iframe>
左：膨らみなし、右：膨らみあり

:::note
**実は拡大・収縮していない？**
この記事を書くにあたってカービィについて調べてみると、本来のカービィは、浮くタイミングで身体の拡大・収縮していないかもしれないことが判明しました。ここはご愛嬌ということで、、、
:::



### 浮くのに合わせて揺れる足
カービィの浮遊アニメーションをより自然な仕上がりに近づけるべく、浮遊アニメーションに対応させて足が少し揺れるように実装しました。

カービィから見て右上の胴体ひとつ分くらい離れた点を中心に、正弦関数を利用して回転をかけています。

![あしの動きのしくみ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984887/d2c19a36-b6bf-b6f3-25df-98bfaa5631cc.png)

<iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/eyBcx3yQK9c?si=B25ro_cr_lfupDLk&loop=1&playlist=eyBcx3yQK9c" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" 
    allowfullscreen>
</iframe>
左：あしの動きなし、右：あしの動きあり


### 浮くのに合わせてはばたく手
浮遊アニメーションには、はばたく動作が必要です。浮遊アニメーションに対応させて、上がるタイミングで手を下にはばたくように実装しました。

胴体の中心を軸に、手だけ回転させています。角度の変化には、拡大・縮小や足の動きと同様に正弦関数を用いています。

```main.pde
    // 1.手の回転
    rotate(PI * sin(x) / 8 + PI / 5);


    // 2. 手の表示noStroke();
    ellipse(135 - 250, 0, 55, 80);
    
    strokeWeight(7);
    stroke(#FFC1DC);
    arc(135 - 250, 0, 55, 80, -sin(x + PI) / 5 + PI / 9, PI / 2); // 影も浮遊に合わせて調整
    
    strokeWeight(3);
    stroke(#700030);
    arc(135 - 250, 0, 90, 80, PI / 2, PI * 3 / 2);
```

<iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/5oAVrYIekmU?si=X-BseI60FWM2CkJx&loop=1&playlist=5oAVrYIekmU" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" 
    allowfullscreen>
</iframe>
左：はばたきなし、右：はばたきあり

### 背景の移動
カービィの座標移動だけではなく、より移動に面白みを追加するため、背景も進行方向と逆に動かしました。
背景自体を動かすのではなく、雲ひとつひとつの座標をずらすようにしました。そして、それぞれの変化量をばらけさせることで、手前と奥の雲の進み具合の違いを表現しました。

```main.pde
    // 雲 1つ目(16 * xで変化)
    ellipse(990 - 500 - 16 * x, 290 - 200, 200, 100);
    ellipse(1090 - 500 - 16 * x, 330 - 200, 200, 100);
    ellipse(1000 - 500 - 16 * x, 360 - 200, 200, 100);
    ellipse(800 - 500 - 16 * x, 300 - 200, 200, 100);
    ellipse(880 - 500 - 16 * x, 340 - 200, 200, 100);
    
    // 雲 2つ目(24 * xで変化)
    ellipse(880 + 500 - 24 * x, 340 + 100, 200, 100);
    ellipse(990 + 500 - 24 * x, 290 + 100, 200, 100);
    ellipse(1090 + 500 - 24 * x, 330 + 100, 200, 100);
    ellipse(1000 + 500 - 24 * x, 360 + 100, 200, 100);

    // 以降、省略
```

<iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/fu5oIJCo-6s?si=eeF1NXLbZGiKSOYG&loop=1&playlist=fu5oIJCo-6s" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" 
    allowfullscreen>
</iframe>

上：背景移動なし、下：背景移動あり

# おわりに
最後までお読みいただき、ありがとうございました。

4回生となった今、当時のコードを見返すと、改善の余地が多くあることに気づきます。それでも、完成したカービィはとても可愛らしく、私にとって満足のいく作品となりました。

これからも、このような自慢できるような作品をひとつずつ増やしていけたらいいなと思います。