PixiJSでスマホブラウザゲームのタップした場所に画像表示実装方法

タップした場所に画像表示

最近のブラウザゲーム(アプリゲーム)だとタップした場所に画像のアニメーションが表示されることが多い。

簡単なものであればCSSとJavaScriptで実装できる。

タップした場所にCSSアニメーション表示

まずCSSアニメーション用のCSSを用意する。

html {
  position: relative;
}
body {
  margin: 0;
  padding: 0;
}
#c {
  position: absolute;
  z-index: 99999;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: cyan;
  opacity: 0;
}

#c.show {
  animation: a 0.3s;
}

@keyframes a {
  0% {
    transform: scale(1);
    opacity: 0.5;
  }
  100% {
    transform: scale(15);
    opacity: 0;
  }
}

* <div id="c"></div> を配置しておく

あとはCSSアニメーションのclassを追加・削除するためのJavaScriptを追加するだけだ。

// アニメーション用に.show追加
var w = window.innerWidth;
var h = window.innerHeight;
var c = document.getElementById('c');
var cs = c.style;
window.addEventListener('click', function(e) {
  cs.top =  e.pageY - 5 + 'px';
  cs.left = e.pageX - 5 + 'px';
  c.classList.add('show');
});

// アニメーション終了後に.show削除
c.addEventListener('animationend', function() {
  this.classList.remove('show');
});

タップした場所にCSSアニメーション表示サンプル

PixiJSで表現の幅を広げる

簡単なものであれば前述のようなやり方で作成できるが、複雑なものであれば複雑な計算式などが必要になる。

しかし、PixiJSを使用すれば比較的簡単に表現の幅を広げることができる。

…と思ったのだが、実際のサンプルを記述してみたら、簡略化しても結構長いコードになるため簡単ではなかった。

(function(window) {
  var Particle = function(imagePaths, config, type, useParticleContainer, stepColors) {
    var canvas = document.getElementById('stage');
    var rendererOptions = {
      view: canvas,
    };
    var stage = new PIXI.Container();
    var emitter = null;
    var renderer = PIXI.autoDetectRenderer(canvas.width, canvas.height, rendererOptions);
    var elapsed = Date.now();
    var updateId;
    var update = function() {
      updateId = requestAnimationFrame(update);
      var now = Date.now();
      if (emitter) {
        emitter.update((now - elapsed) * 0.001);
      }
      elapsed = now;
      renderer.render(stage);
    };
    window.onresize = function(event) {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
      renderer.resize(canvas.width, canvas.height);
    };
    window.onresize();
    var urls = imagePaths.slice();
    var loader = PIXI.loader;
    loader.load(function() {
      var art = [];
      var emitterContainer;
      for (var i = 0; i < imagePaths.length; ++i) {
        art.push(PIXI.Texture.fromImage(imagePaths[i]));
      }
      if (useParticleContainer) {
        emitterContainer = new PIXI.ParticleContainer();
        emitterContainer.setProperties({
          scale: true,
          position: true,
          rotation: true,
          uvs: true,
          alpha: true
        });
      } else
        emitterContainer = new PIXI.Container();
      stage.addChild(emitterContainer);
      window.emitter = emitter = new PIXI.particles.Emitter(
        emitterContainer,
        art,
        config
      );
      emitter.updateOwnerPos(window.innerWidth / 2, window.innerHeight / 2);
      canvas.addEventListener('click', function(e) {
        if (!emitter) return;
        emitter.emit = true;
        emitter.resetPositionTracking();
        emitter.updateOwnerPos(e.offsetX || e.layerX, e.offsetY || e.layerY);
      });
      update();
    });
  };
  window.Particle = Particle;
}(window));

new Particle(
  ['p.png'], {
    "alpha": {
      "start": 0.8,
      "end": 0.1
    },
    "scale": {
      "start": 1,
      "end": 0.3
    },
    "color": {
      "start": "fb1010",
      "end": "f5b830"
    },
    "speed": {
      "start": 200,
      "end": 100
    },
    "startRotation": {
      "min": 0,
      "max": 360
    },
    "rotationSpeed": {
      "min": 0,
      "max": 0
    },
    "lifetime": {
      "min": 0.5,
      "max": 0.5
    },
    "frequency": 0.008,
    "emitterLifetime": 0.31,
    "maxParticles": 1000,
    "pos": {
      "x": 0,
      "y": 0
    },
    "addAtBack": false,
    "spawnType": "circle",
    "spawnCircle": {
      "x": 0,
      "y": 0,
      "r": 10
    }
  }
);

タップした場所にPixiJSアニメーション表示サンプル