From 9813dc3115f49c87e89aa1794bdcc3efdfd1764e Mon Sep 17 00:00:00 2001 From: oc Date: Mon, 25 Mar 2019 00:29:18 +0800 Subject: [PATCH] lineHeight, showImage, splitImage --- _docs/event.md | 17 ++++++---- _server/MotaAction.g4 | 70 +++++++++++++++++++++++++++++---------- _server/editor_blockly.js | 1 + libs/events.js | 27 +++++++++------ libs/loader.js | 2 +- libs/ui.js | 19 ++++++----- libs/utils.js | 26 +++++++++------ 7 files changed, 108 insertions(+), 54 deletions(-) diff --git a/_docs/event.md b/_docs/event.md index 73961975..3beb965a 100644 --- a/_docs/event.md +++ b/_docs/event.md @@ -338,7 +338,7 @@ time为可选项,代表该自动文本的时间。可以不指定,不指定 ``` js "x,y": [ // 实际执行的事件列表 - {"type": "scrollText", "text": "第一排\n第二牌\n\n空行后的一排", "time": 5000, "async": true}, + {"type": "scrollText", "text": "第一排\n第二牌\n\n空行后的一排", "time": 5000, "lineHeight": 1.4, "async": true}, ] ``` @@ -346,6 +346,8 @@ text为正文文本内容。可以使用`${ }`来计算表达式的值,且使 time为可选项,代表总的滚动时间。默认为5000毫秒。 +lineHeight为可选项,代表行距。默认为1.4。 + async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 可以使用下面的[设置剧情文本的属性](event#setText:设置剧情文本的属性)来对文字颜色、文字大小、粗体、距离左边的偏移量进行设置。 @@ -1059,9 +1061,10 @@ loc可忽略,如果忽略则显示为事件当前点。 ``` js "x,y": [ // 实际执行的事件列表 - {"type": "showImage", "code": 1, "image": "bg.jpg", "loc": [231,297], "dw": 100, "dy" : 100, "opacity": 1, "time" : 0}, // 在(231,297)显示bg.jpg - {"type": "showImage", "code": 12, "image": "1.png", "loc": [209,267], "dw": 100, "dy" : 100, "opacity": 0.5, "time" : 1000}, // 在(209,267)渐变显示1.png,渐变时间为1000毫秒,完成时不透明度为0.5,这张图片将遮盖上一张 - {"type": "showImage", "code": 8, "image": "hero.png", "loc": [349,367], "dw": 50, "dy" : 50, "opacity": 1, "time" : 500, "async": true}, // 在(209,267)渐变显示hero.png,大小为原图片的一半,渐变时间为500毫秒,异步执行;这张图片将被上一张遮盖 + {"type": "showImage", "code": 1, "image": "bg.jpg", "loc": [231,297], "opacity": 1, "time" : 0}, // 在(231,297)显示bg.jpg + {"type": "showImage", "code": 12, "image": "1.png", "loc": [209,267], "opacity": 0.5, "time" : 1000}, // 在(209,267)渐变显示1.png,渐变时间为1000毫秒,完成时不透明度为0.5,这张图片将遮盖上一张 + {"type": "showImage", "code": 8, "image": "hero.png", "loc": [349,367], "opacity": 1, "time" : 500, "async": true}, // 在(209,267)渐变显示hero.png,渐变时间为500毫秒,异步执行;这张图片将被上一张遮盖 + {"type": "showImage", "code": 10, "image": "hero.png", "sloc": [100,100,100,100], "loc": [0,0,100,100], "opacity": 1, "time": 0} // 截取原图的一部分绘制到画布上的一部分。 ] ``` @@ -1069,9 +1072,9 @@ code为图片编号,如果两张图片重叠,编号较大会覆盖编号较 image为图片名。**请确保图片在全塔属性中的images中被定义过。** -loc为图片左上角坐标,以像素为单位进行计算。 +sloc为可选项;如果设置了则是个2或4元组,代表裁剪原始图片的左上角像素位置和宽高。 -dw和dh为图片的横向、纵向放大率,默认值为100,即不进行缩放。 +loc为2或4元组,代表要绘制的画布上的左上角像素位置和宽高。 opacity为图片不透明度,在0~1之间,默认值为1,即不透明。 @@ -1097,6 +1100,8 @@ loc为图片左上角坐标,以像素为单位进行计算。 opacity为图片不透明度,在0~1之间,默认值为1,即不透明。 +lineHeight为可选项,代表行距。默认为1.4。 + time为渐变时间,默认值为0,即不渐变直接显示。 async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index 6cf3b5d3..1aa58715 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -268,6 +268,7 @@ action | animate_s | vibrate_s | showImage_s + | showImage_1_s | hideImage_s | showTextImage_s | moveImage_s @@ -380,27 +381,28 @@ return code; */; scrollText_s - : '滚动剧情文本:' '时间' Int '不等待执行完毕' Bool? BGNL? EvalString Newline + : '滚动剧情文本:' '时间' Int '行距' Number '不等待执行完毕' Bool? BGNL? EvalString Newline /* scrollText_s tooltip : scrollText:滚动剧情文本,将从下到上进行滚动显示。 helpUrl : https://h5mota.com/games/template/docs/#/event?id=scrollText%ef%bc%9a%e6%bb%9a%e5%8a%a8%e5%89%a7%e6%83%85%e6%96%87%e6%9c%ac -default : [5000,false,"时间是总时间,可以使用setText事件来控制字体、颜色、大小、偏移量等"] +default : [5000,1.4,false,"时间是总时间,可以使用setText事件来控制字体、颜色、大小、偏移量等"] Bool_0 = Bool_0?', "async": true':''; -var code = '{"type": "scrollText", "text": "'+EvalString_0+'"'+Bool_0+', "time" :'+Int_0+'},\n'; +var code = '{"type": "scrollText", "text": "'+EvalString_0+'"'+Bool_0+', "time" :'+Int_0+', "lineHeight": '+Number_0+'},\n'; return code; */; setText_s - : '设置剧情文本的属性' '位置' SetTextPosition_List '偏移像素' EvalString? BGNL? '标题颜色' EvalString? Colour '正文颜色' EvalString? Colour '背景色' EvalString? Colour BGNL? '粗体' B_1_List '标题字体大小' EvalString? '正文字体大小' EvalString? '打字间隔' EvalString? Newline + : '设置剧情文本的属性' '位置' SetTextPosition_List '偏移像素' EvalString? '对齐' SetTextAlign_List? BGNL? '标题颜色' EvalString? Colour '正文颜色' EvalString? Colour '背景色' EvalString? Colour BGNL? '粗体' B_1_List '标题字体大小' EvalString? '正文字体大小' EvalString? '打字间隔' EvalString? Newline /* setText_s tooltip : setText:设置剧情文本的属性,颜色为RGB三元组或RGBA四元组,打字间隔为剧情文字添加的时间间隔,为整数或不填 helpUrl : https://h5mota.com/games/template/docs/#/event?id=settext%EF%BC%9A%E8%AE%BE%E7%BD%AE%E5%89%A7%E6%83%85%E6%96%87%E6%9C%AC%E7%9A%84%E5%B1%9E%E6%80%A7 -default : [null,"","",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',null,"","",""] +default : [null,"",null,"",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',null,"","",""] SetTextPosition_List_0 =SetTextPosition_List_0==='null'?'': ', "position": "'+SetTextPosition_List_0+'"'; +SetTextAlign_List_0 =SetTextAlign_List_0==='null'?'': ', "align": "'+SetTextAlign_List_0+'"'; var colorRe = /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(,0(\.\d+)?|,1)?$/; if (EvalString_0) { if (!/^\d+$/.test(EvalString_0))throw new Error('像素偏移量必须是整数或不填'); @@ -438,7 +440,7 @@ if (EvalString_6) { EvalString_6 = ', "time": '+EvalString_6; } B_1_List_0 = B_1_List_0==='null'?'':', "bold": '+B_1_List_0; -var code = '{"type": "setText"'+SetTextPosition_List_0+EvalString_0+EvalString_1+EvalString_2+B_1_List_0+EvalString_3+EvalString_4+EvalString_5+EvalString_6+'},\n'; +var code = '{"type": "setText"'+SetTextPosition_List_0+EvalString_0+SetTextAlign_List_0+EvalString_1+EvalString_2+B_1_List_0+EvalString_3+EvalString_4+EvalString_5+EvalString_6+'},\n'; return code; */; @@ -1132,34 +1134,54 @@ return code; */; showImage_s - : '显示图片' '图片编号' Int '图片' EvalString '起点像素位置' 'x' PosString 'y' PosString BGNL? - '放大率 : x' Int '% y' Int '% 不透明度' Number '时间' Int '不等待执行完毕' Bool Newline + : '显示图片' '图片编号' Int '图片' EvalString BGNL? + '绘制的起点像素' 'x' PosString 'y' PosString '不透明度' Number '时间' Int '不等待执行完毕' Bool Newline /* showImage_s tooltip : showImage:显示图片 helpUrl : https://h5mota.com/games/template/docs/#/event?id=showImage%ef%bc%9a%e6%98%be%e7%a4%ba%e5%9b%be%e7%89%87 -default : [1,"bg.jpg","0","0",100,100,1,0,false] +default : [1,"bg.jpg","0","0",1,0,false] colour : this.printColor if(Int_0<=0 || Int_0>50) throw new Error('图片编号在1~50之间'); var async = Bool_0?', "async": true':''; -var code = '{"type": "showImage", "code": '+Int_0+', "image": "'+EvalString_0+'", "loc": ['+PosString_0+','+PosString_1+'], "dw": '+Int_1+', "dh": '+Int_2+', "opacity": '+Number_0+', "time": '+Int_3+async+'},\n'; +var code = '{"type": "showImage", "code": '+Int_0+', "image": "'+EvalString_0+'", "loc": ['+PosString_0+','+PosString_1+'], "opacity": '+Number_0+', "time": '+Int_1+async+'},\n'; +return code; +*/; + +showImage_1_s + : '显示图片' '图片编号' Int '图片' EvalString BGNL? + '裁剪的起点像素' 'x' PosString 'y' PosString '宽' PosString? '高' PosString? '不透明度' Number BGNL? + '绘制的起点像素' 'x' PosString 'y' PosString '宽' PosString? '高' PosString? '时间' Int '不等待执行完毕' Bool Newline + + +/* showImage_1_s +tooltip : showImage_1:显示图片 +helpUrl : https://h5mota.com/games/template/docs/#/event?id=showImage%ef%bc%9a%e6%98%be%e7%a4%ba%e5%9b%be%e7%89%87 +default : [1,"bg.jpg","0","0","","",1,"0","0","","",0,false] +colour : this.printColor +if(Int_0<=0 || Int_0>50) throw new Error('图片编号在1~50之间'); +var async = Bool_0?', "async": true':''; +var code = '{"type": "showImage", "code": '+Int_0+', "image": "'+EvalString_0+'", '+ + '"sloc": ['+PosString_0+','+PosString_1+','+PosString_2+','+PosString_3+'], '+ + '"loc": ['+PosString_4+','+PosString_5+','+PosString_6+','+PosString_7+'], '+ + '"opacity": '+Number_0+', "time": '+Int_1+async+'},\n'; return code; */; showTextImage_s : '显示图片化文本' '文本内容' EvalString BGNL? - '图片编号' Int '起点像素位置' 'x' PosString 'y' PosString '不透明度' Number '时间' Int '不等待执行完毕' Bool Newline + '图片编号' Int '起点像素' 'x' PosString 'y' PosString '行距' Number '不透明度' Number '时间' Int '不等待执行完毕' Bool Newline /* showTextImage_s tooltip : showTextImage:显示图片化文本 helpUrl : https://h5mota.com/games/template/docs/#/event?id=showTextImage%ef%bc%9a%e6%98%be%e7%a4%ba%e6%96%87%e6%9c%ac%e5%8c%96%e5%9b%be%e7%89%87 colour : this.printColor -default : ["可以使用setText事件来控制字体、颜色、大小、偏移量等",1,"0","0",1,0,false] +default : ["可以使用setText事件来控制字体、颜色、大小、偏移量等",1,"0","0",1.4,1,0,false] if(Int_0<=0 || Int_0>50) throw new Error('图片编号在1~50之间'); var async = Bool_0?', "async": true':''; -var code = '{"type": "showTextImage", "code": '+Int_0+', "text": "'+EvalString_0+'", "loc": ['+PosString_0+','+PosString_1+'], "opacity": '+Number_0+', "time": '+Int_1+async+'},\n'; +var code = '{"type": "showTextImage", "code": '+Int_0+', "text": "'+EvalString_0+'", "loc": ['+PosString_0+','+PosString_1+'], "lineHeight": '+Number_0+', "opacity": '+Number_1+', "time": '+Int_1+async+'},\n'; return code; */; @@ -1872,6 +1894,10 @@ SetTextPosition_List : '不改变'|'距离顶部'|'居中'|'距离底部' /*SetTextPosition_List ['null','up','center','down']*/; +SetTextAlign_List + : '不改变'|'左对齐'|'左右居中'|'右对齐' + /*SetTextAlign_List ['null','left','center','right']*/; + ShopUse_List : '金币' | '经验' /*ShopUse_List ['money','experience']*/; @@ -2151,7 +2177,7 @@ ActionParser.prototype.parseAction = function() { break; case "scrollText": this.next = MotaActionBlocks['scrollText_s'].xmlText([ - data.time, data.async||false, this.EvalString(data.text), this.next]); + data.time, data.lineHeight||1.4, data.async||false, this.EvalString(data.text), this.next]); break; case "comment": // 注释 this.next = MotaActionBlocks['comment_s'].xmlText([this.EvalString(data.text),this.next],null,data.text); @@ -2163,7 +2189,7 @@ ActionParser.prototype.parseAction = function() { if (!/^\w+\.png$/.test(data.background)) data.background=setTextfunc(data.background); this.next = MotaActionBlocks['setText_s'].xmlText([ - data.position,data.offset,data.title,'rgba('+data.title+')', + data.position,data.offset,data.align,data.title,'rgba('+data.title+')', data.text,'rgba('+data.text+')',data.background,'rgba('+data.background+')', data.bold,data.titlefont,data.textfont,data.time,this.next]); break; @@ -2308,8 +2334,16 @@ ActionParser.prototype.parseAction = function() { break; case "showImage": // 显示图片 data.loc=data.loc||['',''] - this.next = MotaActionBlocks['showImage_s'].xmlText([ - data.code,data.image||data.name,data.loc[0],data.loc[1],data.dw,data.dh,data.opacity,data.time||0,data.async||false,this.next]); + if (data.sloc) { + this.next = MotaActionBlocks['showImage_1_s'].xmlText([ + data.code,data.image||data.name,data.sloc[0],data.sloc[1],data.sloc[2],data.sloc[3],data.opacity, + data.loc[0],data.loc[1],data.loc[2],data.loc[3],data.time||0,data.async||false,this.next + ]); + } + else { + this.next = MotaActionBlocks['showImage_s'].xmlText([ + data.code,data.image||data.name,data.loc[0],data.loc[1],data.opacity,data.time||0,data.async||false,this.next]); + } break; case "hideImage": // 清除图片 this.next = MotaActionBlocks['hideImage_s'].xmlText([ @@ -2318,7 +2352,7 @@ ActionParser.prototype.parseAction = function() { case "showTextImage": // 显示图片化文本 data.loc=data.loc||['',''] this.next = MotaActionBlocks['showTextImage_s'].xmlText([ - this.EvalString(data.text),data.code,data.loc[0],data.loc[1],data.opacity,data.time||0,data.async||false,this.next]); + this.EvalString(data.text),data.code,data.loc[0],data.loc[1],data.lineHeight||1.4,data.opacity,data.time||0,data.async||false,this.next]); break; case "moveImage": // 移动图片 data.to=data.to||['',''] diff --git a/_server/editor_blockly.js b/_server/editor_blockly.js index 7fdf310f..9ebabaac 100644 --- a/_server/editor_blockly.js +++ b/_server/editor_blockly.js @@ -54,6 +54,7 @@ editor_blockly = function () { 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(), diff --git a/libs/events.js b/libs/events.js index 5aa7f0a4..e15598e3 100644 --- a/libs/events.js +++ b/libs/events.js @@ -885,7 +885,7 @@ events.prototype._action_autoText = function (data, x, y, prefix) { events.prototype._action_scrollText = function (data, x, y, prefix) { if (this.__action_checkReplaying()) return; - this.__action_doAsyncFunc(data.async, core.ui.drawScrollText, data.text, data.time || 5000); + this.__action_doAsyncFunc(data.async, core.ui.drawScrollText, data.text, data.lineHeight || 1.4, data.time || 5000); } events.prototype._action_comment = function (data, x, y, prefix) { @@ -893,7 +893,7 @@ events.prototype._action_comment = function (data, x, y, prefix) { } events.prototype._action_setText = function (data, x, y, prefix) { - ["position", "offset", "bold", "titlefont", "textfont", "time"].forEach(function (t) { + ["position", "offset", "align", "bold", "titlefont", "textfont", "time"].forEach(function (t) { if (data[t] != null) core.status.textAttribute[t] = data[t]; }); ["background", "title", "text"].forEach(function (t) { @@ -1030,10 +1030,9 @@ events.prototype._action_changePos = function (data, x, y, prefix) { } events.prototype._action_showImage = function (data, x, y, prefix) { - var loc = this.__action_getLoc(data.loc, 0, 0, prefix); if (core.isReplaying()) data.time = 0; this.__action_doAsyncFunc(data.async || data.time == 0, this.showImage, - data.code, data.image, loc[0], loc[1], data.dw, data.dh, data.opacity, data.time); + data.code, data.image, data.sloc, data.loc, data.opacity, data.time); } events.prototype._action_showTextImage = function (data, x, y, prefix) { @@ -1815,21 +1814,27 @@ events.prototype.closeDoor = function (x, y, id, callback) { } ////// 显示图片 ////// -events.prototype.showImage = function (code, image, x, y, dw, dh, opacityVal, time, callback) { - dw /= 100; - dh /= 100; - x = core.calValue(x) || 0; - y = core.calValue(y) || 0; +events.prototype.showImage = function (code, image, sloc, loc, opacityVal, time, callback) { if (typeof image == 'string') image = core.material.images.images[image]; if (!image) { if (callback) callback(); return; } + sloc = sloc || []; + var sx = core.calValue(sloc[0]) || 0, sy = core.calValue(sloc[1]) || 0; + var sw = core.calValue(sloc[2]), sh = core.calValue(sloc[3]); + if (sw == null) sw = image.width; + if (sh == null) sh = image.height; + loc = loc || []; + var x = core.calValue(loc[0]) || 0, y = core.calValue(loc[1]) || 0; + var w = core.calValue(loc[2]), h = core.calValue(loc[3]); + if (w == null) w = sw; + if (h == null) h = sh; var zIndex = code + 100; time = time || 0; var name = "image" + zIndex; - var ctx = core.createCanvas(name, x, y, image.width * dw, image.height * dh, zIndex); - ctx.drawImage(image, 0, 0, image.width * dw, image.height * dh); + var ctx = core.createCanvas(name, x, y, w, h, zIndex); + ctx.drawImage(image, sx, sy, sw, sh, 0, 0, w, h); if (time == 0) { core.setOpacity(name, opacityVal); if (callback) callback(); diff --git a/libs/loader.js b/libs/loader.js index 5613c33d..b2da0c6e 100644 --- a/libs/loader.js +++ b/libs/loader.js @@ -38,7 +38,7 @@ loader.prototype._load = function (callback) { loader.prototype._loadIcons = function () { this.loadImage("icons.png", function (id, image) { - var images = core.cropImage(image); + var images = core.splitImage(image); for (var key in core.statusBar.icons) { if (typeof core.statusBar.icons[key] == 'number') { core.statusBar.icons[key] = images[core.statusBar.icons[key]]; diff --git a/libs/ui.js b/libs/ui.js index 72adee7c..73ce42f8 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -873,29 +873,31 @@ ui.prototype._createTextCanvas = function (content, lineHeight) { ctx.canvas.width = width; ctx.canvas.height = height; ctx.clearRect(0, 0, width, height); + return ctx; } ////// 绘制滚动字幕 ////// -ui.prototype.drawScrollText = function (content, time, callback) { +ui.prototype.drawScrollText = function (content, time, lineHeight, callback) { content = core.replaceText(content || ""); + lineHeight = lineHeight || 1.4; time = time || 5000; clearInterval(core.status.event.interval); core.status.event.interval = null; var offset = core.status.textAttribute.offset || 15; - var lineHeight = core.status.textAttribute.textfont * 1.4; + lineHeight *= core.status.textAttribute.textfont; var ctx = this._createTextCanvas(content, lineHeight); var obj = { align: core.status.textAttribute.align, lineHeight: lineHeight }; if (obj.align == 'right') obj.left = this.PIXEL - offset; else if (obj.align != 'center') obj.left = offset; this.drawTextContent(ctx, content, obj); - this._drawScrollText_animate(ctx, height, time, callback); + this._drawScrollText_animate(ctx, time, callback); } -ui.prototype._drawScrollText_animate = function (ctx, height, time, callback) { +ui.prototype._drawScrollText_animate = function (ctx, time, callback) { // 开始绘制到UI上 core.clearMap('ui'); - var per_pixel = 1, per_time = time * per_pixel / (416+height); - var currH = 416; + var per_pixel = 1, height = ctx.canvas.height, per_time = time * per_pixel / (this.PIXEL+height); + var currH = this.PIXEL; core.drawImage('ui', ctx.canvas, 0, currH); var animate = setInterval(function () { core.clearMap('ui'); @@ -913,9 +915,10 @@ ui.prototype._drawScrollText_animate = function (ctx, height, time, callback) { } ////// 文本图片化 ////// -ui.prototype.textImage = function (content) { +ui.prototype.textImage = function (content, lineHeight) { content = core.replaceText(content || ""); - var lineHeight = core.status.textAttribute.textfont * 1.4; + lineHeight = lineHeight || 1.4; + lineHeight *= core.status.textAttribute.textfont; var ctx = this._createTextCanvas(content, lineHeight); this.drawTextContent(ctx, content, { align: core.status.textAttribute.align, lineHeight: lineHeight }); return ctx.canvas; diff --git a/libs/utils.js b/libs/utils.js index 4ebdffe9..1bca52b0 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -311,19 +311,25 @@ utils.prototype.clone = function (data) { } ////// 裁剪图片 ////// -utils.prototype.cropImage = function (image, size) { - size = size || 32; +utils.prototype.splitImage = function (image, width, height) { + if (typeof image == "string") + image = core.material.images.images[image]; + if (!image) return []; + width = width || 32; + height = height || width; var canvas = document.createElement("canvas"); var context = canvas.getContext("2d"); - canvas.width = size; - canvas.height = size; + canvas.width = width; + canvas.height = height; var ans = []; - for (var i = 0; i < image.height; i += size) { - context.drawImage(image, 0, i, size, size, 0, 0, size, size); - var img = new Image(); - img.src = canvas.toDataURL("image/png"); - ans.push(img); - context.clearRect(0, 0, size, size); + for (var j = 0; j < image.height; j += height) { + for (var i = 0; i < image.width; i += width) { + context.drawImage(image, i, j, width, height, 0, 0, width, height); + var img = new Image(); + img.src = canvas.toDataURL("image/png"); + ans.push(img); + context.clearRect(0, 0, width, height); + } } return ans; }