查看: 4986|回复: 5

[原创发布] [脚本] 自由移动 (5.28 重做)

[复制链接]
梦石
0
星屑
1907
在线时间
1555 小时
注册时间
2013-4-13
回帖
783
发表于 2020-5-26 08:56:03 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 沉滞的剑 于 2020-5-28 20:49 编辑

脚本功能: 允许角色自由移动

适用于: 需要让主角更自然地在场景中进行移动

支持键盘/鼠标和手柄

如果有类似成熟的脚本话 请给个链接好不好 我去学习一下 谢谢~

如果有bug欢迎反馈~

更新日志:

5.8 重做, 将人物改为矩形碰撞检测

[pre lang="javascript"]const Base = {};
// Check if it is an object
{
  Base.isObject = (object) => {
    return ["object", "function"].includes(typeof object) && object !== null;
  };
}

// Get value from object by path
{
  const _get = (_object, _path, defaultValue) => {
    if (_path.length) {
      if (!Base.isObject(_object)) {
        return defaultValue;
      }
      const currentPath = _path.shift();
      return _get(_object[currentPath], _path, defaultValue);
    }
    return _object === undefined ? defaultValue : _object;
  };
  Base.get = (object, path, defaultValue) => {
    return _get(object, path.split("."), defaultValue);
  };
}
// Set value from object by path
{
  const _set = (_object, _path, value) => {
    const currentPath = _path.shift();
    if (_path.length) {
      if (!Base.isObject(_object[currentPath])) {
        _object[currentPath] = {};
      }
      _set(_object[currentPath], _path, value);
    } else {
      _object[currentPath] = value;
    }
  };
  Base.set = (object, path, value) => {
    return _set(object, path.split("."), value);
  };
}

// Filter small values within a range
{
  Base.stair = (num, threadhold, offset = 0) => (Math.abs(num + offset) < threadhold ? offset : num);
}
// Input
{
  const { get, stair } = Base;

  Input._axesX = [];
  Input._axesY = [];
  Input._updateGamepadState = function (gamepad) {
    const { buttons, axes, index } = gamepad;
    const newState = [];
    const lastState = get(this, `_gamepadStates.${index}`, []);
    const threshold = 0.3;

    buttons.forEach((v, i) => {
      newState = v.pressed;
    });

    newState[12] = axes[1] < -threshold;
    newState[13] = axes[1] > threshold;
    newState[14] = axes[0] < -threshold;
    newState[15] = axes[0] > threshold;

    newState.forEach((v, i) => {
      if (lastState !== v) {
        const buttonName = this.gamepadMapper;
        this._currentState[buttonName] = !!newState;
      }
    });
    this._gamepadStates[index] = newState;
    Input._axesX[index] = stair(axes[0], threshold);
    Input._axesY[index] = stair(axes[1], threshold);
  };

  Object.defineProperties(Input, {
    axesX: {
      get: () => Input._axesX.find(Boolean) || 0,
    },
    axesY: {
      get: () => Input._axesY.find(Boolean) || 0,
    },
    keyX: {
      get: () => {
        let x = 0;
        if (Input._currentState["left"]) x -= 1;
        if (Input._currentState["right"]) x += 1;
        return x;
      },
    },
    keyY: {
      get: () => {
        let y = 0;
        if (Input._currentState["up"]) y -= 1;
        if (Input._currentState["down"]) y += 1;
        return y;
      },
    },
    velocity: {
      get: () => Math.min(Math.sqrt(Input.axesX ** 2 + Input.axesY ** 2), 100),
    },
    inputX: {
      get: () => (Input.velocity ? Input.axesX : Input.keyX),
    },
    inputY: {
      get: () => (Input.velocity ? Input.axesY : Input.keyY),
    },
  });
}

// Touch Input
{
  Scene_Map.prototype.processMapTouch = function () {
    if (TouchInput.isTriggered() || this._touchCount > 0) {
      if (TouchInput.isPressed()) {
        if (this._touchCount === 0 || this._touchCount >= 15) {
          var x = $gameMap.canvasToMapXTouch(TouchInput.x);
          var y = $gameMap.canvasToMapYTouch(TouchInput.y);
          $gameTemp.setDestination(x, y);
        }
        this._touchCount++;
      } else {
        this._touchCount = 0;
      }
    }
  };

  Scene_Map.prototype.updateDestination = function () {
    if (this.isMapTouchOk()) {
      this.processMapTouch();
    } else {
      this._touchCount = 0;
    }
  };

  Game_Map.prototype.canvasToMapXTouch = function (x) {
    var tileWidth = this.tileWidth();
    var originX = this._displayX * tileWidth;
    var mapX = (originX + x) / tileWidth - 0.5;
    return mapX;
  };

  Game_Map.prototype.canvasToMapYTouch = function (y) {
    var tileHeight = this.tileHeight();
    var originY = this._displayY * tileHeight;
    var mapY = (originY + y) / tileHeight - 0.5;
    return mapY;
  };
}

// Player
{
  const DIR = {
    DOWN_LEFT: 1,
    DOWN: 2,
    DOWN_RIGHT: 3,
    LEFT: 4,
    IDLE: 0,
    RIGHT: 6,
    UP_LEFT: 7,
    UP: 8,
    UP_RIGHT: 9,
  };

  const UNIT_STEP = 0.1;

  Game_Player.prototype.getInputDirection = function () {
    return Input.dir8;
  };

  Game_Player.prototype.reverseDir = function (d) {
    return (10 - d) % 10;
  };

  Game_Player.prototype.executeMove = function (dx, dy) {
    if (Math.abs(dx) > Math.abs(dy)) {
      if (dx > 0) {
        this.setDirection(DIR.RIGHT);
      } else {
        this.setDirection(DIR.LEFT);
      }
    } else {
      if (dy > 0) {
        this.setDirection(DIR.DOWN);
      } else {
        this.setDirection(DIR.UP);
      }
    }
    const check = [];
    if (dx > 0) check.push(DIR.RIGHT);
    if (dx < 0) check.push(DIR.LEFT);
    if (dy > 0) check.push(DIR.DOWN);
    if (dy < 0) check.push(DIR.UP);
    for (let i of check) {
      if (!this.rectCanPass(dx, dy, i)) {
        if ([DIR.RIGHT, DIR.LEFT].includes(i)) dx = 0;
        if ([DIR.DOWN, DIR.UP].includes(i)) dy = 0;
      }
    }
    if (!Math.abs(dx) && !Math.abs(dy)) {
      $gameTemp.clearDestination();
      return;
    }
    this._realX = this._x;
    this._realY = this._y;
    this._x += dx;
    this._y += dy;
  };

  Object.defineProperties(Game_Player.prototype, {
    rect: {
      get: function () {
        return new Rectangle(this._x + 0.06, this._y + 0.06, 0.75, 0.75);
      },
    },
  });

  Game_Player.prototype.rectCanPass = function (dx, dy, direction) {
    const { left, right, top, bottom } = this.rect;
    const rd = this.reverseDir(direction);
    if (!this.canPass(left, top, rd)) return false;
    if (!this.canPass(left, bottom, rd)) return false;
    if (!this.canPass(right, top, rd)) return false;
    if (!this.canPass(right, bottom, rd)) return false;
    if (!this.canPass(left + dx, top + dy, direction)) return false;
    if (!this.canPass(left + dx, bottom + dy, direction)) return false;
    if (!this.canPass(right + dx, top + dy, direction)) return false;
    if (!this.canPass(right + dx, bottom + dy, direction)) return false;
    return true;
  };

  Game_Player.prototype.canPass = function (x, y, d) {
    x = Math.floor(x);
    y = Math.floor(y);
    if (!$gameMap.isValid(x, y)) {
      return false;
    }
    if (this.isThrough() || this.isDebugThrough()) {
      return true;
    }
    if (!this.isMapPassable(x, y, d)) {
      return false;
    }
    if (this.isCollidedWithCharacters(x, y)) {
      return false;
    }
    return true;
  };

  Game_Player.prototype.isMapPassable = function (x, y, d) {
    return $gameMap.isPassable(x, y, d);
  };

  Game_Player.prototype.moveByInput = function () {
    if (!this.isMoving() && this.canMove()) {
      var direction = this.getInputDirection();
      let dx, dy;
      if (direction > 0) {
        $gameTemp.clearDestination();
        dx = +(Input.inputX * UNIT_STEP).toFixed(3);
        dy = +(Input.inputY * UNIT_STEP).toFixed(3);
      } else if ($gameTemp.isDestinationValid()) {
        dx = $gameTemp.destinationX() - this._x;
        dy = $gameTemp.destinationY() - this._y;
        if (Math.abs(dx) < 0.1 && Math.abs(dy) < 0.1) {
          $gameTemp.clearDestination();
          return;
        }
        if (Math.abs(dx) > Math.abs(dy)) {
          dx = dx / Math.abs(dx);
          dy = dy / Math.abs(dx);
        } else {
          dx = dx / Math.abs(dy);
          dy = dy / Math.abs(dy);
        }
        dx *= UNIT_STEP;
        dy *= UNIT_STEP;
      }
      if (dx || dy) {
        this.executeMove(dx, dy);
      }
    }
  };

  Game_Player.prototype.updateNonmoving = function (wasMoving) {
    if (!$gameMap.isEventRunning()) {
      if (wasMoving) {
        $gameParty.onPlayerWalk();
        this.checkEventTriggerHere([1, 2]);
        if ($gameMap.setupStartingEvent()) {
          return;
        }
      }
      if (this.triggerAction()) {
        return;
      }
      if (wasMoving) {
        this.updateEncounterCount();
      }
    }
  };

  Game_Player.prototype.distancePerFrame = function () {
    return Math.pow(2, this.realMoveSpeed()) / 256 / 2;
  };
}

// NPC
{
  Game_CharacterBase.prototype.pos = function (x, y) {
    return Math.abs(this._x - x) <= 0.5 && Math.abs(this._y - y) <= 0.5;
  };

  Game_Event.prototype.isCollidedWithEvents = function (x, y) {
    var events = $gameMap.eventsXyNt(x, y).filter((item) => item !== this);
    return events.length > 0;
  };
}
[/pre]

评分

参与人数 4赞 +4 收起 理由
x18489 + 1 塞糖
遮那 + 1 精品文章
3268006598 + 1 赞赞
马铃薯条 + 1 塞糖

查看全部评分

夏普的道具店

塞露提亚-道具屋的经营妙方同人作品
发布帖:点击这里
梦石
0
星屑
3538
在线时间
918 小时
注册时间
2018-5-18
回帖
474
发表于 2020-5-26 11:23:49 | 显示全部楼层
顶一顶,铁子厉害了
这个人很馋,什么都没有留下。。。
回复

使用道具 举报

梦石
0
星屑
25352
在线时间
1136 小时
注册时间
2019-3-5
回帖
1303
发表于 2020-5-26 15:39:52 | 显示全部楼层
不知道你说的成熟插件是指八方向移动还是像素移动,前者的话可以参考https://rpg.blue/thread-480682-1-1.html的第七楼,我总结了一些目前发现的开源插件。
回复

使用道具 举报

梦石
0
星屑
2582
在线时间
363 小时
注册时间
2015-8-15
回帖
66
发表于 2020-5-27 10:42:41 | 显示全部楼层
移动颗粒为0.25单元格,这个最大的问题在于通行
回复

使用道具 举报

梦石
0
星屑
100
在线时间
7 小时
注册时间
2022-1-29
回帖
2
发表于 2022-6-30 17:33:20 | 显示全部楼层
梦寐以求的插件!!!!
回复

使用道具 举报

梦石
0
星屑
45683
在线时间
183 小时
注册时间
2022-1-8
回帖
167
发表于 2022-7-1 07:14:52 | 显示全部楼层
感谢大佬分享!
我在平台上传的插件均可免费商用,转载
插件传送门:https://rpg.blue/forum.php?mod=v ... eid%26typeid%3D1306
接单中,可接RPGMaker MV/MZ插件定制,QQ:3268006598
回复

使用道具 举报

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

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部