diff --git a/_docs/api.md b/_docs/api.md index b003bf23..af535cda 100644 --- a/_docs/api.md +++ b/_docs/api.md @@ -1126,6 +1126,9 @@ callback: 图片旋转完毕后的回调函数,可选 save: fn(fromUserAction?: bool) 点击存档按钮时的打开操作 +scaleImage: fn(code: number, center?: [number], scale?: number, moveMode?: string, time?: number, callback?: fn()) +放缩一张图片 + setEnemy: fn(id: string, name: string, value: ?, operator?: string, prefix?: string) 设置一项敌人属性并计入存档 例如:core.setEnemy('greenSlime', 'def', 0); // 把绿头怪的防御设为0 diff --git a/_docs/instruction.md b/_docs/instruction.md index f0464956..28a28d80 100644 --- a/_docs/instruction.md +++ b/_docs/instruction.md @@ -159,6 +159,9 @@ V2.8.1起,下拉框中没有的项都可以通过在json区输入并点击“ * time同样不能填0,如果想瞬间得到旋转后的结果,请填1 * 比起移动,旋转本身不支持同时透明度渐变,您可以先写一个不指定终点的移动指令且“不等待执行完毕”来实现单纯的淡入淡出,然后再写一个耗时相同或略长的旋转指令,这样两个指令就会一起执行了。 * 当不指定旋转中心时,本指令可以和移动指令同时使用,从而得到“图片的中心做直线运动、同时图片还在绕着中心自转”的效果。 +5. **图片放缩:**V2.8.1新增,同样支持加速度,放缩中心坐标不填则取图片中心。 + * 此指令对应`core.scaleImage(code, center, scale, moveMode, time, callback)`函数 + * time可以为0,代表立刻进行放缩 5. **显示或清除动图:**需要填写动图的文件名(带.gif后缀),“起点像素位置”含义如前且必须填写,可以双击指令块来预览第一帧的效果。 * 动图不支持淡入淡出和伸缩移动,如果不填任何参数则清除所有动图(只支持全部清除)。 * 该指令对应`core.showGif(name, x, y)`函数。 diff --git a/_server/CodeMirror/defs.js b/_server/CodeMirror/defs.js index 848e3c26..236dc58b 100644 --- a/_server/CodeMirror/defs.js +++ b/_server/CodeMirror/defs.js @@ -3860,6 +3860,10 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "!doc": "旋转一张图片
code: 图片编号
center: 旋转中心像素坐标(以屏幕为基准);不填视为图片本身中心
angle: 旋转角度;正数为顺时针,负数为逆时针
moveMode: 旋转模式
time: 旋转用时,单位为毫秒。不填视为1秒
callback: 图片旋转完毕后的回调函数,可选", "!type": "fn(code: number, center?: [number], angle?: number, moveMode?: string, time?: number, callback?: fn())" }, + "scaleImage": { + "!doc": "放缩一张图片", + "!type": "fn(code: number, center?: [number], scale?: number, moveMode?: string, time?: number, callback?: fn())" + }, "moveTextBox": { "!doc": "移动对话框", "!type": "fn(code: number, loc: [number], relative?: bool, moveMode?: string, time?: number, callback?: fn())" diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index 30afdf0b..c9b4bbd6 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -838,6 +838,7 @@ action | showTextImage_s | moveImage_s | rotateImage_s + | scaleImage_s | showGif_s | setCurtain_0_s | setCurtain_1_s @@ -2217,6 +2218,24 @@ var code = '{"type": "rotateImage", "code": '+NInt_0+loc+', "angle": '+NInt_1+Mo return code; */; +scaleImage_s + : '图片放缩' '图片编号' NInt '中心点像素' 'x' PosString? 'y' PosString? '移动方式' MoveMode_List BGNL? '放缩比例' Number '动画时间' Int '不等待执行完毕' Bool Newline + + +/* scaleImage_s +tooltip : scaleImage:图片放缩 +helpUrl : /_docs/#/instruction +default : [1,'','','',0.8,0,false] +if (Number_0 <= 0) throw new Error('放缩比例需要大于0'); +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": "scaleImage", "code": '+NInt_0+loc+', "scale": '+Number_0+MoveMode_List_0+', "time": '+Int_0+async+'},\n'; +return code; +*/; + setCurtain_0_s : '更改画面色调' ColorString Colour '动画时间' IntString? BGNL? Newline '渐变方式' MoveMode_List '持续到下一个本事件' Bool '不等待执行完毕' Bool Newline diff --git a/_server/MotaActionParser.js b/_server/MotaActionParser.js index 8b63b287..c990026c 100644 --- a/_server/MotaActionParser.js +++ b/_server/MotaActionParser.js @@ -596,6 +596,11 @@ ActionParser.prototype.parseAction = function() { 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 "scaleImage": // 放缩图片 + data.center=data.center||['',''] + this.next = MotaActionBlocks['scaleImage_s'].xmlText([ + data.code, data.center[0], data.center[1], data.moveMode||'', data.scale, 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 718bbbef..9b51fceb 100644 --- a/_server/editor_blocklyconfig.js +++ b/_server/editor_blocklyconfig.js @@ -102,23 +102,24 @@ editor_blocklyconfig=(function(){ MotaActionBlocks['autoText_s'].xmlText(), MotaActionBlocks['scrollText_s'].xmlText(), MotaActionBlocks['setText_s'].xmlText(), - MotaActionBlocks['showImage_s'].xmlText(), - MotaActionBlocks['showImage_1_s'].xmlText(), - 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(), - MotaActionBlocks['lose_s'].xmlText(), - MotaActionBlocks['restart_s'].xmlText(), MotaActionBlocks['confirm_s'].xmlText(), MotaActionBlocks['choices_s'].xmlText([ '选择剑或者盾','流浪者','man',0,0,'',MotaActionBlocks['choicesContext'].xmlText([ '剑','','',null,'','',MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]), ]) ]), + MotaActionBlocks['win_s'].xmlText(), + MotaActionBlocks['lose_s'].xmlText(), + MotaActionBlocks['restart_s'].xmlText(), + MotaActionBlocks['showImage_s'].xmlText(), + MotaActionBlocks['showImage_1_s'].xmlText(), + MotaActionBlocks['hideImage_s'].xmlText(), + MotaActionBlocks['showTextImage_s'].xmlText(), + MotaActionBlocks['moveImage_s'].xmlText(), + MotaActionBlocks['rotateImage_s'].xmlText(), + MotaActionBlocks['scaleImage_s'].xmlText(), + MotaActionBlocks['showGif_s'].xmlText(), ], '数据相关':[ MotaActionBlocks['setValue_s'].xmlText([ diff --git a/libs/events.js b/libs/events.js index 2f978f6b..0d59d42a 100644 --- a/libs/events.js +++ b/libs/events.js @@ -1660,6 +1660,16 @@ events.prototype._precompile_rotateImage = function (data) { return data; } +events.prototype._action_scaleImage = function (data, x, y, prefix) { + if (this.__action_checkReplaying()) return; + this.__action_doAsyncFunc(data.async, core.scaleImage, data.code, data.center, data.scale, data.moveMode, data.time); +} + +events.prototype._precompile_scaleImage = 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, data.moveMode); @@ -3330,6 +3340,65 @@ events.prototype._rotateImage_rotating = function (name, rotateInfo, callback) { } +////// 放缩一张图片 ////// +events.prototype.scaleImage = function (code, center, scale, moveMode, time, callback) { + center = center || []; + var name = "image" + (code + 100); + if (!core.dymCanvas[name]) { + if (callback) callback(); + return; + } + var ctx = core.dymCanvas[name]; + var currScale = 1.0; + if (ctx.canvas.hasAttribute('_scale')) { + currScale = parseFloat(ctx.canvas.getAttribute('_scale')); + } + var ratio = ctx.canvas.hasAttribute('isHD') ? core.domStyle.ratio : 1; + var width = ctx.canvas.width / ratio, height = ctx.canvas.height / ratio; + var currLeft = parseFloat(ctx.canvas.getAttribute("_left")); + var currTop = parseFloat(ctx.canvas.getAttribute("_top")); + var centerX = core.calValue(center[0]), centerY = core.calValue(center[1]); + if (centerX == null || centerY == null) { + centerX = currLeft + width * currScale / 2; + centerY = currTop + height * currScale / 2; + } + var scaleInfo = { + x: (currLeft - centerX) / currScale, y: (currTop - centerY) / currScale, centerX: centerX, centerY: centerY, + width: width, height: height, currScale: currScale, scale: scale, moveMode: moveMode, time: time + } + this._scaleImage_scale(ctx, scaleInfo, callback); +} + +events.prototype._scaleInfo_scale = function (ctx, scaleInfo, scale) { + core.resizeCanvas(ctx, scaleInfo.width * scale, scaleInfo.height * scale, true); + core.relocateCanvas(ctx, scaleInfo.centerX + scaleInfo.x * scale, scaleInfo.centerY + scaleInfo.y * scale); + ctx.canvas.setAttribute('_scale', scale); +} + +events.prototype._scaleImage_scale = function (ctx, scaleInfo, callback) { + if (!scaleInfo.time) { + this._scaleInfo_scale(ctx, scaleInfo, scaleInfo.scale); + if (callback) callback(); + return; + } + + var per_time = 10, step = 0, steps = parseInt(scaleInfo.time / per_time); + if (steps <= 0) steps = 1; + var moveFunc = core.applyEasing(scaleInfo.moveMode); + + var animate = setInterval(function () { + step++; + var scale = scaleInfo.currScale + (scaleInfo.scale - scaleInfo.currScale) * moveFunc(step / steps); + core.events._scaleInfo_scale(ctx, scaleInfo, scale); + 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/runtime.d.ts b/runtime.d.ts index 3da4eea2..372574eb 100644 --- a/runtime.d.ts +++ b/runtime.d.ts @@ -1009,6 +1009,9 @@ declare class events { */ rotateImage(code: number, center?: [number?, number?], angle: number, moveMode?: string, time?: number, callback?: () => void): void + /** 放缩一张图片 */ + scaleImage(code: number, center?: [Number?, number?], scale: number, moveMode?: string, time?: number, callback?: () => void): void + /** * 绘制一张动图或擦除所有动图 * @example core.showGif(); // 擦除所有动图