星を見る王子様[Javascript]


html 5のcanvasでアニメーションを作る過程が面白くて、いろいろなものを触っているうちに、星を見ている王子さまの様子を簡単に表現しました.
画面中央の下には惑星の上に登った王子さまがいて、上には星が回っている形をしています.その後、インタラクティブな要素が追加され、ユーザーが画面をクリックすると、星の速度が徐々に増加します.

星を作る

class Particle {
  constructor(moveRadius, step, position, size) {
    this.moveRadius = moveRadius;
    this.step = step;
    this.position = position;
    this.size = size;
    this.acc = 0.0001;
    this.cnt = 100;
  }
  
  ...
}
基本的に星の属性値を持つParticleクラスを定義します.moveRadiusは回転半径、stepはフレーム移動距離、位置は現在の回転角度、sizeは星の大きさです.今考えてみると、positionは変数名をangleとしたほうがいいです.
class Particle {
  ...

  draw() {
    let x = Math.cos(this.position) * this.moveRadius + canvas.width / 2;
    let y = Math.sin(this.position) * this.moveRadius + canvas.height;

    ctx.beginPath();
    drawStar(x, y, 5, this.size, this.size / 2);
    ctx.closePath();
    ctx.strokeStyle = "white";
    ctx.stroke();
  }

  update() {
    if (!isAccelerated) {
      if (this.cnt >= 101) {
        this.cnt -= 1;
      }
      this.position += this.step * (this.acc * this.cnt * this.cnt);
      this.draw();
    } else {
      if (this.cnt <= 300) {
      	this.cnt += 1;
      }
      this.position += this.step * (this.acc * this.cnt * this.cnt);
      this.draw();
    }
  }
}
これらはParticleクラスの関数です.draw関数で恒星を描画し、update関数を使用して恒星の速度を調整します.中空の星を作るためにstrokeを使いました.
function drawStar(positionX, positionY, spikes, outerRadius, innerRadius) {
  let rotation = (Math.PI / 2) * 3;
  let x = positionX;
  let y = positionY;
  let step = Math.PI / spikes;

  ctx.beginPath();
  ctx.moveTo(positionX, positionY - outerRadius);
  for (let i = 0; i < spikes; i++) {
    x = positionX + Math.cos(rotation) * outerRadius;
    y = positionY + Math.sin(rotation) * outerRadius;
    ctx.lineTo(x, y);
    rotation += step;

    x = positionX + Math.cos(rotation) * innerRadius;
    y = positionY + Math.sin(rotation) * innerRadius;
    ctx.lineTo(x, y);
    rotation += step;
  }
  ctx.lineTo(positionX, positionY - outerRadius);
  ctx.closePath();
}
Particleクラスのdraw関数の内部で星を描くdrawstar関数.星を設定した角度で点描する.spikeパラメータは恒星の頂点数を制御できます.下図を参照してください.

spike = 3



3つの頂点があるので、三角形のように描かれています.

spike = 5



これが一番星に似ている

spike = 7



星というよりインパクト(?)似ている.
いずれにしても、私は頂点を5に置くのが一番好きです.

▼▼初期化と動画実施

function init() {
  particleArray = [];
  for (let i = 0; i < 600; i++) {
    let moveRadius = Math.random() * canvas.width + 250;
    let step = Math.random() * 0.0002 + 0.002;
    let position = Math.random() * Math.PI * 2;
    let size = Math.random() * 8 + 0.5;

    particleArray.push(new Particle(moveRadius, step, position, size));
  }
}
init関数を1回実行し、恒星を作成してParticleArrayに入れます.星のアトリビュートはランダム関数を使用して多様性を生成します.
function animate() {
  requestAnimationFrame(animate);
  if (!isAccelerated) {
    ctx.fillStyle = `rgba(0,10,32,0.1)`;
  } else {
    ctx.fillStyle = `rgba(0,10,32,0.05)`;
  }
  ctx.fillRect(0, 0, innerWidth, innerHeight);

  for (let i = 0; i < particleArray.length; i++) {
    particleArray[i].update();
  }
  drawPrince();
}
requestAnimationFrame関数を使用してanimateの呼び出しを続行します.また、星が移動すると、前の位置で残像効果を生成するためにctxが生成される.fillStyleアルファ値を与えました.その後もすべての星を更新し続けます.

🤴 王子さまを描く


無料の画像をダウンロードして入れました.
function drawPrince() {
  var img = new Image();
  img.src = "prince.png";
  img.onload = function () {
    ctx.drawImage(img, canvas.width / 2 - 150, canvas.height / 1.4, 300, 300);
  };
}
これを行うと,次のような結果が見られる.

👆 インタラクティブ要素の挿入

var isAccelerated = false;

window.addEventListener("mousedown", handleIsAccelerated, false);
window.addEventListener("mouseup", handleIsAccelerated, false);
window.addEventListener("touchstart", handleIsAccelerated, false);
まず,イベントリスナーと変数を用いて,画面を押しているか,取り外しているかを調べる.モバイル環境でもtouchstartを起動してみましたが、私のiphoneでは起動できません.何か間違ったことがあったら先にスキップしましょう.
画面をクリックすると、星のスピードを上げたいです.しかし線形更新後、急加速、急停止のように見え、不自然です.加速度の概念を用いた.クラス内のupdate関数の再表示
class Particle {
  ...
  
  update() {
    if (!isAccelerated) {
      if (this.cnt >= 101) {
        this.cnt -= 1;
      }
      this.position += this.step * (this.acc * this.cnt * this.cnt);
      this.draw();
    } else {
      if (this.cnt <= 300) {
      	this.cnt += 1;
      }
      this.position += this.step * (this.acc * this.cnt * this.cnt);
      this.draw();
    }
  }
}
this.positionは現在の恒星の回転半径であり、この値は常に更新され、各加速度はthisである.これ.cntの二乗を掛ける.このように、反復するたびにスクリーンを押す時間の二乗に応じて星の位置が変化し、かなり自然に速度が変化します.
今はすべて実現しました.結果を見てみましょう.

星の速度が速くなり、尾が長くなる動きがよく見えます.

😃 ポスト


いつもキャンバスで絵を描いていて、ひっきりなしに描いていて、ちょっと似たような作品(?)初めて作りました.一生懸命Googleゲームを作りましたが、思ったより良かったので満足です.
しかしJavaScriptはあまり使われていないので、コード構造が煩わしいようにあちこちに貼り付けられているような気がするので、ちょっと不満です.次のプロジェクトでは、クラスをきれいに使いましょう.
しかもダウンジャケットのページ機能は悪くないようです.これらの簡単なプロジェクトプレゼンテーションが無料で簡単に管理できることに感謝します.
デモを見に行く
コードの表示