图块和视角变速移动

This commit is contained in:
ckcz123 2021-07-26 18:16:24 +08:00
parent 2ae21a0bca
commit a6d74c00aa
9 changed files with 80 additions and 37 deletions

View File

@ -1013,12 +1013,13 @@ lose: fn(reason?: string)
moveEnemyOnPoint: fn(fromX: number, fromY: number, toX: number, toY: number, floorId?: string)
将某个点已经设置的敌人属性移动到其他点
moveImage: fn(code: number, to?: [number], opacityVal?: number, time?: number, callback?: fn())
moveImage: fn(code: number, to?: [number], opacityVal?: number, moveMode?: string, time?: number, callback?: fn())
移动一张图片并/或改变其透明度
例如core.moveImage(1, null, 0.5); // 1秒内把1号图片变为50%透明
code: 图片编号
to: 新的左上角坐标,省略表示原地改变透明度
opacityVal: 新的透明度,省略表示不变
moveMode: 移动模式
time: 移动用时单位为毫秒。不填视为1秒
callback: 图片移动完毕后的回调函数,可选
@ -2012,6 +2013,9 @@ textImage: fn(content: string, lineHeight?: number) -> image
工具函数库,里面有各个样板中使用到的工具函数。
```text
applyEasing: fn(mode?: string) -> fn(t: number) -> number
获得变速移动曲线
arrayToRGB: fn(color: [number]) -> string
颜色数组转字符串
例如core.arrayToRGB([102, 204, 255]); // "#66ccff"

View File

@ -119,7 +119,7 @@ data为整个指令对象x和y为当前点坐标prefix为独立开关的
* 此指令对应`core.showImage()`函数,编号真正的意义,详见[个性化](personalization)
2. **清除图片:**如题,需要指定要清除的图片编号和淡出时间。
* 此指令对应`core.hideImage(code, time, callback)`
3. **图片移动:**其实还包括了透明度渐变,“终点像素位置”指移动结束后的图片在视野中的左上角像素坐标(不填则表示单纯的透明度渐变),“不透明度”指渐变结束后的新的不透明度(不填表示单纯的移动),移动和透明度渐变都是匀速直线进行的。对应`core.moveImage(code, to, opacityVal, time, callback)`
3. **图片移动:**其实还包括了透明度渐变,“终点像素位置”指移动结束后的图片在视野中的左上角像素坐标(不填则表示单纯的透明度渐变),“不透明度”指渐变结束后的新的不透明度(不填表示单纯的移动)。对应`core.moveImage(code, to, opacityVal, moveMode, time, callback)`
4. **显示或清除动图:**需要填写动图的文件名(带.gif后缀“起点像素位置”含义如前且必须填写可以双击指令块来预览第一帧的效果。
* 动图不支持淡入淡出和伸缩移动,如果不填任何参数则清除所有动图。
* 该指令对应`core.showGif(name, x, y)`函数。
@ -462,7 +462,7 @@ core.insertAction({"type": "changeFloor", "floorId": "MT" + core.rand2(20)})
3. **设置和移动视角:**设置视角支持双击从地图选点,不填坐标则重置视角。
* 移动视角的动画时间为每动一格的时间,步伐数组只支持“上下左右”。
* 请注意,勇士重绘时(`core.drawHero()`函数视角也会随之重置。所以视角变化后勇士的坐标、朝向、显隐、行走图事件和API都提供了不重绘参数和跟随者情况暂时都不要动。
* 实际调用`core.setViewport(x, y)`和`core.moveViewport(steps, time, callback)`其中前者的自变量为【像素坐标】且不必为32的倍数必要时可作为原生js使用来实现特殊的演出。
* 实际调用`core.setViewport(x, y)`和`core.moveViewport(x, y, moveMode, time, callback)`其中前者的自变量为【像素坐标】且不必为32的倍数必要时可作为原生js使用来实现特殊的演出。
4. **显隐状态栏:**如题,如果隐藏状态栏期间勇士需要恢复行动,则建议不隐藏竖屏工具栏以方便手机玩家。
* 实际调用`core.showStatusBar()`和`core.hideStatusBar(showToolbox)`
5. **显隐勇士:**如题,动画时间为淡入淡出时间,异步勾选框用法如前。

View File

@ -2530,7 +2530,7 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [
},
"moveViewport": {
"!doc": "移动视野范围",
"!type": "fn(x: number, y: number, time?: number, callback?: fn())"
"!type": "fn(x: number, y: number, moveMode?: string, time?: number, callback?: fn())"
},
"syncLoad": {
"!doc": "从服务器加载存档",
@ -2740,6 +2740,10 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [
"y": "number"
}
},
"applyEasing": {
"!doc": "获得变速移动曲线",
"!type": "fn(mode?: string) -> fn(t: number) -> number"
},
"clamp": {
"!doc": "将x限定在[a,b]区间内注意a和b可交换<br/>例如core.clamp(1200, 1, 1000); // 1000<br/>x: 原始值,!x为true时x一律视为0<br/>a: 下限值大于b将导致与b交换<br/>b: 上限值小于a将导致与a交换",
"!type": "fn(x: number, a: number, b: number) -> number"
@ -3802,7 +3806,7 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [
},
"moveImage": {
"!doc": "移动一张图片并/或改变其透明度<br/>例如core.moveImage(1, null, 0.5); // 1秒内把1号图片变为50%透明<br/>code: 图片编号<br/>to: 新的左上角坐标,省略表示原地改变透明度<br/>opacityVal: 新的透明度,省略表示不变<br/>time: 移动用时单位为毫秒。不填视为1秒<br/>callback: 图片移动完毕后的回调函数,可选",
"!type": "fn(code: number, to?: [number], opacityVal?: number, time?: number, callback?: fn())"
"!type": "fn(code: number, to?: [number], opacityVal?: number, moveMode?: string, time?: number, callback?: fn())"
},
"openSettings": {
"!doc": "点击设置按钮时的操作",

View File

@ -2053,13 +2053,13 @@ return code;
*/;
setViewport_s
: '设置视角' '左上角坐标' 'x' PosString? ',' 'y' PosString? '动画时间' Int '不等待执行完毕' Bool Newline
: '设置视角' '左上角坐标' 'x' PosString? ',' 'y' PosString? '移动方式' MoveMode_List '动画时间' Int '不等待执行完毕' Bool Newline
/* setViewport_s
tooltip : setViewport: 设置视角
helpUrl : /_docs/#/instruction
default : ["","",0,false]
default : ["","","",0,false]
selectPoint : ["PosString_0", "PosString_1"]
colour : this.soundColor
var loc = '';
@ -2068,18 +2068,19 @@ if (PosString_0 && PosString_1) {
}
Int_0 = Int_0 ?(', "time": '+Int_0):'';
Bool_0 = Bool_0?', "async": true':'';
var code = '{"type": "setViewport"'+loc+Int_0+Bool_0+'},\n';
MoveMode_List_0 = (MoveMode_List_0!=='') ? (', "moveMode": "'+MoveMode_List_0+'"'):'';
var code = '{"type": "setViewport"'+loc+MoveMode_List_0+Int_0+Bool_0+'},\n';
return code;
*/;
setViewport_1_s
: '设置视角' '增量坐标' 'dx' PosString? ',' 'dy' PosString? '动画时间' Int '不等待执行完毕' Bool Newline
: '设置视角' '增量坐标' 'dx' PosString? ',' 'dy' PosString? '移动方式' MoveMode_List '动画时间' Int '不等待执行完毕' Bool Newline
/* setViewport_1_s
tooltip : setViewport: 设置视角
helpUrl : /_docs/#/instruction
default : ["0","0",0,false]
default : ["0","0","",0,false]
colour : this.soundColor
var loc = '';
if (PosString_0 && PosString_1) {
@ -2087,7 +2088,8 @@ if (PosString_0 && PosString_1) {
}
Int_0 = Int_0 ?(', "time": '+Int_0):'';
Bool_0 = Bool_0?', "async": true':'';
var code = '{"type": "setViewport"'+loc+Int_0+Bool_0+'},\n';
MoveMode_List_0 = (MoveMode_List_0!=='') ? (', "moveMode": "'+MoveMode_List_0+'"'):'';
var code = '{"type": "setViewport"'+loc+MoveMode_List_0+Int_0+Bool_0+'},\n';
return code;
*/;
@ -2182,19 +2184,20 @@ return code;
moveImage_s
: '图片移动' '图片编号' NInt '终点像素位置' 'x' PosString? 'y' PosString? BGNL?
'不透明度' EvalString? '移动时间' Int '不等待执行完毕' Bool Newline
'不透明度' EvalString? '移动方式' MoveMode_List '移动时间' Int '不等待执行完毕' Bool Newline
/* moveImage_s
tooltip : moveImage图片移动
helpUrl : /_docs/#/instruction
default : [1,'','','',500,false]
default : [1,'','','','',500,false]
var toloc = '';
if (PosString_0 && PosString_1)
toloc = ', "to": ['+PosString_0+','+PosString_1+']';
EvalString_0 = (EvalString_0!=='') ? (', "opacity": '+EvalString_0):'';
MoveMode_List_0 = (MoveMode_List_0!=='') ? (', "moveMode": "'+MoveMode_List_0+'"'):'';
var async = Bool_0?', "async": true':'';
var code = '{"type": "moveImage", "code": '+NInt_0+toloc+EvalString_0+',"time": '+Int_0+async+'},\n';
var code = '{"type": "moveImage", "code": '+NInt_0+toloc+MoveMode_List_0+EvalString_0+',"time": '+Int_0+async+'},\n';
return code;
*/;
@ -3962,6 +3965,10 @@ Move_List
: '上'|'下'|'左'|'右'|'前'|'后'|'左上'|'左下'|'右上'|'右下'|'设置速度'
/*Move_List ['up','down','left','right','forward','backward','leftup','leftdown','rightup','rightdown','speed']*/;
MoveMode_List
: '匀速移动'|'缓入快出'|'快入缓出'|'缓入缓出'
/*MoveMode_List ['', 'easeIn', 'easeOut', 'easeInOut']*/;
NameMap_List
: '确定'|'取消'|'操作失败'|'光标移动'|'打开界面'|'读档'|'存档'|'获得道具'|'回血'|'炸弹'|'飞行器'|'开关门'|'上下楼'|'跳跃'|'破墙镐'|'阻激夹域'|'穿脱装备'
/*NameMap_List ['确定','取消','操作失败','光标移动','打开界面','读档','存档','获得道具','回血','炸弹','飞行器','开关门','上下楼','跳跃','破墙镐','阻激夹域','穿脱装备']*/;

View File

@ -516,11 +516,11 @@ ActionParser.prototype.parseAction = function() {
case "setViewport": // 设置视角
if (data.dxy) {
this.next = MotaActionBlocks['setViewport_1_s'].xmlText([
data.dxy[0],data.dxy[1],data.time||0,data.async||false,this.next]);
data.dxy[0],data.dxy[1],data.moveMode||'', data.time||0,data.async||false,this.next]);
} else {
data.loc = data.loc||['',''];
this.next = MotaActionBlocks['setViewport_s'].xmlText([
data.loc[0],data.loc[1],data.time||0,data.async||false,this.next]);
data.loc[0],data.loc[1],data.moveMode||'', data.time||0,data.async||false,this.next]);
}
break;
case "vibrate": // 画面震动
@ -551,7 +551,7 @@ ActionParser.prototype.parseAction = function() {
case "moveImage": // 移动图片
data.to=data.to||['','']
this.next = MotaActionBlocks['moveImage_s'].xmlText([
data.code, data.to[0], data.to[1], data.opacity, data.time||0, data.async||false, this.next]);
data.code, data.to[0], data.to[1], data.opacity, data.moveMode||'', data.time||0, data.async||false, this.next]);
break;
case "showGif": // 显示动图
data.loc=data.loc||['','']

View File

@ -968,23 +968,25 @@ control.prototype.setViewport = function (px, py) {
}
////// 移动视野范围 //////
control.prototype.moveViewport = function (x, y, time, callback) {
control.prototype.moveViewport = function (x, y, moveMode, time, callback) {
time = time || 0;
time /= Math.max(core.status.replay.speed, 1)
var per_time = 10, step = parseInt(time / per_time);
if (step <= 0) {
var per_time = 10, step = 0, steps = parseInt(time / per_time);
if (steps <= 0) {
this.setViewport(32 * x, 32 * y);
if (callback) callback();
return;
}
}
var px = core.clamp(32 * x, 0, 32 * core.bigmap.width - core.__PIXELS__);
var py = core.clamp(32 * y, 0, 32 * core.bigmap.height - core.__PIXELS__);
var dx = (px - core.bigmap.offsetX) / step, dy = (py - core.bigmap.offsetY) / step;
var cx = core.bigmap.offsetX;
var cy = core.bigmap.offsetY;
var moveFunc = core.applyEasing(moveMode);
var animate=window.setInterval(function() {
core.setViewport(core.bigmap.offsetX + dx, core.bigmap.offsetY + dy);
step--;
if (step <= 0) {
step++;
core.setViewport(cx + moveFunc(step / steps) * (px - cx), cy + moveFunc(step / steps) * (py - cy));
if (step == steps) {
delete core.animateFrame.asyncId[animate];
clearInterval(animate);
core.setViewport(px, py);

View File

@ -1449,7 +1449,7 @@ events.prototype._action_setViewport = function (data, x, y, prefix) {
data.loc = this.__action_getLoc(data.loc, x, y, prefix);
}
console.log(data.loc);
this.__action_doAsyncFunc(data.async, core.moveViewport, data.loc[0], data.loc[1], data.time);
this.__action_doAsyncFunc(data.async, core.moveViewport, data.loc[0], data.loc[1], data.moveMode, data.time);
}
events.prototype._action_move = function (data, x, y, prefix) {
@ -1567,7 +1567,7 @@ events.prototype._action_showGif = function (data, x, y, prefix) {
events.prototype._action_moveImage = function (data, x, y, prefix) {
if (this.__action_checkReplaying()) return;
this.__action_doAsyncFunc(data.async, core.moveImage, data.code, data.to, data.opacity, data.time);
this.__action_doAsyncFunc(data.async, core.moveImage, data.code, data.to, data.opacity, data.moveMode, data.time);
}
events.prototype._precompile_moveImage = function (data) {
@ -2988,7 +2988,7 @@ events.prototype.showImage = function (code, image, sloc, loc, opacityVal, time,
return;
}
core.setOpacity(name, 0);
this.moveImage(code, null, opacityVal, time, callback);
this.moveImage(code, null, opacityVal, null, time, callback);
}
////// 隐藏图片 //////
@ -3000,14 +3000,14 @@ events.prototype.hideImage = function (code, time, callback) {
if (callback) callback();
return;
}
this.moveImage(code, null, 0, time, function () {
this.moveImage(code, null, 0, null, time, function () {
core.deleteCanvas(name);
if (callback) callback();
});
}
////// 移动图片 //////
events.prototype.moveImage = function (code, to, opacityVal, time, callback) {
events.prototype.moveImage = function (code, to, opacityVal, moveMode, time, callback) {
time = time || 1000;
to = to || [];
var name = "image" + (code + 100);
@ -3028,21 +3028,22 @@ events.prototype.moveImage = function (code, to, opacityVal, time, callback) {
this._moveImage_moving(name, {
fromX: fromX, fromY: fromY, toX: toX, toY: toY, opacity: opacity, toOpacity: toOpacity,
time: time / Math.max(core.status.replay.speed, 1)
moveMode: moveMode, time: time / Math.max(core.status.replay.speed, 1)
}, callback)
}
events.prototype._moveImage_moving = function (name, moveInfo, callback) {
var per_time = 10, step = 0, steps = parseInt(moveInfo.time / 10);
var per_time = 10, step = 0, steps = parseInt(moveInfo.time / per_time);
if (steps <= 0) steps = 1;
var fromX = moveInfo.fromX, fromY = moveInfo.fromY, toX = moveInfo.toX, toY = moveInfo.toY,
opacity = moveInfo.opacity, toOpacity = moveInfo.toOpacity;
var currX = fromX, currY = fromY, currOpacity = opacity;
var moveFunc = core.applyEasing(moveInfo.moveMode);
var animate = setInterval(function () {
step++;
currOpacity = opacity + (toOpacity - opacity) * step / steps;
currX = parseInt(fromX + (toX - fromX) * step / steps);
currY = parseInt(fromY + (toY - fromY) * step / steps);
currX = parseInt(fromX + (toX - fromX) * moveFunc(step / steps));
currY = parseInt(fromY + (toY - fromY) * moveFunc(step / steps));
core.setOpacity(name, currOpacity);
core.relocateCanvas(name, currX, currY);
if (step == steps) {

View File

@ -480,6 +480,27 @@ utils.prototype.formatBigNumber = function (x, onMap) {
return c + x;
}
////// 变速移动 //////
utils.prototype.applyEasing = function(name) {
var list = {
"easeIn": function(t) {
return Math.pow(t, 3);
},
"easeOut": function(t) {
return 1 - Math.pow(1 - t, 3);
},
"easeInOut": function(t) {
// easeInOut试了一下感觉二次方效果明显点
if (t < 0.5) return Math.pow(t, 2) * 2;
else return 1 - Math.pow(1 - t, 2) * 2;
},
"linear": function(t) {
return t
}
}
return list[name] || list.linear;
}
////// 数组转RGB //////
utils.prototype.arrayToRGB = function (color) {
if (!(color instanceof Array)) return color;

10
runtime.d.ts vendored
View File

@ -646,7 +646,7 @@ declare class control {
setViewport(px?: number, py?: number): void
/** 移动视野范围 */
moveViewport(x: number, y: number, time?: number, callback?: () => any): void
moveViewport(x: number, y: number, moveMode?: string, time?: number, callback?: () => any): void
/** 更新跟随者坐标 */
updateFollowers(): void
@ -976,14 +976,15 @@ declare class events {
/**
* /
* @example core.moveImage(1, undefined, 0.5); // 1秒内把1号图片变为50%透明
* @example core.moveImage(1, null, 0.5); // 1秒内把1号图片变为50%透明
* @param code
* @param to
* @param opacityVal
* @param moveMode
* @param time 1
* @param callback
*/
moveImage(code: number, to?: [number?, number?], opacityVal?: number, time?: number, callback?: () => void): void
moveImage(code: number, to?: [number?, number?], opacityVal?: number, moveMode?: string, time?: number, callback?: () => void): void
/**
*
@ -2381,6 +2382,9 @@ declare class utils {
*/
formatBigNumber(x: number, onMap?: boolean): string
/** 变速移动 */
applyEasing(mode?: string): (number) => number;
/**
*
* @example core.arrayToRGB([102, 204, 255]); // "#66ccff",加载画面的宣传色