phantom-soul-sword-lambda-n.../www/js/plugins/KMS_Minimap.js
2025-07-11 18:31:55 -07:00

1546 lines
38 KiB
JavaScript

//=============================================================================
// KMS_Minimap.js
// last update: 2019/01/01
//=============================================================================
/*:
* @plugindesc
* [v0.2.0] 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.0] 画面上にミニマップを表示します。
*
* @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, x, 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();
};
})();