6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

phina.jsAdvent Calendar 2018

Day 13

バグphina

Last updated at Posted at 2018-12-22

image.png

image.png

image.png

image.png

解説

以下のようなglitchというメソッドを用意し、Spriteクラスの描画元になるTextureをぐちゃぐちゃにすることでバグったっぽくしています。

/**
 * @param  {Number} [chipSize] chip粒度ピクセル数 0は無効
 * @param  {Number} [seed] int ランダムシード:結果を固定したい場合に指定
 * @param  {Number} [discreteFreq] int 歯抜けの頻度、高いほど頻度低
 * @return {this}
 */
phina.asset.Texture.prototype.glitch = function(chipSize, seed, discreteFreq) {
  chipSize = chipSize || 16;
  var image;

  if (!this.baseImageElement) {
    image = this.baseImageElement = this.domElement;
    this.glitchedImage = phina.graphics.Canvas().setSize(image.width, image.height);
    this.domElement = this.glitchedImage.domElement;
  }

  image = this.baseImageElement;
  var random = phina.util.Random(seed);
  var canvas = this.glitchedImage;
  var row = Math.floor(image.height / chipSize);
  var col = Math.floor(image.width / chipSize);

  canvas.clear();
  row.times(function(y) {
    col.times(function(x) {
      // たまに歯抜け
      if (discreteFreq && random.randint(0, discreteFreq) === 0) {
        return;
      }
      var sx = random.randint(0, col-1) * chipSize;
      var sy = random.randint(0, row-1) * chipSize;
      var left = x * chipSize;
      var top = y * chipSize;
      canvas.context.drawImage(image,
        sx, sy, chipSize, chipSize,
        left, top, chipSize, chipSize
      );
    }, this);
  }, this);

  return this;
};

手法は上のコードから何となく感じ取ってほしいのですが、簡単に言えば元画像からランダムで矩形範囲(chipSizeで決定)を拾い、表示用のcanvasにそれを敷き詰めています。

Shape系クラスでの実装

タイム部分のphina.display.LabelクラスはShape派生クラスですが、これらのクラスはpostrenderというメソッドを用意していると描画結果にさらなる加工ができます。

これを利用し、postrenderで上のglitchと似たような処理をすることでバグってる感を実現(?)できます。
※ただしpostrenderはオーバーライドされない前提。


phina.display.Shape.prototype.isGlitched = false;
phina.display.Shape.watchRenderProperty('isGlitched'); // 変更があったら再描画をかける
phina.display.Shape.prototype.postrender = function(canvas) {
  if (!this.isGlitched) return;

  // パラメータ
  var chipSize = 16;
  var discreteFreq = 0;
  var seed = null;

  var image;
  var random = phina.util.Random(seed);

  if (!this.cachedCanvas) {
    this.cachedCanvas = phina.graphics.Canvas();
  }

  // 加工結果を一旦保存
  this.cachedCanvas
    .setSize(canvas.width, canvas.height)
    .clear();
  this.cachedCanvas.context.drawImage(canvas.domElement, 0, 0);

  image = this.cachedCanvas.domElement;
  var row = Math.floor(image.height / chipSize);
  var col = Math.floor(image.width / chipSize);

  // 元canvasをバグ状態にする
  canvas.resetTransform();
  canvas.clear();
  row.times(function(y) {
    col.times(function(x) {
      // たまに歯抜け
      if (discreteFreq && random.randint(0, discreteFreq) === 0) {
        return;
      }
      var sx = random.randint(0, col-1) * chipSize;
      var sy = random.randint(0, row-1) * chipSize;
      var left = x * chipSize;
      var top = y * chipSize;
      canvas.context.drawImage(image,
        sx, sy, chipSize, chipSize,
        left, top, chipSize, chipSize
      );
    }, this);
  }, this);
};

参考

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?