设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 6207|回复: 17
打印 上一主题 下一主题

[原创发布] 像素移动

[复制链接]

Lv1.梦旅人

梦石
0
星屑
50
在线时间
46 小时
注册时间
2014-3-14
帖子
37
跳转到指定楼层
1
发表于 2016-6-7 17:25:25 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 moe2333 于 2016-6-7 17:35 编辑

暂时不支持座驾。
JAVASCRIPT 代码复制下载
  1. //=============================================================================
  2. // PixelMovement.js
  3. //=============================================================================
  4.  
  5. /*:
  6.  * @plugindesc Like you don't know what this does.
  7.  */
  8.  
  9. (function () {
  10.     //-----------------------------------------------------------------------------
  11.  
  12.     // An even number between 2 and 48, inclusive
  13.     var tileSection = 4;
  14.     // Gives you precise collision mask but can significantly compromise the performance
  15.     var analyzeTilesetBitmap = true;
  16.     // A section of the bitmap will be masked impassable if the valid pixel rate reaches this threshold
  17.     var bitmapAnalysisThreshold = 0.5;
  18.     // (x, y, width, height)
  19.     var characterCollisionBox = new Rectangle(1, 2, 2, 2);
  20.     // Tiles with this terrain tag are forced to be passable
  21.     var forcePassableTerrainTag = 3;
  22.     // Max distance between two followers
  23.     var followerDistance = 1;
  24.     // For debugging
  25.     var drawCollisionMask = true;
  26.     // [map, ladder, bush, counter, damageFloor, boat, ship], for debugging
  27.     var collisionMaskLayerColors = ['red', 'grey', 'green', 'yellow', 'crimson', 'lightBlue', 'blue'];
  28.  
  29.     //-----------------------------------------------------------------------------
  30.     var toPixel = function (t) {
  31.         return t * tileSection;
  32.     };
  33.  
  34.     var toTile = function (p) {
  35.         return p / tileSection;
  36.     };
  37.  
  38.     //-----------------------------------------------------------------------------
  39.     // Table2
  40.  
  41.     function Table2(xSize, ySize) {
  42.         this.initialize.apply(this, arguments);
  43.     }
  44.  
  45.     Table2.prototype.initialize = function (xSize, ySize) {
  46.         this.xSize = xSize;
  47.         this.ySize = ySize;
  48.         this.data = [];
  49.     };
  50.  
  51.     Table2.prototype.get = function (x, y) {
  52.         return this.data[y * this.xSize + x];
  53.     };
  54.  
  55.     Table2.prototype.set = function (x, y, data) {
  56.         this.data[y * this.xSize + x] = data;
  57.     };
  58.  
  59.     //-----------------------------------------------------------------------------
  60.     // Table3
  61.  
  62.     function Table3() {
  63.         this.initialize.apply(this, arguments);
  64.     }
  65.  
  66.     Table3.prototype.initialize = function (xSize, ySize, zSize) {
  67.         this.xSize = xSize;
  68.         this.ySize = ySize;
  69.         this.zSize = zSize;
  70.         this.data = [];
  71.     };
  72.  
  73.     Table3.prototype.get = function (x, y, z) {
  74.         return this.data[z * this.ySize * this.xSize + y * this.xSize + x];
  75.     };
  76.  
  77.     Table3.prototype.set = function (x, y, z, data) {
  78.         return this.data[z * this.ySize * this.xSize + y * this.xSize + x] = data;
  79.     };
  80.  
  81.     //-----------------------------------------------------------------------------
  82.     // Bitmap
  83.  
  84.     Bitmap.prototype.isOccupied = function (x, y, w, h, threshold) {
  85.         var data = this._context.getImageData(x, y, w, h).data;
  86.         var occupied = 0;
  87.         for (var i = 3; i < data.length; i += 4) {
  88.             if (data[i] === 255) {
  89.                 occupied++;
  90.             }
  91.         }
  92.         return (occupied / (data.length / 4)) > threshold;
  93.     };
  94.  
  95.     //-----------------------------------------------------------------------------
  96.     // Tilemap
  97.  
  98.     var aliasTilemapPrototypeUpdate = Tilemap.prototype.update;
  99.     Tilemap.prototype.update = function () {
  100.         aliasTilemapPrototypeUpdate.apply(this, arguments);
  101.         if (this._needRefreshCollisionMask && this.isReady()) {
  102.             this._needRefreshCollisionMask = false;
  103.             this.refreshCollisionMask();
  104.         }
  105.     };
  106.  
  107.     var aliasTilemapPrototypeRefresh = Tilemap.prototype.refresh;
  108.     Tilemap.prototype.refresh = function () {
  109.         aliasTilemapPrototypeRefresh.apply(this, arguments);
  110.         this._needRefreshCollisionMask = true;
  111.     };
  112.  
  113.     Tilemap.prototype.refreshCollisionMask = function () {
  114.         console.time('Collision Mask Generation');
  115.         $gameMap.collisionMask = new Table3($gameMap.widthPx(), $gameMap.heightPx(), 8);
  116.         this._tileCollisionMaskCaches = {};
  117.         for (var tx = 0; tx < this._mapWidth; tx++) {
  118.             for (var ty = 0; ty < this._mapHeight; ty++) {
  119.                 this.drawTileCollisionMask(tx, ty);
  120.             }
  121.         }
  122.         this._tileCollisionMaskCaches = null;
  123.         console.timeEnd('Collision Mask Generation');
  124.         if (drawCollisionMask) {
  125.             this.debugDrawCollisionMask();
  126.         }
  127.     };
  128.  
  129.     Tilemap.prototype.drawTileCollisionMask = function (tx, ty) {
  130.         var forcePassable = $gameMap.terrainTag(tx, ty) === forcePassableTerrainTag;
  131.  
  132.         var mcm = $gameMap.collisionMask;
  133.  
  134.         var flags = this.flags;
  135.         var tileIds = $gameMap.layeredTiles(tx, ty);
  136.  
  137.         var impassableSections = [];
  138.         var totalSections = tileSection * tileSection;
  139.  
  140.         for (var tileId, flag, i = 0; i < tileIds.length; i++) {
  141.             tileId = tileIds[i];
  142.  
  143.             if (!Tilemap.isVisibleTile(tileId)) {
  144.                 continue;
  145.             }
  146.  
  147.             var tcm = this._tileCollisionMaskCaches[tileId];
  148.             if (tcm) {
  149.                 if (!forcePassable) {
  150.                     for (var sx = 0; sx < tileSection; sx++) {
  151.                         for (var sy = 0; sy < tileSection; sy++) {
  152.                             for (var z = 0; z < 8; z++) {
  153.                                 var bit = tcm.get(sx, sy, z);
  154.                                 if (bit === 1) {
  155.                                     mcm.set(toPixel(tx) + sx, toPixel(ty) + sy, z, bit);
  156.                                     if (z === 0) { // tile collision layer
  157.                                         var sectionId = sy * tileSection + sx;
  158.                                         if (!impassableSections.contains(sectionId)) {
  159.                                             impassableSections.push(sectionId);
  160.                                         }
  161.                                     }
  162.                                 }
  163.                             }
  164.                         }
  165.                     }
  166.                     if (impassableSections.length >= totalSections) {
  167.                         break;
  168.                     } else {
  169.                         continue;
  170.                     }
  171.                 }
  172.             } else {
  173.                 tcm = new Table3(tileSection, tileSection, 8);
  174.                 this._tileCollisionMaskCaches[tileId] = tcm;
  175.             }
  176.  
  177.             flag = flags[tileId];
  178.  
  179.             // other layers of the collision mask
  180.             for (var bp = 5; bp < 9; bp++) { // ladder, bush, counter, damageFloor
  181.                 if ((flag & (1 << bp)) !== 0) {
  182.                     for (var sx = 0; sx < tileSection; sx++) {
  183.                         for (var sy = 0; sy < tileSection; sy++) {
  184.                             var z = bp - 4;
  185.                             mcm.set(toPixel(tx) + sx, toPixel(ty) + sy, z, 1);
  186.                             tcm.set(sx, sy, z, 1);
  187.                         }
  188.                     }
  189.                 }
  190.             }
  191.             if (!forcePassable) {
  192.                 for (var bp = 9; bp < 12; bp++) { // boat, ship, airship
  193.                     if ((flag & (1 << bp)) === 0) {
  194.                         for (var sx = 0; sx < tileSection; sx++) {
  195.                             for (var sy = 0; sy < tileSection; sy++) {
  196.                                 var z = bp - 4;
  197.                                 mcm.set(toPixel(tx) + sx, toPixel(ty) + sy, z, 1);
  198.                                 tcm.set(sx, sy, z, 1);
  199.                             }
  200.                         }
  201.                     }
  202.                 }
  203.             }
  204.  
  205.             if (forcePassable) {
  206.                 break;
  207.             }
  208.  
  209.             // 0th layer of the collision mask
  210.             if ((flag & 0xf) === 0xf) { // all dirs are not passable
  211.                 if (analyzeTilesetBitmap) {
  212.                     if (Tilemap.isAutotile(tileId)) { // TODO: need to check the collision masks for autotiles too
  213.                         for (var sx = 0; sx < tileSection; sx++) {
  214.                             for (var sy = 0; sy < tileSection; sy++) {
  215.                                 mcm.set(toPixel(tx) + sx, toPixel(ty) + sy, 0, 1);
  216.                                 tcm.set(sx, sy, 0, 1);
  217.                             }
  218.                         }
  219.                         break;
  220.                     } else {
  221.                         var bitmap = this.bitmaps[Tilemap.isTileA5(tileId) ? 4 : 5 + Math.floor(tileId / 256)];
  222.                         var tw = this._tileWidth;
  223.                         var th = this._tileHeight;
  224.                         var sw = $gameMap.tileWidthPx();
  225.                         var sh = $gameMap.tileHeightPx();
  226.                         var bx = (Math.floor(tileId / 128) % 2 * 8 + tileId % 8) * tw;
  227.                         var by = (Math.floor(tileId % 256 / 8) % 16) * th;
  228.                         for (var sx = 0; sx < tileSection; sx++) {
  229.                             for (var sy = 0; sy < tileSection; sy++) {
  230.                                 if (bitmap.isOccupied(bx + sx * sw, by + sy * sh, sw, sh, bitmapAnalysisThreshold)) {
  231.                                     mcm.set(toPixel(tx) + sx, toPixel(ty) + sy, 0, 1);
  232.                                     tcm.set(sx, sy, 0, 1);
  233.                                     var sectionId = sy * tileSection + sx;
  234.                                     if (!impassableSections.contains(sectionId)) {
  235.                                         impassableSections.push(sectionId);
  236.                                     }
  237.                                 }
  238.                             }
  239.                         }
  240.                         if (impassableSections.length >= totalSections) {
  241.                             break;
  242.                         }
  243.                     }
  244.                 } else {
  245.                     for (var sx = 0; sx < tileSection; sx++) {
  246.                         for (var sy = 0; sy < tileSection; sy++) {
  247.                             mcm.set(toPixel(tx) + sx, toPixel(ty) + sy, 0, 1);
  248.                             tcm.set(sx, sy, 0, 1);
  249.                         }
  250.                     }
  251.                     break;
  252.                 }
  253.             } else if ((flag & 0xf) !== 0) { // some dirs are passable, but not all
  254.                 for (var bp = 0; bp < 4; bp++) {
  255.                     if ((flag & (1 << bp)) !== 0) {
  256.                         switch (bp) {
  257.                             case 0: // down
  258.                                 for (var sx = 0; sx < tileSection; sx++) {
  259.                                     mcm.set(toPixel(tx) + sx, toPixel(ty) + tileSection - 1, 0, 1);
  260.                                     tcm.set(sx, tileSection - 1, 0, 1)
  261.                                 }
  262.                                 break;
  263.                             case 1: // left
  264.                                 for (var sy = 0; sy < tileSection; sy++) {
  265.                                     mcm.set(toPixel(tx), toPixel(ty) + sy, 0, 1);
  266.                                     tcm.set(0, sy, 0, 1)
  267.                                 }
  268.                                 break;
  269.                             case 2: // right
  270.                                 for (var sy = 0; sy < tileSection; sy++) {
  271.                                     mcm.set(toPixel(tx) + tileSection - 1, toPixel(ty) + sy, 0, 1);
  272.                                     tcm.set(tileSection - 1, sy, 0, 1)
  273.                                 }
  274.                                 break;
  275.                             case 3: // up
  276.                                 for (var sx = 0; sx < tileSection; sx++) {
  277.                                     mcm.set(toPixel(tx) + sx, toPixel(ty), 0, 1);
  278.                                     tcm.set(sx, 0, 0, 1)
  279.                                 }
  280.                                 break;
  281.                         }
  282.                     }
  283.                 }
  284.             }
  285.         }
  286.     };
  287.  
  288.     Tilemap.prototype.debugDrawCollisionMask = function () {
  289.         var cm = $gameMap.collisionMask;
  290.         var sw = $gameMap.tileWidthPx();
  291.         var sh = $gameMap.tileHeightPx();
  292.         for (var layerIndex = 0; layerIndex < 7; layerIndex++) {
  293.             var sprite = new Sprite(new Bitmap(this._mapWidth * this._tileWidth, this._mapHeight * this._tileHeight));
  294.             sprite.pivot = this.origin;
  295.             sprite.opacity = 80;
  296.             for (var px = 0; px < cm.xSize; px++) {
  297.                 for (var py = 0; py < cm.ySize; py++) {
  298.                     if (cm.get(px, py, layerIndex) === 1) {
  299.                         sprite.bitmap.fillRect(px * sw, py * sh, sw, sh, collisionMaskLayerColors[layerIndex]);
  300.                     }
  301.                 }
  302.             }
  303.             this.parent.addChild(sprite);
  304.         }
  305.     };
  306.  
  307.     //------------------------------------------------------------
  308.     // Game_Temp
  309.  
  310.     var aliasGameTempPrototypeInitialize = Game_Temp.prototype.initialize;
  311.     Game_Temp.prototype.initialize = function () {
  312.         aliasGameTempPrototypeInitialize.apply(this, arguments);
  313.         this._destinationPx = null;
  314.         this._destinationPy = null;
  315.         this._route = null;
  316.     };
  317.  
  318.     Game_Temp.prototype.isDestinationValid = function () {
  319.         return this._route && this._route.length > 0;
  320.     };
  321.  
  322.     Game_Temp.prototype.setDestination = function (px, py) {
  323.         if (!this._route || px !== this._destinationPx || py !== this._destinationPy) {
  324.             this._destinationPx = px;
  325.             this._destinationPy = py;
  326.             this._route = $gamePlayer.findRouteTo(px, py);
  327.         }
  328.     };
  329.  
  330.     Game_Temp.prototype.clearDestination = function () {
  331.         this._destinationPx = null;
  332.         this._destinationPy = null;
  333.         this._route = null;
  334.     };
  335.  
  336.     Game_Temp.prototype.destinationPx = function () {
  337.         return this._destinationPx;
  338.     };
  339.  
  340.     Game_Temp.prototype.destinationPy = function () {
  341.         return this._destinationPy;
  342.     };
  343.  
  344.     Game_Temp.prototype.nextDirection = function () {
  345.         return this._route ? this._route.pop() : 0;
  346.     };
  347.  
  348.     //------------------------------------------------------------
  349.     // Game_Actor
  350.  
  351.     /* TODO: Only damage characters that are on the damage floor
  352.     Game_Actor.prototype.checkFloorEffect = function () {
  353.         if ($gamePlayer.isOnDamageFloor()) {
  354.             this.executeFloorDamage();
  355.         }
  356.     };
  357.     */
  358.  
  359.     //------------------------------------------------------------
  360.     // Game_Map
  361.  
  362.     Object.defineProperty(Game_Map.prototype, 'collisionMask', {
  363.         get: function () {
  364.             return this._collisionMask;
  365.         },
  366.         set: function (value) {
  367.             this._collisionMask = value;
  368.         },
  369.         configurable: true
  370.     });
  371.  
  372.     Game_Map.prototype.isCollisionMaskSet = function () {
  373.         return this._collisionMask !== null;
  374.     };
  375.  
  376.     var aliasGameMapPrototypeInitialize = Game_Map.prototype.initialize;
  377.     Game_Map.prototype.initialize = function () {
  378.         aliasGameMapPrototypeInitialize.apply(this, arguments);
  379.         this._collisionMask = null;
  380.     };
  381.  
  382.     Game_Map.prototype.tileWidthPx = function () {
  383.         return this.tileWidth() / tileSection;
  384.     };
  385.  
  386.     Game_Map.prototype.tileHeightPx = function () {
  387.         return this.tileHeight() / tileSection;
  388.     };
  389.  
  390.     Game_Map.prototype.widthPx = function () {
  391.         return $dataMap.width * tileSection;
  392.     };
  393.  
  394.     Game_Map.prototype.heightPx = function () {
  395.         return $dataMap.height * tileSection;
  396.     };
  397.  
  398.     Game_Map.prototype.adjustPx = function (px) {
  399.         return toPixel(this.adjustX(toTile(px)));
  400.     };
  401.  
  402.     Game_Map.prototype.adjustPy = function (py) {
  403.         return toPixel(this.adjustY(toTile(py)));
  404.     };
  405.  
  406.     Game_Map.prototype.roundPx = function (px) {
  407.         return this.isLoopHorizontal() ? px.mod(this.widthPx()) : px;
  408.     };
  409.  
  410.     Game_Map.prototype.roundPy = function (py) {
  411.         return this.isLoopVertical() ? py.mod(this.heightPx()) : py;
  412.     };
  413.  
  414.     Game_Map.prototype.pxWithDirection = function (px, d) {
  415.         return px + (d === 6 ? 1 : d === 4 ? -1 : 0);
  416.     };
  417.  
  418.     Game_Map.prototype.pyWithDirection = function (py, d) {
  419.         return py + (d === 2 ? 1 : d === 8 ? -1 : 0);
  420.     };
  421.  
  422.     Game_Map.prototype.roundPxWithDirection = function (px, d) {
  423.         return this.roundPx(px + (d === 6 ? 1 : d === 4 ? -1 : 0));
  424.     };
  425.  
  426.     Game_Map.prototype.roundPyWithDirection = function (py, d) {
  427.         return this.roundPy(py + (d === 2 ? 1 : d === 8 ? -1 : 0));
  428.     };
  429.  
  430.     Game_Map.prototype.deltaPx = function (px1, px2) {
  431.         var result = px1 - px2;
  432.         if (this.isLoopHorizontal() && Math.abs(result) > this.widthPx() / 2) {
  433.             result += result < 0 ? this.widthPx() : -this.widthPx();
  434.         }
  435.         return result;
  436.     };
  437.  
  438.     Game_Map.prototype.deltaPy = function (py1, py2) {
  439.         var result = py1 - py2;
  440.         if (this.isLoopVertical() && Math.abs(result) > this.heightPx() / 2) {
  441.             result += result < 0 ? this.heightPx() : -this.heightPx();
  442.         }
  443.         return result;
  444.     };
  445.  
  446.     Game_Map.prototype.distancePx = function (px1, py1, px2, py2) {
  447.         return Math.abs(this.deltaPx(px1, px2)) + Math.abs(this.deltaPy(py1, py2));
  448.     };
  449.  
  450.     Game_Map.prototype.canvasToMapPx = function (x) {
  451.         return this.roundPx(Math.round((this._displayX * this.tileWidth() + x) / $gameMap.tileWidthPx()));
  452.     };
  453.  
  454.     Game_Map.prototype.canvasToMapPy = function (y) {
  455.         return this.roundPy(Math.round((this._displayY * this.tileHeight() + y) / $gameMap.tileHeightPx()));
  456.     };
  457.  
  458.     Game_Map.prototype.collidedEventsPx = function (px, py, cm) {
  459.         return this.events().filter(function (event) {
  460.             return $gameMap.areTwoCollisionMasksCollided(px, py, cm, event.px, event.py, event.collisionMask);
  461.         });
  462.     };
  463.  
  464.     Game_Map.prototype.areTwoCollisionMasksCollided = function (px1, py1, cm1, px2, py2, cm2) {
  465.         var xs1 = cm1.xSize;
  466.         var ys1 = cm1.ySize;
  467.         var xs2 = cm2.xSize;
  468.         var ys2 = cm2.ySize;
  469.         var spx1 = px1 - xs1 / 2;
  470.         var spy1 = py1 - ys1;
  471.         var spx2 = px2 - xs2 / 2;
  472.         var spy2 = py2 - ys2;
  473.         if (spx1 > spx2 + xs2 || spx1 + xs1 < spx2 || spy1 > spy2 + ys2 || spy1 + ys1 < spy2) {
  474.             return false;
  475.         }
  476.         var mpw = this.widthPx();
  477.         var poses1 = [];
  478.         var poses2 = [];
  479.         for (var cmx1 = 0; cmx1 < xs1; cmx1++) {
  480.             for (var cmy1 = 0; cmy1 < ys1; cmy1++) {
  481.                 cm1.get(cmx1, cmy1) && poses1.push(this.roundPy(spy1 + cmy1) * mpw + this.roundPx(spx1 + cmx1));
  482.             }
  483.         }
  484.         for (var cmx2 = 0; cmx2 < xs2; cmx2++) {
  485.             for (var cmy2 = 0; cmy2 < ys2; cmy2++) {
  486.                 cm2.get(cmx2, cmy2) && poses2.push(this.roundPy(spy2 + cmy2) * mpw + this.roundPx(spx2 + cmx2));
  487.             }
  488.         }
  489.         for (var i = 0; i < poses1.length; i++) {
  490.             for (var j = 0; j < poses2.length; j++) {
  491.                 if (poses1[i] === poses2[j]) {
  492.                     return true;
  493.                 }
  494.             }
  495.         }
  496.         return false;
  497.     };
  498.  
  499.     Game_Map.prototype.isValidPx = function (px, py) {
  500.         return px > -1 && px < this.widthPx() && py > -1 && py < this.heightPx();
  501.     };
  502.  
  503.     Game_Map.prototype.isPassablePx = function (px, py) {
  504.         return !this._collisionMask.get(px, py, 0);
  505.     };
  506.  
  507.     Game_Map.prototype.isPassableWithCollisionMask = function (px, py, cm) {
  508.         var spx = px - cm.xSize / 2;
  509.         var spy = py - cm.ySize;
  510.         for (var cmx = 0; cmx < cm.xSize; cmx++) {
  511.             for (var cmy = 0; cmy < cm.ySize; cmy++) {
  512.                 if (cm.get(cmx, cmy)) {
  513.                     var apx = this.roundPx(spx + cmx);
  514.                     var apy = this.roundPy(spy + cmy);
  515.                     if (!this.isValidPx(apx, apy) || !this.isPassablePx(apx, apy)) {
  516.                         return false;
  517.                     }
  518.                 }
  519.             }
  520.         }
  521.         return true;
  522.     };
  523.  
  524.     Game_Map.prototype.isBoatPassablePx = function (px, py) {
  525.         return false;
  526.     };
  527.  
  528.     Game_Map.prototype.isShipPassablePx = function (px, py) {
  529.         return false;
  530.     };
  531.  
  532.     Game_Map.prototype.isAirshipLandOkPx = function (px, py) {
  533.         return false;
  534.     };
  535.  
  536.     Game_Map.prototype.isLadderPx = function (px, py) {
  537.         if (!this.isCollisionMaskSet()) {
  538.             return false;
  539.         }
  540.         return this.isValidPx(px, py) && this._collisionMask.get(px, py, 1);
  541.     };
  542.  
  543.     Game_Map.prototype.isBushPx = function (px, py) {
  544.         if (!this.isCollisionMaskSet()) {
  545.             return false;
  546.         }
  547.         return this.isValidPx(px, py) && this._collisionMask.get(px, py, 2);
  548.     };
  549.  
  550.     Game_Map.prototype.isCounterPx = function (px, py) {
  551.         if (!this.isCollisionMaskSet()) {
  552.             return false;
  553.         }
  554.         return this.isValidPx(px, py) && this._collisionMask.get(px, py, 3);
  555.     };
  556.  
  557.     Game_Map.prototype.isDamageFloorPx = function (px, py) {
  558.         if (!this.isCollisionMaskSet()) {
  559.             return false;
  560.         }
  561.         return this.isValidPx(px, py) && this._collisionMask.get(px, py, 4);
  562.     };
  563.  
  564.     //------------------------------------------------------------
  565.     // Game_CharacterBase
  566.  
  567.     Object.defineProperty(Game_CharacterBase.prototype, 'collisionMask', {
  568.         get: function () {
  569.             return this._collisionMask
  570.         },
  571.         set: function (value) {
  572.             this._collisionMask = value
  573.         },
  574.         configurable: true
  575.     });
  576.  
  577.     Object.defineProperty(Game_CharacterBase.prototype, 'px', {
  578.         get: function () {
  579.             return this._px
  580.         },
  581.         configurable: true
  582.     });
  583.  
  584.     Object.defineProperty(Game_CharacterBase.prototype, 'py', {
  585.         get: function () {
  586.             return this._py
  587.         },
  588.         configurable: true
  589.     });
  590.  
  591.     var aliasGameCharacterBasePrototypeInitMembers = Game_CharacterBase.prototype.initMembers;
  592.     Game_CharacterBase.prototype.initMembers = function () {
  593.         aliasGameCharacterBasePrototypeInitMembers.apply(this, arguments);
  594.         this._px = 0;
  595.         this._py = 0;
  596.         this._realPx = 0;
  597.         this._realPy = 0;
  598.         this.createCollisionMask();
  599.     };
  600.  
  601.     Game_CharacterBase.prototype.createCollisionMask = function () { // TODO: Support bitmap analysis and custom collision box
  602.         this._collisionMask = new Table2(tileSection, tileSection);
  603.         var box = characterCollisionBox;
  604.         for (var x = box.x; x < box.x + box.width; x++) {
  605.             for (var y = box.y; y < box.y + box.height; y++) {
  606.                 this._collisionMask.set(x, y, 1);
  607.             }
  608.         }
  609.     };
  610.  
  611.     Game_CharacterBase.prototype.synchronizeTileCoordinate = function () {
  612.         this._realX = toTile(this._realPx);
  613.         this._realY = toTile(this._realPy);
  614.         this._x = Math.floor(this._realX);
  615.         this._y = Math.floor(this._realY);
  616.     };
  617.  
  618.     Game_CharacterBase.prototype.isMoving = function () {
  619.         return this._realPx !== this._px || this._realPy !== this._py;
  620.     };
  621.  
  622.     Game_CharacterBase.prototype.canPassPx = function (px, py, d) {
  623.         var npx = $gameMap.roundPxWithDirection(px, d);
  624.         var npy = $gameMap.roundPyWithDirection(py, d);
  625.         if (this.isThrough() || this.isDebugThrough()) {
  626.             return true;
  627.         }
  628.         if (!this.isMapPassablePx(px, py, d)) {
  629.             return false;
  630.         }
  631.         if (this.isCollidedWithCharactersPx(npx, npy)) {
  632.             return false;
  633.         }
  634.         return true;
  635.     };
  636.  
  637.     Game_CharacterBase.prototype.canPassDiagonallyPx = function (px, py, horz, vert) {
  638.         var npx = $gameMap.roundPxWithDirection(px, horz);
  639.         var npy = $gameMap.roundPyWithDirection(py, vert);
  640.         if (this.canPassPx(px, py, vert) && this.canPassPx(px, npy, horz)) {
  641.             return true;
  642.         }
  643.         if (this.canPassPx(px, py, horz) && this.canPassPx(npx, py, vert)) {
  644.             return true;
  645.         }
  646.         return false;
  647.     };
  648.  
  649.     Game_CharacterBase.prototype.isMapPassablePx = function (px, py, d) {
  650.         /*
  651.          var px2 = $gameMap.roundPxWithDirection(px, d);
  652.          var py2 = $gameMap.roundPyWithDirection(py, d);
  653.          return $gameMap.isPassableWithCollisionMask(px, py, this._collisionMask) && $gameMap.isPassableWithCollisionMask(px2, py2, this._collisionMask);
  654.          */
  655.         return $gameMap.isPassableWithCollisionMask($gameMap.roundPxWithDirection(px, d), $gameMap.roundPyWithDirection(py, d), this._collisionMask);
  656.     };
  657.  
  658.     Game_CharacterBase.prototype.isCollidedWithCharactersPx = function (px, py) {
  659.         return this.isCollidedWithEventsPx(px, py) || this.isCollidedWithVehiclesPx(px, py);
  660.     };
  661.  
  662.     Game_CharacterBase.prototype.isCollidedWithEventsPx = function (px, py) {
  663.         var events = $gameMap.events();
  664.         var cm = this._collisionMask;
  665.         var self = this;
  666.         return events.some(function (event) {
  667.             return event !== self && !event.isThrough() && event.isNormalPriority() && $gameMap.areTwoCollisionMasksCollided(px, py, cm, event.px, event.py, event.collisionMask);
  668.         });
  669.     };
  670.  
  671.     Game_CharacterBase.prototype.isCollidedWithVehiclesPx = function (px, py) {
  672.         return false;
  673.     };
  674.  
  675.     Game_CharacterBase.prototype.setPosition = function (tx, ty) {
  676.         this.setPositionPx(toPixel(tx) + tileSection / 2, toPixel(ty) + tileSection);
  677.     };
  678.     Game_CharacterBase.prototype.setPositionPx = function (px, py) {
  679.         this._px = Math.round(px);
  680.         this._py = Math.round(py);
  681.         this._realPx = px;
  682.         this._realPy = py;
  683.         this.synchronizeTileCoordinate();
  684.     };
  685.  
  686.     Game_CharacterBase.prototype.copyPosition = function (character) {
  687.         this._direction = character._direction;
  688.         this._px = character._px;
  689.         this._py = character._py;
  690.         this._realPx = character._realPx;
  691.         this._realPy = character._realPy;
  692.         this.synchronizeTileCoordinate();
  693.     };
  694.  
  695.     Game_CharacterBase.prototype.locate = function (tx, ty) {
  696.         this.locatePx(toPixel(tx) + tileSection / 2, toPixel(ty) + tileSection);
  697.     };
  698.     Game_CharacterBase.prototype.locatePx = function (px, py) {
  699.         this.setPositionPx(px, py);
  700.         this.straighten();
  701.         this.refreshBushDepth();
  702.     };
  703.  
  704.     Game_CharacterBase.prototype.screenX = function () {
  705.         return Math.round(toPixel(this.scrolledX()) * $gameMap.tileWidthPx());
  706.     };
  707.  
  708.     Game_CharacterBase.prototype.screenY = function () {
  709.         return Math.round(toPixel(this.scrolledY()) * $gameMap.tileHeightPx() - this.shiftY() - this.jumpHeight());
  710.     };
  711.  
  712.     Game_CharacterBase.prototype.update = function() {
  713.         this.updateAnimation();
  714.         if (this.isStopping()) {
  715.             this.updateStop();
  716.         }
  717.         if (this.isJumping()) {
  718.             this.updateJump();
  719.         } else if (this.isMoving()) {
  720.             this.updateMove();
  721.         }
  722.     };
  723.  
  724.     Game_CharacterBase.prototype.updateJump = function () {
  725.         this._jumpCount--;
  726.         this._realPx = (this._realPx * this._jumpCount + this._px) / (this._jumpCount + 1.0);
  727.         this._realPy = (this._realPy * this._jumpCount + this._py) / (this._jumpCount + 1.0);
  728.         this.refreshBushDepth();
  729.         if (this._jumpCount === 0) {
  730.             this._realPx = this._px = $gameMap.roundPx(this._px);
  731.             this._realPy = this._py = $gameMap.roundPy(this._py);
  732.         }
  733.         this.synchronizeTileCoordinate();
  734.     };
  735.  
  736.     Game_CharacterBase.prototype.updateMove = function () {
  737.         var dpf = toPixel(this.distancePerFrame());
  738.         if (this._px < this._realPx) {
  739.             this._realPx = Math.max(this._realPx - dpf, this._px);
  740.         }
  741.         if (this._px > this._realPx) {
  742.             this._realPx = Math.min(this._realPx + dpf, this._px);
  743.         }
  744.         if (this._py < this._realPy) {
  745.             this._realPy = Math.max(this._realPy - dpf, this._py);
  746.         }
  747.         if (this._py > this._realPy) {
  748.             this._realPy = Math.min(this._realPy + dpf, this._py);
  749.         }
  750.         this.synchronizeTileCoordinate();
  751.         if (!this.isMoving()) {
  752.             this.refreshBushDepth();
  753.         }
  754.     };
  755.  
  756.     Game_CharacterBase.prototype.isOnLadder = function () {
  757.         var cm = this._collisionMask;
  758.         var xs = cm.xSize;
  759.         var ys = cm.ySize;
  760.         var spx = this._px - xs / 2;
  761.         var spy = this._py - ys;
  762.         for (var cmx = 0; cmx < xs; cmx++) {
  763.             for (var cmy = 0; cmy < ys; cmy++) {
  764.                 if ($gameMap.isLadderPx(spx + cmx, spy + cmy)) {
  765.                     return true;
  766.                 }
  767.             }
  768.         }
  769.         return false;
  770.     };
  771.  
  772.     Game_CharacterBase.prototype.isOnBush = function () {
  773.         var cm = this._collisionMask;
  774.         var xs = cm.xSize;
  775.         var ys = cm.ySize;
  776.         var spx = this._px - xs / 2;
  777.         var spy = this._py - ys;
  778.         for (var cmx = 0; cmx < xs; cmx++) {
  779.             for (var cmy = 0; cmy < ys; cmy++) {
  780.                 if (!$gameMap.isBushPx(spx + cmx, spy + cmy)) {
  781.                     return false;
  782.                 }
  783.             }
  784.         }
  785.         return true;
  786.     };
  787.  
  788.     Game_CharacterBase.prototype.isOnDamageFloor = function () {
  789.         var cm = this._collisionMask;
  790.         var xs = cm.xSize;
  791.         var ys = cm.ySize;
  792.         var spx = this._px - xs / 2;
  793.         var spy = this._py - ys;
  794.         for (var cmx = 0; cmx < xs; cmx++) {
  795.             for (var cmy = 0; cmy < ys; cmy++) {
  796.                 if ($gameMap.isDamageFloorPx(spx + cmx, spy + cmy)) {
  797.                     return true;
  798.                 }
  799.             }
  800.         }
  801.         return false;
  802.     };
  803.  
  804.     Game_CharacterBase.prototype.isFacingCounter = function () {
  805.         var cm = this._collisionMask;
  806.         var direction = this.direction();
  807.         var npx = $gameMap.roundPxWithDirection(this._px, direction);
  808.         var npy = $gameMap.roundPyWithDirection(this._py, direction);
  809.         var xs = cm.xSize;
  810.         var ys = cm.ySize;
  811.         var spx = npx - xs / 2;
  812.         var spy = npy - ys;
  813.         for (var cmx = 0; cmx < xs; cmx++) {
  814.             for (var cmy = 0; cmy < ys; cmy++) {
  815.                 if ($gameMap.isCounterPx(spx + cmx, spy + cmy)) {
  816.                     return true;
  817.                 }
  818.             }
  819.         }
  820.         return false;
  821.     };
  822.  
  823.     Game_CharacterBase.prototype.checkEventTriggerTouchFrontPx = function (d) {
  824.         this.checkEventTriggerTouchPx($gameMap.roundPxWithDirection(this._px, d), $gameMap.roundPyWithDirection(this._py, d));
  825.     };
  826.  
  827.     Game_CharacterBase.prototype.checkEventTriggerTouchPx = function (px, py) {
  828.         return false;
  829.     };
  830.  
  831.     Game_CharacterBase.prototype.moveStraight = function (d) {
  832.         this.setMovementSuccess(this.canPassPx(this._px, this._py, d));
  833.         if (this.isMovementSucceeded()) {
  834.             this.setDirection(d);
  835.             this._px = $gameMap.roundPxWithDirection(this._px, d);
  836.             this._py = $gameMap.roundPyWithDirection(this._py, d);
  837.             this._realPx = $gameMap.pxWithDirection(this._px, this.reverseDir(d));
  838.             this._realPy = $gameMap.pyWithDirection(this._py, this.reverseDir(d));
  839.             this.increaseSteps();
  840.         } else {
  841.             this.setDirection(d);
  842.             this.checkEventTriggerTouchFrontPx(d);
  843.         }
  844.     };
  845.  
  846.     Game_CharacterBase.prototype.moveDiagonally = function (horz, vert) {
  847.         this.setMovementSuccess(this.canPassDiagonallyPx(this._px, this._py, horz, vert));
  848.         if (this.isMovementSucceeded()) {
  849.             this._px = $gameMap.roundPxWithDirection(this._px, horz);
  850.             this._py = $gameMap.roundPyWithDirection(this._py, vert);
  851.             this._realPx = $gameMap.pxWithDirection(this._px, this.reverseDir(horz));
  852.             this._realPy = $gameMap.pyWithDirection(this._py, this.reverseDir(vert));
  853.             this.increaseSteps();
  854.         }
  855.         if (this._direction === this.reverseDir(horz)) this.setDirection(horz);
  856.         if (this._direction === this.reverseDir(vert)) this.setDirection(vert);
  857.     };
  858.  
  859.     Game_CharacterBase.prototype.moveDir8 = function (d) {
  860.         switch (d) {
  861.             case 2:
  862.             case 4:
  863.             case 6:
  864.             case 8:
  865.                 this.moveStraight(d);
  866.                 break;
  867.             case 1:
  868.                 this.moveDiagonally(4, 2);
  869.                 break;
  870.             case 3:
  871.                 this.moveDiagonally(6, 2);
  872.                 break;
  873.             case 7:
  874.                 this.moveDiagonally(4, 8);
  875.                 break;
  876.             case 9:
  877.                 this.moveDiagonally(6, 8);
  878.                 break;
  879.         }
  880.     };
  881.  
  882.     Game_CharacterBase.prototype.jump = function (xPlus, yPlus) {
  883.         if (Math.abs(xPlus) > Math.abs(yPlus)) {
  884.             if (xPlus !== 0) {
  885.                 this.setDirection(xPlus < 0 ? 4 : 6);
  886.             }
  887.         } else {
  888.             if (yPlus !== 0) {
  889.                 this.setDirection(yPlus < 0 ? 8 : 2);
  890.             }
  891.         }
  892.         this._px += toPixel(xPlus);
  893.         this._py += toPixel(yPlus);
  894.         var distance = Math.round(Math.sqrt(xPlus * xPlus + yPlus * yPlus));
  895.         this._jumpPeak = 10 + distance - this._moveSpeed;
  896.         this._jumpCount = this._jumpPeak * 2;
  897.         this.resetStopCount();
  898.         this.straighten();
  899.     };
  900.  
  901.     //------------------------------------------------------------
  902.     // Game_Character
  903.     Game_Character.prototype.deltaPxFrom = function (px) {
  904.         return $gameMap.deltaPx(this._px, px);
  905.     };
  906.  
  907.     Game_Character.prototype.deltaPyFrom = function (py) {
  908.         return $gameMap.deltaPy(this._py, py);
  909.     };
  910.  
  911.     Game_Character.prototype.moveRandom = function () {
  912.         var d = 2 + Math.randomInt(4) * 2;
  913.         if (this.canPassPx(this.px, this.py, d)) {
  914.             this.moveStraight(d);
  915.         }
  916.     };
  917.  
  918.     Game_Character.prototype.moveTowardCharacter = function (character) {
  919.         var dpx = this.deltaPxFrom(character.px);
  920.         var dpy = this.deltaPyFrom(character.py);
  921.         if (Math.abs(dpx) > Math.abs(dpy)) {
  922.             this.moveStraight(dpx > 0 ? 4 : 6);
  923.             if (!this.isMovementSucceeded() && dpy !== 0) {
  924.                 this.moveStraight(dpy > 0 ? 8 : 2);
  925.             }
  926.         } else if (dpy !== 0) {
  927.             this.moveStraight(dpy > 0 ? 8 : 2);
  928.             if (!this.isMovementSucceeded() && dpx !== 0) {
  929.                 this.moveStraight(dpx > 0 ? 4 : 6);
  930.             }
  931.         }
  932.     };
  933.  
  934.     Game_Character.prototype.moveAwayFromCharacter = function (character) {
  935.         var dpx = this.deltaPxFrom(character.px);
  936.         var dpy = this.deltaPyFrom(character.py);
  937.         if (Math.abs(dpx) > Math.abs(dpy)) {
  938.             this.moveStraight(dpx > 0 ? 6 : 4);
  939.             if (!this.isMovementSucceeded() && dpy !== 0) {
  940.                 this.moveStraight(dpy > 0 ? 2 : 8);
  941.             }
  942.         } else if (dpy !== 0) {
  943.             this.moveStraight(dpy > 0 ? 2 : 8);
  944.             if (!this.isMovementSucceeded() && dpx !== 0) {
  945.                 this.moveStraight(dpx > 0 ? 6 : 4);
  946.             }
  947.         }
  948.     };
  949.  
  950.     Game_Character.prototype.turnTowardCharacter = function (character) {
  951.         var dpx = this.deltaPxFrom(character.px);
  952.         var dpy = this.deltaPyFrom(character.py);
  953.         if (Math.abs(dpx) > Math.abs(dpy)) {
  954.             this.setDirection(dpx > 0 ? 4 : 6);
  955.         } else if (dpy !== 0) {
  956.             this.setDirection(dpy > 0 ? 8 : 2);
  957.         }
  958.     };
  959.  
  960.     Game_Character.prototype.turnAwayFromCharacter = function (character) {
  961.         var dpx = this.deltaPxFrom(character.px);
  962.         var dpy = this.deltaPyFrom(character.py);
  963.         if (Math.abs(dpx) > Math.abs(dpy)) {
  964.             this.setDirection(dpx > 0 ? 6 : 4);
  965.         } else if (dpy !== 0) {
  966.             this.setDirection(dpy > 0 ? 2 : 8);
  967.         }
  968.     };
  969.  
  970.     Game_Character.prototype.findRouteTo = function (goalPx, goalPy) {
  971.         var searchLimit = toPixel(Math.max($gameMap.screenTileX(), $gameMap.screenTileY()));
  972.  
  973.         var px = this._px;
  974.         var py = this._py;
  975.  
  976.         if (px === goalPx && py === goalPy) {
  977.             return [];
  978.         }
  979.  
  980.         var makeNode = function (parent, px, py, gScore, fScore, direction) {
  981.             return {
  982.                 parent: parent,
  983.                 px: px,
  984.                 py: py,
  985.                 gScore: gScore,
  986.                 fScore: fScore,
  987.                 direction: direction
  988.             };
  989.         };
  990.         var makeId = function (px, py) {
  991.             return py * $gameMap.widthPx() + px;
  992.         };
  993.         var estimateCost = function (px1, py1, px2, py2) {
  994.             return $gameMap.distancePx(px1, py1, px2, py2);
  995.         };
  996.  
  997.         var reconstructPath = function (node) {
  998.             var current = node;
  999.             var path = [current.direction];
  1000.             while (current.parent !== start) {
  1001.                 current = current.parent;
  1002.                 path.push(current.direction);
  1003.             }
  1004.             return path;
  1005.         };
  1006.  
  1007.         var start = makeNode(null, px, py, 0, estimateCost(px, py, goalPx, goalPy), 0);
  1008.  
  1009.         var openSet = [start];
  1010.         var closedSet = [];
  1011.  
  1012.         var reserveSet = []; // used when failed
  1013.  
  1014.         while (openSet.length > 0) {
  1015.             var current = openSet[0];
  1016.             var currentIndex = 0;
  1017.  
  1018.             for (var i = 1; i < openSet.length; i++) {
  1019.                 if (openSet[i].fScore < current.fScore) {
  1020.                     current = openSet[i];
  1021.                     currentIndex = i;
  1022.                 }
  1023.             }
  1024.  
  1025.             if (current.px === goalPx && current.py === goalPy) {
  1026.                 return reconstructPath(current);
  1027.             }
  1028.  
  1029.             openSet.splice(currentIndex, 1);
  1030.             closedSet.push(makeId(current.px, current.py));
  1031.  
  1032.             reserveSet.push(current);
  1033.  
  1034.             if (current.gScore > searchLimit) {
  1035.                 continue;
  1036.             }
  1037.  
  1038.             for (var direction = 2; direction <= 8; direction += 2) {
  1039.                 var npx = $gameMap.roundPxWithDirection(current.px, direction);
  1040.                 var npy = $gameMap.roundPyWithDirection(current.py, direction);
  1041.  
  1042.                 if (closedSet.indexOf(makeId(npx, npy)) > -1) {
  1043.                     continue;
  1044.                 }
  1045.  
  1046.                 if (!this.canPassPx(current.px, current.py, direction)) {
  1047.                     closedSet.push(makeId(npx, npy));
  1048.                     continue;
  1049.                 }
  1050.  
  1051.                 var tentativeGScore = current.gScore + 1;
  1052.  
  1053.                 var nodeFound = null;
  1054.                 for (var i = 0; i < openSet.length; i++) {
  1055.                     var node = openSet[i];
  1056.                     if (node.px === npx && node.py === npy) {
  1057.                         nodeFound = node;
  1058.                     }
  1059.                 }
  1060.  
  1061.                 if (!nodeFound || tentativeGScore < nodeFound.gScore) {
  1062.                     var neighbor;
  1063.                     if (!nodeFound) {
  1064.                         neighbor = {
  1065.                             px: npx,
  1066.                             py: npy
  1067.                         };
  1068.                         openSet.push(neighbor);
  1069.                     } else {
  1070.                         neighbor = nodeFound;
  1071.                     }
  1072.  
  1073.                     neighbor.parent = current;
  1074.                     neighbor.gScore = tentativeGScore;
  1075.                     neighbor.fScore = tentativeGScore + estimateCost(npx, npy, goalPx, goalPy);
  1076.                     neighbor.direction = direction;
  1077.                 }
  1078.             }
  1079.         }
  1080.  
  1081.         // when failed
  1082.         var closest = reserveSet[0];
  1083.         for (var i = 1; i < reserveSet.length; i++) {
  1084.             var current = reserveSet[i];
  1085.             if (current.fScore - current.gScore < closest.fScore - closest.gScore) {
  1086.                 closest = current;
  1087.             }
  1088.         }
  1089.  
  1090.         var goalDirection;
  1091.         var dpx = $gameMap.deltaPx(closest.px, goalPx);
  1092.         var dpy = $gameMap.deltaPy(closest.py, goalPy);
  1093.         if (Math.abs(dpx) > Math.abs(dpy)) {
  1094.             goalDirection = dpx > 0 ? 4 : 6;
  1095.         } else if (dpy !== 0) {
  1096.             goalDirection = dpy > 0 ? 8 : 2;
  1097.         }
  1098.  
  1099.         if (closest === start) {
  1100.             return [goalDirection];
  1101.         } else {
  1102.             var path = reconstructPath(closest);
  1103.             path.unshift(goalDirection);
  1104.             return path;
  1105.         }
  1106.     };
  1107.  
  1108.     //------------------------------------------------------------
  1109.     // Game_Player
  1110.  
  1111.     Game_Player.prototype.moveByInput = function () {
  1112.         if (!this.isMoving() && this.canMove()) {
  1113.             var direction = this.getInputDirection();
  1114.             if (direction > 0) {
  1115.                 $gameTemp.clearDestination();
  1116.             } else if ($gameTemp.isDestinationValid()) {
  1117.                 direction = $gameTemp.nextDirection();
  1118.             }
  1119.             if (direction > 0) {
  1120.                 this.executeMove(direction);
  1121.                 if (!this.isMovementSucceeded()) {
  1122.                     switch (direction) {
  1123.                         case 2:
  1124.                             this.executeMove(1);
  1125.                             if (!this.isMovementSucceeded()) {
  1126.                                 this.executeMove(3)
  1127.                             }
  1128.                             break;
  1129.                         case 4:
  1130.                             this.executeMove(1);
  1131.                             if (!this.isMovementSucceeded()) {
  1132.                                 this.executeMove(7)
  1133.                             }
  1134.                             break;
  1135.                         case 6:
  1136.                             this.executeMove(3);
  1137.                             if (!this.isMovementSucceeded()) {
  1138.                                 this.executeMove(9)
  1139.                             }
  1140.                             break;
  1141.                         case 8:
  1142.                             this.executeMove(7);
  1143.                             if (!this.isMovementSucceeded()) {
  1144.                                 this.executeMove(9)
  1145.                             }
  1146.                             break;
  1147.                     }
  1148.                 }
  1149.             }
  1150.         }
  1151.     };
  1152.  
  1153.     Game_Player.prototype.getInputDirection = function () {
  1154.         return Input.dir8;
  1155.     };
  1156.  
  1157.     Game_Player.prototype.executeMove = function (direction) {
  1158.         this.moveDir8(direction);
  1159.     };
  1160.  
  1161.     Game_Player.prototype.updateNonmoving = function (wasMoving) {
  1162.         if (!$gameMap.isEventRunning()) {
  1163.             if (wasMoving) {
  1164.                 $gameParty.onPlayerWalk();
  1165.                 this.checkEventTriggerHere([1, 2]);
  1166.                 if ($gameMap.setupStartingEvent()) {
  1167.                     return;
  1168.                 }
  1169.             }
  1170.             if (this.triggerAction()) {
  1171.                 return;
  1172.             }
  1173.             if (wasMoving) {
  1174.                 this.updateEncounterCount();
  1175.             } else if (!$gameTemp.isDestinationValid()) {
  1176.                 $gameTemp.clearDestination();
  1177.             }
  1178.         }
  1179.     };
  1180.  
  1181.     Game_Player.prototype.triggerTouchAction = function () {
  1182.         return false;
  1183.     };
  1184.  
  1185.     Game_Player.prototype.checkEventTriggerHere = function (triggers) {
  1186.         if (this.canStartLocalEvents()) {
  1187.             this.startCollidedEventsPx(this._px, this._py, triggers, false);
  1188.         }
  1189.     };
  1190.  
  1191.     Game_Player.prototype.checkEventTriggerThere = function (triggers) { // front, literally
  1192.         if (this.canStartLocalEvents()) {
  1193.             var direction = this.direction();
  1194.             var npx = $gameMap.roundPxWithDirection(this._px, direction);
  1195.             var npy = $gameMap.roundPyWithDirection(this._py, direction);
  1196.             this.startCollidedEventsPx(npx, npy, triggers, true);
  1197.             if (!$gameMap.isEventRunning() && this.isFacingCounter()) {
  1198.                 if (direction === 2 || direction === 8) {
  1199.                     this.startCollidedEventsPx(npx, npy + (direction === 2 ? tileSection : -tileSection), triggers, true);
  1200.                 } else if (direction === 4 || direction === 6) {
  1201.                     this.startCollidedEventsPx(npx + (direction === 4 ? -tileSection : tileSection), npy, triggers, true);
  1202.                 }
  1203.             }
  1204.         }
  1205.     };
  1206.  
  1207.     Game_Player.prototype.checkEventTriggerTouchPx = function (px, py) {
  1208.         if (this.canStartLocalEvents()) {
  1209.             this.startCollidedEventsPx(px, py, [1, 2], true);
  1210.         }
  1211.     };
  1212.  
  1213.     Game_Player.prototype.startCollidedEventsPx = function (px, py, triggers, normal) {
  1214.         if (!$gameMap.isEventRunning()) {
  1215.             $gameMap.collidedEventsPx(px, py, this._collisionMask).forEach(function (event) {
  1216.                 if (event.isTriggerIn(triggers) && event.isNormalPriority() === normal) {
  1217.                     event.start();
  1218.                 }
  1219.             });
  1220.         }
  1221.     };
  1222.  
  1223.     Game_Player.prototype.isOnDamageFloor = function () {
  1224.         var cm = this._collisionMask;
  1225.         var xs = cm.xSize;
  1226.         var ys = cm.ySize;
  1227.         var spx = this._px - xs / 2;
  1228.         var spy = this._py - ys;
  1229.         for (var cmx = 0; cmx < xs; cmx++) {
  1230.             for (var cmy = 0; cmy < ys; cmy++) {
  1231.                 if ($gameMap.isDamageFloorPx(spx + cmx, spy + cmy)) {
  1232.                     return true;
  1233.                 }
  1234.             }
  1235.         }
  1236.         return false;
  1237.     };
  1238.  
  1239.     Game_Player.prototype.moveStraight = function (d) {
  1240.         Game_Character.prototype.moveStraight.call(this, d);
  1241.         if (this.isMovementSucceeded()) {
  1242.             this._followers.updateMove();
  1243.         }
  1244.     };
  1245.  
  1246.     Game_Player.prototype.moveDiagonally = function (horz, vert) {
  1247.         Game_Character.prototype.moveDiagonally.call(this, horz, vert);
  1248.         if (this.isMovementSucceeded()) {
  1249.             this._followers.updateMove();
  1250.         }
  1251.     };
  1252.  
  1253.     //------------------------------------------------------------
  1254.     // Game_Follower
  1255.  
  1256.     Game_Follower.prototype.canPassPx = function (px, py, d) {
  1257.         /*
  1258.          if (this.isThrough() || this.isDebugThrough()) {
  1259.          return true;
  1260.          }
  1261.          */
  1262.         if (!this.isMapPassablePx(px, py, d)) {
  1263.             return false;
  1264.         }
  1265.         if (this.isCollidedWithCharactersPx($gameMap.roundPxWithDirection(px, d), $gameMap.roundPyWithDirection(py, d))) {
  1266.             return false;
  1267.         }
  1268.         return true;
  1269.     };
  1270.  
  1271.     Game_Follower.prototype.chaseCharacter = function (character) {
  1272.         var dpx = this.deltaPxFrom(character.px);
  1273.         var dpy = this.deltaPyFrom(character.py);
  1274.         dpx = Math.abs(dpx) > followerDistance ? dpx : 0;
  1275.         dpy = Math.abs(dpy) > followerDistance ? dpy : 0;
  1276.         if (dpx !== 0 || dpy !== 0) {
  1277.             if (dpx !== 0 && dpy !== 0) {
  1278.                 this.moveDiagonally(dpx > 0 ? 4 : 6, dpy > 0 ? 8 : 2);
  1279.             } else if (dpx !== 0) {
  1280.                 this.moveStraight(dpx > 0 ? 4 : 6);
  1281.             } else if (dpy !== 0) {
  1282.                 this.moveStraight(dpy > 0 ? 8 : 2);
  1283.             }
  1284.             if (!this.isMovementSucceeded()) {
  1285.                 this.moveDir8(this.findChaseDirection(character));
  1286.             }
  1287.             this.setMoveSpeed($gamePlayer.realMoveSpeed());
  1288.         }
  1289.     };
  1290.  
  1291.     Game_Follower.prototype.findChaseDirection = function (character) {
  1292.         var nodes = [];
  1293.  
  1294.         var px = this._px;
  1295.         var py = this._py;
  1296.  
  1297.         var makeNode = function (px, py, gScore, fScore, direction) {
  1298.             return {
  1299.                 px: px,
  1300.                 py: py,
  1301.                 g: gScore,
  1302.                 f: fScore,
  1303.                 direction: direction
  1304.             };
  1305.         };
  1306.  
  1307.         for (var direction = 1; direction <= 9; direction++) {
  1308.             if (direction === 5) {
  1309.                 continue;
  1310.             }
  1311.             var npx = px;
  1312.             var npy = py;
  1313.             switch (direction) {
  1314.                 case 2:
  1315.                 case 4:
  1316.                 case 6:
  1317.                 case 8:
  1318.                     npx = $gameMap.roundPxWithDirection(npx, direction);
  1319.                     npy = $gameMap.roundPyWithDirection(npy, direction);
  1320.                     break;
  1321.                 case 1:
  1322.                     npx--;
  1323.                     npy++;
  1324.                     break;
  1325.                 case 3:
  1326.                     npx++;
  1327.                     npy++;
  1328.                     break;
  1329.                 case 7:
  1330.                     npx--;
  1331.                     npy--;
  1332.                     break;
  1333.                 case 9:
  1334.                     npx++;
  1335.                     npy--;
  1336.                     break;
  1337.             }
  1338.             if (direction % 2 === 0) {
  1339.                 if (!this.canPassPx(px, py, direction)) {
  1340.                     continue;
  1341.                 }
  1342.             } else {
  1343.                 if (!this.canPassDiagonallyPx(px, py, npx - px > 0 ? 6 : 4, npy - py > 0 ? 2 : 8)) {
  1344.                     continue;
  1345.                 }
  1346.             }
  1347.             nodes.push(makeNode(npx, npy, 1, 1 + $gameMap.distancePx(npx, npy, character.px, character.py), direction));
  1348.         }
  1349.  
  1350.         if (nodes.length < 1) {
  1351.             return 0;
  1352.         }
  1353.  
  1354.         var best = nodes[0];
  1355.         for (var i = 1; i < nodes.length; i++) {
  1356.             var current = nodes[i];
  1357.             if (current.f < best.f) {
  1358.                 best = current;
  1359.             }
  1360.         }
  1361.         return best.direction;
  1362.     };
  1363.  
  1364.     //-----------------------------------------------------------------------------
  1365.     // Game_Followers
  1366.  
  1367.     Game_Followers.prototype.jumpAll = function () {
  1368.         if ($gamePlayer.isJumping()) {
  1369.             for (var i = 0; i < this._data.length; i++) {
  1370.                 var follower = this._data[i];
  1371.                 var sx = toTile($gamePlayer.deltaPxFrom(follower.px));
  1372.                 var sy = toTile($gamePlayer.deltaPyFrom(follower.py));
  1373.                 follower.jump(sx, sy);
  1374.             }
  1375.         }
  1376.     };
  1377.  
  1378.     /*
  1379.      Game_Followers.prototype.isSomeoneCollided = function(x, y) {
  1380.      return this.visibleFollowers().some(function(follower) {
  1381.      return follower.pos(x, y);
  1382.      }, this);
  1383.      };
  1384.      */
  1385.  
  1386.     //-----------------------------------------------------------------------------
  1387.     // Game_Vehicle
  1388.  
  1389.     // TODO: Support vehicles
  1390.  
  1391.     //-----------------------------------------------------------------------------
  1392.     // Sprite_Character
  1393.  
  1394.     var aliasSpriteCharacterPrototypeSetCharacter = Sprite_Character.prototype.setCharacter;
  1395.     Sprite_Character.prototype.setCharacter = function () {
  1396.         aliasSpriteCharacterPrototypeSetCharacter.apply(this, arguments);
  1397.         if (drawCollisionMask && this._character) {
  1398.             this.debugDrawCollisionMask();
  1399.         }
  1400.     };
  1401.  
  1402.     Sprite_Character.prototype.debugDrawCollisionMask = function () {
  1403.         var sprite = new Sprite(new Bitmap($gameMap.tileWidth(), $gameMap.tileHeight()));
  1404.         sprite.anchor = this.anchor;
  1405.         sprite.opacity = 80;
  1406.         var cm = this._character.collisionMask;
  1407.         var sw = $gameMap.tileWidthPx();
  1408.         var sh = $gameMap.tileHeightPx();
  1409.         for (var sx = 0; sx < cm.xSize; sx++) {
  1410.             for (var sy = 0; sy < cm.ySize; sy++) {
  1411.                 if (cm.get(sx, sy)) {
  1412.                     sprite.bitmap.fillRect(sx * sw, sy * sh, sw, sh, this._character.isThrough() || !this._character.isNormalPriority() ? 'green' : 'red');
  1413.                 }
  1414.             }
  1415.         }
  1416.         this.addChild(sprite);
  1417.     };
  1418.  
  1419.     //------------------------------------------------------------
  1420.     // Sprite_Destination
  1421.  
  1422.     Sprite_Destination.prototype.updatePosition = function () {
  1423.         var dpx = $gameTemp.destinationPx();
  1424.         var dpy = $gameTemp.destinationPy();
  1425.         this.x = $gameMap.adjustX(toTile(dpx)) * tileSection * $gameMap.tileWidthPx();
  1426.         this.y = ($gameMap.adjustY(toTile(dpy)) * tileSection - 1) * $gameMap.tileHeightPx();
  1427.     };
  1428.  
  1429.     //------------------------------------------------------------
  1430.     // Scene_Map
  1431.     Scene_Map.prototype.processMapTouch = function () {
  1432.         if (TouchInput.isTriggered()) {
  1433.             $gameTemp.setDestination($gameMap.canvasToMapPx(TouchInput.x), $gameMap.canvasToMapPy(TouchInput.y));
  1434.         }
  1435.     };
  1436.  
  1437.     var aliasSceneMapPrototypeUpdate = Scene_Map.prototype.update;
  1438.     Scene_Map.prototype.update = function () {
  1439.         if ($gameMap.isCollisionMaskSet()) {
  1440.             aliasSceneMapPrototypeUpdate.apply(this, arguments);
  1441.         } else {
  1442.             Scene_Base.prototype.update.call(this);
  1443.         }
  1444.     };
  1445. })();

评分

参与人数 1星屑 +66 收起 理由
MeowSnow + 66 叼叼叼

查看全部评分

Lv1.梦旅人

梦石
0
星屑
97
在线时间
308 小时
注册时间
2014-1-16
帖子
467
2
发表于 2016-6-8 18:05:39 | 只看该作者
这个。。。有什么用?解释一下
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
491 小时
注册时间
2015-1-7
帖子
124
3
发表于 2016-6-8 21:30:43 | 只看该作者
现在的难道不是像素移动?

点评

明显不是。。。RM一直都是跑格子  发表于 2016-6-9 04:07
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1286
在线时间
6552 小时
注册时间
2010-12-30
帖子
8949
4
发表于 2016-6-9 00:48:37 | 只看该作者

_(:з」∠)_啊喏,虽然像素移动的效果很棒,但是火车队列变成了扭曲的效果呢……还有行走图上出现了不明的小方块,即使关了火车队列或者队伍中只有一个角色时,这些小方块也存在。
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
46 小时
注册时间
2014-3-14
帖子
37
5
 楼主| 发表于 2016-6-9 02:03:10 | 只看该作者
本帖最后由 moe2333 于 2016-6-9 02:25 编辑
MeowSnow 发表于 2016-6-9 00:48
_(:з」∠)_啊喏,虽然像素移动的效果很棒,但是火车队列变成了扭曲的效果呢……还有行走图上出现了不明的 ...


是我把火车队列定义成这样的:
只要一个跟随者跟随的角色的X距离或者Y距离不超过followerDistance这个follower就不会移动,我觉得这样会让队列更自然
关于小方块,那是角色的碰撞面具,把25行的drawCollisionMask设置为false就可以了。
因为测试的时候需要绘制碰撞面具所以默认是true的状态
至于为什么关了火车还会有是因为不管队伍里有多少队员默认状态下都会有3个follower跟着主角,队员不足或者不显示follower的时候MV做的只是把那几个follower的sprite隐藏掉了而已

哦,对了
告诉你一下还有什么是我没有做的:
1. 虽然优化了寻路的算法但是鼠标不能触发事件了(现在懒得弄所以直接禁用掉了,不过以后会弄的)
2. 暂时不支持交通工具,关于交通工具的一切(乘坐,移动...)都可能会有bug,不过bug长什么样子我没去看,总之即使坐上去了也不能移动。(其实交通工具需要的碰撞检测数据已经在refreshCollisionMask方法里生成了,所以要做应该也不是难事)
3. 暂时不支持autotile的位图分析,所以只要autotile的flag是0x0f的话那整个autotile都会被mask掉,不管位图长什么样子
4. 其他肯定还有很多bug和兼容的问题
5. 我好懒

最近pewdiepie有在搞一个rpg maker competition,我其实想参加的,但是一个人好像没什么动力,你们想不想一起来?如果有人帮忙的话我就去参加了

点评

之前一直在折腾碰撞检测引擎,看到也在折腾这块的感觉好亲切!!!【https://coding.net/u/shitake/p/box2d-ruby/git/blob/master/box2d.rb 以前折腾个一个  发表于 2016-6-9 16:58
你说的这些东西我都没有用上。也许你可以帮我改进一下  发表于 2016-6-9 15:52
你说的这些东西我都没有用上。也许你可以帮我改进一下  发表于 2016-6-9 15:51
话说难倒不是脏矩阵么。以及貌似是有AABB?OBB和sphere呢?有实现吗?  发表于 2016-6-9 13:20
(っ´ω`c) 要是做一个素材量不大的弹幕游戏的话,我愿意帮助菊苣做像素美术  发表于 2016-6-9 11:04
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
46 小时
注册时间
2014-3-14
帖子
37
6
 楼主| 发表于 2016-6-9 02:07:00 | 只看该作者
西姐 发表于 2016-6-8 21:30
现在的难道不是像素移动?

像素移动只是相对像素而已
默认状态下MV是48像素一个tile,这个脚本允许你把tile size设置得更小
具体参照tileSection
另外这个脚本还加入了更精确的碰撞检测以及自动分析tileset bitmap的功能
你可以新建一个工程看看效果
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
46 小时
注册时间
2014-3-14
帖子
37
7
 楼主| 发表于 2016-6-9 02:09:04 | 只看该作者
超音速 发表于 2016-6-8 18:05
这个。。。有什么用?解释一下

默认状态下MV一按方向键就走一整个大格,你想不想让移动更自由一点,比如说一小格一小格的移动呢?

点评

明白了  发表于 2016-6-9 12:14
回复 支持 反对

使用道具 举报

Lv3.寻梦者 (版主)

…あたしは天使なんかじゃないわ

梦石
0
星屑
2208
在线时间
4033 小时
注册时间
2010-10-4
帖子
10779

开拓者贵宾

8
发表于 2016-6-9 07:42:20 | 只看该作者
Quasi Movement 这个插件我觉得挺不错的,楼主可以参考一下
回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
0
星屑
22923
在线时间
8637 小时
注册时间
2011-12-31
帖子
3367
9
发表于 2016-6-9 08:34:36 | 只看该作者
本帖最后由 tseyik 于 2016-6-9 08:37 编辑
SAN_AnalogMove

也不錯

点评

呃,谢谢  发表于 2016-6-9 09:06
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
46 小时
注册时间
2014-3-14
帖子
37
10
 楼主| 发表于 2016-6-9 08:49:48 | 只看该作者
本帖最后由 moe2333 于 2016-6-9 08:51 编辑
taroxd 发表于 2016-6-9 07:42
Quasi Movement 这个插件我觉得挺不错的,楼主可以参考一下


quasi movement如果想要更精确的collision mask需要给每张地图制作一张额外的collision map...然而我不希望这样

如果我找得到合适的也就不会自己写了...我的游戏里不需要交通工具和鼠标操作,于是就变成现在这个样子了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-11-10 23:37

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表