ほたる

クラスとArrayListを使ったシンプルなサンプルです。クリックしたところにホタルがあらわれます。ゆらゆらと動きながら点滅を繰り返します。

Java

class FireFly {
  int count;
  PVector pos;

  FireFly(float x, float y){
    pos = new PVector(x, y);
  }
  
  void paint() {
    float alpha = sin(radians(count++))*128+128;
    fill(0, 255, 0, alpha);
    ellipse(pos.x, pos.y, 10, 10);    
    pos.x += random(-1, 1);
    pos.y += random(-1, 1);
  }
}

PImage back;
ArrayList<FireFly> flies = new ArrayList<FireFly>();

void setup() {
  back = loadImage("hotaru_back.png");
  size(600, 500);
  noStroke();
}

void draw() {
  background(0);
  image(back, 0, 0);
  for(FireFly f : flies){
    f.paint();
  }
}

void mousePressed(){
  flies.add(new FireFly(mouseX, mouseY));
}

ゆっくり点滅させるために三角関数を使用しています。
ランダムにホタルを移動するためにrandom関数を使用しています。これでもそれなりの雰囲気はでていますが、スムーズに移動するニュアンスが表現できていません。FireFlyクラスを以下のように修正すると、よりリアルな感じが表現できます。

class FireFly {
  int count;
  PVector pos;
  float dx, dy;
  long xSeed, ySeed;

  FireFly(float x, float y){
    pos = new PVector(x, y);
    dx = 1;
    dy = 1;
    xSeed = (int)random(0, 300);
    ySeed = (int)random(0, 300);
  }
  
  void paint() {
    float alpha = sin(radians(count++))*128 + 128;
    fill(0, 255, 0, alpha);
    ellipse(pos.x, pos.y, 10, 10);    
    noiseSeed(xSeed);
    dx += 0.01;     
    pos.x += (noise(dx)*2 - 1);
    noiseSeed(ySeed);
    dy += 0.01;     
    pos.y += (noise(dy)*2 - 1);
  }
}

p5js

<html>

<head>
  <style>
    body,
    html {
      margin: 0;
      padding: 0;
    }

  </style>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
  <script>
    function FireFly(x, y) {
      this.count = 0;
      this.pos = createVector(x, y)
      this.dx = 1
      this.dy = 1
      this.xSeed = random(0, 300)
      this.ySeed = random(0, 300)
      this.paint = function () {
        var alpha = sin(radians(this.count++)) * 128 + 128;
        fill(0, 255, 0, alpha)
        ellipse(this.pos.x, this.pos.y, 10, 10)
        noiseSeed(this.xSeed)
        this.dx += 0.01;
        this.pos.x += noise(this.dx) * 2 - 1;
        noiseSeed(this.ySeed)
        this.dy += 0.01;
        this.pos.y += noise(this.dy) * 2 - 1;
      }
    }
    var back;
    var fires = [];

    function preload() {
      back = loadImage("hotaru_back.png")
    }

    function setup() {
      createCanvas(600, 500);
      noStroke();
      for(var i = 0 ; i < 20 ; i++){
        var x = random(width);
        var y = random(height);
        fires.push(new FireFly(x, y));
      }
    }

    function draw() {
      background(0);
      image(back, 0, 0);
      for(var i = 0 ; i < fires.length ; i++){
        fires[i].paint();
      }
    }

    function mousePressed() {
      fires.push(new FireFly(mouseX, mouseY));
    }

  </script>
</head>

<body>
</body>

</html>