topical media & game development

talk show tell print

mobile-graphic-enchant-dev-src-Map.js / js



  
@scope enchant.Map.prototype

  
  enchant.Map = enchant.Class.create(enchant.Entity, {
      
@name enchant.Map @class [lang:ja] タイルセットからマップを生成して表示するクラス.
parameter: {Number} tileWidth タイルの横幅.
parameter: {Number} tileHeight タイルの高さ. [/lang] [lang:en] A class to create and display maps from a tile set.
parameter: {Number} tileWidth Tile width.
parameter: {Number} tileHeight Tile height. [/lang] [lang:de] Eine Klasse mit der Karten aus Kacheln (Tiles) erstellt und angezeigt werden können.
parameter: {Number} tileWidth Kachelbreite.
parameter: {Number} tileHeight Kachelhöhe. [/lang] @constructs @extends enchant.Entity

  
      initialize: function(tileWidth, tileHeight) {
          var core = enchant.Core.instance;
  
          enchant.Entity.call(this);
  
          var surface = new enchant.Surface(core.width, core.height);
          this._surface = surface;
          var canvas = surface._element;
          canvas.style.position = 'absolute';
          if (enchant.ENV.RETINA_DISPLAY && core.scale === 2) {
              canvas.width = core.width * 2;
              canvas.height = core.height * 2;
              this._style.webkitTransformOrigin = '0 0';
              this._style.webkitTransform = 'scale(0.5)';
          } else {
              canvas.width = core.width;
              canvas.height = core.height;
          }
          this._context = canvas.getContext('2d');
  
          this._tileWidth = tileWidth || 0;
          this._tileHeight = tileHeight || 0;
          this._image = null;
          this._data = [
              [
                  []
              ]
          ];
          this._dirty = false;
          this._tight = false;
  
          this.touchEnabled = false;
  
          
[lang:ja] タイルが衝突判定を持つかを表す値の二元配列. [/lang] [lang:en] Two dimensional array to store if collision detection should be performed for a tile. [/lang] [lang:de] Ein 2-Dimensionales Array um zu speichern, ob für eine Kachel Kollesionsdetektion durchgeführt werden soll. [/lang] @type {Array.<Array.<Number>>}

  
          this.collisionData = null;
  
          this._listeners['render'] = null;
          this.addEventListener('render', function() {
              if (this._dirty || this._previousOffsetX == null) {
                  this.redraw(0, 0, core.width, core.height);
              } else if (this._offsetX !== this._previousOffsetX ||
                  this._offsetY !== this._previousOffsetY) {
                  if (this._tight) {
                      var x = -this._offsetX;
                      var y = -this._offsetY;
                      var px = -this._previousOffsetX;
                      var py = -this._previousOffsetY;
                      var w1 = x - px + core.width;
                      var w2 = px - x + core.width;
                      var h1 = y - py + core.height;
                      var h2 = py - y + core.height;
                      if (w1 > this._tileWidth && w2 > this._tileWidth &&
                          h1 > this._tileHeight && h2 > this._tileHeight) {
                          var sx, sy, dx, dy, sw, sh;
                          if (w1 < w2) {
                              sx = 0;
                              dx = px - x;
                              sw = w1;
                          } else {
                              sx = x - px;
                              dx = 0;
                              sw = w2;
                          }
                          if (h1 < h2) {
                              sy = 0;
                              dy = py - y;
                              sh = h1;
                          } else {
                              sy = y - py;
                              dy = 0;
                              sh = h2;
                          }
  
                          if (core._buffer == null) {
                              core._buffer = document.createElement('canvas');
                              core._buffer.width = this._context.canvas.width;
                              core._buffer.height = this._context.canvas.height;
                          }
                          var context = core._buffer.getContext('2d');
                          if (this._doubledImage) {
                              context.clearRect(0, 0, sw * 2, sh * 2);
                              context.drawImage(this._context.canvas,
                                  sx * 2, sy * 2, sw * 2, sh * 2, 0, 0, sw * 2, sh * 2);
                              context = this._context;
                              context.clearRect(dx * 2, dy * 2, sw * 2, sh * 2);
                              context.drawImage(core._buffer,
                                  0, 0, sw * 2, sh * 2, dx * 2, dy * 2, sw * 2, sh * 2);
                          } else {
                              context.clearRect(0, 0, sw, sh);
                              context.drawImage(this._context.canvas,
                                  sx, sy, sw, sh, 0, 0, sw, sh);
                              context = this._context;
                              context.clearRect(dx, dy, sw, sh);
                              context.drawImage(core._buffer,
                                  0, 0, sw, sh, dx, dy, sw, sh);
                          }
  
                          if (dx === 0) {
                              this.redraw(sw, 0, core.width - sw, core.height);
                          } else {
                              this.redraw(0, 0, core.width - sw, core.height);
                          }
                          if (dy === 0) {
                              this.redraw(0, sh, core.width, core.height - sh);
                          } else {
                              this.redraw(0, 0, core.width, core.height - sh);
                          }
                      } else {
                          this.redraw(0, 0, core.width, core.height);
                      }
                  } else {
                      this.redraw(0, 0, core.width, core.height);
                  }
              }
              this._previousOffsetX = this._offsetX;
              this._previousOffsetY = this._offsetY;
          });
      },
      
[lang:ja] データを設定する. タイルががimageプロパティの画像に左上から順に配列されていると見て, 0から始まる インデックスの二元配列を設定する.複数指定された場合は後のものから順に表示される.
parameter: {...Array>} data タイルのインデックスの二元配列. 複数指定できる. [/lang] [lang:en] Set map data. Sets the tile data, whereas the data (two-dimensional array with indizes starting from 0) is mapped on the image starting from the upper left corner. When more than one map data array is set, they are displayed in reverse order.
parameter: {...Array>} data Two-dimensional array of tile indizes. Multiple designations possible. [/lang] [lang:de] Setzt die Kartendaten. Setzt die Kartendaten, wobei die Daten (ein 2-Dimensionales Array bei dem die Indizes bei 0 beginnen) auf das Bild, beginned bei der linken oberen Ecke) projeziert werden. Sollte mehr als ein Array übergeben worden sein, werden die Karten in invertierter Reihenfolge dargestellt.
parameter: {...Array>} data 2-Dimensionales Array mit Kachel Indizes. Mehrfachangaben möglich. [/lang]

  
      loadData: function(data) {
          this._data = Array.prototype.slice.apply(arguments);
          this._dirty = true;
  
          this._tight = false;
          for (var i = 0, len = this._data.length; i < len; i++) {
              var c = 0;
              data = this._data[i];
              for (var y = 0, l = data.length; y < l; y++) {
                  for (var x = 0, ll = data[y].length; x < ll; x++) {
                      if (data[y][x] >= 0) {
                          c++;
                      }
                  }
              }
              if (c / (data.length * data[0].length) > 0.2) {
                  this._tight = true;
                  break;
              }
          }
      },
      
[lang:ja] ある座標のタイルが何か調べる.
parameter: {Number} x マップ上の点のx座標.
parameter: {Number} y マップ上の点のy座標.
returns: {*} ある座標のタイルのデータ. [/lang] [lang:en] Checks what tile is present at the given position.
parameter: {Number} x x coordinates of the point on the map.
parameter: {Number} y y coordinates of the point on the map.
returns: {*} The tile data for the given position. [/lang] [lang:de] Überprüft welche Kachel an der gegeben Position vorhanden ist.
parameter: {Number} x Die x Koordinataten des Punktes auf der Karte.
parameter: {Number} y Die y Koordinataten des Punktes auf der Karte.
returns: {*} Die Kachel für die angegebene Position. [/lang]

  
      checkTile: function(x, y) {
          if (x < 0 || this.width <= x || y < 0 || this.height <= y) {
              return false;
          }
          var width = this._image.width;
          var height = this._image.height;
          var tileWidth = this._tileWidth || width;
          var tileHeight = this._tileHeight || height;
          x = x / tileWidth | 0;
          y = y / tileHeight | 0;
          //                return this._data[y][x];
          var data = this._data[0];
          return data[y][x];
      },
      
[lang:ja] Map上に障害物があるかどうかを判定する.
parameter: {Number} x 判定を行うマップ上の点のx座標.
parameter: {Number} y 判定を行うマップ上の点のy座標.
returns: {Boolean} 障害物があるかどうか. [/lang] [lang:en] Judges whether or not obstacles are on top of Map.
parameter: {Number} x x coordinates of detection spot on map.
parameter: {Number} y y coordinates of detection spot on map.
returns: {Boolean} True, if there are obstacles. [/lang] [lang:de] Überprüft ob auf der Karte Hindernisse vorhanden sind.
parameter: {Number} x Die x Koordinataten des Punktes auf der Karte, der überprüft werden soll.
parameter: {Number} y Die y Koordinataten des Punktes auf der Karte, der überprüft werden soll.
returns: {Boolean} True, falls Hindernisse vorhanden sind. [/lang]

  
      hitTest: function(x, y) {
          if (x < 0 || this.width <= x || y < 0 || this.height <= y) {
              return false;
          }
          var width = this._image.width;
          var height = this._image.height;
          var tileWidth = this._tileWidth || width;
          var tileHeight = this._tileHeight || height;
          x = x / tileWidth | 0;
          y = y / tileHeight | 0;
          if (this.collisionData != null) {
              return this.collisionData[y] && !!this.collisionData[y][x];
          } else {
              for (var i = 0, len = this._data.length; i < len; i++) {
                  var data = this._data[i];
                  var n;
                  if (data[y] != null && (n = data[y][x]) != null &&
                      0 <= n && n < (width / tileWidth | 0) * (height / tileHeight | 0)) {
                      return true;
                  }
              }
              return false;
          }
      },
      
[lang:ja] Mapで表示するタイルセット画像. [/lang] [lang:en] Image with which the tile set is displayed on the map. [/lang] [lang:de] Das Bild mit dem die Kacheln auf der Karte dargestellt werden. [/lang] @type {enchant.Surface}

  
      image: {
          get: function() {
              return this._image;
          },
          set: function(image) {
              var core = enchant.Core.instance;
  
              this._image = image;
              if (enchant.ENV.RETINA_DISPLAY && core.scale === 2) {
                  var img = new enchant.Surface(image.width * 2, image.height * 2);
                  var tileWidth = this._tileWidth || image.width;
                  var tileHeight = this._tileHeight || image.height;
                  var row = image.width / tileWidth | 0;
                  var col = image.height / tileHeight | 0;
                  for (var y = 0; y < col; y++) {
                      for (var x = 0; x < row; x++) {
                          img.draw(image, x * tileWidth, y * tileHeight, tileWidth, tileHeight,
                              x * tileWidth * 2, y * tileHeight * 2, tileWidth * 2, tileHeight * 2);
                      }
                  }
                  this._doubledImage = img;
              }
              this._dirty = true;
          }
      },
      
[lang:ja] Mapのタイルの横幅. [/lang] [lang:en] Map tile width. [/lang] [lang:de] Kachelbreite [/lang] @type {Number}

  
      tileWidth: {
          get: function() {
              return this._tileWidth;
          },
          set: function(tileWidth) {
              this._tileWidth = tileWidth;
              this._dirty = true;
          }
      },
      
[lang:ja] Mapのタイルの高さ. [/lang] [lang:en] Map tile height. [/lang] [lang:de] Kachelhöhe. [/lang] @type {Number}

  
      tileHeight: {
          get: function() {
              return this._tileHeight;
          },
          set: function(tileHeight) {
              this._tileHeight = tileHeight;
              this._dirty = true;
          }
      },
      
@private

  
      width: {
          get: function() {
              return this._tileWidth * this._data[0][0].length;
          }
      },
      
@private

  
      height: {
          get: function() {
              return this._tileHeight * this._data[0].length;
          }
      },
      
@private

  
      redraw: function(x, y, width, height) {
          if (this._image == null) {
              return;
          }
  
          var image, tileWidth, tileHeight, dx, dy;
          if (this._doubledImage) {
              image = this._doubledImage;
              tileWidth = this._tileWidth * 2;
              tileHeight = this._tileHeight * 2;
              dx = -this._offsetX * 2;
              dy = -this._offsetY * 2;
              x *= 2;
              y *= 2;
              width *= 2;
              height *= 2;
          } else {
              image = this._image;
              tileWidth = this._tileWidth;
              tileHeight = this._tileHeight;
              dx = -this._offsetX;
              dy = -this._offsetY;
          }
          var row = image.width / tileWidth | 0;
          var col = image.height / tileHeight | 0;
          var left = Math.max((x + dx) / tileWidth | 0, 0);
          var top = Math.max((y + dy) / tileHeight | 0, 0);
          var right = Math.ceil((x + dx + width) / tileWidth);
          var bottom = Math.ceil((y + dy + height) / tileHeight);
  
          var source = image._element;
          var context = this._context;
          var canvas = context.canvas;
          context.clearRect(x, y, width, height);
          for (var i = 0, len = this._data.length; i < len; i++) {
              var data = this._data[i];
              var r = Math.min(right, data[0].length);
              var b = Math.min(bottom, data.length);
              for (y = top; y < b; y++) {
                  for (x = left; x < r; x++) {
                      var n = data[y][x];
                      if (0 <= n && n < row * col) {
                          var sx = (n % row) * tileWidth;
                          var sy = (n / row | 0) * tileHeight;
                          context.drawImage(source, sx, sy, tileWidth, tileHeight,
                              x * tileWidth - dx, y * tileHeight - dy, tileWidth, tileHeight);
                      }
                  }
              }
          }
      },
      cvsRender: function(ctx) {
          var core = enchant.Core.instance;
          if (this.width !== 0 && this.height !== 0) {
              ctx.save();
              ctx.setTransform(1, 0, 0, 1, 0, 0);
              var cvs = this._context.canvas;
                  ctx.drawImage(cvs, 0, 0, core.width, core.height);
              ctx.restore();
          }
      },
      domRender: function(element) {
          if (this._image) {
              this._style['background-image'] = this._surface._css;
              // bad performance
              this._style[enchant.ENV.VENDOR_PREFIX + 'Transform'] = 'matrix(1, 0, 0, 1, 0, 0)';
          }
      }
  });
  
  


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.