四角い車輪を再発明する…!

シーンを構築するノード

Cocos2d-xみたいにシーンにツリー状にオブジェクトを登録して、あとは自動的に描画とかしてくれるような仕組みを作る:

var Node = (function() {
  'use strict';

  var Node = defineClass({
    init: function() {
      var self = this;
      self.children = [];
    },
    addChild: function(node) {
      var self = this;
      self.children.push(node);
    },
    draw: function(G) {
      var self = this;
      var children = self.children;
      var len = children.length;
      for (var i = 0; i < len; ++i)
        children[i].draw(G);
    },
  };
  return Node;
})();
  • addChildで子供をぶら下げておいて、あとはフレームごとにルートに対してdrawを呼び出すとツリーを辿って描画してくれる

Nodeを継承して実際に描画を行うクラス、例えば画像をSpriteなどを用意する:

// スプライト
var Sprite = (function() {
  'use strict';

  var Sprite = defineClass({
    parent: Node,
    init: function(image, x, y) {
      var self = this;
      Node.call(self);  // super.
      self.image = image;
      self.pos = new Point(x, y);
      self.scale = new Point(1, 1);
      self.anchorPoint = new Point(0.5, 0.5);
    },
    draw: function(G) {
      var self = this;
      var x = self.pos.x - self.anchorPoint.x * self.image.width * self.scale.x;
      var y = self.pos.y - self.anchorPoint.y * self.image.height * self.scale.y;
      var w = self.image.width * self.scale.x;
      var h = self.image.height * self.scale.y;
      G.drawImage(self.image, x, y, w, h);

      // 子供の描画呼び出し
      Node.prototype.draw.call(self, G);  // super.
    },
  });
  return Sprite;
})();

アクション

ノードにrunActionとしてアクションを登録すると、位置の移動とかフェードイン・アウトなどをといったアクションを自動的に実行してくれる仕組みを用意する。

ベースクラス:

// アクション
var Action = (function() {
  'use strict';

  var Action = defineClass({
    init: function(duration) {
      var self = this;
      self.duration = duration;
    },
    update: function(target, time) {
      var self = this;
      if (time >= self.duration)
        time = self.duration;
      return time;
    },
    isFinished: function(time) {
      var self = this;
      return time >= self.duration;
    },
  });
  return Action;
})();

アクションを実行する仕組み:

// アクションランナー
var ActionRunner = (function() {
  'use strict';

  var ActionRunner = defineClass({
    init: function(action) {
      var self = this;
      self.time = 0;
      self.action = action;
    },
    update: function(target, dt) {
      var self = this;
      self.time = self.action.update(target, self.time + dt);
      return !self.action.isFinished(self.time);
    },
  });
  return ActionRunner;
})();

あとはアクションを継承していろんなアクションを作ってやる:

// 移動
var ActionMoveTo = (function() {
  'use strict';

  var ActionMoveTo = defineClass({
    parent: Action,
    init: function(duration, targetPos) {
      var self = this;
      Action.call(self, duration);
      self.targetPos = targetPos;
    },
    update: function(target, time) {
      var self = this;
      if (time == 0) {
        self.initialPos = new Point(target.pos.x, target.pos.y);
      } else {
        if (time >= self.duration)
          time = self.duration;
        var t = time / self.duration;
        target.pos.set((self.targetPos.x - self.initialPos.x) * t + self.initialPos.x,
                       (self.targetPos.y - self.initialPos.y) * t + self.initialPos.y);
      }
      return time;
    },
  });
  return ActionMoveTo;
})();

アクションを格納した配列を受け取って順に実行するSequenceとか指定回数繰り返すRepeatとか、はたまたJSの関数を呼び出すCallFuncとかいうものを用意してやる。


  • ぼくのJSのくらすのていぎのてんぷれ を使っている