原子生命

原子生命 | ひまあそび-ミニゲーム hi0a.com

view source

JavaScript

document.title = '原子生命';

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

var style = document.createElement('style');
style.innerText = 'html,body{overflow:hidden;cursor:none;user-select:none;}';
document.getElementsByTagName('head').item(0).appendChild(style);



var hue = 90;

/*
let styleImg = document.createElement('style');
styleImg.innerText = '#demo img{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);height:100vh;opacity:1;cursor:none;}';
document.getElementsByTagName('head').item(0).appendChild(styleImg);
let img = document.createElement('img');
demo.appendChild(img);
img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw%3D%3D';
*/

let search = location.search.slice(1);
let params = new URLSearchParams(search);
let q = params.get('q');
if(q){
  img.src = q;
}

var t = 0;
var bgcolor = '#000';
var color = '#0f0';
// 線のパラメータ
const cracks = [];
const numCracks = 15; // 一度のクリックで作られるひびの数
const crackLength = 200; // 最大長さ

ctx.font = '16px serif';
if(location.search){
  text = location.search.substring(1);
  text = decodeURI(text);
}
$(function(){
  let key = getURLKEY();
  if(key){
    text = key;
    pace = 299;
  }
})


class Crack {
  constructor(x, y, angle, depth = 0) {
    this.x = x;
    this.y = y;
    this.angle = angle;
    this.length = 0;
    this.maxLength = 50 + Math.random() * 100;
    this.speed = 1 + Math.random() * 1.5;
    this.depth = depth; // 分岐の深さ
    this.active = true;
  }

  update() {
    if (!this.active) return;

    let prevX = this.x;
    let prevY = this.y;

    // ランダムに角度をゆらす
    this.angle += (Math.random() - 0.5) * 0.2;

    // 前方に進む
    this.x += Math.cos(this.angle) * this.speed;
    this.y += Math.sin(this.angle) * this.speed;
    this.length += this.speed;

    // 線を描く
    ctx.beginPath();
    ctx.moveTo(prevX, prevY);
    ctx.lineTo(this.x, this.y);
    ctx.strokeStyle = 'white';
    ctx.lineWidth = 1;
    ctx.stroke();

    // 一定距離進んだら分岐
    if (this.length > this.maxLength && this.depth < 4) {
      this.active = false;
      cracks.push(new Crack(this.x, this.y, this.angle + Math.PI / 4 * (Math.random() - 0.5), this.depth + 1));
      cracks.push(new Crack(this.x, this.y, this.angle - Math.PI / 4 * (Math.random() - 0.5), this.depth + 1));
    }

    // 画面外に出たら停止
    if (this.x < 0 || this.y < 0 || this.x > canvas.width || this.y > canvas.height) {
      this.active = false;
    }
  }
}


// 初期ひび
function startCrack(x, y) {
  for (let i = 0; i < 6 + Math.random() * 4; i++) {
    const angle = Math.random() * Math.PI * 2;
    cracks.push(new Crack(x, y, angle));
  }
}

canvas.addEventListener('click', (e) => {
  startCrack(e.clientX, e.clientY);
});

function animate() {
  requestAnimationFrame(animate);
  ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'; // 残像残し
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  cracks.forEach(c => c.update());
}

canvas.addEventListener('click', (e) => {
  //console.log([e.clientX, e.clientY])
  startCrack(e.clientX, e.clientY);
});

animate();

function startRandomCrackLoop() {
  const interval = 100 + Math.random() * 900; //
  setTimeout(() => {
    const x = Math.random() * canvas.width;
    const y = Math.random() * canvas.height;
    startCrack(x, y); // ランダム位置
    startRandomCrackLoop(); // 再帰的に繰り返す
  }, interval);
}

startRandomCrackLoop(); // 実行開始


// ファイルアップロード
/*
var dragArea = document.getElementById('demo');
dragArea.classList.add('ready');
dragArea.addEventListener('dragstart', function(event){
  event.dataTranfer.addElement(container);
});
dragArea.addEventListener('dragover', function(event){
  event.preventDefault();
  this.classList.add('drag');
});
dragArea.addEventListener('dragleave', function(event){
  event.preventDefault();
  this.classList.remove('drag');
});
dragArea.addEventListener('drop', function(event){
  event.preventDefault();
  this.classList.remove('drag');
  console.log(event.dataTransfer.files);
  if(!event.dataTransfer.files.length){
    return;
  }
  var file = event.dataTransfer.files[0];
  fileName = file.name.substring(0,12).split('.')[0] || 'name';
  console.log(file);

  var reader = new FileReader();
  reader.readAsDataURL(file)

  reader.addEventListener('load', function(){
    var dataURL = reader.result;
    console.log(dataURL);

    var newImage = new Image();
    img.src = dataURL;
    newImage.src = dataURL;
    newImage.onload = function(){
    }
  });
});
*/

let opacity = 1;



document.oncontextmenu = function () {return false;}
function resize() {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
  console.table({w:canvas.width, h:canvas.height});
  w = document.body.clientWidth;
  h = document.body.clientHeight;
  cx = w/2;
  cy = h/2;
}

window.onresize = resize;


document.addEventListener('fullscreenchange',function(e){
  resize();
});

CSS

HTML

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

view-source:https://hi0a.com/game/canvas-atomic-life/

ABOUT

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

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

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

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

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

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

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