slave-princess-charlotte/data/Script/utility/utility-scrolltextview.js
2025-10-12 13:17:46 -05:00

465 lines
10 KiB
JavaScript

var ScrollTextView = defineObject(BaseObject,
{
_text: null,
_moveTime: 0,
_nextTime: 0,
_isMove: false,
_scrollTextParam: null,
_factoryArray: null,
_blockArray: null,
_isAcceleration: false,
openScrollTextViewCycle: function(scrollTextParam) {
this._prepareMemberData(scrollTextParam);
this._completeMemberData(scrollTextParam);
},
moveScrollTextViewCycle: function() {
var i, count;
// 表示しきったブロックは削除
if (this._blockArray.length > 0) {
if (this._blockArray[0].isLastBlock()) {
this._blockArray.shift();
}
}
if (!this._checkMove()) {
return MoveResult.CONTINUE;
}
// 経過時間をカウントする
this._moveTime += this.getBlockInterval();
// ブロックの表示間隔を一定にするために、高速化の検出も一定の間隔で行う
if (this._moveTime % this._getBaseTime() === 0) {
if (this._isAcceleration) {
if (!Miscellaneous.isGameAcceleration()) {
this._isAcceleration = false;
}
}
else {
if (Miscellaneous.isGameAcceleration()) {
this._isAcceleration = true;
}
}
}
count = this._blockArray.length;
for (i = 0; i < count; i++) {
this._blockArray[i].notifyTime(this._moveTime);
this._blockArray[i].moveBlock();
}
if (count === 0) {
return MoveResult.END;
}
return MoveResult.CONTINUE;
},
drawScrollTextViewCycle: function() {
var i;
var count = this._blockArray.length;
this._drawScrollWindow();
for (i = 0; i < count; i++) {
this._blockArray[i].drawBlock();
}
},
// _getBaseTimeを割り切れる数値を返す
getBlockInterval: function() {
var n;
var speedType = this._scrollTextParam.speedType;
if (this._isAcceleration) {
return 20;
}
if (speedType === SpeedType.DIRECT) {
n = 8;
}
else if (speedType === SpeedType.SUPERHIGH) {
n = 5;
}
else if (speedType === SpeedType.HIGH) {
n = 4;
}
else if (speedType === SpeedType.NORMAL) {
n = 2.5;
}
else if (speedType === SpeedType.LOW) {
n = 2;
}
else {
n = 1;
}
return n;
},
getMoveTime: function() {
return this._moveTime;
},
setNextTime: function(nextTime) {
nextTime = this._nextTime;
},
getScrollTextParam: function() {
return this._scrollTextParam;
},
_prepareMemberData: function(scrollTextParam) {
this._text = scrollTextParam.text;
this._moveTime = 0;
this._nextTime = 0;
this._isMove = false;
this._scrollTextParam = scrollTextParam;
this._factoryArray = [];
this._configureFactoryObject(this._factoryArray);
this._blockArray = [];
},
_completeMemberData: function(scrollTextParam) {
var i, count, oneblock;
var text = this._text;
while (text.length !== 0) {
// WaitBlockFactoryがthis._nextTimeを変更するため、毎回初期化している
this._nextTime = this._getBaseTime();
// テキストから一行取得する
oneblock = this._readBlock(text);
// 取得した行を処理できるオブジェクトを探す
count = this._factoryArray.length;
for (i = 0; i < count; i++) {
if (this._factoryArray[i].checkBlock(oneblock, this._blockArray, this)) {
// 行を処理できた場合は次の行を探すため抜ける
break;
}
}
// 仮の経過時間をカウントする
this._moveTime += this._nextTime;
// 次の行の先頭のテキストを取得
text = this._nextBlock(text);
}
// 後のmoveScrollTextViewCycleのために、初期化
this._moveTime = 0;
},
_readBlock: function(text) {
var i;
var count = text.length;
for (i = 0; i < count; i++) {
if (text.charAt(i) === '\n') {
// 改行までに存在していたテキストを取得
return text.substring(0, i);
}
}
// 改行がない場合は、これが最後の行であるためそのまま返してよい
return text;
},
_nextBlock: function(text) {
var i;
var count = text.length;
for (i = 0; i < count; i++) {
if (text.charAt(i) === '\n') {
// 改行までに存在していたテキストを取得
return text.substring(i + 1, text.length);
}
}
return '';
},
_checkMove: function() {
if (!DataConfig.isHighPerformance()) {
return true;
}
this._isMove = !this._isMove;
return this._isMove;
},
_getBaseTime: function() {
return 40;
},
_drawScrollWindow: function() {
var textui = root.queryTextUI('messagescroll_window');
var pic = textui.getUIImage();
var n = this._scrollTextParam.margin;
var x = n;
var y = n;
var width = root.getGameAreaWidth() - (n * 2);
var height = root.getGameAreaHeight() - (n * 2);
if (pic !== null) {
WindowRenderer.drawStretchWindow(x, y, width, height, pic);
}
},
_configureFactoryObject: function(groupArray) {
groupArray.appendObject(BlockFactory.Picture);
groupArray.appendObject(BlockFactory.Wait);
// テキスト処理オブジェクトには\spaceなどの印を持たない。
// よって、最後に確認されるようにする。
groupArray.appendObject(BlockFactory.Text);
}
}
);
// BaseBlockFactoryは、ScrollBlockを作成するオブジェクト
var BaseBlockFactory = defineObject(BaseObject,
{
checkBlock: function(text, arr, parentTextView) {
return true;
}
}
);
var BlockFactory = {};
BlockFactory.Text = defineObject(BaseBlockFactory,
{
checkBlock: function(text, arr, parentTextView) {
var obj = createObject(TextScrollBlock);
obj.setBlockData(text, parentTextView);
arr.push(obj);
return true;
}
}
);
BlockFactory.Picture = defineObject(BaseBlockFactory,
{
checkBlock: function(text, arr, parentTextView) {
var obj;
var key = this.getKey();
var c = text.match(key);
if (c !== null) {
obj = createObject(PictureScrollBlock);
obj.setBlockData(c[1], parentTextView);
arr.push(obj);
return true;
}
return false;
},
getKey: function() {
var key = /\\pic\[(.+)\]/;
return key;
}
}
);
BlockFactory.Wait = defineObject(BaseBlockFactory,
{
checkBlock: function(text, arr, parentTextView) {
var key = this.getKey();
var c = text.match(key);
if (c !== null) {
parentTextView.setNextTime(Number(c[1]));
return true;
}
return false;
},
getKey: function() {
var key = /\\space\[(\d+)\]/;
return key;
}
}
);
// BaseScrollBlockは、画面上を実際に移動するオブジェクト
var BaseScrollBlock = defineObject(BaseObject,
{
_x: 0,
_y: 0,
_top: 0,
_bottom: 0,
_value: null,
_startTime: 0,
_isStart: false,
_isLast: false,
_alpha: 0,
_parentTextView: null,
setBlockData: function(value, parentTextView) {
var scrollTextParam = parentTextView.getScrollTextParam();
var n = scrollTextParam.margin;
var size = root.queryTextUI('messagescroll_window').getFont().getSize();
this._top = n;
this._bottom = root.getGameAreaHeight() - n - size;
this._x = scrollTextParam.x;
this._y = this._bottom;
this._value = value;
this._startTime = parentTextView.getMoveTime();
this._isStart = false;
this._isLast = false;
this._alpha = 0;
this._parentTextView = parentTextView;
},
moveBlock: function() {
var zone = this._getAlphaZone();
var blockInterval = this._parentTextView.getBlockInterval();
var d = Math.floor(zone / blockInterval);
var da = Math.floor(255 / d);
if (this._isLast) {
return MoveResult.END;
}
if (this._isStart) {
// 現在位置がbottom - zoneの値より大きい場合は、アルファ値を上げる
if (this._y > this._bottom - zone) {
this._alpha += da;
if (this._alpha > 255) {
this._alpha = 255;
}
}
// 現在位置がtopの値より低い場合は、アルファ値を下げる
if (this._y < this._top + zone) {
this._alpha -= da;
if (this._alpha < 0) {
this._alpha = 0;
}
}
this._y -= blockInterval;
// 現在位置が、top - zoneを超えている場合は完全に透明になっているはずだから、終了フラグを立てる
if (this._y < this._top) {
this._isLast = true;
}
}
return MoveResult.CONTINUE;
},
drawBlock: function() {
},
isLastBlock: function() {
return this._isLast;
},
notifyTime: function(time) {
if (!this._isStart) {
// 通知された時間が、ブロックが動き始めるべき時間を超えた場合
if (time >= this._startTime) {
// ブロックの動きを開始する
this._isStart = true;
}
}
},
_getAlphaZone: function() {
return 40;
}
}
);
var TextScrollBlock = defineObject(BaseScrollBlock,
{
drawBlock: function() {
var x, width, textui, color, font;
var text = this._value;
if (this._isStart) {
textui = root.queryTextUI('messagescroll_window');
color = textui.getColor();
font = textui.getFont();
if (this._x === -1) {
width = TextRenderer.getTextWidth(text, font);
x = LayoutControl.getCenterX(-1, width);
}
else {
x = this._x;
}
TextRenderer.drawAlphaText(x, this._y, text, -1, color, this._alpha, font);
}
}
}
);
var PictureScrollBlock = defineObject(BaseScrollBlock,
{
_pictureId: -1,
setBlockData: function(value, parentTextView) {
var i, data;
var list = root.getBaseData().getGraphicsResourceList(GraphicsType.PICTURE, false);
var count = list.getCount();
BaseScrollBlock.setBlockData.call(this, value, parentTextView);
for (i = 0; i < count; i++) {
data = list.getCollectionData(i, 0);
if (data.getName() === value) {
this._pictureId = data.getId();
}
}
},
drawBlock: function() {
var x, width, pic;
var text = this._value;
if (this._isStart) {
pic = this._getGraphics(text);
if (pic === null) {
return;
}
width = pic.getWidth();
if (this._x === -1) {
x = LayoutControl.getCenterX(-1, width);
}
else {
x = this._x;
}
pic.setAlpha(this._alpha);
pic.draw(x, this._y);
}
},
_getGraphics: function(text) {
var list = root.getBaseData().getGraphicsResourceList(GraphicsType.PICTURE, false);
return list.getCollectionDataFromId(this._pictureId, 0);
}
}
);