diff --git a/docs/element.md b/docs/element.md index 087937c0..b961fe2d 100644 --- a/docs/element.md +++ b/docs/element.md @@ -262,6 +262,17 @@ floorId指定的是目标楼层的唯一标识符(ID)。 **从2.1.1开始,楼层属性中提供了`upFloor`和`downFloor`两项。如果设置此项(比如`"upFloor": [2,3]`),则写stair:upFloor或者楼传器的落点将用此点来替换楼梯位置(即类似于RM中的上箭头)。** +## 剧情文本控制 + +在写剧情文本时,可以: + +- 使用`\t[...]`来给文字加上标题和图标。如`\t[老人,man]`。 +- 使用`\b[...]`来制作对话框效果,如`\b[up,3,2]`。 +- 使用`\v[...]`来动态修改局部文本的颜色,如`\v[red]`。 +- 使用`${}`来计算一个表达式的值,如`${status:atk+status:def}`。 + +详细信息请参见[剧情文本控制](event#text:显示一段文字(剧情))中的说明。 + ## 大地图 从V2.4开始,H5魔塔开始支持大地图。 diff --git a/docs/event.md b/docs/event.md index 979f00ab..3fd250bb 100644 --- a/docs/event.md +++ b/docs/event.md @@ -237,6 +237,15 @@ !> `\t[...]`必须在`\b[...]`前面!不然两者都无法正常显示。 +还可以使用`\v[...]`来调整剧情文本的颜色。 + +``` js +"x,y": [ // 实际执行的事件列表 + "这句话是默认颜色,\v[red]将颜色变成红色,\v[blue]将颜色变成蓝色", + "\v[#FF00FF]还可以使用RGB值来控制颜色,\v如果不加中括号则回到默认颜色", + "\t[hero]\b[up,hero]啊啊啊,别过来,\v[red]别过来!!!\n\v你到底是什么东西!" +] +``` 另外值得一提的是,我们是可以在文字中计算一个表达式的值的。只需要将表达式用 `${ }`整个括起来就可以。 diff --git a/libs/ui.js b/libs/ui.js index 70ef4b41..fbeb4605 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -283,6 +283,64 @@ ui.prototype.drawText = function (contents, callback) { // core.drawTextBox(content); } +ui.prototype.getTitleAndIcon = function (content) { + var id=null, name=null, image=null, icon=null, iconHeight=32, animate=null; + + var getInfo = function (v) { + ["enemy48", "enemys", "npc48", "npcs"].forEach(function (x) { + if (core.isset(core.material.icons[x][v])) { + image = core.material.images[x]; + icon = core.material.icons[x][v]; + if (x.indexOf("48")>=0) { + iconHeight = 48; + animate = 4; + } + else { + iconHeight = 32; + animate = 2; + } + } + }); + }; + + if (content.indexOf("\t[")==0 || content.indexOf("\\t[")==0) { + var index = content.indexOf("]"); + if (index>=0) { + var str=content.substring(2, index); + if (content.indexOf("\\t[")==0) str=content.substring(3, index); + content=content.substring(index+1); + var ss=str.split(","); + if (ss.length==1) { + id=ss[0]; + if (id=='hero') name = core.status.hero.name; + else if (core.isset(core.material.enemys[id])) { + name = core.material.enemys[id].name; + getInfo(id); + } + else { + name=id; + id='npc'; + } + } + else { + name=ss[0]; + id = 'npc'; + if (ss[1]=='hero') id = 'hero'; + else getInfo(ss[1]); + } + } + } + return { + "content": content, + "id": id, + "name": name, + "image": image, + "icon": icon, + "iconHeight": iconHeight, + "animate": animate + }; +} + ////// 绘制一个对话框 ////// ui.prototype.drawTextBox = function(content, showAll) { @@ -294,78 +352,9 @@ ui.prototype.drawTextBox = function(content, showAll) { core.status.event.interval = null; // 获得name, image, icon - var id=null, name=null, image=null, icon=null, iconHeight=32, animate=null; - if (content.indexOf("\t[")==0 || content.indexOf("\\t[")==0) { - var index = content.indexOf("]"); - if (index>=0) { - var str=content.substring(2, index); - if (content.indexOf("\\t[")==0) str=content.substring(3, index); - content=content.substring(index+1); - var ss=str.split(","); - if (ss.length==1) { - // id - id=ss[0]; - if (id=='hero') { - name = core.status.hero.name; - } - else { - if (core.isset(core.material.enemys[id])) { - name = core.material.enemys[id].name; - - if (core.isset(core.material.icons.enemy48[id])) { - image = core.material.images.enemy48; - icon = core.material.icons.enemy48[id]; - iconHeight = 48; - animate=4; - } - else { - image = core.material.images.enemys; - icon = core.material.icons.enemys[id]; - iconHeight = 32; - animate=2; - } - } - else { - name=id; - id='npc'; - image=null; - icon=null; - } - } - } - else { - name=ss[0]; - id = 'npc'; - if (ss[1]=='hero') { - id = 'hero'; - } - else if (core.isset(core.material.icons.npc48[ss[1]])) { - image = core.material.images.npc48; - icon = core.material.icons.npc48[ss[1]]; - iconHeight = 48; - animate=4; - } - else if (core.isset(core.material.icons.npcs[ss[1]])){ - image = core.material.images.npcs; - icon = core.material.icons.npcs[ss[1]]; - iconHeight = 32; - animate=2; - } - else if (core.isset(core.material.icons.enemy48[ss[1]])) { - image = core.material.images.enemy48; - icon = core.material.icons.enemy48[ss[1]]; - iconHeight = 48; - animate=4; - } - else if (core.isset(core.material.icons.enemys[ss[1]])) { - image = core.material.images.enemys; - icon = core.material.icons.enemys[ss[1]]; - iconHeight = 32; - animate=2; - } - } - } - } + var info = this.getTitleAndIcon(content); + content = info.content; + var id=info.id, name=info.name, image=info.image, icon=info.icon, iconHeight=info.iconHeight, animate=info.animate; // 获得位置信息 @@ -415,16 +404,17 @@ ui.prototype.drawTextBox = function(content, showAll) { // var contents = content.split('\n'); // var contents = core.splitLines('ui', content, ); - var left=10, right=416-2*left; + var left=7, right=416-2*left; var content_left = left + 25; if (id=='hero' || core.isset(icon)) content_left=left+63; var validWidth = right-(content_left-left)-13; var font = textfont + 'px Verdana'; if (textAttribute.bold) font = "bold "+font; - var contents = core.splitLines("ui", content, validWidth, font); + var realContent = content.replace(/(\v|\\v)(\[.*?])?/g, ""); - var height = 20 + (textfont+5)*(contents.length+1) + (id=='hero'?core.material.icons.hero.height-10:core.isset(name)?iconHeight-10:0); + var height = 20 + (textfont+5)*(core.splitLines("ui", realContent, validWidth, font).length+1) + + (id=='hero'?core.material.icons.hero.height-10:core.isset(name)?iconHeight-10:0); var xoffset = 6, yoffset = 22; @@ -434,20 +424,16 @@ ui.prototype.drawTextBox = function(content, showAll) { top = parseInt((416 - height) / 2); } else if (position=='up') { - if (px==null || py==null) { + if (px==null || py==null) top = 5 + offset; - } - else { + else top = 32 * py - height - ydelta - yoffset; - } } else if (position=='down') { - if (px==null || py==null) { + if (px==null || py==null) top = 416 - height - 5 - offset; - } - else { + else top = 32 * py + 32 + yoffset; - } } // var left = 97, top = 64, right = 416 - 2 * left, bottom = 416 - 2 * top; @@ -459,11 +445,10 @@ ui.prototype.drawTextBox = function(content, showAll) { core.setFillStyle('ui', core.arrayToRGB(textAttribute.background)); core.setStrokeStyle('ui', borderColor); - core.fillRect('ui', left, top, right, height); core.strokeRect('ui', left - 1, top - 1, right + 1, height + 1, borderColor, 2); - var xoffset = 9; + var xoffset = 10; // draw triangle if (position=='up' && core.isset(px) && core.isset(py)) { @@ -534,32 +519,66 @@ ui.prototype.drawTextBox = function(content, showAll) { } } + var defaultColor = core.arrayToRGB(textAttribute.text); + var offsetx = content_left, offsety = content_top; + core.setFont('ui', font); + core.setAlpha('ui', textAttribute.text[3]); + core.setFillStyle('ui', defaultColor); + var index = 0, currcolor = defaultColor, changed = false; - var drawContent = function (content) { - - core.clearMap("ui", content_left, content_top - 18, validWidth, top + height - content_top + 10); - core.setAlpha('ui', textAttribute.background[3]); - core.setFillStyle('ui', core.arrayToRGB(textAttribute.background)); - core.fillRect("ui", content_left, content_top - 18, validWidth, top + height - content_top + 11); - - core.setAlpha('ui', textAttribute.text[3]); - core.setFillStyle('ui', core.arrayToRGB(textAttribute.text)); - var contents = core.splitLines("ui", content, validWidth, font); - - for (var i=0;i= content.length) return false; + if (changed) { + core.setFillStyle('ui', currcolor); + changed = false; } - } + // get next character + var char = content.charAt(index++); + // \n, \\n + if (char == '\n' || (char=='\\' && content.charAt(index)=='n')) { + offsetx = content_left; + offsety += textfont+5; + if (char=='\\') index++; + return drawNext(); + } + // \v, \\v + if (char == '\v' || (char=='\\' && content.charAt(index)=='v')) { + if (char == '\\') index++; + changed = true; + // 检查是不是 [] + var index2; + if (content.charAt(index) == '[' && ((index2=content.indexOf(']', index))>=0)) { + // 变色 + var str = content.substring(index+1, index2); + if (str=="") currcolor = defaultColor; + else currcolor = str; + index = index2+1; + } + else currcolor = defaultColor; + return drawNext(); + } + // 检查是不是自动换行 + var charwidth = core.canvas.ui.measureText(char).width; + if (offsetx + charwidth > content_left + validWidth) { + index--; + offsetx = content_left; + offsety += textfont+5; + return drawNext(); + } + // 输出 + core.fillText('ui', char, offsetx, offsety); + offsetx += charwidth; + return true; + }; if (showAll || textAttribute.time<=0 || core.status.event.id!='action') { - drawContent(content); + while (drawNext()); } else { - var index=0; core.status.event.interval = setInterval(function () { - drawContent(content.substring(0, ++index)); - if (index==content.length) { + changed = true; + if (!drawNext()) { clearInterval(core.status.event.interval); core.status.event.interval = null; } @@ -604,82 +623,13 @@ ui.prototype.drawChoices = function(content, choices) { if (core.isset(content)) { // 获得name, image, icon - if (content.indexOf("\t[")==0 || content.indexOf("\\t[")==0) { - var index = content.indexOf("]"); - if (index>=0) { - var str=content.substring(2, index); - if (content.indexOf("\\t[")==0) str=content.substring(3, index); - content=content.substring(index+1); - var ss=str.split(","); - if (ss.length==1) { - // id - id=ss[0]; - if (id=='hero') { - name = core.status.hero.name; - } - else { - if (core.isset(core.material.enemys[id])) { - name = core.material.enemys[id].name; - - if (core.isset(core.material.icons.enemy48[id])) { - image = core.material.images.enemy48; - icon = core.material.icons.enemy48[id]; - iconHeight = 48; - animate=4; - } - else { - image = core.material.images.enemys; - icon = core.material.icons.enemys[id]; - iconHeight = 32; - animate=2; - } - } - else { - name=id; - id='npc'; - image=null; - icon=null; - } - } - } - else { - name=ss[0]; - id = 'npc'; - if (ss[1]=='hero') { - id = 'hero'; - } - else if (core.isset(core.material.icons.npc48[ss[1]])) { - image = core.material.images.npc48; - icon = core.material.icons.npc48[ss[1]]; - iconHeight = 48; - animate=4; - } - else if (core.isset(core.material.icons.npcs[ss[1]])){ - image = core.material.images.npcs; - icon = core.material.icons.npcs[ss[1]]; - iconHeight = 32; - animate=2; - } - else if (core.isset(core.material.icons.enemy48[ss[1]])) { - image = core.material.images.enemy48; - icon = core.material.icons.enemy48[ss[1]]; - iconHeight = 48; - animate=4; - } - else if (core.isset(core.material.icons.enemys[ss[1]])) { - image = core.material.images.enemys; - icon = core.material.icons.enemys[ss[1]]; - iconHeight = 32; - animate=2; - } - } - } - } - content = core.replaceText(content); - + // 获得name, image, icon + var info = this.getTitleAndIcon(content); + content = core.replaceText(info.content); + id=info.id; name=info.name; image=info.image; + icon=info.icon; iconHeight=info.iconHeight; animate=info.animate; if (id=='hero' || core.isset(icon)) content_left = left+60; - contents = core.splitLines('ui', content, width-(content_left-left)-10, 'bold 15px Verdana'); // content部分高度 @@ -746,7 +696,8 @@ ui.prototype.drawChoices = function(content, choices) { // 选项 core.canvas.ui.textAlign = "center"; for (var i = 0; i < choices.length; i++) { - core.fillText('ui', core.replaceText(choices[i].text || choices[i]), 208, choice_top + 32 * i, "#FFFFFF", "bold 17px Verdana"); + core.setFillStyle(choices[i].color || "#FFFFFF"); + core.fillText('ui', core.replaceText(choices[i].text || choices[i]), 208, choice_top + 32 * i, null, "bold 17px Verdana"); } if (choices.length>0) { diff --git a/libs/utils.js b/libs/utils.js index 72ce81f5..44e23fd9 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -13,7 +13,7 @@ utils.prototype.init = function () { ////// 将文字中的${和}(表达式)进行替换 ////// utils.prototype.replaceText = function (text) { - return text.replace(/\${([^}]+)}/g, function (word, value) { + return text.replace(/\${(.*?)}/g, function (word, value) { return core.calValue(value); }); }