diff --git a/_docs/api.md b/_docs/api.md
index ea875434..c5b644ba 100644
--- a/_docs/api.md
+++ b/_docs/api.md
@@ -1088,6 +1088,15 @@ resetGame: fn(hero?: ?, hard?: ?, floorId?: string, maps?: ?, values?: ?)
restart: fn()
重新开始游戏;此函数将回到标题页面
+rotateImage: fn(code: number, center?: [number], angle?: number, moveMode?: string, time?: number, callback?: fn())
+旋转一张图片
+code: 图片编号
+center: 旋转中心像素坐标(以屏幕为基准);不填视为图片本身中心
+angle: 旋转角度;正数为顺时针,负数为逆时针
+moveMode: 旋转模式
+time: 旋转用时,单位为毫秒。不填视为1秒
+callback: 图片旋转完毕后的回调函数,可选
+
save: fn(fromUserAction?: bool)
点击存档按钮时的打开操作
@@ -1952,6 +1961,10 @@ relocateCanvas: fn(name: string, x: number, y: number)
resizeCanvas: fn(name: string, x: number, y: number)
重新设置一个自定义画布的大小
+rotateCanvas: fn(name: string, angle: number, centerX?: number, centerY?: number)
+设置一个自定义画布的旋转角度
+centerX, centerY: 旋转中心(以屏幕像素为基准);不填视为图片正中心。
+
saveCanvas: fn(name: string|CanvasRenderingContext2D)
保存某个canvas状态
diff --git a/_server/CodeMirror/defs.js b/_server/CodeMirror/defs.js
index 308ea708..9cf5f9c3 100644
--- a/_server/CodeMirror/defs.js
+++ b/_server/CodeMirror/defs.js
@@ -3503,6 +3503,10 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [
"!doc": "重新定位一个自定义画布",
"!type": "fn(name: string, x: number, y: number)"
},
+ "rotateCanvas": {
+ "!doc": "设置一个自定义画布的旋转角度
centerX, centerY: 旋转中心(以屏幕像素为基准);不填视为图片正中心。",
+ "!type": "fn(name: string, angle: number, centerX?: number, centerY?: number)"
+ },
"closePanel": {
"!doc": "结束一切事件和绘制,关闭UI窗口,返回游戏进程",
"!type": "fn()"
@@ -3828,6 +3832,10 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [
"!doc": "移动一张图片并/或改变其透明度
例如:core.moveImage(1, null, 0.5); // 1秒内把1号图片变为50%透明
code: 图片编号
to: 新的左上角坐标,省略表示原地改变透明度
opacityVal: 新的透明度,省略表示不变
time: 移动用时,单位为毫秒。不填视为1秒
callback: 图片移动完毕后的回调函数,可选",
"!type": "fn(code: number, to?: [number], opacityVal?: number, moveMode?: string, time?: number, callback?: fn())"
},
+ "rotateImage": {
+ "!doc": "旋转一张图片
code: 图片编号
center: 旋转中心像素坐标(以屏幕为基准);不填视为图片本身中心
angle: 旋转角度;正数为顺时针,负数为逆时针
moveMode: 旋转模式
time: 旋转用时,单位为毫秒。不填视为1秒
callback: 图片旋转完毕后的回调函数,可选",
+ "!type": "fn(code: number, center?: [number], angle?: number, moveMode?: string, time?: number, callback?: fn())"
+ },
"openSettings": {
"!doc": "点击设置按钮时的操作",
"!type": "fn(fromUserAction?: bool)"
diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4
index 8d49f688..b99e8246 100644
--- a/_server/MotaAction.g4
+++ b/_server/MotaAction.g4
@@ -831,6 +831,7 @@ action
| hideImage_s
| showTextImage_s
| moveImage_s
+ | rotateImage_s
| showGif_s
| setCurtain_0_s
| setCurtain_1_s
@@ -2205,6 +2206,7 @@ tooltip : showImage:显示图片
helpUrl : /_docs/#/instruction
default : [1,"bg.jpg","null","0","0",1,0,false]
allImages : ['EvalString_0']
+menu : [['选择图片','editor_blockly.selectMaterial(block, ["./project/images/", "EvalString_0"])']]
previewBlock : true
if (Reverse_List_0 && Reverse_List_0 != 'null') {
Reverse_List_0 = ', "reverse": "' + Reverse_List_0 + '"';
@@ -2225,6 +2227,7 @@ tooltip : showImage_1:显示图片
helpUrl : /_docs/#/instruction
default : [1,"bg.jpg","null","0","0","","",1,"0","0","","",0,false]
allImages : ['EvalString_0']
+menu : [['选择图片','editor_blockly.selectMaterial(block, ["./project/images/", "EvalString_0"])']]
previewBlock : true
if (Reverse_List_0 && Reverse_List_0 != 'null') {
Reverse_List_0 = ', "reverse": "' + Reverse_List_0 + '"';
@@ -2299,7 +2302,24 @@ if (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+MoveMode_List_0+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;
+*/;
+
+rotateImage_s
+ : '图片旋转' '图片编号' NInt '中心点像素' 'x' PosString? 'y' PosString? '移动方式' MoveMode_List BGNL? '旋转度数(正数顺时针,负数逆时针)' NInt '旋转时间' Int '不等待执行完毕' Bool Newline
+
+
+/* rotateImage_s
+tooltip : rotateImage:图片旋转
+helpUrl : /_docs/#/instruction
+default : [1,'','','',90,500,false]
+var loc = '';
+if (PosString_0 && PosString_1)
+ loc = ', "center": ['+PosString_0+','+PosString_1+']';
+MoveMode_List_0 = (MoveMode_List_0!=='') ? (', "moveMode": "'+MoveMode_List_0+'"'):'';
+var async = Bool_0?', "async": true':'';
+var code = '{"type": "rotateImage", "code": '+NInt_0+loc+', "angle": '+NInt_1+MoveMode_List_0+', "time": '+Int_0+async+'},\n';
return code;
*/;
diff --git a/_server/MotaActionParser.js b/_server/MotaActionParser.js
index 17803178..2118755d 100644
--- a/_server/MotaActionParser.js
+++ b/_server/MotaActionParser.js
@@ -580,6 +580,11 @@ ActionParser.prototype.parseAction = function() {
this.next = MotaActionBlocks['moveImage_s'].xmlText([
data.code, data.to[0], data.to[1], data.opacity, data.moveMode||'', data.time||0, data.async||false, this.next]);
break;
+ case "rotateImage": // 旋转图片
+ data.center=data.center||['','']
+ this.next = MotaActionBlocks['rotateImage_s'].xmlText([
+ data.code, data.center[0], data.center[1], data.moveMode||'', data.angle||0, data.time||0, data.async||false, this.next]);
+ break;
case "showGif": // 显示动图
data.loc=data.loc||['','']
this.next = MotaActionBlocks['showGif_s'].xmlText([
diff --git a/_server/editor_blocklyconfig.js b/_server/editor_blocklyconfig.js
index 22f5a190..cba73bcf 100644
--- a/_server/editor_blocklyconfig.js
+++ b/_server/editor_blocklyconfig.js
@@ -105,6 +105,7 @@ editor_blocklyconfig=(function(){
MotaActionBlocks['hideImage_s'].xmlText(),
MotaActionBlocks['showTextImage_s'].xmlText(),
MotaActionBlocks['moveImage_s'].xmlText(),
+ MotaActionBlocks['rotateImage_s'].xmlText(),
MotaActionBlocks['showGif_s'].xmlText(),
MotaActionBlocks['tip_s'].xmlText(),
MotaActionBlocks['win_s'].xmlText(),
diff --git a/libs/events.js b/libs/events.js
index 260f1cbe..9f1a9be6 100644
--- a/libs/events.js
+++ b/libs/events.js
@@ -1615,6 +1615,16 @@ events.prototype._precompile_moveImage = function (data) {
return data;
}
+events.prototype._action_rotateImage = function (data, x, y, prefix) {
+ if (this.__action_checkReplaying()) return;
+ this.__action_doAsyncFunc(data.async, core.rotateImage, data.code, data.center, data.angle, data.moveMode, data.time);
+}
+
+events.prototype._precompile_rotateImage = function (data) {
+ data.center = this.__precompile_array(data.center);
+ return data;
+}
+
events.prototype._action_setCurtain = function (data, x, y, prefix) {
if (data.async) {
core.setCurtain(data.color, data.time);
@@ -3091,7 +3101,7 @@ events.prototype._moveImage_moving = function (name, moveInfo, callback) {
var moveFunc = core.applyEasing(moveInfo.moveMode);
var animate = setInterval(function () {
step++;
- currOpacity = opacity + (toOpacity - opacity) * step / steps;
+ currOpacity = opacity + (toOpacity - opacity) * moveFunc(step / steps);
currX = parseInt(fromX + (toX - fromX) * moveFunc(step / steps));
currY = parseInt(fromY + (toY - fromY) * moveFunc(step / steps));
core.setOpacity(name, currOpacity);
@@ -3106,6 +3116,44 @@ events.prototype._moveImage_moving = function (name, moveInfo, callback) {
core.animateFrame.asyncId[animate] = true;
}
+////// 旋转图片 //////
+events.prototype.rotateImage = function (code, center, angle, moveMode, time, callback) {
+ time = time || 1000;
+ center = center || [];
+ var name = "image" + (code + 100);
+ if (!core.dymCanvas[name]) {
+ if (callback) callback();
+ return;
+ }
+ var canvas = core.dymCanvas[name].canvas;
+ var centerX = core.calValue(center[0]), centerY = core.calValue(center[1]);
+
+ var fromAngle = parseFloat(canvas.getAttribute('_angle')) || 0;
+ var rotateInfo = {
+ fromAngle: fromAngle, angle: angle, centerX: centerX, centerY: centerY,
+ moveMode: moveMode, time: time / Math.max(core.status.replay.speed, 1)
+ }
+ this._rotateImage_rotating(name, rotateInfo, callback);
+}
+
+events.prototype._rotateImage_rotating = function (name, rotateInfo, callback) {
+ var per_time = 10, step = 0, steps = parseInt(rotateInfo.time / per_time);
+ if (steps <= 0) steps = 1;
+ var moveFunc = core.applyEasing(rotateInfo.moveMode);
+ var animate = setInterval(function () {
+ step++;
+ var currAngle = rotateInfo.fromAngle + rotateInfo.angle * moveFunc(step / steps);
+ core.rotateCanvas(name, currAngle, rotateInfo.centerX, rotateInfo.centerY);
+ if (step == steps) {
+ delete core.animateFrame.asyncId[animate];
+ clearInterval(animate);
+ if (callback) callback();
+ }
+ }, per_time);
+ core.animateFrame.asyncId[animate] = true;
+
+}
+
////// 绘制或取消一张gif图片 //////
events.prototype.showGif = function (name, x, y) {
name = core.getMappedName(name);
diff --git a/libs/ui.js b/libs/ui.js
index 69898eca..804342a1 100644
--- a/libs/ui.js
+++ b/libs/ui.js
@@ -3149,8 +3149,11 @@ ui.prototype._drawStatistics_items = function (floorId, floor, id, obj) {
if (obj.cls[id]=='items' && id!='superPotion') {
var temp = core.clone(core.status.hero);
core.setFlag("__statistics__", true);
+ var ratio = core.status.thisMap.ratio;
+ core.status.thisMap.ratio = core.clone(core.status.maps[floorId].ratio);
try { eval(core.material.items[id].itemEffect); }
catch (e) {}
+ core.status.thisMap.ratio = ratio;
hp = core.status.hero.hp - temp.hp;
atk = core.status.hero.atk - temp.atk;
def = core.status.hero.def - temp.def;
@@ -3299,6 +3302,27 @@ ui.prototype.relocateCanvas = function (name, x, y) {
return ctx;
}
+////// canvas旋转 //////
+ui.prototype.rotateCanvas = function (name, angle, centerX, centerY) {
+ var ctx = core.getContextByName(name);
+ if (!ctx) return null;
+ var canvas = ctx.canvas;
+ angle = angle || 0;
+ if (centerX == null || centerY == null) {
+ canvas.style.transformOrigin = '';
+ } else {
+ var left = parseFloat(canvas.getAttribute("_left"));
+ var top = parseFloat(canvas.getAttribute("_top"));
+ canvas.style.transformOrigin = (centerX - left) * core.domStyle.scale + 'px ' + (centerY - top) * core.domStyle.scale + 'px';
+ }
+ if (angle == 0) {
+ canvas.style.transform = '';
+ } else {
+ canvas.style.transform = 'rotate(' + angle +'deg)';
+ }
+ canvas.setAttribute('_angle', angle);
+}
+
////// canvas重置 //////
ui.prototype.resizeCanvas = function (name, width, height, styleOnly) {
var ctx = core.getContextByName(name);
diff --git a/runtime.d.ts b/runtime.d.ts
index 23405a5d..caf1e344 100644
--- a/runtime.d.ts
+++ b/runtime.d.ts
@@ -985,7 +985,18 @@ declare class events {
* @param callback 图片移动完毕后的回调函数,可选
*/
moveImage(code: number, to?: [number?, number?], opacityVal?: number, moveMode?: string, time?: number, callback?: () => void): void
-
+
+ /**
+ * 旋转一张图片
+ * @param code 图片编号
+ * @param center 旋转中心像素(以屏幕为基准);不填视为图片本身中心
+ * @param angle 旋转角度;正数为顺时针,负数为逆时针
+ * @param moveMode 旋转模式
+ * @param time 移动用时,单位为毫秒。不填视为1秒
+ * @param callback 图片移动完毕后的回调函数,可选
+ */
+ rotateImage(code: number, center?: [number?, number?], angle: number, moveMode?: string, time?: number, callback?: () => void): void
+
/**
* 绘制一张动图或擦除所有动图
* @example core.showGif(); // 擦除所有动图
@@ -2110,6 +2121,9 @@ declare class ui {
/** 重新设置一个自定义画布的大小 */
resizeCanvas(name: string, x: number, y: number): void
+ /** 设置一个自定义画布的旋转角度 */
+ rotateCanvas(name: string, angle: number, centerX?: number, centerY?: number): void
+
/** 删除一个自定义画布 */
deleteCanvas(name: string): void