ultimate-angel-zerachiel/www/js/plugins/KMS_Minimap.js
2024-01-17 11:38:37 -06:00

1418 lines
37 KiB
JavaScript

//=============================================================================
// KMS_Minimap.js
// last update: 2020/04/21
//=============================================================================
/*:
* @plugindesc
* [v0.2.0a] Display minimap.
*
* @author TOMY (Kamesoft)
*
* @param Map rect
* @default 524, 32, 260, 200
* @desc
* Specify minimap position and its size.
* Format: X, Y, Width, Height
*
* @param Grid size
* @default 10
* @desc Grid size of the minimap in pixel.
*
* @param Blink time
* @default 180
* @desc Blinking interval of icons on the minimap in frames.
*
* @param Foreground color
* @default rgba(224, 224, 240, 0.6)
* @desc
* Format: rgba(Red, Green, Blue, Alpha)
*
* @param Background color
* @default rgba(0, 0, 160, 0.6)
* @desc
* Format: rgba(Red, Green, Blue, Alpha)
*
* @param Mask style
* @default 0
* @desc
* Mask style for minimap.
* 0: None 1: Ellipse 2: Rounded rectangle 3, 4: Hex
*
* @param Mask radius
* @default 48
* @desc
* The radius of each of the corners.
* (Rounded rectangle style only)
*
* @help
* ## Disable minimap
*
* Add <NoMinimap> to the note field in a map, the minimap will be disabled on that map.
*
*
* ## Plugin command
*
* Minimap show # Show minimap. If <NoMinimap> is specified, the minimap can't be shown.
* Minimap hide # Hide minimap.
* Minimap refresh # Redraw minimap.
*
* @requiredAssets img/system/MinimapPlayerIcon
* @requiredAssets img/system/MinimapObjectIcon
*/
/*:ja
* @plugindesc
* [v0.2.0a] 画面上にミニマップを表示します。
*
* @author TOMY (Kamesoft)
*
* @param Map rect
* @default 524, 32, 260, 200
* @desc
* ミニマップの表示位置とサイズをピクセル単位で指定します。
* 書式: X, Y, 幅, 高さ
*
* @param Grid size
* @default 10
* @desc ミニマップの 1 マスのサイズをピクセル単位で指定します。
*
* @param Blink time
* @default 180
* @desc ミニマップ上のアイコンを点滅させる時間をフレーム単位で指定します。
*
* @param Foreground color
* @default rgba(224, 224, 240, 0.6)
* @desc
* ミニマップの通行可能領域の色を CSS カラーで指定します。
* 書式: rgba(赤, 緑, 青, 不透明度)
*
* @param Background color
* @default rgba(0, 0, 160, 0.6)
* @desc
* ミニマップの通行不可領域の色を CSS カラーで指定します。
* 書式: rgba(赤, 緑, 青, 不透明度)
*
* @param Mask style
* @default 0
* @desc
* ミニマップの表示領域のマスク方法を指定します。
* 0: なし 1: 楕円 2: 角丸矩形 3: 六角形1 4: 六角形2
*
* @param Mask radius
* @default 48
* @desc
* 角丸矩形マスクを指定した場合の、角の丸め具合を指定します。
*
* @help
* ## ミニマップの非表示
*
* マップのメモ欄に <NoMinimap> を追加すると、そのマップではミニマップが表示されなくなります。
*
*
* ## プラグインコマンド
*
* Minimap show # ミニマップを表示します。<NoMinimap> を指定したマップでは表示できません。
* Minimap hide # ミニマップを隠します。
* Minimap refresh # ミニマップを再描画します。
*
* @requiredAssets img/system/MinimapPlayerIcon
* @requiredAssets img/system/MinimapObjectIcon
*/
var KMS = KMS || {};
(function () {
"use strict";
KMS.imported = KMS.imported || {};
KMS.imported["Minimap"] = true;
/**
* 矩形を表す文字列を解析
*/
var parseRect = function (str) {
var rectReg = /([-]?\d+),\s*([-]?\d+),\s*([-]?\d+),\s*([-]?\d+)/;
var rect = new PIXI.Rectangle(524, 32, 260, 200);
var match = rectReg.exec(str);
if (match) {
rect.x = Number(match[1]);
rect.y = Number(match[2]);
rect.width = Number(match[3]);
rect.height = Number(match[4]);
}
return rect;
};
var pluginParams = PluginManager.parameters("KMS_Minimap");
var Params = {};
Params.mapRect = parseRect(pluginParams["Map rect"]);
Params.gridSize = Number(pluginParams["Grid size"] || 10);
Params.blinkTime = Number(pluginParams["Blink time"] || 180);
Params.foregroundColor =
pluginParams["Foreground color"] || "rgba(224, 224, 240, 0.6)";
Params.backgroundColor =
pluginParams["Background color"] || "rgba( 0, 0, 160, 0.6)";
Params.playerIconImage = pluginParams["Player icon"] || "MinimapPlayerIcon";
Params.objectIconImage = pluginParams["Object icon"] || "MinimapObjectIcon";
Params.displayTileImage = pluginParams["Display tile"];
Params.maskStyle = Number(pluginParams["Mask style"] || 0);
Params.maskRadius = Number(pluginParams["Mask radius"] || 48);
var Minimap = {};
Minimap.passageCacheCountMax = 5;
Minimap.regex = {
wallEvent: /<(?:ミニマップ|MINIMAP)\s*[:\s]\s*(?:壁|障害物|WALL)>/i,
moveEvent: /<(?:ミニマップ|MINIMAP)\s*[:\s]\s*(?:移動|MOVE)>/i,
person: /<(?:ミニマップ|MINIMAP)\s*[:\s]\s*(?:人物|PERSON)\s*(\d+)>/i,
object: /<(?:ミニマップ|MINIMAP)\s*[:\s]\s*OBJ(?:ECT)?\s*(\d+)>/i,
};
Minimap.keysRequireNumber = ["person", "object"];
Minimap.dirFlags = { down: 0x01, left: 0x02, right: 0x04, up: 0x08 };
Minimap.maskStyles = {
none: 0,
ellipse: 1,
roundedRect: 2,
hex1: 3,
hex2: 4,
};
/**
* 指定した円に内接する正 n 角形の塗り潰し
*/
var fillRegularPolygon = function (
graphics,
x,
y,
width,
height,
startRad,
vertexCount
) {
if (vertexCount < 1) {
return;
}
var points = [];
for (var i = 0; i < vertexCount; i++) {
var angle = (i * Math.PI * 2) / vertexCount - Math.PI / 2 + startRad;
points.push(x + Math.cos(angle) * width);
points.push(y + Math.sin(angle) * height);
}
graphics.drawPolygon(points);
};
//-----------------------------------------------------------------------------
// Plugin commands
var _KMS_Game_Interpreter_pluginCommand =
Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function (command, args) {
_KMS_Game_Interpreter_pluginCommand.call(this, command, args);
if (command !== "Minimap") {
return;
}
switch (args[0]) {
case "show":
$gameSystem.setMinimapEnabled(true);
break;
case "hide":
$gameSystem.setMinimapEnabled(false);
break;
case "refresh":
$gameMap.refreshMinimapCache();
break;
default:
// 不明なコマンド
console.log("[Minimap %1] Unknown command.".format(args[0]));
break;
}
};
//-----------------------------------------------------------------------------
// Tilemap
Tilemap.prototype.getTileCount = function () {
return {
x: Math.ceil(this._width / this._tileWidth) + 1,
y: Math.ceil(this._height / this._tileHeight) + 1,
};
};
//-----------------------------------------------------------------------------
// Game_Temp
var _KMS_Game_Temp_initialize = Game_Temp.prototype.initialize;
Game_Temp.prototype.initialize = function () {
_KMS_Game_Temp_initialize.call(this);
this._minimapPassageCache = [];
this._minimapCacheRefreshFlag = false;
};
Object.defineProperty(Game_Temp.prototype, "minimapCacheRefreshFlag", {
get: function () {
return this._minimapCacheRefreshFlag;
},
set: function (value) {
this._minimapCacheRefreshFlag = value;
},
configurable: true,
});
Game_Temp.prototype.getMinimapPassageCache = function (mapId) {
return null;
};
/**
* 通行可否キャッシュの登録
*/
Game_Temp.prototype.registerMinimapPassageCache = function (mapId, passage) {
// 最新のキャッシュは先頭に置く
var newCache = [{ mapId: mapId, passage: passage }].concat(
this._minimapPassageCache.filter(function (cache) {
return cache.mapId !== mapId;
})
);
// しばらく参照されていないキャッシュは消す
this._minimapPassageCache = newCache.slice(0, Minimap.passageCacheCountMax);
};
/**
* 通行可否キャッシュの取得
*/
Game_Temp.prototype.getMinimapPassageCache = function (mapId) {
for (var i = 0; i < this._minimapPassageCache.length; i++) {
var tempCache = this._minimapPassageCache[i];
if (tempCache.mapId !== mapId) {
continue;
}
if (i > 0) {
// 取得したキャッシュは先頭に移す
this.registerMinimapPassageCache(mapId, tempCache);
}
return tempCache;
}
return null;
};
/**
* 通行可否キャッシュをクリア
*/
Game_Temp.prototype.clearMinimapPassageCache = function (mapId) {
this._minimapPassageCache = [];
this._minimapCacheRefreshFlag = true;
};
//-----------------------------------------------------------------------------
// Game_System
/**
* ミニマップの有効状態を取得
*/
Game_System.prototype.isMinimapEnabled = function () {
return this._minimapEnabled != null ? this._minimapEnabled : true;
};
/**
* ミニマップの有効状態を設定
*/
Game_System.prototype.setMinimapEnabled = function (enabled) {
this._minimapEnabled = !!enabled;
};
//-----------------------------------------------------------------------------
// Game_Map
var _KMS_Game_Map_setup = Game_Map.prototype.setup;
Game_Map.prototype.setup = function (mapId) {
_KMS_Game_Map_setup.call(this, mapId);
this.setupMinimap();
};
/**
* ミニマップに関する設定
*/
Game_Map.prototype.setupMinimap = function () {
this._minimapEnabled = !$dataMap.meta.NoMinimap;
};
/**
* ミニマップの表示可否を取得
*/
Game_Map.prototype.isMinimapEnabled = function () {
return this._minimapEnabled;
};
/**
* ミニマップのキャッシュを再構築
*/
Game_Map.prototype.refreshMinimapCache = function () {
$gameTemp.clearMinimapPassageCache();
};
//-----------------------------------------------------------------------------
// Game_Character
Game_Character.prototype.isMinimapAttributeDirty = function () {
// 何もしない
};
Game_Character.prototype.setMinimapAttributeDirty = function () {
// 何もしない
};
Game_Character.prototype.clearMinimapAttributeDirty = function () {
// 何もしない
};
//-----------------------------------------------------------------------------
// Game_Event
var _KMS_Game_Event_setupPage = Game_Event.prototype.setupPage;
Game_Event.prototype.setupPage = function () {
_KMS_Game_Event_setupPage.call(this);
this.setupMinimapAttribute();
};
/**
* ミニマップ用属性の設定
*/
Game_Event.prototype.setupMinimapAttribute = function () {
this._minimapAttribute = {
dirty: true,
wall: false,
move: false,
person: -1,
object: -1,
};
var isComment = function (command) {
return command && (command.code === 108 || command.code === 408);
};
// 注釈以外に達するまで解析
var page = this.page();
if (!page) {
return;
}
var commands = page.list;
var index = 0;
var command = commands[index++];
while (isComment(command)) {
var comment = command.parameters[0];
this._minimapAttribute.wall |= Minimap.regex.wallEvent.test(comment);
this._minimapAttribute.move |= Minimap.regex.moveEvent.test(comment);
Minimap.keysRequireNumber.forEach(function (key) {
var match = Minimap.regex[key].exec(comment);
if (match) {
this._minimapAttribute[key] = Number(match[1]);
}
}, this);
command = commands[index++];
}
};
Game_Event.prototype.isMinimapAttributeDirty = function () {
return this._minimapAttribute.dirty;
};
Game_Event.prototype.setMinimapAttributeDirty = function () {
this._minimapAttribute.dirty = true;
};
Game_Event.prototype.clearMinimapAttributeDirty = function () {
this._minimapAttribute.dirty = false;
};
Game_Event.prototype.isMinimapWall = function () {
return this._minimapAttribute.wall;
};
Game_Event.prototype.isMinimapMove = function () {
return this._minimapAttribute.move;
};
Game_Event.prototype.minimapPersonType = function () {
return this._minimapAttribute.person;
};
Game_Event.prototype.minimapObjectType = function () {
return this._minimapAttribute.object;
};
//-----------------------------------------------------------------------------
// Game_Vehicle
/**
* 現在のマップに存在するか
*/
Game_Vehicle.prototype.isInCurrentMap = function () {
return this._mapId === $gameMap.mapId();
};
//-----------------------------------------------------------------------------
// Game_MinimapPassageCache
function Game_MinimapPassageCache() {
this.initialize.apply(this, arguments);
}
Game_MinimapPassageCache.prototype.initialize = function (map, grid) {
this._mapId = map.mapId();
this._width = map.width();
this._height = map.height();
this._grid = grid;
this._blockCount = {
x: Math.floor((this._width + grid.x - 1) / grid.x),
y: Math.floor((this._height + grid.y - 1) / grid.y),
};
// 各タイルの通行可否フラグ
this._flags = new Array(this._width * this._height);
// チェック済みブロックフラグ
this._blockChecked = new Array(this._blockCount.x * this._blockCount.y);
};
/**
* ブロック数の取得
*/
Game_MinimapPassageCache.prototype.getBlockCount = function () {
return this._blockCount;
};
/**
* ブロックチェック済み判定
*/
Game_MinimapPassageCache.prototype.isBlockChecked = function (bx, by) {
return this._blockChecked[bx + by * this._blockCount.y];
};
/**
* ブロックチェック済みフラグの設定
*/
Game_MinimapPassageCache.prototype.setBlockChecked = function (
bx,
by,
checked
) {
this._blockChecked[bx + by * this._blockCount.y] = checked;
};
/**
* 通行フラグの取得
*/
Game_MinimapPassageCache.prototype.getFlag = function (x, y) {
if ($gameMap.isLoopHorizontal()) {
x = (x + this._width) % this._width;
} else if (x < 0 || x >= this._width) {
return 0;
}
if ($gameMap.isLoopVertical()) {
y = (y + this._height) % this._height;
} else if (y < 0 || y >= this._height) {
return 0;
}
return this._flags[x + y * this._width];
};
/**
* 通行フラグの設定
*/
Game_MinimapPassageCache.prototype.setFlag = function (x, y, flag) {
this._flags[x + y * this._width] = flag;
};
/**
* 指定位置が通行可能か
*/
Game_MinimapPassageCache.prototype.isPassable = function (x, y) {
return this.getFlag(x, y) !== 0;
};
/**
* 指定方向への通行が可能か
*/
Game_MinimapPassageCache.prototype.isPassableDir = function (x, y, dir) {
var flag = this.getFlag(x, y);
switch (dir) {
case 2:
return (flag & Minimap.dirFlags.down) !== 0;
case 4:
return (flag & Minimap.dirFlags.left) !== 0;
case 6:
return (flag & Minimap.dirFlags.right) !== 0;
case 8:
return (flag & Minimap.dirFlags.up) !== 0;
default:
return false;
}
};
//-----------------------------------------------------------------------------
// Sprite_Minimap
//
// ミニマップ用のスプライトです。
function Sprite_Minimap() {
this.initialize.apply(this, arguments);
}
Sprite_Minimap.prototype = Object.create(Sprite_Base.prototype);
Sprite_Minimap.prototype.constructor = Sprite_Minimap;
Sprite_Minimap.prototype.initialize = function () {
Sprite_Base.prototype.initialize.call(this);
var rect = Params.mapRect;
this._gridNumber = {
x: Math.floor((rect.width + Params.gridSize - 1) / Params.gridSize),
y: Math.floor((rect.height + Params.gridSize - 1) / Params.gridSize),
};
this._drawGridNumber = {
x: this._gridNumber.x + 2,
y: this._gridNumber.y + 2,
};
this._drawRange = {
begin: new PIXI.Point(0, 0),
end: new PIXI.Point(0, 0),
};
this._lastPosition = new Point($gamePlayer.x, $gamePlayer.y);
this._scrollDiff = new Point();
this.createSubSprites();
this._baseOpacity = 255;
this.setColorTone([-64, -64, 128, 64]);
this.move(rect.x, rect.y);
};
/**
* 内部のスプライトを作成
*/
Sprite_Minimap.prototype.createSubSprites = function () {
this._bitmapSize = {
width: (this._gridNumber.x + 2) * Params.gridSize,
height: (this._gridNumber.y + 2) * Params.gridSize,
};
this.createBaseSprite();
this.createPassageSprite();
this.createObjectSprites();
this.createPlayerSprite();
};
/**
* ベース部分のスプライトを作成
*/
Sprite_Minimap.prototype.createBaseSprite = function () {
var rect = Params.mapRect;
this._baseSprite = new Sprite();
this._baseSprite.bitmap = new Bitmap(rect.width, rect.height);
this._baseSprite.bitmap.fillAll(Params.backgroundColor);
this.addChild(this._baseSprite);
if (Params.displayTileImage) {
this._tilemap = Graphics.isWebGL() ? new ShaderTilemap() : new Tilemap();
// 軽量化のためにタイルのアニメーションを切る
this._tilemap.update = null;
this.addChild(this._tilemap);
}
this.applyMask(rect);
};
/**
* マスクの適用
*/
Sprite_Minimap.prototype.applyMask = function (rect) {
this._maskGraphic = new PIXI.Graphics();
this._maskGraphic.beginFill(0x000000);
switch (Params.maskStyle) {
case Minimap.maskStyles.ellipse:
this._maskGraphic.drawEllipse(
rect.width / 2,
rect.height / 2,
rect.width / 2,
rect.height / 2
);
break;
case Minimap.maskStyles.roundedRect:
this._maskGraphic.drawRoundedRect(0, 0, rect.width, rect.height, 64);
break;
case Minimap.maskStyles.hex1:
case Minimap.maskStyles.hex2:
fillRegularPolygon(
this._maskGraphic,
rect.width / 2,
rect.height / 2,
rect.width / 2,
rect.height / 2,
Params.maskStyle === Minimap.maskStyles.hex1 ? 0 : Math.PI / 2,
6
);
break;
default:
this._maskGraphic.drawRect(0, 0, rect.width, rect.height);
break;
}
this._maskGraphic.endFill();
this.addChild(this._maskGraphic);
this.mask = this._maskGraphic;
};
/**
* 通行可能領域スプライトの作成
*/
Sprite_Minimap.prototype.createPassageSprite = function () {
this._passageSprite = new Sprite_MinimapPassage(
this._bitmapSize.width,
this._bitmapSize.height
);
this.updateScroll();
this.addChild(this._passageSprite);
};
/**
* オブジェクトスプライトの作成
*/
Sprite_Minimap.prototype.createObjectSprites = function () {
this._objectSprites = [];
var objects = $gameMap.events().concat($gameMap.vehicles());
objects.forEach(function (obj) {
var sprite = new Sprite_MinimapIcon();
sprite.setObject(obj);
this._objectSprites.push(sprite);
this.addChild(sprite);
}, this);
};
/**
* 現在位置スプライトの作成
*/
Sprite_Minimap.prototype.createPlayerSprite = function () {
var rect = Params.mapRect;
this._playerSprite = new Sprite_MinimapIcon();
this._playerSprite.bitmap = ImageManager.loadSystem(Params.playerIconImage);
this._playerSprite.x = rect.width / 2;
this._playerSprite.y = rect.height / 2;
this.addChild(this._playerSprite);
};
/**
* 全体の不透明度を設定
*/
Sprite_Minimap.prototype.setWholeOpacity = function (baseOpacity) {
this.opacity = (this._baseOpacity * baseOpacity) / 255;
};
/**
* ミニマップ位置の移動
*/
Sprite_Minimap.prototype.move = function (x, y) {
this.x = x;
this.y = y;
};
Sprite_Minimap.prototype.isNeedUpdate = function () {
return this.visible && this.opacity > 0;
};
Sprite_Minimap.prototype.update = function () {
Sprite_Base.prototype.update.call(this);
this.updateVisibility();
if ($gameTemp.minimapCacheRefreshFlag) {
$gameTemp.minimapCacheRefreshFlag = false;
this.refreshPassageTable();
}
if (!this.isNeedUpdate()) {
return;
}
this.updatePosition();
this.updateTilemap();
this.updatePassageSprite();
this.updateObjectSprites();
this.updatePlayerSprite();
};
/**
* 可視状態の更新
*/
Sprite_Minimap.prototype.updateVisibility = function () {
this.visible =
$gameSystem.isMinimapEnabled() && $gameMap.isMinimapEnabled();
};
/**
* 描画範囲の更新
*/
Sprite_Minimap.prototype.updateDrawRange = function () {
var range = {
x: Math.floor(this._drawGridNumber.x / 2),
y: Math.floor(this._drawGridNumber.y / 2),
};
this._drawRange.begin.x = $gamePlayer.x - range.x;
this._drawRange.begin.y = $gamePlayer.y - range.y;
this._drawRange.end.x = $gamePlayer.x + range.x;
this._drawRange.end.y = $gamePlayer.y + range.y;
};
/**
* タイルマップの表示領域を更新
*/
Sprite_Minimap.prototype.updateTilemap = function () {
if (!this._tilemap) {
return;
}
this._tilemap.origin.x =
($gamePlayer._realX - this._tileCount.x / 2.0 + 1.5) *
$gameMap.tileWidth();
this._tilemap.origin.y =
($gamePlayer._realY - this._tileCount.y / 2.0 + 1.5) *
$gameMap.tileHeight();
};
/**
* 通行可能領域スプライトの更新
*/
Sprite_Minimap.prototype.updatePassageSprite = function () {
// TODO: 実装
};
/**
* オブジェクトスプライトの更新
*/
Sprite_Minimap.prototype.updateObjectSprites = function () {
this._objectSprites.forEach(function (sprite) {
var obj = sprite.getObject();
if (!obj || !this.isInDrawRange(obj.x - 1, obj.y - 1)) {
sprite.visible = false;
return;
}
sprite.updatePosition(this._drawRange.begin, this._scrollDiff);
}, this);
};
/**
* 現在位置スプライトの更新
*/
Sprite_Minimap.prototype.updatePlayerSprite = function () {
// スプライトの向きを設定
var angle;
if (KMS.imported["3DVehicle"] && $gameMap.is3DMode()) {
angle = -$gameMap.get3DPlayerAngle();
} else {
switch ($gamePlayer.direction()) {
case 2:
angle = Math.PI;
break;
case 4:
angle = (Math.PI * 3) / 2;
break;
case 6:
angle = Math.PI / 2;
break;
case 8:
angle = 0;
break;
default:
angle = 0;
break;
}
}
this._playerSprite.rotation = angle;
};
/**
* ミニマップの再構築
*/
Sprite_Minimap.prototype.refresh = function () {
this.updatePosition();
this.refreshTilemap();
this.refreshParameters();
this.refreshMapImage();
};
/**
* タイルマップの再構築
*/
Sprite_Minimap.prototype.refreshTilemap = function () {
if (!this._tilemap) {
return;
}
var rect = Params.mapRect;
var baseSize = {
width: Math.floor((rect.width * $gameMap.tileWidth()) / Params.gridSize),
height: Math.floor(
(rect.height * $gameMap.tileHeight()) / Params.gridSize
),
};
// タイルマップのパラメータを設定
this._tilemap.tileWidth = $gameMap.tileWidth();
this._tilemap.tileHeight = $gameMap.tileHeight();
this._tilemap.width = baseSize.width;
this._tilemap.height = baseSize.height;
this._tilemap.setData($gameMap.width(), $gameMap.height(), $gameMap.data());
this._tilemap.horizontalWrap = $gameMap.isLoopHorizontal();
this._tilemap.verticalWrap = $gameMap.isLoopVertical();
var scaleX = Params.mapRect.width / this._tilemap.width;
var scaleY = Params.mapRect.height / this._tilemap.height;
this._tilemap.scale.x = scaleX;
this._tilemap.scale.y = scaleY;
this._tilemap.x += this._tilemap._margin * scaleX;
this._tilemap.y += this._tilemap._margin * scaleY;
//this._tilemap.width += this._tilemap._margin * 2;
//this._tilemap.height += this._tilemap._margin * 2;
Spriteset_Map.prototype.loadTileset.call(this);
// タイルマップを再描画するために update を呼ぶ
(Graphics.isWebGL() ? ShaderTilemap : Tilemap).prototype.update.call(
this._tilemap
);
this._tileCount = this._tilemap.getTileCount();
};
/**
* ミニマップ用パラメータの再構築
*/
Sprite_Minimap.prototype.refreshParameters = function () {
this.updateDrawRange();
this.refreshPassageTable();
};
/**
* 通行フラグテーブルの更新
*/
Sprite_Minimap.prototype.refreshPassageTable = function () {
this._passageCache = this.getPassageTableCache();
};
/**
* 現在のマップに対応する通行フラグキャッシュを取得
*/
Sprite_Minimap.prototype.getPassageTableCache = function () {
return new Game_MinimapPassageCache($gameMap, this._drawGridNumber);
};
/**
* マップ画像の再構築
*/
Sprite_Minimap.prototype.refreshMapImage = function () {
this.drawMap();
};
/**
* 指定した座標が含まれるブロックの通行フラグをスキャン
*/
Sprite_Minimap.prototype.scanPassage = function (x, y) {
var mapWidth = $gameMap.width();
var mapHeight = $gameMap.height();
if ($gameMap.isLoopHorizontal()) {
x = (x + mapWidth) % mapWidth;
}
if ($gameMap.isLoopVertical()) {
y = (y + mapHeight) % mapHeight;
}
var blocks = this._passageCache.getBlockCount();
var bx = Math.floor(x / this._drawGridNumber.x);
var by = Math.floor(y / this._drawGridNumber.y);
if (bx < 0 || bx >= blocks.x || by < 0 || by >= blocks.y) {
// マップ範囲外
return;
}
if (this._passageCache.isBlockChecked(bx, by)) {
// 探索済み
return;
}
var range = {
x: {
begin: bx * this._drawGridNumber.x,
end: (bx + 1) * this._drawGridNumber.x,
},
y: {
begin: by * this._drawGridNumber.y,
end: (by + 1) * this._drawGridNumber.y,
},
};
// 探索範囲内の通行テーブルを生成
for (var ty = range.y.begin; ty < range.y.end; ty++) {
if (ty < 0 || ty >= mapHeight) {
continue;
}
for (var tx = range.x.begin; tx < range.x.end; tx++) {
if (tx < 0 || tx >= mapWidth) {
continue;
}
// 通行方向フラグの作成
// (方向は 2, 4, 6, 8)
var flag = 0;
for (var i = 0; i < 4; i++) {
var dir = (i + 1) * 2;
if ($gameMap.isPassable(tx, ty, dir)) {
flag |= 1 << (dir / 2 - 1);
}
}
this._passageCache.setFlag(tx, ty, flag);
}
}
this._passageCache.setBlockChecked(bx, by, true);
};
/**
* プレイヤー周囲の通行フラグテーブルを更新
*/
Sprite_Minimap.prototype.updateAroundPassageTable = function () {
var gx = this._drawGridNumber.x;
var gy = this._drawGridNumber.y;
var dx = $gamePlayer.x - Math.floor(gx / 2);
var dy = $gamePlayer.y - Math.floor(gy / 2);
this.scanPassage(dx, dy);
this.scanPassage(dx + gx, dy);
this.scanPassage(dx, dy + gy);
this.scanPassage(dx + gx, dy + gy);
};
/**
* プレイヤー位置の更新
*/
Sprite_Minimap.prototype.updatePosition = function () {
this._scrollDiff.x = ($gamePlayer._realX - $gamePlayer.x) * Params.gridSize;
this._scrollDiff.y = ($gamePlayer._realY - $gamePlayer.y) * Params.gridSize;
this.updateScroll();
if (
this._lastPosition.x !== $gamePlayer.x ||
this._lastPosition.y !== $gamePlayer.y
) {
this.updateDrawRange();
this.drawMap();
this._lastPosition.x = $gamePlayer.x;
this._lastPosition.y = $gamePlayer.y;
}
};
/**
* スクロール処理
*/
Sprite_Minimap.prototype.updateScroll = function () {
var offset = {
x: Math.floor(Params.gridSize * 1.5) + this._scrollDiff.x,
y: Math.floor(Params.gridSize * 1.5) + this._scrollDiff.y,
};
var rect = Params.mapRect;
this._passageSprite.setFrame(offset.x, offset.y, rect.width, rect.height);
};
/**
* 描画範囲か判定
*/
Sprite_Minimap.prototype.isInDrawRange = function (x, y) {
var begin = this._drawRange.begin;
var end = this._drawRange.end;
var dx = x;
if ($gameMap.isLoopHorizontal()) {
dx = (dx + $gameMap.width()) % $gameMap.width();
}
var dy = y;
if ($gameMap.isLoopVertical()) {
dy = (dy + $gameMap.height()) % $gameMap.height();
}
return x >= begin.x && x <= end.x && y >= begin.y && y <= end.y;
};
/**
* マップの範囲内か判定
*/
Sprite_Minimap.prototype.isInMapRange = function (x, y) {
return x >= 0 && x < $gameMap.width() && y >= 0 && y < $gameMap.height();
};
/**
* マップ画像の描画
*/
Sprite_Minimap.prototype.drawMap = function () {
this.updateAroundPassageTable();
var bitmap = this._passageSprite.bitmap;
bitmap.clear();
this.drawMapForeground(bitmap);
};
/**
* 移動可能領域の描画
*/
Sprite_Minimap.prototype.drawMapForeground = function (bitmap) {
for (var y = this._drawRange.begin.y; y < this._drawRange.end.y; y++) {
for (var x = this._drawRange.begin.x; x < this._drawRange.end.x; x++) {
this.drawMapForegroundGrid(bitmap, Math.floor(x), Math.floor(y));
}
}
};
/**
* 移動可能グリッドの描画
*/
Sprite_Minimap.prototype.drawMapForegroundGrid = function (bitmap, x, y) {
var passage = this._passageCache;
if (!passage.isPassable(x, y)) {
return;
}
var dx = (x - this._drawRange.begin.x) * Params.gridSize;
var dy = (y - this._drawRange.begin.y) * Params.gridSize;
var dw = Params.gridSize;
var dh = Params.gridSize;
if (!passage.isPassableDir(x, y, 2)) {
// 下方向移動不可
dh -= 1;
}
if (!passage.isPassableDir(x, y, 4)) {
// 左方向移動不可
dx += 1;
dw -= 1;
}
if (!passage.isPassableDir(x, y, 6)) {
// 右方向移動不可
dw -= 1;
}
if (!passage.isPassableDir(x, y, 8)) {
// 上方向移動不可
dy += 1;
dh -= 1;
}
bitmap.fillRect(dx, dy, dw, dh, Params.foregroundColor);
};
//-----------------------------------------------------------------------------
// Sprite_MinimapPassage
//
// ミニマップ上の通行可能領域表示用スプライトです。
function Sprite_MinimapPassage() {
this.initialize.apply(this, arguments);
}
Sprite_MinimapPassage.prototype = Object.create(Sprite.prototype);
Sprite_MinimapPassage.prototype.constructor = Sprite_MinimapPassage;
Sprite_MinimapPassage.prototype.initialize = function (width, height) {
Sprite.prototype.initialize.call(this);
this.bitmap = new Bitmap(width, height);
};
//-----------------------------------------------------------------------------
// Sprite_MinimapIcon
//
// ミニマップ上のアイコン用スプライトです。
function Sprite_MinimapIcon() {
this.initialize.apply(this, arguments);
}
Sprite_MinimapIcon.prototype = Object.create(Sprite.prototype);
Sprite_MinimapIcon.prototype.constructor = Sprite_MinimapIcon;
Sprite_MinimapIcon.prototype.initialize = function () {
Sprite.prototype.initialize.call(this);
this.bitmap = ImageManager.loadSystem(Params.objectIconImage);
this.anchor.x = 0.5;
this.anchor.y = 0.5;
this._object = null;
this._lastIconIndex = -1;
this._blinkDuration = 0;
};
/**
* 表示準備ができているか
*/
Sprite_MinimapIcon.prototype.isReady = function () {
return this.bitmap && this.bitmap.isReady();
};
/**
* 追従するオブジェクトの取得
*/
Sprite_MinimapIcon.prototype.getObject = function () {
return this._object;
};
/**
* 追従するオブジェクトの設定
*/
Sprite_MinimapIcon.prototype.setObject = function (object) {
this._object = object;
if (object) {
this.bitmap = ImageManager.loadSystem(Params.objectIconImage);
this.updateIconInfo();
}
this.refresh();
};
/**
* 表示位置の更新
*
* @param {Point} begin - ミニマップの表示開始座標
* @param {Point} scrollDiff - 位置補正のためのマップスクロール量
*/
Sprite_MinimapIcon.prototype.updatePosition = function (begin, scrollDiff) {
var x = (this._object.x - begin.x - 1) * Params.gridSize;
var y = (this._object.y - begin.y - 1) * Params.gridSize;
this.x = x - scrollDiff.x;
this.y = y - scrollDiff.y;
if (KMS.imported["AreaEvent"]) {
// 表示サイズに応じた位置補正
this.x += (this._iconSize * (this.scale.x - 1.0)) / 2;
this.y += (this._iconSize * (this.scale.y - 1.0)) / 2;
}
};
/**
* アイコン情報の更新
*/
Sprite_MinimapIcon.prototype.updateIconInfo = function () {
if (!this.isReady()) {
this._iconSize = null;
this._iconColumns = null;
return;
}
this._iconSize = Math.floor(this.bitmap.height / 3);
this._iconColumns = Math.floor(this.bitmap.width / this._iconSize);
};
/**
* リフレッシュ
*/
Sprite_MinimapIcon.prototype.refresh = function () {
this._lastIconIndex = -1;
};
/**
* オブジェクト更新
*/
Sprite_MinimapIcon.prototype.update = function () {
Sprite.prototype.update.call(this);
this.updateImage();
this.updateBlink();
};
/**
* 表示する画像の更新
*/
Sprite_MinimapIcon.prototype.updateImage = function () {
if (!this._object) {
return;
}
if (!this._iconColumns) {
this.updateIconInfo();
}
var iconIndex = this.getCurrentIconIndex();
if (iconIndex >= 0) {
if (
iconIndex !== this._lastIconIndex ||
this._object.isMinimapAttributeDirty()
) {
this.setIconIndex(iconIndex);
}
} else {
this._lastIconIndex = iconIndex;
this.visible = false;
}
};
/**
* 現在のオブジェクトに対応するオブジェクトアイコン番号の取得
*/
Sprite_MinimapIcon.prototype.getCurrentIconIndex = function () {
if (!(this._object && this.isReady())) {
return -1;
}
if (this._object instanceof Game_Vehicle) {
return this.getCurrentIconIndexForVehicle();
} else {
return this.getCurrentIconIndexForEvent();
}
};
/**
* 現在のイベントに対応するアイコン番号の取得
*/
Sprite_MinimapIcon.prototype.getCurrentIconIndexForEvent = function () {
var obj = this._object;
if (obj.isMinimapMove()) {
return 0;
} else if (obj.minimapPersonType() >= 0) {
// person は 2 行目
return this._iconColumns + obj.minimapPersonType();
} else if (obj.minimapObjectType() >= 0) {
// object は 3 行目
return this._iconColumns * 2 + obj.minimapObjectType();
} else {
return -1;
}
};
/**
* 現在の乗り物に対応するアイコン番号の取得
*/
Sprite_MinimapIcon.prototype.getCurrentIconIndexForVehicle = function () {
var obj = this._object;
if (!obj.isInCurrentMap()) {
return -1;
} else if (obj.isBoat()) {
return $gamePlayer.isInBoat() ? -1 : 1;
} else if (obj.isShip()) {
return $gamePlayer.isInShip() ? -1 : 2;
} else if (obj.isAirship()) {
return $gamePlayer.isInAirship() ? -1 : 3;
} else {
// 不明な乗り物
return -1;
}
};
/**
* オブジェクトアイコン番号の設定
*/
Sprite_MinimapIcon.prototype.setIconIndex = function (iconIndex) {
this.setFrame(
(iconIndex % this._iconColumns) * this._iconSize,
Math.floor(iconIndex / this._iconColumns) * this._iconSize,
this._iconSize,
this._iconSize
);
this.updateDisplaySize();
this._object.clearMinimapAttributeDirty();
this._lastIconIndex = iconIndex;
this.visible = true;
};
/**
* オブジェクトアイコン表示サイズの更新
*/
Sprite_MinimapIcon.prototype.updateDisplaySize = function () {
if (!KMS.imported["AreaEvent"] || !(this._object instanceof Game_Event)) {
return;
}
var area = this._object.getEventTriggerArea();
this.scale.x = area.width;
this.scale.y = area.height;
};
/**
* 明滅エフェクトの更新
*/
Sprite_MinimapIcon.prototype.updateBlink = function () {
this._blinkDuration = (this._blinkDuration + 1) % Params.blinkTime;
var alpha =
128 *
(Math.sin((this._blinkDuration * Math.PI * 2) / Params.blinkTime) + 1);
var color = [255, 255, 255, alpha];
this.setBlendColor(color);
};
//-----------------------------------------------------------------------------
// Spriteset_Map
var _KMS_Spriteset_Map_createUpperLayer =
Spriteset_Map.prototype.createUpperLayer;
Spriteset_Map.prototype.createUpperLayer = function () {
_KMS_Spriteset_Map_createUpperLayer.call(this);
this.createMinimap();
};
/**
* ミニマップの作成
*/
Spriteset_Map.prototype.createMinimap = function () {
this._minimap = new Sprite_Minimap();
this._minimap.refresh();
this.addChild(this._minimap);
};
var _KMS_Spriteset_Map = Spriteset_Map.prototype.update;
Spriteset_Map.prototype.update = function () {
_KMS_Spriteset_Map.call(this);
this.updateMinimap();
};
/**
* ミニマップの更新
*/
Spriteset_Map.prototype.updateMinimap = function () {
this._minimap.setWholeOpacity(255 - this._fadeSprite.opacity);
this._minimap.update();
};
})();