diff --git a/README.md b/README.md index aa6b6e24..0f8cc25a 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏! * [x] 同一个点的多事件处理(做法详见文档)。 * [x] 增加新地图后可以接档而不用重新开始。 * [x] 增加可以接收用户输入的事件(type:input)。 +* [x] 滚动字幕;自动剧情文本。 * [x] 可以同时show/hide多个事件。 * [x] 现在可以支持滑冰和推箱子事件了。 * [x] 地图中每个块的可通行方向控制(悬崖效果)。 diff --git a/docs/event.md b/docs/event.md index b2482c59..34990c84 100644 --- a/docs/event.md +++ b/docs/event.md @@ -150,14 +150,14 @@ ### text:显示一段文字(剧情) -使用`{"type": "text"}`可以显示一段文字。后面`"data"`可以指定文字内容。 +使用`{"type": "text"}`可以显示一段文字。后面`"text"`可以指定文字内容。 ``` js "events": { // 该楼的所有可能事件列表 // 如果大括号里只有"data"项(没有"action"或"enable"),则可以省略到只剩下中括号 "x,y": [ // 实际执行的事件列表 - {"type": "text", "data": "在界面上的一段文字"}, // 显示文字事件 - {"type": "text", "data": "这是第二段文字"}, // 显示第二个文字事件 + {"type": "text", "text": "在界面上的一段文字"}, // 显示文字事件 + {"type": "text", "text": "这是第二段文字"}, // 显示第二个文字事件 // ... // 按顺序写事件,直到结束 ] @@ -171,7 +171,7 @@ // 如果大括号里只有"data"项(没有"action"或"enable"),则可以省略到只剩下中括号 "x,y": [ // 实际执行的事件列表 "在界面上的一段文字",// 直接简写,和下面写法完全等价 - {"type": "text", "data": "这是第二段文字"}, // 显示第二个文字事件 + {"type": "text", "text": "这是第二段文字"}, // 显示第二个文字事件 // ... // 按顺序写事件,直到结束 ] @@ -261,26 +261,49 @@ ![调试](./img/eventdebug.png) +### autoText:自动剧情文本 + +使用`{"type": "autoText"}`可以使用剧情文本。 + +``` js +"x,y": [ // 实际执行的事件列表 + {"type": "autoText", "text": "一段自动显示的剧情文字", "time": 5000} +] +``` + +text为文本正文内容,和上面的写法完全一致。 + +time为可选项,代表该自动文本的时间。可以不指定,不指定默认为3000毫秒。 + +用户无法跳过自动剧情文本,只能等待time时间结束后自动过。 + +回放录像时将忽略自动剧情文本的显示。 + +!> 由于用户无法跳过自动剧情文本,因此对于大段剧情文本请自行添加“是否跳过剧情”的提示,否则可能会非常不友好。 + ### setText:设置剧情文本的属性 使用`{"type": "setText"}`可以设置剧情文本的各项属性。 ``` js "x,y": [ // 实际执行的事件列表 - {"type": "setText", "position": "up", "title": [255,0,0], "text": [255,255,0], "background": [0,0,255,0.3], "bold": true}, - "这段话将显示在上方,标题为红色,正文为黄色粗体,背景为透明度0.3的蓝色" + {"type": "setText", "title": [255,0,0], "text": [255,255,0], "background": [0,0,255,0.3]}, + {"type": "setText", "position": "up", "bold": true, "scroll": 70}, + "这段话将显示在上方,标题为红色,正文为黄色粗体,背景为透明度0.3的蓝色,70毫秒速度滚动" ] ``` -position为可选项,表示设置文字显示位置。只能为up(上),center(中)和down(下)三者。 +title为可选项,如果设置则为一个RGB三元组或RGBA四元组,表示标题(名字)颜色。 默认值:`[255,215,0,1]` -title为可选项,如果设置则为一个RGB三元组或RGBA四元组,表示标题(名字)颜色。 +text为可选项,如果设置则为一个RGB三元组或RGBA四元组,表示正文颜色。 默认值:`[255,255,255,1]` -text为可选项,如果设置则为一个RGB三元组或RGBA四元组,表示正文颜色。 +background为可选项,如果设置则为一个RGB三元组或RGBA四元组,表示背景色。 默认值:`[0,0,0,0.85]` -background为可选项,如果设置则为一个RGB三元组或RGBA四元组,表示背景色。 +position为可选项,表示设置文字显示位置。只能为up(上),center(中)和down(下)三者。 默认值: `center` -bold为可选项,如果设置则为true或false,表示正文是否使用粗体。 +bold为可选项,如果设置则为true或false,表示正文是否使用粗体。 默认值:`false` + +scroll为可选项,表示文字滚动的速度。若此项设置为0将直接全部显示,若大于0则会设置为相邻字符依次显示的时间间隔。 默认值:`50` ### tip:显示一段提示文字 diff --git a/libs/core.js b/libs/core.js index c40c2373..867e0831 100644 --- a/libs/core.js +++ b/libs/core.js @@ -124,6 +124,7 @@ function core() { 'data': null, 'selection': null, 'ui': null, + 'interval': null, }, 'textAttribute': { 'position': "center", @@ -131,6 +132,7 @@ function core() { "background": [0,0,0,0.85], "text": [255,255,255,1], "bold": false, + "scroll": 50, }, 'curtainColor': null, 'usingCenterFly':false, diff --git a/libs/events.js b/libs/events.js index 95a8283d..2fd9391e 100644 --- a/libs/events.js +++ b/libs/events.js @@ -266,6 +266,8 @@ events.prototype.doEvents = function (list, x, y, callback) { events.prototype.doAction = function() { // 清空boxAnimate和UI层 core.status.boxAnimateObjs = []; + clearInterval(core.status.event.interval); + core.clearMap('ui', 0, 0, 416, 416); core.setAlpha('ui', 1.0); @@ -301,7 +303,17 @@ events.prototype.doAction = function() { if (core.status.replay.replaying) core.events.doAction(); else - core.ui.drawTextBox(data.data); + core.ui.drawTextBox(data.text); + break; + case "autoText": + if (core.status.replay.replaying) + core.events.doAction(); + else { + core.ui.drawTextBox(data.text); + setTimeout(function () { + core.events.doAction(); + }, data.time || 3000); + } break; case "setText": // 设置文本状态 if (data.position=='up'||data.position=='down'||data.position=='center') { @@ -316,6 +328,9 @@ events.prototype.doAction = function() { if (core.isset(data.bold)) { core.status.textAttribute.bold=data.bold; } + if (core.isset(data.scroll)) { + core.status.textAttribute.scroll=data.scroll; + } core.events.doAction(); break; case "tip": diff --git a/libs/ui.js b/libs/ui.js index 34aafaf4..14507b3d 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -15,6 +15,7 @@ main.instance.ui = new ui(); ////// 结束一切事件和绘制,关闭UI窗口,返回游戏进程 ////// ui.prototype.closePanel = function () { core.status.boxAnimateObjs = []; + clearInterval(core.status.event.interval); core.clearMap('ui', 0, 0, 416, 416); core.setAlpha('ui', 1.0); core.unLockControl(); @@ -22,11 +23,14 @@ ui.prototype.closePanel = function () { core.status.event.id = null; core.status.event.selection = null; core.status.event.ui = null; + core.status.event.interval = null; } ////// 绘制一个对话框 ////// ui.prototype.drawTextBox = function(content) { + clearInterval(core.status.event.interval); + // 获得name, image, icon var id=null, name=null, image=null, icon=null; if (content.indexOf("\t[")==0 || content.indexOf("\\t[")==0) { @@ -97,13 +101,6 @@ ui.prototype.drawTextBox = function(content) { } } } - /* - if (ss.length==3) { - px=parseInt(ss[1]); - py=parseInt(ss[2]); - } - */ - } } @@ -131,7 +128,7 @@ ui.prototype.drawTextBox = function(content) { var top; if (position=='center') { - top = (416 - height) / 2; + top = parseInt((416 - height) / 2); } else if (position=='up') { if (px==null || py==null) { @@ -227,15 +224,37 @@ ui.prototype.drawTextBox = function(content) { } } - core.setAlpha('ui', textAttribute.text[3]); - core.setFillStyle('ui', core.arrayToRGB(textAttribute.text)); - for (var i=0;i', 270, top+height-13, '#CCCCCC', '13px Verdana'); } ////// 绘制一个选项界面 ////// @@ -400,7 +419,7 @@ ui.prototype.drawConfirmBox = function (text, yesCallback, noCallback) { max_length = Math.max(max_length, core.canvas.ui.measureText(contents[i]).width); } - var left = Math.min(208 - 40 - max_length / 2, 100); + var left = Math.min(208 - 40 - parseInt(max_length / 2), 100); var top = 140 - (lines-1)*30; var right = 416 - 2 * left, bottom = 416 - 140 - top; @@ -418,10 +437,10 @@ ui.prototype.drawConfirmBox = function (text, yesCallback, noCallback) { var len=core.canvas.ui.measureText("确定").width; if (core.status.event.selection==0) { - core.strokeRect('ui', 208-38-len/2-5, top+bottom-35-20, len+10, 28, "#FFD700", 2); + core.strokeRect('ui', 208-38-parseInt(len/2)-5, top+bottom-35-20, len+10, 28, "#FFD700", 2); } if (core.status.event.selection==1) { - core.strokeRect('ui', 208+38-len/2-5, top+bottom-35-20, len+10, 28, "#FFD700", 2); + core.strokeRect('ui', 208+38-parseInt(len/2)-5, top+bottom-35-20, len+10, 28, "#FFD700", 2); } } @@ -776,7 +795,7 @@ ui.prototype.drawWaiting = function(text) { var text_length = core.canvas.ui.measureText(text).width; var right = Math.max(text_length+50, 220); - var left = 208-right/2, top = 208 - 32 - 16, bottom = 416 - 2 * top; + var left = 208-parseInt(right/2), top = 208 - 32 - 16, bottom = 416 - 2 * top; core.fillRect('ui', left, top, right, bottom, background); core.strokeRect('ui', left - 1, top - 1, right + 1, bottom + 1, '#FFFFFF', 2); @@ -822,7 +841,7 @@ ui.prototype.drawPagination = function (page, totalPage) { var length = core.canvas.ui.measureText(page + " / " + page).width; core.canvas.ui.textAlign = 'left'; - core.fillText('ui', page + " / " + totalPage, (416 - length) / 2, 403); + core.fillText('ui', page + " / " + totalPage, parseInt((416 - length) / 2), 403); core.canvas.ui.textAlign = 'center'; if (page > 1) @@ -1231,7 +1250,7 @@ ui.prototype.drawSLPanel = function(index) { core.setAlpha('ui', 1); core.canvas.ui.textAlign = 'center'; - var u=416/6, size=117; + var u=416/6, size=118; var name=core.status.event.id=='save'?"存档":"读档"; for (var i=0;i<6;i++) { diff --git a/更新说明.txt b/更新说明.txt index ffbff98f..a394bc45 100644 --- a/更新说明.txt +++ b/更新说明.txt @@ -4,6 +4,7 @@ 同一个点的多事件处理(做法详见文档)。 增加新地图后可以接档而不用重新开始。 增加可以接收用户输入的事件(type:input)。 +滚动字幕;自动剧情文本。 可以同时show/hide多个事件。 现在可以支持滑冰和推箱子事件了。 地图中每个块的可通行方向控制(悬崖效果)。