デジタル焚き火

キャンプ体験:火を眺めて時間を過ごそう

view source

JavaScript

document.title = 'デジタル焚き火';
//キャンプ体験:火を眺めて時間を過ごそう

let { canvas, ctx, cx, cy, w, h, min, demo } = readyCanvas();


const fireCenter = { x: canvas.width / 2, y: canvas.height * 0.6 };


function centerBiasedRandom(scale) {
  return (Math.random() - 0.5) * Math.random() * scale;
}

function generateFireColor(alpha) {
  const isYellow = Math.random() < 0.3; // 30%で黄色系
  if (isYellow) {
    const g = 100 + Math.floor(Math.random() * 56); // 200–255
    const b = 30 + Math.floor(Math.random() * 50);       // 0–50
    return `rgba(255, ${g}, ${b}, ${alpha})`;
  } else {
    const r = 200 + Math.floor(Math.random() * 56); // 200–255
    const g = 30 + Math.floor(Math.random() * 50);  // 30–80
    return `rgba(${r}, ${g}, 0, ${alpha})`;
  }
}

class Fire {
  constructor() {
    const angle = Math.random() * Math.PI - Math.PI / 2; // 上方向に放射
    const speed = Math.random() * min/160 - min/320;
    this.vx = Math.cos(angle) * speed;
    this.vy = Math.sin(angle) * speed - min/200; // 上昇

    // 発生点:
    this.x = fireCenter.x + centerBiasedRandom(min / 2);
    this.y = fireCenter.y + centerBiasedRandom(min / 2);

    // 中心からの距離に応じてサイズ補正(距離が大きいほど小さく)
    const dx = this.x - fireCenter.x;
    const dy = this.y - fireCenter.y;
    const dist = Math.sqrt(dx * dx + dy * dy);
    const maxDist = min / 4;
    const distFactor = 1 - Math.min(dist / maxDist, 1); // 0〜1

    this.size = (Math.random() * 0.5 + 0.5) * min / 40 * distFactor + min / 40;

    this.alpha = Math.random() * 0.5 + 0.3;
    this.color = generateFireColor(this.alpha);
  }

  update() {
    this.x += this.vx;
    this.y += this.vy;
    this.size *= 0.96;
    this.alpha *= 0.96;
    return this.size > 4;
  }

  draw(ctx) {
    ctx.fillStyle = this.color;
    ctx.fillRect(this.x, this.y, this.size, this.size);
  }
}

const fires = [];

function animate() {
  ctx.fillStyle = 'rgba(0, 0, 0, 0.2)'; // 残像を残す
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  // 新しい炎をランダムに追加
  for (let i = 0; i < 3; i++) {
    if (Math.random() < 0.8) fires.push(new Fire());
  }

  // 既存の炎を更新・描画
  for (let i = fires.length - 1; i >= 0; i--) {
    if (!fires[i].update()) {
      fires.splice(i, 1);
    } else {
      fires[i].draw(ctx);
    }
  }

  requestAnimationFrame(animate);
}

animate();

CSS

HTML

ページのソースを表示 : Ctrl+U , DevTools : F12

view-source:https://hi0a.com/game/canvas-bonfire/

ABOUT

hi0a.com 「ひまあそび」は無料で遊べるミニゲームや便利ツールを公開しています。

プログラミング言語の動作デモやWEBデザイン、ソースコード、フロントエンド等の開発者のための技術を公開しています。

必要な機能の関数をコピペ利用したり勉強に活用できます。

プログラムの動作サンプル結果は画面上部に出力表示されています。

環境:最新のブラウザ GoogleChrome / Windows / Android / iPhone 等の端末で動作確認しています。

画像素材や音素材は半分自作でフリー素材配布サイトも利用しています。LINK参照。

仕様変更、API廃止等、実験途中で動かないページもあります。