查看: 6781|回复: 12

[通用发布] 【MV发布】瞎糊一个真·八方向脚本试试js怎么玩

[复制链接]

无限の剣制

梦石
0
星屑
10445
在线时间
5019 小时
注册时间
2013-2-28
回帖
4942

开拓者贵宾

发表于 2015-11-11 00:01:50 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 VIPArcher 于 2015-11-11 09:32 编辑

[pre lang="JAVASCRIPT"]//=============================================================================
// VIPArcher_Dir8.js
//=============================================================================
/*:
* @plugindesc 真 · 八方向移动
* @author VIPArcher
*
* @param Dir8_flag
* @desc 使用八方向素材的标志
* @default %
*
* @param Dir8_Affix
* @desc 八方向素材文件后缀
* @default _8D
*
* @help 使用八方向的行走图素材文件名前面添加一个标志,
* 与之对应的8方向的素材与其同名并在后面添加后缀以区别。
* 例如默认的设置就是使用八方向的素材命名为:
* !$%VIPArcher.png
*
* 那么与之对应的八方向的素材就应命名为:
* !$%VIPArcher_8D.png
*
*/
(function() {
    var parameters = PluginManager.parameters('VIPArcher_Dir8');
    var dir8_flag = String(parameters['Dir8_flag'] || '%');
    var dir8_affix = String(parameters['Dir8_Affix'] || '_8D');
    ImageManager.isDir8Character = function(filename) {
        var reg = new RegExp("^\[\\!\\$\\" + dir8_flag + "]+")
        var sign = filename.match(reg);
        return sign && sign[0].contains(dir8_flag);
    };
    Game_Player.prototype.moveByInput = function() {
        if (!this.isMoving() && this.canMove()) {
            var direction = Input.dir8
            if (direction > 0) {
                $gameTemp.clearDestination();
            } else if ($gameTemp.isDestinationValid()){
                var x = $gameTemp.destinationX();
                var y = $gameTemp.destinationY();
                direction = this.findDirectionTo(x, y);
            }
            if (direction > 0) {
                if (direction % 2 == 0){
                    this.moveStraight(direction);
                    return;
                }
                if (direction < 5){
                    this.moveDiagonally(direction + 3 , 2);
                } else{
                    this.moveDiagonally(direction - 3 , 8);
                }
            }
        }
    };
    var dir8_move_diagonal = Game_Player.prototype.moveDiagonally;
    Game_Player.prototype.moveDiagonally = function(horz, vert) {
        if (!this.canPass(this._x, this._y, horz) && !this.canPass(this._x, this._y, vert)){
            this.setMovementSuccess(false);
            return;
        }
        if (this.canPass(this._x, this._y, horz) && !this.canPass(this._x, this._y, vert)){
            this.moveStraight(horz);
            return;
        }
        if (this.canPass(this._x, this._y, vert) && !this.canPass(this._x, this._y, horz)){
            this.moveStraight(vert);
            return;
        }
        if (!this.canPassDiagonally(this._x, this._y, horz, vert)) {
            if (Math.random() > 0.5){
                this.setDirection(vert); this.moveStraight(vert)
            } else {
                this.setDirection(horz); this.moveStraight(horz)
            }
            return;
        }
        dir8_move_diagonal.call(this, horz, vert);
        if (horz > 5) {
            vert > 5 ? this.setDirection(9) : this.setDirection(7);
        }
        else {
            vert > 5 ? this.setDirection(3) : this.setDirection(1);
        };
    };
    Sprite_Character.prototype.characterPatternY = function() {
        if (this._character.direction() % 2 == 0){
            if (this.dir8_bitmap){ this.bitmap = this.dir4_bitmap; }
            return (this._character.direction() - 2) / 2;
        } else {
            if (this.dir8_bitmap){ this.bitmap = this.dir8_bitmap; }
            return parseInt((this._character.direction() + 1) / 3);
        }
    };
    var dir8_set_CharacterBitmap = Sprite_Character.prototype.setCharacterBitmap
    Sprite_Character.prototype.setCharacterBitmap = function() {
        dir8_set_CharacterBitmap.call(this);
        this._isDir8Character = ImageManager.isDir8Character(this._characterName);
        if (this._isDir8Character) {
            this.dir4_bitmap = this.bitmap;
            this.dir8_bitmap = ImageManager.loadCharacter(this._characterName + dir8_affix);
        };
    };
})();[/pre]
[fold=更新记录]2015.11.11 修正队员在斜向移动遇到障碍会跳格问题[/fold]
对js啥都不懂的萌新瞎玩了一会js。发个插件试试。我自己并没有做过多测试。
有啥问题就直接回帖子反馈吧,反正我也不懂能不能结决
中文注释有点low啊

…あたしは天

梦石
0
星屑
2308
在线时间
4033 小时
注册时间
2010-10-4
回帖
10548

开拓者贵宾

发表于 2015-11-11 06:28:03 | 显示全部楼层
泥看我就说js不用学就能瞎糊吧

点评

我信了,我就没接触过任何编程语言,基础都不懂。。要是我现在不能用JS瞎糊弄一套系统出来。我就去弹你家玻璃!  发表于 2015-11-11 09:30

评分

参与人数 1星屑 +233 收起 理由
VIPArcher + 233 我很赞同

查看全部评分

回复

使用道具 举报

永夜蟄居の玖瀨

梦石
0
星屑
71
在线时间
1018 小时
注册时间
2011-9-5
回帖
2707

开拓者贵宾

发表于 2015-11-12 00:04:03 | 显示全部楼层
用鼠标的话会不会斜向寻路?还是只会走直线然后拐弯?我瞎糊的就不行

点评

寻路算法要改的就我说的那几个地方啊,除了 canPass 函数其他都已经改好了啊  发表于 2015-11-18 20:48
[s]不用在意,那已经是寻路脚本的事了。[/s]  发表于 2015-11-12 09:05

回复

使用道具 举报

梦石
0
星屑
676
在线时间
224 小时
注册时间
2006-12-7
回帖
780
发表于 2015-11-12 10:14:50 | 显示全部楼层
马克学习一下
回复

使用道具 举报

梦石
0
星屑
2673
在线时间
1602 小时
注册时间
2014-9-28
回帖
2698

开拓者

发表于 2015-11-13 01:27:29 | 显示全部楼层
楼主你不知道RPG Maker MV 讨论区是专门发布MV脚本的么!

点评

http://m.shabixiaoshuo.com/info-1255/ 神藏  发表于 2015-12-15 21:13
这我真不知道,那版主帮我移一下帖子吧=。=  发表于 2015-11-13 09:07
回复

使用道具 举报

梦石
0
星屑
676
在线时间
224 小时
注册时间
2006-12-7
回帖
780
发表于 2015-11-18 15:15:15 | 显示全部楼层
测试可用 就是开始说明没太看懂
刚开始加了!$在前面发现rmmv的编辑器都识别有问题,不是按4×2的读的
说明白点就是要
%标准四向行走图
%四个斜向的行走图_8D
两个文件对应上就ok

评分

参与人数 1星屑 +10 收起 理由
VIPArcher + 10 嗯。语文不好,不太会表述&gt;.&lt;.

查看全部评分

回复

使用道具 举报

梦石
1
星屑
23236
在线时间
9564 小时
注册时间
2012-6-19
回帖
7018

开拓者短篇九导演组冠军

发表于 2015-11-18 17:53:30 | 显示全部楼层
本帖最后由 喵呜喵5 于 2015-11-18 18:04 编辑
千葉玖濑 发表于 2015-11-12 00:04
用鼠标的话会不会斜向寻路?还是只会走直线然后拐弯?我瞎糊的就不行 ...


寻路在 Game_Character 的 findDirectionTo 中,算法为 A*

为了分析方便单独拎出来:

[pre lang="javascript"]Game_Character.prototype.findDirectionTo = function(goalX, goalY) {
    var searchLimit = this.searchLimit();
    var mapWidth = $gameMap.width();
    var nodeList = [];
    var openList = [];
    var closedList = [];
    var start = {};
    var best = start;
    if (this.x === goalX && this.y === goalY) {
        return 0
    }
    start.parent = null;
    start.x = this.x;
    start.y = this.y;
    start.g = 0;
    start.f = $gameMap.distance(start.x, start.y, goalX, goalY);
    nodeList.push(start);
    openList.push(start.y * mapWidth + start.x);
    while (nodeList.length > 0) {
        var bestIndex = 0;
        for (var i = 0; i < nodeList.length; i++) {
            if (nodeList.f < nodeList[bestIndex].f) {
                bestIndex = i
            }
        }
        var current = nodeList[bestIndex];
        var x1 = current.x;
        var y1 = current.y;
        var pos1 = y1 * mapWidth + x1;
        var g1 = current.g;
        nodeList.splice(bestIndex, 1);
        openList.splice(openList.indexOf(pos1), 1);
        closedList.push(pos1);
        if (current.x === goalX && current.y === goalY) {
            best = current;
            goaled = true;
            break
        }
        if (g1 >= searchLimit) {
            continue
        }
        for (var j = 0; j < 4; j++) {
            var direction = 2 + j * 2;
            var x2 = $gameMap.roundXWithDirection(x1, direction);
            var y2 = $gameMap.roundYWithDirection(y1, direction);
            var pos2 = y2 * mapWidth + x2;
            if (closedList.contains(pos2)) {
                continue
            }
            if (!this.canPass(x1, y1, direction)) {
                continue
            }
            var g2 = g1 + 1;
            var index2 = openList.indexOf(pos2);
            if (index2 < 0 || g2 < nodeList[index2].g) {
                var neighbor;
                if (index2 >= 0) {
                    neighbor = nodeList[index2]
                } else {
                    neighbor = {};
                    nodeList.push(neighbor);
                    openList.push(pos2)
                }
                neighbor.parent = current;
                neighbor.x = x2;
                neighbor.y = y2;
                neighbor.g = g2;
                neighbor.f = g2 + $gameMap.distance(x2, y2, goalX, goalY);
                if (!best || neighbor.f - neighbor.g < best.f - best.g) {
                    best = neighbor
                }
            }
        }
    }
    var node = best;
    while (node.parent && node.parent !== start) {
        node = node.parent
    }
    var deltaX1 = $gameMap.deltaX(node.x, start.x);
    var deltaY1 = $gameMap.deltaY(node.y, start.y);
    if (deltaY1 > 0) {
        return 2
    } else if (deltaX1 < 0) {
        return 4
    } else if (deltaX1 > 0) {
        return 6
    } else if (deltaY1 < 0) {
        return 8
    }
    var deltaX2 = this.deltaXFrom(goalX);
    var deltaY2 = this.deltaYFrom(goalY);
    if (Math.abs(deltaX2) > Math.abs(deltaY2)) {
        return deltaX2 > 0 ? 4 : 6
    } else if (deltaY2 !== 0) {
        return deltaY2 > 0 ? 8 : 2
    }
    return 0
};[/pre]

42~45行是选择要寻路的点,

具体就是四次循环得出 2/4/6/8 这四个方向然后根据当前方向算出朝指定方向移动后的 x2 和 y2 值

[pre lang="javascript"]        for (var j = 0; j < 4; j++) {
            var direction = 2 + j * 2;
            var x2 = $gameMap.roundXWithDirection(x1, direction);
            var y2 = $gameMap.roundYWithDirection(y1, direction);[/pre]

要八方向的话稍微改改就好,仅提供一个简单的思路,出自兰触(https://rpg.blue/forum.php?mod=viewthread&tid=368249):

[pre lang="javascript"]        for (var j = 1; j <= 9; j++) {
            var direction = j;
            if (direction == 5) continue;
            var x2 = x1 + (direction - 4) % 3 - 1;
            var y2 = y1 - ((direction - 4) / 3);[/pre]

50行的 canPass 函数是判定是否能从当前位置向指定方向移动一步的,因为加了八方向,所以自己根据自己的需要稍微更改一下判定条件,比如如果左边有个老太太是否还能向左上角移动啥的

[pre lang="javascript"]            if (!this.canPass(x1, y1, direction)) {[/pre]

79行开始的代码就是最终找到路径

[pre lang="javascript"]    var deltaX1 = $gameMap.deltaX(node.x, start.x);
    var deltaY1 = $gameMap.deltaY(node.y, start.y);
    if (deltaY1 > 0) {
        return 2
    } else if (deltaX1 < 0) {
        return 4
    } else if (deltaX1 > 0) {
        return 6
    } else if (deltaY1 < 0) {
        return 8
    }
    var deltaX2 = this.deltaXFrom(goalX);
    var deltaY2 = this.deltaYFrom(goalY);
    if (Math.abs(deltaX2) > Math.abs(deltaY2)) {
        return deltaX2 > 0 ? 4 : 6
    } else if (deltaY2 !== 0) {
        return deltaY2 > 0 ? 8 : 2
    }
    return 0[/pre]

node.x 和 node.y 就是下一步要移动的XY坐标,但是这个函数原本的返回值是移动方向的方位数(2/4/6/8)而不是最终的坐标,所以继续用兰触公式转换一下

[pre lang="javascript"]return 5 + 3 * -(node.y - start.y) + (node.x - start.x)[/pre]

这样寻路部分的逻辑就支持八方向寻路了


不过要真的让角色支持八方向寻路,还有一个要改的地方是这里:

[pre lang="javascript"]Game_Player.prototype.executeMove = function(direction) {
    this.moveStraight(direction)
};[/pre]

上面整个寻路过程最终得出的方位数是传到这个函数中的,原生的 moveStraight 应该不支持八方向,因此这里也要修改一下让direction为1379时角色能走的动


==========

以上纯粹是理论,是否正确还需要测试。因为我完全没有用过MV,只看过MV的源代码

评分

参与人数 2星屑 +300 收起 理由
VIPArcher + 150 我很赞同
千葉玖濑 + 150 我也找到了这个然而不知道怎么改寻路算法or.

查看全部评分

回复

使用道具 举报

无限の剣制

梦石
0
星屑
10445
在线时间
5019 小时
注册时间
2013-2-28
回帖
4942

开拓者贵宾

 楼主| 发表于 2015-11-19 09:04:31 | 显示全部楼层
喵呜喵5 发表于 2015-11-18 17:53
寻路在 Game_Character 的 findDirectionTo 中,算法为 A*

为了分析方便单独拎出来:


瞎试了一下,发现js和ruby的 / 和 % 还是有区别的。所以大概可以这样写
[pre lang="JAVASCRIPT"]for (var j = 1; j <= 9; j++) {
    var direction = j;
    if (direction == 5) continue;
    var x2 = x1 + (direction - 4 > 0 ? direction - 4 : direction - 1) % 3 - 1;
    var y2 = y1 + Math.floor((direction - 4) / 3);[/pre]
回复

使用道具 举报

梦石
1
星屑
23236
在线时间
9564 小时
注册时间
2012-6-19
回帖
7018

开拓者短篇九导演组冠军

发表于 2015-11-19 09:14:53 | 显示全部楼层
VIPArcher 发表于 2015-11-19 09:04
瞎试了一下,发现js和ruby的 / 和 % 还是有区别的。所以大概可以这样写
for (var j = 1; j  0 ? directio ...

哦对,忘了这茬,用 Number.prototype.mod ( n )  代替 %

点评

好吧,其实我还没认真看过F1 >.<  发表于 2015-11-19 11:56
F1帮助文档  发表于 2015-11-19 09:42
(这些内置对象的额外prototype有什么地方有文档可以看到么?  发表于 2015-11-19 09:24
回复

使用道具 举报

梦石
0
星屑
676
在线时间
224 小时
注册时间
2006-12-7
回帖
780
发表于 2015-11-19 14:20:48 | 显示全部楼层
话说楼主打算做增加帧数的功能么
试了下英文论坛的发现完全冲突,那个破坏力太强了直接把整个行走图划分了读,不是按默认的一个行走图分四个人物的
http://mvplugins.com/plugin/Shaz/More%20Character%20Frames
这种模式跟另外一个待机/走路/跑步的插件也冲突
http://mvplugins.com/plugin/Galv/Galvs%20Character%20Animations
回复

使用道具 举报

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

本版积分规则

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

在本版发帖返回顶部