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/actions.js b/libs/actions.js index 5bf8c43a..c8e9baeb 100644 --- a/libs/actions.js +++ b/libs/actions.js @@ -7,6 +7,11 @@ actions.js:用户交互的事件的处理 function actions() { this._init(); + this.SIZE = core.__SIZE__; + this.HSIZE = core.__HALF_SIZE__; + this.LAST = this.SIZE - 1; + this.CHOICES_LEFT = 5; // choices + this.CHOICES_RIGHT = this.LAST - this.CHOICES_LEFT; } actions.prototype._init = function () { @@ -109,7 +114,7 @@ actions.prototype.checkReplaying = function () { ////// 检查是否在录像播放中,如果是,则停止交互 actions.prototype._sys_checkReplay = function () { - if (core.actions.checkReplaying()) return true; + if (this.checkReplaying()) return true; } ////// 按下某个键时 ////// @@ -127,10 +132,10 @@ actions.prototype._sys_onkeyDown = function (e) { } } core.status.holdingKeys.push(e.keyCode); - core.actions.pressKey(e.keyCode); + this.pressKey(e.keyCode); } else { if (e.keyCode == 17) core.status.ctrlDown = true; - core.actions.keyDown(e.keyCode); + this.keyDown(e.keyCode); } } @@ -140,7 +145,7 @@ actions.prototype.onkeyUp = function (e) { } actions.prototype._sys_onkeyUp_replay = function (e) { - if (core.actions.checkReplaying()) { + if (this.checkReplaying()) { if (e.keyCode == 27) // ESCAPE core.stopReplay(); else if (e.keyCode == 90) // Z @@ -179,10 +184,10 @@ actions.prototype._sys_onkeyUp = function (e) { break; } } - core.actions.keyUp(e.keyCode, e.altKey); + this.keyUp(e.keyCode, e.altKey); } else { if (e.keyCode == 17) core.status.ctrlDown = false; - core.actions.keyUp(e.keyCode, e.altKey); + this.keyUp(e.keyCode, e.altKey); } } @@ -209,32 +214,32 @@ actions.prototype._sys_keyDown_lockControl = function (keyCode) { if (!core.status.lockControl) return false; // Ctrl跳过对话 if (keyCode == 17) { - core.actions.keyDownCtrl(); + this.keyDownCtrl(); return true; } switch (core.status.event.id) { case 'action': - core.actions._keyDownAction(keyCode); + this._keyDownAction(keyCode); break; case 'book': - core.actions._keyDownBook(keyCode); + this._keyDownBook(keyCode); break; case 'fly': - core.actions._keyDownFly(keyCode); + this._keyDownFly(keyCode); break; case 'viewMaps': - core.actions._keyDownViewMaps(keyCode); + this._keyDownViewMaps(keyCode); break; case 'equipbox': - core.actions._keyDownEquipbox(keyCode); + this._keyDownEquipbox(keyCode); break; case 'toolbox': - core.actions._keyDownToolbox(keyCode); + this._keyDownToolbox(keyCode); break; case 'save': case 'load': case 'replayLoad': - core.actions._keyDownSL(keyCode); + this._keyDownSL(keyCode); break; case 'shop': case 'selectShop': @@ -246,10 +251,10 @@ actions.prototype._sys_keyDown_lockControl = function (keyCode) { case 'storageRemove': case 'replay': case 'gameInfo': - core.actions._keyDownChoices(keyCode); + this._keyDownChoices(keyCode); break; case 'cursor': - core.actions._keyDownCursor(keyCode); + this._keyDownCursor(keyCode); break; } return true; @@ -271,7 +276,6 @@ actions.prototype._sys_keyDown = function (keyCode) { case 40: core.moveHero('down'); break; - break; } return true; } @@ -282,7 +286,7 @@ actions.prototype.keyUp = function (keyCode, altKey, fromReplay) { } actions.prototype._sys_keyUp_replay = function (keyCode, altKey, fromReplay) { - if (!fromReplay && core.actions.checkReplaying()) return true; + if (!fromReplay && this.checkReplaying()) return true; } actions.prototype._sys_keyUp_lockControl = function (keyCode, altKey) { @@ -298,81 +302,81 @@ actions.prototype._sys_keyUp_lockControl = function (keyCode, altKey) { ok() && core.drawText(); break; case 'confirmBox': - core.actions._keyUpConfirmBox(keyCode); + this._keyUpConfirmBox(keyCode); break; case 'action': - core.actions._keyUpAction(keyCode); + this._keyUpAction(keyCode); break; case 'about': - ok() && core.ui.closePanel(); + ok() && core.closePanel(); break; case 'help': - ok() && core.ui.closePanel(); + ok() && core.closePanel(); break; case 'book': - core.actions._keyUpBook(keyCode); + this._keyUpBook(keyCode); break; case 'book-detail': - ok() && core.actions._clickBookDetail(); + ok() && this._clickBookDetail(); break; case 'fly': this._keyUpFly(keyCode); break; case 'viewMaps': - core.actions._keyUpViewMaps(keyCode); + this._keyUpViewMaps(keyCode); break; case 'shop': - core.actions._keyUpShop(keyCode); + this._keyUpShop(keyCode); break; case 'selectShop': - core.actions._keyUpQuickShop(keyCode); + this._keyUpQuickShop(keyCode); break; case 'toolbox': - core.actions._keyUpToolbox(keyCode); + this._keyUpToolbox(keyCode); break; case 'equipbox': - core.actions._keyUpEquipbox(keyCode, altKey); + this._keyUpEquipbox(keyCode, altKey); break; case 'save': case 'load': case 'replayLoad': - core.actions._keyUpSL(keyCode); + this._keyUpSL(keyCode); break; case 'keyBoard': - ok() && core.ui.closePanel(); + ok() && core.closePanel(); break; case 'switchs': - core.actions._keyUpSwitchs(keyCode); + this._keyUpSwitchs(keyCode); break; case 'settings': - core.actions._keyUpSettings(keyCode); + this._keyUpSettings(keyCode); break; case 'syncSave': - core.actions._keyUpSyncSave(keyCode); + this._keyUpSyncSave(keyCode); break; case 'syncSelect': - core.actions._keyUpSyncSelect(keyCode); + this._keyUpSyncSelect(keyCode); break; case 'localSaveSelect': - core.actions._keyUpLocalSaveSelect(keyCode); + this._keyUpLocalSaveSelect(keyCode); break; case 'storageRemove': - core.actions._keyUpStorageRemove(keyCode); + this._keyUpStorageRemove(keyCode); break; case 'cursor': - core.actions._keyUpCursor(keyCode); + this._keyUpCursor(keyCode); break; case 'replay': - core.actions._keyUpReplay(keyCode); + this._keyUpReplay(keyCode); break; case 'gameInfo': - core.actions._keyUpGameInfo(keyCode); + this._keyUpGameInfo(keyCode); break; case 'centerFly': - core.actions._keyUpCenterFly(keyCode); + this._keyUpCenterFly(keyCode); break; case 'paint': - core.actions._keyUpPaint(keyCode); + this._keyUpPaint(keyCode); break; } return true; @@ -399,7 +403,7 @@ actions.prototype.ondown = function (loc) { actions.prototype._sys_ondown_paint = function (x, y, px, py) { // 画板 if (core.status.played && (core.status.event || {}).id == 'paint') { - core.actions._ondownPaint(px, py); + this._ondownPaint(px, py); return true; } } @@ -492,7 +496,7 @@ actions.prototype.onup = function () { actions.prototype._sys_onup_paint = function () { // 画板 if (core.status.played && (core.status.event || {}).id == 'paint') { - core.actions._onupPaint(); + this._onupPaint(); return true; } } @@ -567,75 +571,75 @@ actions.prototype._sys_onclick_lockControl = function (x, y) { if (!core.status.lockControl) return false; switch (core.status.event.id) { case 'centerFly': - core.actions._clickCenterFly(x, y); + this._clickCenterFly(x, y); break; case 'book': - core.actions._clickBook(x, y); + this._clickBook(x, y); break; case 'book-detail': - core.actions._clickBookDetail(x, y); + this._clickBookDetail(x, y); break; case 'fly': - core.actions._clickFly(x, y); + this._clickFly(x, y); break; case 'viewMaps': - core.actions._clickViewMaps(x, y); + this._clickViewMaps(x, y); break; case 'switchs': - core.actions._clickSwitchs(x, y); + this._clickSwitchs(x, y); break; case 'settings': - core.actions._clickSettings(x, y); + this._clickSettings(x, y); break; case 'shop': - core.actions._clickShop(x, y); + this._clickShop(x, y); break; case 'selectShop': - core.actions._clickQuickShop(x, y); + this._clickQuickShop(x, y); break; case 'equipbox': - core.actions._clickEquipbox(x, y); + this._clickEquipbox(x, y); break; case 'toolbox': - core.actions._clickToolbox(x, y); + this._clickToolbox(x, y); break; case 'save': case 'load': case 'replayLoad': - core.actions._clickSL(x, y); + this._clickSL(x, y); break; case 'confirmBox': - core.actions._clickConfirmBox(x, y); + this._clickConfirmBox(x, y); break; case 'keyBoard': - core.actions._clickKeyBoard(x, y); + this._clickKeyBoard(x, y); break; case 'action': - core.actions._clickAction(x, y); + this._clickAction(x, y); break; case 'text': core.drawText(); break; case 'syncSave': - core.actions._clickSyncSave(x, y); + this._clickSyncSave(x, y); break; case 'syncSelect': - core.actions._clickSyncSelect(x, y); + this._clickSyncSelect(x, y); break; case 'localSaveSelect': - core.actions._clickLocalSaveSelect(x, y); + this._clickLocalSaveSelect(x, y); break; case 'storageRemove': - core.actions._clickStorageRemove(x, y); + this._clickStorageRemove(x, y); break; case 'cursor': - core.actions._clickCursor(x, y); + this._clickCursor(x, y); break; case 'replay': - core.actions._clickReplay(x, y); + this._clickReplay(x, y); break; case 'gameInfo': - core.actions._clickGameInfo(x, y); + this._clickGameInfo(x, y); break; case 'about': case 'help': @@ -668,15 +672,15 @@ actions.prototype._sys_onmousewheel = function (direct) { // 楼层飞行器 if (core.status.lockControl && core.status.event.id == 'fly') { - if (direct == 1) core.ui.drawFly(core.actions._getNextFlyFloor(1)); - if (direct == -1) core.ui.drawFly(core.actions._getNextFlyFloor(-1)); + if (direct == 1) core.ui.drawFly(this._getNextFlyFloor(1)); + if (direct == -1) core.ui.drawFly(this._getNextFlyFloor(-1)); return; } // 怪物手册 if (core.status.lockControl && core.status.event.id == 'book') { - if (direct == 1) core.ui.drawBook(core.status.event.data - 6); - if (direct == -1) core.ui.drawBook(core.status.event.data + 6); + if (direct == 1) core.ui.drawBook(core.status.event.data - this.HSIZE); + if (direct == -1) core.ui.drawBook(core.status.event.data + this.HSIZE); return; } @@ -689,8 +693,8 @@ actions.prototype._sys_onmousewheel = function (direct) { // 浏览地图 if (core.status.lockControl && core.status.event.id == 'viewMaps') { - if (direct == 1) core.actions._clickViewMaps(6, 3); - if (direct == -1) core.actions._clickViewMaps(6, 9); + if (direct == 1) this._clickViewMaps(this.HSIZE, this.HSIZE - 3); + if (direct == -1) this._clickViewMaps(this.HSIZE, this.HSIZE + 3); return; } @@ -740,7 +744,7 @@ actions.prototype._sys_longClick_lockControl = function (x, y) { // 长按楼传器的箭头可以快速翻页 if (core.status.event.id == 'fly') { if ((x == 10 || x == 11) && (y == 5 || y == 9)) { - core.actions._clickFly(x, y); + this._clickFly(x, y); return true; } } @@ -772,14 +776,14 @@ actions.prototype._sys_longClick = function (x, y, fromEvent) { // 数字键快速选择选项 actions.prototype._selectChoices = function (length, keycode, callback) { - var topIndex = 6 - parseInt((length - 1) / 2); + var topIndex = this.HSIZE - parseInt((length - 1) / 2); if (keycode == 13 || keycode == 32 || keycode == 67) { - callback.apply(this, [6, topIndex + core.status.event.selection]); + callback.apply(this, [this.HSIZE, topIndex + core.status.event.selection]); } if (keycode >= 49 && keycode <= 57) { var index = keycode - 49; if (index < length) { - callback.apply(this, [6, topIndex + index]); + callback.apply(this, [this.HSIZE, topIndex + index]); } } } @@ -824,9 +828,9 @@ actions.prototype._keyUpCenterFly = function (keycode) { ////// 点击确认框时 ////// actions.prototype._clickConfirmBox = function (x, y) { - if ((x == 4 || x == 5) && y == 7 && core.status.event.data.yes) + if ((x == this.HSIZE-2 || x == this.HSIZE-1) && y == this.HSIZE+1 && core.status.event.data.yes) core.status.event.data.yes(); - if ((x == 7 || x == 8) && y == 7 && core.status.event.data.no) + if ((x == this.HSIZE+2 || x == this.HSIZE+1) && y == this.HSIZE+1 && core.status.event.data.no) core.status.event.data.no(); } @@ -877,8 +881,8 @@ actions.prototype._clickAction = function (x, y) { var data = core.status.event.data.current; var choices = data.choices; if (choices.length == 0) return; - if (x >= 5 && x <= 7) { - var topIndex = 6 - parseInt((choices.length - 1) / 2); + if (x >= this.CHOICES_LEFT && x <= this.CHOICES_RIGHT) { + var topIndex = this.HSIZE - parseInt((choices.length - 1) / 2); if (y >= topIndex && y < topIndex + choices.length) { // 选择 core.status.route.push("choices:" + (y - topIndex)); @@ -925,17 +929,17 @@ actions.prototype._keyUpAction = function (keycode) { ////// 怪物手册界面的点击操作 ////// actions.prototype._clickBook = function (x, y) { // 上一页 - if ((x == 3 || x == 4) && y == 12) { - core.ui.drawBook(core.status.event.data - 6); + if ((x == this.HSIZE-2 || x == this.HSIZE-3) && y == this.LAST) { + core.ui.drawBook(core.status.event.data - this.HSIZE); return; } // 下一页 - if ((x == 8 || x == 9) && y == 12) { - core.ui.drawBook(core.status.event.data + 6); + if ((x == this.HSIZE+2 || x == this.HSIZE+3) && y == this.LAST) { + core.ui.drawBook(core.status.event.data + this.HSIZE); return; } // 返回 - if (x >= 10 && x <= 12 && y == 12) { + if (x >= this.LAST-2 && y == this.LAST) { if (core.events.recoverEvents(core.status.event.interval)) { return; } @@ -948,9 +952,9 @@ actions.prototype._clickBook = function (x, y) { } // 怪物信息 var data = core.status.event.data; - if (data != null && y < 12) { - var page = parseInt(data / 6); - var index = 6 * page + parseInt(y / 2); + if (data != null && y < this.LAST) { + var page = parseInt(data / this.HSIZE); + var index = this.HSIZE * page + parseInt(y / 2); core.ui.drawBook(index); core.ui.drawBookDetail(index); } @@ -959,12 +963,12 @@ actions.prototype._clickBook = function (x, y) { ////// 怪物手册界面时,按下某个键的操作 ////// actions.prototype._keyDownBook = function (keycode) { - if (keycode == 37) core.ui.drawBook(core.status.event.data - 6); + if (keycode == 37) core.ui.drawBook(core.status.event.data - this.HSIZE); if (keycode == 38) core.ui.drawBook(core.status.event.data - 1); - if (keycode == 39) core.ui.drawBook(core.status.event.data + 6); + if (keycode == 39) core.ui.drawBook(core.status.event.data + this.HSIZE); if (keycode == 40) core.ui.drawBook(core.status.event.data + 1); - if (keycode == 33) core.ui.drawBook(core.status.event.data - 6); - if (keycode == 34) core.ui.drawBook(core.status.event.data + 6); + if (keycode == 33) core.ui.drawBook(core.status.event.data - this.HSIZE); + if (keycode == 34) core.ui.drawBook(core.status.event.data + this.HSIZE); return; } @@ -984,7 +988,7 @@ actions.prototype._keyUpBook = function (keycode) { if (keycode == 13 || keycode == 32 || keycode == 67) { var data = core.status.event.data; if (data != null) { - this._clickBook(6, 2 * (data % 6)); + this._clickBook(this.HSIZE, 2 * (data % this.HSIZE)); } return; } @@ -998,12 +1002,12 @@ actions.prototype._clickBookDetail = function () { ////// 楼层传送器界面时的点击操作 ////// actions.prototype._clickFly = function (x, y) { - if ((x == 10 || x == 11) && y == 9) core.ui.drawFly(this._getNextFlyFloor(-1)); - if ((x == 10 || x == 11) && y == 5) core.ui.drawFly(this._getNextFlyFloor(1)); - if ((x == 10 || x == 11) && y == 10) core.ui.drawFly(this._getNextFlyFloor(-10)); - if ((x == 10 || x == 11) && y == 4) core.ui.drawFly(this._getNextFlyFloor(10)); - if (x >= 5 && x <= 7 && y == 12) core.ui.closePanel(); - if (x >= 0 && x <= 9 && y >= 3 && y <= 11) + if ((x == this.SIZE-2 || x == this.SIZE-3) && y == this.HSIZE+3) core.ui.drawFly(this._getNextFlyFloor(-1)); + if ((x == this.SIZE-2 || x == this.SIZE-3) && y == this.HSIZE-1) core.ui.drawFly(this._getNextFlyFloor(1)); + if ((x == this.SIZE-2 || x == this.SIZE-3) && y == this.HSIZE+4) core.ui.drawFly(this._getNextFlyFloor(-10)); + if ((x == this.SIZE-2 || x == this.SIZE-3) && y == this.HSIZE-2) core.ui.drawFly(this._getNextFlyFloor(10)); + if (x >= this.HSIZE-1 && x <= this.HSIZE+1 && y == this.LAST) core.ui.closePanel(); + if (x >= 0 && x <= this.HSIZE+3 && y >= 3 && y <= this.LAST - 1) core.flyTo(core.floorIds[core.status.event.data]); return; } @@ -1041,7 +1045,7 @@ actions.prototype._keyUpFly = function (keycode) { if (keycode == 71 || keycode == 27 || keycode == 88) core.ui.closePanel(); if (keycode == 13 || keycode == 32 || keycode == 67) - this._clickFly(5, 5); + this._clickFly(this.HSIZE-1, this.HSIZE-1); return; } @@ -1051,60 +1055,60 @@ actions.prototype._clickViewMaps = function (x, y) { core.ui.drawMaps(core.floorIds.indexOf(core.status.floorId)); return; } - var now = core.floorIds.indexOf(core.status.floorId); var index = core.status.event.data.index; var cx = core.status.event.data.x, cy = core.status.event.data.y; var floorId = core.floorIds[index], mw = core.floors[floorId].width, mh = core.floors[floorId].height; + var per = this.HSIZE - 4; - if (x == 0 && y == 0) { + if (x <= per - 2 && y <= per - 2) { core.status.event.data.damage = !core.status.event.data.damage; core.ui.drawMaps(index, cx, cy); return; } - if (x == 0 && y == 12) { + if (x <= per - 2 && y >= this.SIZE + 1 - per) { core.status.event.data.paint = !core.status.event.data.paint; core.ui.drawMaps(index, cx, cy); return; } - if (x == 12 && y == 0) { + if (x >= this.SIZE + 1 - per && y <= per - 2) { core.status.event.data.all = !core.status.event.data.all; core.ui.drawMaps(index, cx, cy); return; } - if (x >= 2 && x <= 10 && y <= 1 && mh > 13) { + if (x >= per && x <= this.LAST - per && y <= per - 1 && mh > this.SIZE) { core.ui.drawMaps(index, cx, cy - 1); return; } - if (x >= 2 && x <= 10 && y >= 11 && mh > 13) { + if (x >= per && x <= this.LAST - per && y >= this.SIZE - per && mh > this.SIZE) { core.ui.drawMaps(index, cx, cy + 1); return; } - if (x <= 1 && y >= 2 && y <= 10) { + if (x <= per - 1 && y >= per && y <= this.LAST - per) { core.ui.drawMaps(index, cx - 1, cy); return; } - if (x >= 11 && y >= 2 && y <= 10) { + if (x >= this.SIZE - per && y >= per && y <= this.LAST - per) { core.ui.drawMaps(index, cx + 1, cy); return; } - if (y <= 4 && (mh == 13 || (x >= 2 && x <= 10))) { + if (y <= this.HSIZE - 2 && (mh == this.SIZE || (x >= per && x <= this.LAST - per))) { index++; while (index < core.floorIds.length && index != now && core.status.maps[core.floorIds[index]].cannotViewMap) index++; if (index < core.floorIds.length) core.ui.drawMaps(index); } - else if (y >= 8 && (mh == 13 || (x >= 2 && x <= 10))) { + else if (y >= this.HSIZE + 2 && (mh == this.SIZE || (x >= per && x <= this.LAST - per))) { index--; while (index >= 0 && index != now && core.status.maps[core.floorIds[index]].cannotViewMap) index--; if (index >= 0) core.ui.drawMaps(index); } - else if (x >= 2 && x <= 10 && y >= 5 && y <= 7) { + else if (x >= per && x <= this.LAST - per && y >= this.HSIZE - 1 && y <= this.HSIZE + 1) { core.clearMap('data'); core.ui.closePanel(); } @@ -1116,12 +1120,12 @@ actions.prototype._keyDownViewMaps = function (keycode) { var floorId = core.floorIds[core.status.event.data.index], mh = core.floors[floorId].height; - if (keycode == 38 || keycode == 33) this._clickViewMaps(6, 3); - if (keycode == 40 || keycode == 34) this._clickViewMaps(6, 9); - if (keycode == 87 && mh > 13) this._clickViewMaps(6, 0); - if (keycode == 65) this._clickViewMaps(0, 6); - if (keycode == 83 && mh > 13) this._clickViewMaps(6, 12); - if (keycode == 68) this._clickViewMaps(12, 6); + if (keycode == 38 || keycode == 33) this._clickViewMaps(this.HSIZE, this.HSIZE - 3); + if (keycode == 40 || keycode == 34) this._clickViewMaps(this.HSIZE, this.HSIZE + 3); + if (keycode == 87 && mh > this.SIZE) this._clickViewMaps(this.HSIZE, 0); + if (keycode == 65) this._clickViewMaps(0, this.HSIZE); + if (keycode == 83 && mh > this.SIZE) this._clickViewMaps(this.HSIZE, this.LAST); + if (keycode == 68) this._clickViewMaps(this.LAST, this.HSIZE); return; } @@ -1167,8 +1171,8 @@ actions.prototype._keyUpViewMaps = function (keycode) { actions.prototype._clickShop = function (x, y) { var shop = core.status.event.data.shop; var choices = shop.choices; - if (x >= 5 && x <= 7) { - var topIndex = 6 - parseInt(choices.length / 2); + if (x >= this.CHOICES_LEFT && x <= this.CHOICES_RIGHT) { + var topIndex = this.HSIZE - parseInt(choices.length / 2); if (y >= topIndex && y < topIndex + choices.length) { return core.events._useShop(shop, y - topIndex); } @@ -1196,8 +1200,8 @@ actions.prototype._clickQuickShop = function (x, y) { var shopList = core.status.shops, keys = Object.keys(shopList).filter(function (shopId) { return shopList[shopId].visited || !shopList[shopId].mustEnable }); - if (x >= 5 && x <= 7) { - var topIndex = 6 - parseInt(keys.length / 2); + if (x >= this.CHOICES_LEFT && x <= this.CHOICES_RIGHT) { + var topIndex = this.HSIZE - parseInt(keys.length / 2); if (y >= topIndex && y < topIndex + keys.length) { var reason = core.events.canUseQuickShop(keys[y - topIndex]); if (!core.flags.enableDisabledShop && reason) { @@ -1749,9 +1753,9 @@ actions.prototype._keyUpSL = function (keycode) { ////// 系统设置界面时的点击操作 ////// actions.prototype._clickSwitchs = function (x, y) { - if (x < 5 || x > 7) return; + if (x < this.CHOICES_LEFT || x > this.CHOICES_RIGHT) return; var choices = core.status.event.ui.choices; - var topIndex = 6 - parseInt((choices.length - 1) / 2); + var topIndex = this.HSIZE - parseInt((choices.length - 1) / 2); if (y >= topIndex && y < topIndex + choices.length) { var selection = y - topIndex; core.status.event.selection = selection; @@ -1844,11 +1848,11 @@ actions.prototype._keyUpSwitchs = function (keycode) { this._selectChoices(core.status.event.ui.choices.length, keycode, this._clickSwitchs); } -////// 系统菜单栏界面时的点击事件 ////// +////// 系统菜单栏界面时的点击操作 ////// actions.prototype._clickSettings = function (x, y) { - if (x < 5 || x > 7) return; + if (x < this.CHOICES_LEFT || x > this.CHOICES_RIGHT) return; var choices = core.status.event.ui.choices; - var topIndex = 6 - parseInt((choices.length - 1) / 2); + var topIndex = this.HSIZE - parseInt((choices.length - 1) / 2); if (y >= topIndex && y < topIndex + choices.length) { var selection = y - topIndex; core.status.event.selection = selection; @@ -1897,9 +1901,9 @@ actions.prototype._keyUpSettings = function (keycode) { ////// 同步存档界面时的点击操作 ////// actions.prototype._clickSyncSave = function (x, y) { - if (x < 5 || x > 7) return; + if (x < this.CHOICES_LEFT || x > this.CHOICES_RIGHT) return; var choices = core.status.event.ui.choices; - var topIndex = 6 - parseInt((choices.length - 1) / 2); + var topIndex = this.HSIZE - parseInt((choices.length - 1) / 2); if (y >= topIndex && y < topIndex + choices.length) { var selection = y - topIndex; core.status.event.selection = selection; @@ -1979,10 +1983,10 @@ actions.prototype._keyUpSyncSave = function (keycode) { ////// 同步存档选择界面时的点击操作 ////// actions.prototype._clickSyncSelect = function (x, y) { - if (x < 5 || x > 7) return; + if (x < this.CHOICES_LEFT || x > this.CHOICES_RIGHT) return; var choices = core.status.event.ui.choices; - var topIndex = 6 - parseInt((choices.length - 1) / 2); + var topIndex = this.HSIZE - parseInt((choices.length - 1) / 2); if (y >= topIndex && y < topIndex + choices.length) { var selection = y - topIndex; core.status.event.selection = selection; @@ -2013,10 +2017,10 @@ actions.prototype._keyUpSyncSelect = function (keycode) { ////// 存档下载界面时的点击操作 ////// actions.prototype._clickLocalSaveSelect = function (x, y) { - if (x < 5 || x > 7) return; + if (x < this.CHOICES_LEFT || x > this.CHOICES_RIGHT) return; var choices = core.status.event.ui.choices; - var topIndex = 6 - parseInt((choices.length - 1) / 2); + var topIndex = this.HSIZE - parseInt((choices.length - 1) / 2); if (y >= topIndex && y < topIndex + choices.length) { var selection = y - topIndex; @@ -2051,10 +2055,10 @@ actions.prototype._keyUpLocalSaveSelect = function (keycode) { ////// 存档删除界面时的点击操作 ////// actions.prototype._clickStorageRemove = function (x, y) { - if (x < 5 || x > 7) return; + if (x < this.CHOICES_LEFT || x > this.CHOICES_RIGHT) return; var choices = core.status.event.ui.choices; - var topIndex = 6 - parseInt((choices.length - 1) / 2); + var topIndex = this.HSIZE - parseInt((choices.length - 1) / 2); if (y >= topIndex && y < topIndex + choices.length) { var selection = y - topIndex; @@ -2132,10 +2136,10 @@ actions.prototype._keyUpStorageRemove = function (keycode) { ////// 回放选择界面时的点击操作 ////// actions.prototype._clickReplay = function (x, y) { - if (x < 5 || x > 7) return; + if (x < this.CHOICES_LEFT || x > this.CHOICES_RIGHT) return; var choices = core.status.event.ui.choices; - var topIndex = 6 - parseInt((choices.length - 1) / 2); + var topIndex = this.HSIZE - parseInt((choices.length - 1) / 2); if (y >= topIndex && y < topIndex + choices.length) { var selection = y - topIndex; @@ -2186,10 +2190,10 @@ actions.prototype._keyUpReplay = function (keycode) { ////// 游戏信息界面时的点击操作 ////// actions.prototype._clickGameInfo = function (x, y) { - if (x < 5 || x > 7) return; + if (x < this.CHOICES_LEFT || x > this.CHOICES_RIGHT) return; var choices = core.status.event.ui.choices; - var topIndex = 6 - parseInt((choices.length - 1) / 2); + var topIndex = this.HSIZE - parseInt((choices.length - 1) / 2); if (y >= topIndex && y < topIndex + choices.length) { var selection = y - topIndex; @@ -2248,11 +2252,12 @@ actions.prototype._keyUpGameInfo = function (keycode) { ////// “虚拟键盘”界面时的点击操作 ////// actions.prototype._clickKeyBoard = function (x, y) { - if (y == 3 && x >= 1 && x <= 11) { + var m = this.HSIZE; + if (y == m - 3 && x >= m - 5 && x <= m + 5) { core.ui.closePanel(); - core.keyUp(112 + x - 1); // F1-F12: 112-122 + core.keyUp(112 + x + 5 - m); } - if (y == 3 && x == 12) { + if (y == m - 3 && x == m + 6) { var val = prompt(); if (val != null) { try { @@ -2262,9 +2267,9 @@ actions.prototype._clickKeyBoard = function (x, y) { } } } - if (y == 4 && x >= 1 && x <= 10) { + if (y == m - 2 && x >= m - 5 && x <= m + 4) { core.ui.closePanel(); - core.keyUp(x == 10 ? 48 : 48 + x); // 1-9: 49-57; 0: 48 + core.keyUp(x == m + 4 ? 48 : 49 + x + 5 - m); // 1-9: 49-57; 0: 48 } // 字母 var lines = [ @@ -2272,46 +2277,46 @@ actions.prototype._clickKeyBoard = function (x, y) { ["A", "S", "D", "F", "G", "H", "J", "K", "L"], ["Z", "X", "C", "V", "B", "N", "M"], ]; - if (y == 5 && x >= 1 && x <= 10) { + if (y == m - 1 && x >= m - 5 && x <= m + 4) { core.ui.closePanel(); - core.keyUp(lines[0][x - 1].charCodeAt(0)); + core.keyUp(lines[0][x + 5 - m].charCodeAt(0)); } - if (y == 6 && x >= 1 && x <= 9) { + if (y == m && x >= m - 5 && x <= m + 3) { core.ui.closePanel(); - core.keyUp(lines[1][x - 1].charCodeAt(0)); + core.keyUp(lines[1][x + 5 - m].charCodeAt(0)); } - if (y == 7 && x >= 1 && x <= 7) { + if (y == m + 1 && x >= m - 5 && x <= m + 1) { core.ui.closePanel(); - core.keyUp(lines[2][x - 1].charCodeAt(0)); + core.keyUp(lines[2][x + 5 - m].charCodeAt(0)); } - if (y == 8 && x >= 1 && x <= 11) { + if (y == m + 2 && x >= m - 5 && x <= m + 5) { core.ui.closePanel(); - if (x == 1) core.keyUp(189); // - - if (x == 2) core.keyUp(187); // = - if (x == 3) core.keyUp(219); // [ - if (x == 4) core.keyUp(221); // ] - if (x == 5) core.keyUp(220); // \ - if (x == 6) core.keyUp(186); // ; - if (x == 7) core.keyUp(222); // ' - if (x == 8) core.keyUp(188); // , - if (x == 9) core.keyUp(190); // . - if (x == 10) core.keyUp(191); // / - if (x == 11) core.keyUp(192); // ` + if (x == m - 5) core.keyUp(189); // - + if (x == m - 4) core.keyUp(187); // = + if (x == m - 3) core.keyUp(219); // [ + if (x == m - 2) core.keyUp(221); // ] + if (x == m - 1) core.keyUp(220); // \ + if (x == m) core.keyUp(186); // ; + if (x == m + 1) core.keyUp(222); // ' + if (x == m + 2) core.keyUp(188); // , + if (x == m + 3) core.keyUp(190); // . + if (x == m + 4) core.keyUp(191); // / + if (x == m + 5) core.keyUp(192); // ` } - if (y == 9 && x >= 1 && x <= 10) { + if (y == m + 3 && x >= m - 5 && x <= m + 4) { core.ui.closePanel(); - if (x == 1) core.keyUp(27); // ESC - if (x == 2) core.keyUp(9); // TAB - if (x == 3) core.keyUp(20); // CAPS - if (x == 4) core.keyUp(16); // SHIFT - if (x == 5) core.keyUp(17); // CTRL - if (x == 6) core.keyUp(18); // ALT - if (x == 7) core.keyUp(32); // SPACE - if (x == 8) core.keyUp(8); // BACKSPACE - if (x == 9) core.keyUp(13); // ENTER - if (x == 10) core.keyUp(46); // DEL + if (x == m - 5) core.keyUp(27); // ESC + if (x == m - 4) core.keyUp(9); // TAB + if (x == m - 3) core.keyUp(20); // CAPS + if (x == m - 2) core.keyUp(16); // SHIFT + if (x == m - 1) core.keyUp(17); // CTRL + if (x == m) core.keyUp(18); // ALT + if (x == m + 1) core.keyUp(32); // SPACE + if (x == m + 2) core.keyUp(8); // BACKSPACE + if (x == m + 3) core.keyUp(13); // ENTER + if (x == m + 4) core.keyUp(46); // DEL } - if (y == 10 && x >= 9 && x <= 11) + if (y == m + 4 && x >= m + 3 && x <= m + 5) core.ui.closePanel(); } diff --git a/libs/control.js b/libs/control.js index 3b4ddc2b..e3946a74 100644 --- a/libs/control.js +++ b/libs/control.js @@ -625,6 +625,7 @@ control.prototype.moveAction = function (callback) { } control.prototype._moveAction_noPass = function (canMove, callback) { + core.status.route.push(core.getHeroLoc('direction')); core.status.automaticRoute.moveStepBeforeStop = []; core.status.automaticRoute.lastDirection = core.getHeroLoc('direction'); if (canMove) core.events._trigger(core.nextX(), core.nextY()); @@ -641,6 +642,7 @@ control.prototype._moveAction_moving = function (callback) { core.setHeroMoveInterval(function () { var direction = core.getHeroLoc('direction'); core.control._moveAction_popAutomaticRoute(); + core.status.route.push(direction); // 无事件的道具(如血瓶)需要优先于阻激夹域判定 var nowx = core.getHeroLoc('x'), nowy = core.getHeroLoc('y'); @@ -1608,11 +1610,11 @@ control.prototype.syncSave = function (type) { core.ui.drawWaiting("正在同步,请稍后..."); core.control.getSaves(type=='all'?null:core.saves.saveIndex, function (saves) { if (!saves) return core.drawText("没有要同步的存档"); - core.control._syncSave_http(saves); + core.control._syncSave_http(type, saves); }) } -control.prototype._syncSave_http = function (saves) { +control.prototype._syncSave_http = function (type, saves) { var formData = new FormData(); formData.append('type', 'save'); formData.append('name', core.firstData.name); diff --git a/libs/core.js b/libs/core.js index 58d41ec9..4ef06a69 100644 --- a/libs/core.js +++ b/libs/core.js @@ -227,13 +227,7 @@ core.prototype._init_flags = function () { core.flags = core.clone(core.data.flags); core.values = core.clone(core.data.values); core.firstData = core.clone(core.data.firstData); - - if (!core.flags.enableExperience) core.flags.enableLevelUp = false; - if (!core.flags.enableLevelUp) core.flags.levelUpLeftMode = false; - if (core.flags.equipboxButton) core.flags.equipment = true; - core.flags.displayEnemyDamage = core.getLocalStorage('enemyDamage', core.flags.displayEnemyDamage); - core.flags.displayCritical = core.getLocalStorage('critical', core.flags.displayCritical); - core.flags.displayExtraDamage = core.getLocalStorage('extraDamage', core.flags.displayExtraDamage); + this._init_sys_flags(); core.dom.versionLabel.innerHTML = core.firstData.version; core.dom.logoLabel.innerHTML = core.firstData.title; @@ -248,6 +242,15 @@ core.prototype._init_flags = function () { core.material.icons = core.icons.getIcons(); } +core.prototype._init_sys_flags = function () { + if (!core.flags.enableExperience) core.flags.enableLevelUp = false; + if (!core.flags.enableLevelUp) core.flags.levelUpLeftMode = false; + if (core.flags.equipboxButton) core.flags.equipment = true; + core.flags.displayEnemyDamage = core.getLocalStorage('enemyDamage', core.flags.displayEnemyDamage); + core.flags.displayCritical = core.getLocalStorage('critical', core.flags.displayCritical); + core.flags.displayExtraDamage = core.getLocalStorage('extraDamage', core.flags.displayExtraDamage); +} + core.prototype._init_platform = function () { core.platform.isOnline = location.protocol.indexOf("http") == 0; if (!core.platform.isOnline) alert("请勿直接打开html文件!使用启动服务或者APP进行离线游戏。"); diff --git a/libs/events.js b/libs/events.js index 5aa7f0a4..fd81f219 100644 --- a/libs/events.js +++ b/libs/events.js @@ -16,7 +16,7 @@ events.prototype._init = function () { /// 初始化游戏 events.prototype.resetGame = function (hero, hard, floorId, maps, values) { - return this.eventdata.resetGame(hero, hard, floorId, maps, values); + this.eventdata.resetGame(hero, hard, floorId, maps, values); } ////// 游戏开始事件 ////// @@ -75,7 +75,11 @@ events.prototype._startGame_afterStart = function (nowLoc, callback) { core.ui.closePanel(); core.showStatusBar(); core.dom.musicBtn.style.display = 'none'; - core.changeFloor(core.firstData.floorId, null, nowLoc, null, callback); + core.changeFloor(core.firstData.floorId, null, nowLoc, null, function () { + // 插入一个空事件避免直接回放录像出错 + core.insertAction([]); + if (callback) callback(); + }); this._startGame_upload(); } @@ -885,7 +889,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 +897,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 +1034,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 +1818,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/maps.js b/libs/maps.js index a457b23b..cb7dbb7b 100644 --- a/libs/maps.js +++ b/libs/maps.js @@ -412,7 +412,7 @@ maps.prototype._canMoveHero_checkPoint = function (x, y, direction, floorId, ext return false; var nx = x + core.utils.scan[direction].x, ny = y + core.utils.scan[direction].y; - if (nx < 0 || ny < 0 || nx >= core.floors[floorId].width || ny >= core.floors[floorId].width) + if (nx < 0 || ny < 0 || nx >= core.floors[floorId].width || ny >= core.floors[floorId].height) return false; // 2. 检查该点素材的 cannotOut 和下一个点的 cannotIn diff --git a/libs/ui.js b/libs/ui.js index 4ab8359a..14007f9a 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -13,7 +13,7 @@ function ui() { this.HSIZE = core.__HALF_SIZE__; this.LAST = this.SIZE - 1; this.PIXEL = core.__PIXELS__; - this.HPIXEL = this.PIX / 2; + this.HPIXEL = this.PIXEL / 2; } // 初始化UI @@ -218,9 +218,7 @@ ui.prototype.drawImage = function (name, image, x, y, w, h, x1, y1, w1, h1) { ////// 结束一切事件和绘制,关闭UI窗口,返回游戏进程 ////// ui.prototype.closePanel = function () { - core.status.boxAnimateObjs = []; - clearInterval(core.status.event.interval); - core.clearSelector(); + this.clearUI(); core.maps.generateGroundPattern(); core.updateStatusBar(); core.unLockControl(); @@ -231,6 +229,15 @@ ui.prototype.closePanel = function () { core.status.event.interval = null; } +ui.prototype.clearUI = function () { + clearInterval(core.status.event.interval); + core.status.event.interval = null; + core.status.boxAnimateObjs = []; + core.clearSelector(); + core.clearMap('ui'); + core.setAlpha('ui', 1); +} + ////// 清除光标 ////// ui.prototype.clearSelector = function () { if (core.dymCanvas._selector) core.deleteCanvas("_selector"); @@ -341,10 +348,11 @@ ui.prototype._getTitleAndIcon = function (content) { if (blockInfo != null) { if (core.material.enemys[s4]) title = core.material.enemys[s4].name; image = blockInfo.image; - icon = blockInfo.posX; + icon = blockInfo.posY; height = blockInfo.height; animate = blockInfo.animate; } + else title = s4; } } if (s3) title = s3; @@ -360,69 +368,37 @@ ui.prototype._getTitleAndIcon = function (content) { }; } -ui.prototype.getTitleAndIcon = function (content) { - var id=null, name=null, image=null, icon=null, iconHeight=32, animate=null; - - var getInfo = function (v) { - var number = core.maps.getNumberById(v); - if (number>0) { - var block = core.maps.initBlock(0,0,number,true); - var cls = block.event.cls; - image = core.material.images[cls]; - icon = core.material.icons[cls][v]; - iconHeight = block.event.height; - animate = block.event.animate; - } - }; - - 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) { - if (/^[-\w.]+\.png$/.test(ss[0])) { - image = core.material.images.images[ss[0]]; - } - else { - 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 if (/^[-\w.]+\.png$/.test(ss[1])) { - image = core.material.images.images[ss[1]]; - } - else getInfo(ss[1]); - } - } +////// 正则处理 \b[up,xxx] 问题 +ui.prototype._getPosition = function (content) { + var pos = null, px = null, py = null; + if (core.status.event.id=='action') { + px = core.status.event.data.x; + py = core.status.event.data.y; } - return { - "content": content, - "id": id, - "name": name, - "image": image, - "icon": icon, - "iconHeight": iconHeight, - "animate": animate - }; + content = content.replace("\b", "\\b") + .replace(/\\b\[(up|center|down)(,(hero|null|\d+,\d+))?]/g, function (s0, s1, s2, s3) { + pos = s1; + if (s3 == 'hero') { + px = core.status.hero.loc.x; + py = core.status.hero.loc.y; + } + else if (s3 == 'null') { + px = py = null; + } + else if (s3) { + var str = s3.split(','); + px = parseInt(str[0]); + py = parseInt(str[1]); + } + return ""; + }); + return {content: content, position: pos, px: px, py: py}; } ////// 绘制选择光标 ui.prototype.drawWindowSelector = function(background, x, y, w, h) { + if (typeof background == 'string') + background = core.material.images.images[background]; w = Math.round(w), h = Math.round(h); var dstImage = core.ui.createCanvas("_selector", x, y, w, h, 165); core.setOpacity("_selector", 0.8); @@ -480,9 +456,9 @@ ui.prototype.drawWindowSkin = function(background, ctx, x, y, w, h, direction, p } ////// 计算有效文本框的宽度 -ui.prototype.calTextBoxWidth = function (ctx, content, min_width, max_width) { +ui.prototype.calTextBoxWidth = function (ctx, content, min_width, max_width, font) { // 无限长度自动换行 - var allLines = core.splitLines(ctx, content); + var allLines = core.splitLines(ctx, content, null, font); // 如果不存在手动换行,尽量调成半行形式 if (allLines.length == 1) { @@ -515,8 +491,10 @@ ui.prototype._getDrawableIconInfo = function (id) { return [image,icon]; } -ui.prototype._buildFont = function (fontSize) { - return (core.status.textAttribute.bold?"bold ":"") + fontSize + "px " +core.status.globalAttribute.font; +ui.prototype._buildFont = function (fontSize, bold) { + var textAttribute = core.status.textAttribute, globalAttribute = core.status.globalAttribute; + if (bold == null) bold = textAttribute.bold; + return (bold?"bold ":"") + (fontSize || textAttribute.textfont) + "px " + globalAttribute.font; } ////// 绘制一段文字到某个画布上面 @@ -524,7 +502,7 @@ ui.prototype._buildFont = function (fontSize) { // content:要绘制的内容;转义字符目前只允许留 \n, \r[...] 和 \i[...] // config:绘制配置项,目前暂时包含如下内容(均为可选) // left, top:起始点位置;maxWidth:单行最大宽度;color:默认颜色;align:左中右 -// fontSize:字体大小;font:字体样式;lineHeight:行高;time:打字机间隔 +// fontSize:字体大小;lineHeight:行高;time:打字机间隔 ui.prototype.drawTextContent = function (ctx, content, config) { ctx = core.getContextByName(ctx); if (!ctx) return; @@ -533,316 +511,211 @@ ui.prototype.drawTextContent = function (ctx, content, config) { config.left = config.left || 0; config.right = config.left + (config.maxWidth == null ? ctx.canvas.width : config.maxWidth); config.top = config.top || 0; - config.color = config.color || "#FFFFFF"; - config.align = config.align || "left"; + config.color = config.color || core.arrayToRGBA(core.status.textAttribute.text); + config.bold = config.bold || false; + config.align = config.align || core.status.textAttribute.align || "left"; config.fontSize = config.fontSize || core.status.textAttribute.textfont; - config.lineHeight = config.lineHeight || (config.fontSize * 1.2); + config.lineHeight = config.lineHeight || (config.fontSize * 1.3); config.time = config.time || 0; config.index = 0; - config.changed = true; config.currcolor = config.color; config.offsetX = 0; config.offsetY = 0; + config.line = 0; + config.blocks = []; // 创建一个新的临时画布 - var tempCtx = document.createElement('canvas').getContext('2d'); - tempCtx.canvas.height = config.lineHeight; + var tempCtx = core.bigmap.tempCanvas; + tempCtx.canvas.height = ctx.canvas.height; tempCtx.canvas.width = ctx.canvas.width; + var _textBaseLine = tempCtx.textBaseline; tempCtx.textBaseline = 'top'; - tempCtx.font = this._buildFont(config.fontSize); - + tempCtx.font = this._buildFont(config.fontSize, config.bold); + tempCtx.fillStyle = config.color; this._drawTextContent_draw(ctx, tempCtx, content, config); + tempCtx.textBaseline = _textBaseLine; } +// 绘制的基本逻辑: +// 1. 一个个字符绘制到对应画布上(靠左对齐);这个过程中,记下来每个字对应的方块 [x, y, w, h] +// 2. 每次换行时,计算当前行的宽度,然后如果是居中或者靠右对齐,则对当前行的每个小方块增加偏移量 +// 3. 实际绘制时,从临时画布直接将一个个小方块绘制到目标画布上,一次全部绘制,或者打字机效果一个个绘制 ui.prototype._drawTextContent_draw = function (ctx, tempCtx, content, config) { + // Step 1: 绘制到tempCtx上,并记录下图块信息 + while (this._drawTextContent_next(tempCtx, content, config)); + + // Step 2: 从tempCtx绘制到画布上 + config.index = 0; + var _drawNext = function () { + if (config.index >= config.blocks.length) return false; + var block = config.blocks[config.index++]; + ctx.drawImage(tempCtx.canvas, block.left, block.top, block.width, block.height, + config.left + block.left + block.marginLeft, config.top + block.top, block.width, block.height); + return true; + } if (config.time == 0) { - while (!core.ui._drawTextContent_next(ctx, tempCtx, content, config)); - core.ui._drawTextContent_drawLineToCtx(ctx, tempCtx, content, config); + while (_drawNext()); } else { core.status.event.interval = setInterval(function () { - config.changed = true; - if (!core.ui._drawTextContent_next(ctx, tempCtx, content, config)) { + if (!_drawNext()) { clearInterval(core.status.event.interval); core.status.event.interval = null; - core.ui._drawTextContent_drawLineToCtx(ctx, tempCtx, content, config); } - }, time); + }, config.time); } } -// 进行下一次绘制 -ui.prototype._drawTextContent_next = function (ctx, tempCtx, content, config) { - if (config.index >= content.length) return false; - // 是否需要改变颜色 - if (config.changed) { - core.setFillStyle(tempCtx, config.currcolor); - config.changed = false; +ui.prototype._drawTextContent_next = function (tempCtx, content, config) { + if (config.index >= content.length) { + this._drawTextContent_newLine(tempCtx, config); + return false; } // get next character var ch = content.charAt(config.index++); - return this._drawTextContent_drawChar(ctx, tempCtx, content, config, ch); + return this._drawTextContent_drawChar(tempCtx, content, config, ch); } // 绘制下一个字符 -ui.prototype._drawTextContent_drawChar = function (ctx, tempCtx, content, config, ch) { +ui.prototype._drawTextContent_drawChar = function (tempCtx, content, config, ch) { // \n, \\n if (ch == '\n' || (ch=='\\' && content.charAt(config.index)=='n')) { - this._drawTextContent_drawLineToCtx(ctx, tempCtx, content, config); + this._drawTextContent_newLine(tempCtx, config); if (ch=='\\') config.index++; - return this._drawTextContent_next(ctx, tempCtx, content, config); + return this._drawTextContent_next(tempCtx, content, config); } // \r, \\r if (ch == '\r' || (ch=='\\' && content.charAt(config.index)=='r')) { if (ch == '\\') config.index++; - return this._drawTextContent_changeColor(ctx, tempCtx, content, config); + return this._drawTextContent_changeColor(tempCtx, content, config); } // \\i 绘制图标 if (ch == '\\' && content.charAt(config.index)=='i') { - return this._drawTextContent_drawIcon(ctx, tempCtx, content, config); + return this._drawTextContent_drawIcon(tempCtx, content, config); } // 检查是不是自动换行 var charwidth = core.calWidth(tempCtx, ch); if (config.maxWidth != null && config.offsetX + charwidth > config.maxWidth) { - this._drawTextContent_drawLineToCtx(ctx, tempCtx, content, config); + this._drawTextContent_newLine(tempCtx, config); config.index--; - return this._drawTextContent_next(ctx, tempCtx, content, config); + return this._drawTextContent_next(tempCtx, content, config); } // 输出 - core.fillText(tempCtx, ch, config.offsetX, 0); + var left = config.offsetX, top = config.offsetY + (config.lineHeight - config.fontSize) / 2; + core.fillText(tempCtx, ch, left, top); + config.blocks.push({left: config.offsetX, top: config.offsetY, + width: charwidth, height: config.lineHeight, line: config.line, marginLeft: 0}); config.offsetX += charwidth; return true; } -// 从临时画布绘制到正式画布上面 -ui.prototype._drawTextContent_drawLineToCtx = function (ctx, tempCtx, content, config) { - // 计算坐标,宽高 - var left = config.left, top = config.top + config.offsetY; - var width = config.offsetX, height = config.lineHeight; - // 计算起点横坐标 +ui.prototype._drawTextContent_newLine = function (tempCtx, config) { + // 计算偏移量 + var width = config.offsetX, totalWidth = config.right - config.left; + var marginLeft = 0; if (config.align == 'center') - left = (config.left + config.right - width) / 2; + marginLeft = (totalWidth - width) / 2; else if (config.align == 'right') - left = config.right - width; + marginLeft = totalWidth - width; - core.drawImage(ctx, tempCtx.canvas, 0, 0, width, height, left, top, width, height); + config.blocks.forEach(function (b) { + if (b.line == config.line) + b.marginLeft = marginLeft; + }); config.offsetX = 0; config.offsetY += config.lineHeight; + config.line++; } -ui.prototype._drawTextContent_changeColor = function (ctx, tempCtx, content, config) { - config.changed = true; +ui.prototype._drawTextContent_changeColor = function (tempCtx, content, config) { // 检查是不是 [] var index = config.index, index2; if (content.charAt(index) == '[' && ((index2=content.indexOf(']', index))>=0)) { // 变色 var str = content.substring(index+1, index2); - if (str=="") config.currcolor = config.color; - else config.currcolor = str; + if (str=="") tempCtx.fillStyle = config.color; + else tempCtx.fillStyle = str; config.index = index2 + 1; } - else config.currcolor = color; - return this._drawTextContent_next(ctx, tempCtx,content, config); + else tempCtx.fillStyle = config.color; + return this._drawTextContent_next(tempCtx, content, config); } -ui.prototype._drawTextContent_drawIcon = function (ctx, tempCtx, content, config) { +ui.prototype._drawTextContent_drawIcon = function (tempCtx, content, config) { // 绘制一个 \i 效果 var index = config.index, index2; if (content.charAt(config.index+1) == '[' && ((index2=content.indexOf(']', index+1))>=0)) { var str = content.substring(index+2, index2); // --- 获得图标 var iconInfo = core.ui._getDrawableIconInfo(str), image = iconInfo[0], icon = iconInfo[1]; - if (image == null) return this._drawTextContent_next(ctx, tempCtx, content, config); + if (image == null) return this._drawTextContent_next(tempCtx, content, config); // 检查自动换行 - var width = config.fontSize + 2, left = config.offsetX + 2, top = (config.lineHeight - width) / 2; + var width = config.fontSize + 2, left = config.offsetX + 2, top = config.offsetY + (config.lineHeight - width) / 2 - 1; if (config.maxWidth != null && left + width > config.maxWidth) { - this._drawTextContent_drawLineToCtx(ctx, tempCtx, content, config); + this._drawTextContent_newLine(tempCtx, config); config.index--; - this._drawTextContent_next(ctx, tempCtx, content, config); + this._drawTextContent_next(tempCtx, content, config); } // 绘制到画布上 core.drawImage(tempCtx, image, 0, 32*icon, 32, 32, left, top, width, width); + + config.blocks.push({left: left, top: config.offsetY, + width: config.lineHeight, height: config.lineHeight, line: config.line, marginLeft: 0}); + config.offsetX += width + 6; config.index = index2 + 1; return true; } - return this._drawTextContent_next(ctx, tempCtx, content, config); + return this._drawTextContent_next(tempCtx, content, config); } -ui.prototype.__drawText = function (canvas, content, content_left, content_top, valid_width, - color, per_height, text_font, time) { - core.setTextAlign(canvas, 'left'); - - var offsetx = content_left, offsety = content_top; - core.setFillStyle(canvas, color); - var index = 0, currcolor = color, changed = false; - - var drawNext = function () { - if (index >= content.length) return false; - if (changed) { - core.setFillStyle(canvas, currcolor); - changed = false; - } - - // get next character - var ch = content.charAt(index++); - // \n, \\n - if (ch == '\n' || (ch=='\\' && content.charAt(index)=='n')) { - offsetx = content_left; - offsety += per_height; - if (ch=='\\') index++; - return drawNext(); - } - // \r, \\r - if (ch == '\r' || (ch=='\\' && content.charAt(index)=='r')) { - if (ch == '\\') index++; - changed = true; - // 检查是不是 [] - var index2; - if (content.charAt(index) == '[' && ((index2=content.indexOf(']', index))>=0)) { - // 变色 - var str = content.substring(index+1, index2); - if (str=="") currcolor = color; - else currcolor = str; - index = index2+1; - } - else currcolor = color; - return drawNext(); - } - // \\i 绘制图标 - if (ch == '\\' && content.charAt(index)=='i') { - // 绘制图标 - var index2; - if (content.charAt(index+1) == '[' && ((index2=content.indexOf(']', index+1))>=0)) { - var str = content.substring(index+2, index2); - // --- 获得图标 - var iconInfo = core.ui._getDrawableIconInfo(str), image = iconInfo[0], icon = iconInfo[1]; - if (image != null) { - if (core.isset(valid_width) && offsetx + text_font + 6 > content_left + valid_width) { - index --; - offsetx = content_left; - offsety += per_height; - return drawNext(); - } - // --- 绘制 - core.drawImage(canvas, image, 0, 32*icon, 32, 32, offsetx + 2, offsety - text_font + 1, text_font+2, text_font+2); - offsetx += text_font + 6; - index = index2+1; - return true; - } - } - } - // 检查是不是自动换行 - var charwidth = core.calWidth(canvas, ch); - if (core.isset(valid_width) && offsetx + charwidth > content_left + valid_width) { - index--; - offsetx = content_left; - offsety += per_height; - return drawNext(); - } - // 输出 - core.fillText(canvas, ch, offsetx, offsety); - offsetx += charwidth; - return true; - }; - - if (!core.isset(time) || time<=0) while (drawNext()); - else { - core.status.event.interval = setInterval(function () { - changed = true; - if (!drawNext()) { - clearInterval(core.status.event.interval); - core.status.event.interval = null; - } - }, time); - } +ui.prototype._getRealContent = function (content) { + return content.replace(/(\r|\\r)(\[.*?])?/g, "").replace(/(\\i)(\[.*?])?/g, "占1"); } ////// 绘制一个对话框 ////// ui.prototype.drawTextBox = function(content, showAll) { - - if (core.isset(core.status.event) && core.status.event.id=='action') { + if (core.status.event && core.status.event.id == 'action') core.status.event.ui = content; - } - clearInterval(core.status.event.interval); - core.status.event.interval = null; - - // 获得name, image, icon - 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; - - // 获得颜色的盒子等信息 - var textAttribute = core.status.textAttribute || core.initStatus.textAttribute; - var titlefont = textAttribute.titlefont || 22; - var textfont = textAttribute.textfont || 16; - var offset = textAttribute.offset || 0; - var background = core.status.textAttribute.background; - var isWindowSkin = false; - if (typeof background == 'string') { - background = core.material.images.images[background]; - if (core.isset(background) && background.width==192 && background.height==128) isWindowSkin = true; - else background = core.initStatus.textAttribute.background; - } - - var titleColor = core.arrayToRGBA(textAttribute.title); - var textColor = core.arrayToRGBA(textAttribute.text); - var borderColor = core.status.globalAttribute.borderColor; - var alpha = isWindowSkin?0.85:background[3]; - - // 获得位置信息 - var position = textAttribute.position, px=null, py=null, ydelta=iconHeight-32; - if (content.indexOf("\b[")==0 || content.indexOf("\\b[")==0) { - var index = content.indexOf("]"); - if (index>=0) { - var str = content.substring(2, index); - if (content.indexOf("\\b[")==0) str = content.substring(3, index); - content = content.substring(index + 1); - - var ss=str.split(","); - - if (ss[0]=='up' || ss[0]=='center' || ss[0]=='down') { - position=ss[0]; - if (core.status.event.id=='action') { - px = core.status.event.data.x; - py = core.status.event.data.y; - } - else { - px = null; py=null; - } - - if (ss.length>=2) { - if (ss[1]=='hero') { - px=core.getHeroLoc('x'); - py=core.getHeroLoc('y'); - ydelta = core.material.icons.hero.height-32; - } - else if (ss[1] == 'null') { - px = py = null; - } - else if (ss.length>=3) { - px=parseInt(ss[1]); - py=parseInt(ss[2]); - } - } - } - } - } + this.clearUI(); content = core.replaceText(content); - core.status.boxAnimateObjs = []; - core.clearSelector(); + // Step 1: 获得标题信息和位置信息 + var textAttribute = core.status.textAttribute; + var titleInfo = this._getTitleAndIcon(content); + var posInfo = this._getPosition(titleInfo.content); + if (!posInfo.position) posInfo.position = textAttribute.position; + if (posInfo.position != 'up' && posInfo.position != 'down') posInfo.px = posInfo.py = null; + content = this._drawTextBox_drawImages(posInfo.content); - // drawImage - content = content.replace(/(\f|\\f)\[(.*?)]/g, function (text, sympol, str) { + // Step 2: 计算对话框的矩形位置 + var hPos = this._drawTextBox_getHorizontalPosition(content, titleInfo, posInfo); + var vPos = this._drawTextBox_getVerticalPosition(content, titleInfo, posInfo, hPos.validWidth); + + // Step 3: 绘制背景图 + var isWindowSkin = this._drawTextBox_drawBackground(titleInfo, posInfo, hPos, vPos); + var alpha = isWindowSkin ? 0.85 : (textAttribute.background[3] || core.initStatus.textAttribute.background[3]); + + // Step 4: 绘制标题、头像、 + var content_top = this._drawTextBox_drawTitleAndIcon(titleInfo, hPos, vPos, alpha); + + // Step 5: 绘制正文 + this.drawTextContent('ui', content, { + left: hPos.content_left, top: content_top, maxWidth: hPos.validWidth, + lineHeight: vPos.lineHeight, time: (showAll || textAttribute.time<=0 || core.status.event.id!='action')?0:textAttribute.time + }); +} + +ui.prototype._drawTextBox_drawImages = function (content) { + return content.replace(/(\f|\\f)\[(.*?)]/g, function (text, sympol, str) { var ss = str.split(","); if (ss.length!=3 && ss.length!=5 && ss.length!=9) return ""; var img = core.material.images.images[ss[0]]; - if (!core.isset(img)) return ""; + if (!img) return ""; // 绘制 if (ss.length==3) core.drawImage('ui', img, parseFloat(ss[1]), parseFloat(ss[2])); @@ -852,184 +725,183 @@ ui.prototype.drawTextBox = function(content, showAll) { core.drawImage('ui', img, parseFloat(ss[1]), parseFloat(ss[2]), parseFloat(ss[3]), parseFloat(ss[4]), parseFloat(ss[5]), parseFloat(ss[6]), parseFloat(ss[7]), parseFloat(ss[8])); return ""; }); +} - var globalFont = core.status.globalAttribute.font; - var font = textfont + 'px '+globalFont; - if (textAttribute.bold) font = "bold "+font; - var realContent = content.replace(/(\r|\\r)(\[.*?])?/g, "").replace(/(\\i)(\[.*?])?/g, "啊1"); - - var leftSpace = 25, rightSpace = 12; - if (core.isset(px) && core.isset(py)) leftSpace = 20; - if (id=='hero' || core.isset(icon)) leftSpace = 62; // 行走图:15+32+15 - else if (core.isset(image)) leftSpace = 90; // 大头像:10+70+10 - var left = 7, right = 416 - left, width = right - left, validWidth = width - leftSpace - rightSpace; - +ui.prototype._drawTextBox_getHorizontalPosition = function (content, titleInfo, posInfo) { + var realContent = this._getRealContent(content); + var paddingLeft = 25, paddingRight = 12; + if (posInfo.px != null && posInfo.py != null) paddingLeft = 20; + if (titleInfo.icon != null) paddingLeft = 62; // 15 + 32 + 15 + else if (titleInfo.image) paddingLeft = 90; // 10 + 70 + 10 + var left = 7 + 3 * (this.HSIZE - 6), right = this.PIXEL - left, + width = right - left, validWidth = width - paddingLeft - paddingRight; // 对话框效果:改为动态计算 - if (core.isset(px) && core.isset(py)) { - var min_width = 220 - leftSpace, max_width = validWidth; + if (posInfo.px != null && posInfo.py != null) { + var min_width = 220 - paddingLeft, max_width = validWidth; // 无行走图或头像,则可以适当缩小min_width - if (leftSpace == 20) min_width = 160; - core.setFont('ui', font); - validWidth = this.calTextBoxWidth('ui', realContent, min_width, max_width); - width = validWidth + leftSpace + rightSpace; - // left必须在7~416-7-width区间内,以保证left>=7,right<=416-7 - left = core.clamp(32*px+16-width/2-core.bigmap.offsetX, 7, 416-7-width); + if (titleInfo.image == null) min_width = 160; + validWidth = this.calTextBoxWidth('ui', realContent, min_width, max_width, this._buildFont()); + width = validWidth + paddingLeft + paddingRight; + left = core.clamp(32 * posInfo.px + 16 - width / 2 - core.bigmap.offsetX, left, right - width); right = left + width; } + return { left: left, right: right, width: width, validWidth: validWidth, xoffset: 11, content_left: left + paddingLeft }; +} - var content_left = left + leftSpace; - var height = 30 + (textfont+5)*core.splitLines("ui", realContent, validWidth, font).length; - if (core.isset(name)) height += titlefont + 5; - if (id == 'hero') - height = Math.max(height, core.material.icons.hero.height+50); - else if (core.isset(icon)) - height = Math.max(height, iconHeight+50); - else if (core.isset(image)) +ui.prototype._drawTextBox_getVerticalPosition = function (content, titleInfo, posInfo, validWidth) { + var textAttribute = core.status.textAttribute || core.initStatus.textAttribute; + var lineHeight = textAttribute.textfont + 5; + var realContent = this._getRealContent(content); + var height = 30 + lineHeight * core.splitLines("ui", realContent, validWidth, this._buildFont()).length; + if (titleInfo.title) height += textAttribute.titlefont + 5; + if (titleInfo.icon != null) + height = Math.max(height, titleInfo.height+50); + else if (titleInfo.image) height = Math.max(height, 90); - var xoffset = 11, yoffset = 16; - - var top; - if (position=='center') { - top = parseInt((416 - height) / 2); - } - else if (position=='up') { - if (px==null || py==null) - top = 5 + offset; - else { - top = 32 * py - height - ydelta - yoffset; - top -= core.bigmap.offsetY; - } - } - else if (position=='down') { - if (px==null || py==null) - top = 416 - height - 5 - offset; - else { - top = 32 * py + 32 + yoffset; - top -= core.bigmap.offsetY; - } - } - var bottom = top + height; - - if (isWindowSkin) { - core.setAlpha('ui', alpha); - this.drawWindowSkin(background,'ui',left,top,width,height,position,px==null?null:px*32-core.bigmap.offsetX,py==null?null:py*32-core.bigmap.offsetY); - core.setAlpha('ui', 1); - } - else { - yoffset -= 4; - core.setAlpha('ui', alpha); - core.setStrokeStyle('ui', borderColor); - core.setFillStyle('ui', core.arrayToRGB(background)); - core.setLineWidth('ui', 2); - // 绘制 - var canvas = core.canvas.ui; - canvas.beginPath(); - canvas.moveTo(left,top); - // 上边缘 - if (position=='down' && core.isset(px) && core.isset(py)) { - canvas.lineTo(32*px+xoffset - core.bigmap.offsetX, top); - canvas.lineTo(32*px+16 - core.bigmap.offsetX, top-yoffset); - canvas.lineTo(32*(px+1)-xoffset - core.bigmap.offsetX, top); - } - canvas.lineTo(right, top); - canvas.lineTo(right, bottom); - // 下边缘 - if (position=='up' && core.isset(px) && core.isset(py)) { - canvas.lineTo(32*(px+1)-xoffset - core.bigmap.offsetX, bottom); - canvas.lineTo(32*px+16 - core.bigmap.offsetX, bottom+yoffset); - canvas.lineTo(32*px+xoffset - core.bigmap.offsetX, bottom); - } - canvas.lineTo(left, bottom); - canvas.closePath(); - canvas.fill(); - canvas.stroke(); - core.setAlpha('ui', 1); - } - // 名称 - core.setTextAlign('ui', 'left'); - - var content_top = top + 15 + textfont; - if (core.isset(id)) { - - content_top += (titlefont + 5); - core.setFillStyle('ui', titleColor); - core.setStrokeStyle('ui', titleColor); - - if (id == 'hero') { - var heroHeight=core.material.icons.hero.height; - core.setAlpha('ui', alpha); - core.strokeRect('ui', left + 15 - 1, top + 40 - 1, 34, heroHeight+2, null, 2); - core.setAlpha('ui', 1); - core.fillText('ui', name, content_left, top + 8 + titlefont, null, 'bold '+titlefont+'px '+globalFont); - core.clearMap('ui', left + 15, top + 40, 32, heroHeight); - core.fillRect('ui', left + 15, top + 40, 32, heroHeight, core.material.groundPattern); - var heroIcon = core.material.icons.hero['down']; - core.drawImage('ui', core.material.images.hero, heroIcon.stop * 32, heroIcon.loc * heroHeight, 32, heroHeight, left+15, top+40, 32, heroHeight); - } - else { - core.fillText('ui', name, content_left, top + 8 + titlefont, null, 'bold '+titlefont+'px '+globalFont); - if (core.isset(icon)) { - core.setAlpha('ui', alpha); - core.strokeRect('ui', left + 15 - 1, top + 40-1, 34, iconHeight + 2, null, 2); - core.setAlpha('ui', 1); - core.status.boxAnimateObjs = []; - core.status.boxAnimateObjs.push({ - 'bgx': left + 15, 'bgy': top + 40, 'bgWidth': 32, 'bgHeight': iconHeight, - 'x': left+15, 'y': top+40, 'height': iconHeight, 'animate': animate, - 'image': image, - 'pos': icon*iconHeight - }); - core.drawBoxAnimate(); + var yoffset = 16; + var top = parseInt((this.PIXEL - height) / 2); + switch (posInfo.position) { + case 'center': top = parseInt((this.PIXEL - height) / 2); break; + case 'up': + if (posInfo.px==null || posInfo.py==null) + top = 5 + textAttribute.offset; + else + top = 32 * posInfo.py - height - (titleInfo.height - 32) - yoffset - core.bigmap.offsetY; + break; + case 'down': + if (posInfo.px==null || posInfo.py==null) + top = this.PIXEL - height - 5 - textAttribute.offset; + else { + top = 32 * posInfo.py + 32 + yoffset - core.bigmap.offsetY; } + } + + return { top: top, height: height, bottom: top + height, yoffset: yoffset, lineHeight: lineHeight }; +} + +ui.prototype._drawTextBox_drawBackground = function (titleInfo, posInfo, hPos, vPos) { + var background = core.status.textAttribute.background; + var px = posInfo.px == null ? null : posInfo.px * 32 - core.bigmap.offsetX; + var py = posInfo.py == null ? null : posInfo.py * 32 - core.bigmap.offsetY; + var xoffset = hPos.xoffset, yoffset = vPos.yoffset - 4; + var left = hPos.left, right = hPos.right, top = vPos.top, bottom = vPos.bottom; + + if (typeof background == 'string' && core.material.images.images[background]) { + var image = core.material.images.images[background]; + if (image.width==192 && image.height==128) { + core.setAlpha('ui', 0.85); + this.drawWindowSkin(image, 'ui', left, top, right - left, bottom - top, posInfo.position, px, py); + core.setAlpha('ui', 1); + return true; + } + background = core.initStatus.textAttribute.background; + } + + var alpha = background[3]; + core.setAlpha('ui', alpha); + core.setStrokeStyle('ui', core.status.globalAttribute.borderColor); + core.setFillStyle('ui', core.arrayToRGB(background)); + core.setLineWidth('ui', 2); + + // 绘制 + var ctx = core.canvas.ui; + ctx.beginPath(); + ctx.moveTo(left, top); + // 上边缘三角 + if (posInfo.position == 'down' && px != null && py != null) { + ctx.lineTo(px + xoffset, top); + ctx.lineTo(px + 16, top - yoffset); + ctx.lineTo(px + 32 - xoffset, top); + } + ctx.lineTo(right, top); + ctx.lineTo(right, bottom); + // 下边缘三角 + if (posInfo.position == 'up' && px != null && py != null) { + ctx.lineTo(px + 32 - xoffset, bottom); + ctx.lineTo(px + 16, bottom + yoffset); + ctx.lineTo(px + xoffset, bottom); + } + ctx.lineTo(left, bottom); + ctx.closePath(); + ctx.fill(); + ctx.stroke(); + core.setAlpha('ui', 1); + return false; +} + +ui.prototype._drawTextBox_drawTitleAndIcon = function (titleInfo, hPos, vPos, alpha) { + core.setTextAlign('ui', 'left'); + var textAttribute = core.status.textAttribute; + var content_top = vPos.top + 15; + if (titleInfo.title != null) { + var titlefont = textAttribute.titlefont; + content_top += titlefont + 5; + core.setFillStyle('ui', core.arrayToRGB(textAttribute.title)); + core.setStrokeStyle('ui', core.arrayToRGB(textAttribute.title)); + + // --- title也要居中或者右对齐? + var title_width = core.calWidth('ui', titleInfo.title, 'bold '+titlefont+'px '+core.status.globalAttribute.font); + var title_left = hPos.content_left; + if (textAttribute.align == 'center') + title_left = hPos.left + (hPos.width - title_width) / 2; + else if (textAttribute.align == 'right') + title_left = hPos.right - title_width - 12; + + core.fillText('ui', titleInfo.title, title_left, vPos.top + 8 + titlefont); + + if (titleInfo.icon != null) { + core.setAlpha('ui', alpha); + core.strokeRect('ui', hPos.left + 15 - 1, vPos.top + 40-1, 34, titleInfo.height + 2, null, 2); + core.setAlpha('ui', 1); + core.status.boxAnimateObjs = []; + core.status.boxAnimateObjs.push({ + 'bgx': hPos.left + 15, 'bgy': vPos.top + 40, 'bgWidth': 32, 'bgHeight': titleInfo.height, + 'x': hPos.left + 15, 'y': vPos.top + 40, 'height': titleInfo.height, 'animate': titleInfo.animate, + 'image': titleInfo.image, 'pos': titleInfo.icon * titleInfo.height + }); + core.drawBoxAnimate(); } } - if (core.isset(image) && !core.isset(icon)) { - core.drawImage('ui', image, 0, 0, image.width, image.height, left+10, top+10, 70, 70); + if (titleInfo.image != null && titleInfo.icon == null) { // 头像图 + core.drawImage('ui', titleInfo.image, 0, 0, titleInfo.image.width, titleInfo.image.height, + hPos.left+10, vPos.top+10, 70, 70); } + return content_top; +} - core.setFont('ui', font); - - this.__drawText('ui', content, content_left, content_top, validWidth, textColor, textfont + 5, textfont, - (showAll || textAttribute.time<=0 || core.status.event.id!='action')?0:textAttribute.time); - +ui.prototype._createTextCanvas = function (content, lineHeight) { + var realContent = this._getRealContent(content); + var lines = core.splitLines('ui', realContent, null, this._buildFont()); + var width = this.PIXEL, height = lines.length * lineHeight; + var ctx = document.createElement('canvas').getContext('2d'); + ctx.canvas.width = width; + ctx.canvas.height = height; + ctx.clearRect(0, 0, width, height); + return ctx; } ////// 绘制滚动字幕 ////// -ui.prototype.drawScrollText = function (content, time, callback) { - - content = content || ""; +ui.prototype.drawScrollText = function (content, time, lineHeight, callback) { + content = core.replaceText(content || ""); + lineHeight = lineHeight || 1.4; time = time || 5000; + this.clearUI(); + var offset = core.status.textAttribute.offset || 15; + 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, time, callback); +} - clearInterval(core.status.event.interval); - core.status.event.interval = null; - - // 获得颜色的盒子等信息 - var textAttribute = core.status.textAttribute || core.initStatus.textAttribute; - var textfont = textAttribute.textfont || 16; - var offset = textAttribute.offset || 15; - var textColor = core.arrayToRGBA(textAttribute.text); - - var font = textfont+"px "+core.status.globalAttribute.font; - if (textAttribute.bold) font = "bold "+font; - var realContent = content.replace(/(\r|\\r)(\[.*?])?/g, "").replace(/(\\i)(\[.*?])?/g, "啊1"); - var contents = core.splitLines('ui', realContent), lines = contents.length; - - // 计算总高度,按1.4倍行距计算 - var width = 416, height = textfont * 1.4 * lines; - var tempCanvas = core.bigmap.tempCanvas; - tempCanvas.canvas.width = width; - tempCanvas.canvas.height = height; - tempCanvas.clearRect(0, 0, width, height); - tempCanvas.font = font; - - this.__drawText(tempCanvas, content, offset, textfont, null, textColor, 1.4*textfont, textfont, 0); - +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; - core.drawImage('ui', tempCanvas.canvas, 0, currH); + 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'); currH -= per_pixel; @@ -1039,271 +911,184 @@ ui.prototype.drawScrollText = function (content, time, callback) { if (core.isset(callback)) callback(); return; } - core.drawImage('ui', tempCanvas.canvas, 0, currH); + core.drawImage('ui', ctx.canvas, 0, currH); }, per_time); core.animateFrame.asyncId[animate] = true; } +////// 文本图片化 ////// +ui.prototype.textImage = function (content, lineHeight) { + content = core.replaceText(content || ""); + 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; +} + ////// 绘制一个选项界面 ////// ui.prototype.drawChoices = function(content, choices) { choices = core.clone(choices || []); - var background = core.status.textAttribute.background; - var isWindowSkin = false; - if (typeof background == 'string') { - background = core.material.images.images[background]; - if (core.isset(background) && background.width==192 && background.height==128) isWindowSkin = true; - else background = core.initStatus.textAttribute.background; - } - if (!isWindowSkin) background = core.arrayToRGBA(background); - var borderColor = core.status.globalAttribute.borderColor; - var textColor = core.arrayToRGBA(core.status.textAttribute.text); - var titleColor = core.arrayToRGBA(core.status.textAttribute.title); - core.status.event.ui = {"text": content, "choices": choices}; + this.clearUI(); - // Step 1: 计算长宽高 - var length = choices.length; + content = core.replaceText(content || ""); + var titleInfo = this._getTitleAndIcon(content); + var hPos = this._drawChoices_getHorizontalPosition(titleInfo, choices); + var vPos = this._drawChoices_getVerticalPosition(titleInfo, choices, hPos); + var isWindowSkin = this._drawTextBox_drawBackground(titleInfo, {}, hPos, vPos); + this._drawChoices_drawTitle(titleInfo, hPos, vPos); + this._drawChoices_drawChoices(choices, isWindowSkin, hPos, vPos); +} + +ui.prototype._drawChoices_getHorizontalPosition = function (titleInfo, choices) { // 宽度计算:考虑选项的长度 - var width = 416 - 2*85; - var globalFont = core.status.globalAttribute.font; - core.setFont('ui', "bold 17px "+globalFont); + var width = 246; + core.setFont('ui', "bold 17px "+core.status.globalAttribute.font); for (var i = 0; i < choices.length; i++) { if (typeof choices[i] === 'string') choices[i] = {"text": choices[i]}; choices[i].text = core.replaceText(choices[i].text); choices[i].width = core.calWidth('ui', core.replaceText(choices[i].text)); - if (core.isset(choices[i].icon)) choices[i].width += 28; + if (choices[i].icon != null) choices[i].width += 28; width = Math.max(width, choices[i].width+30); } + var left = (this.PIXEL - width) / 2, right = left + width; + var content_left = left + (titleInfo.icon == null ? 15: 60), validWidth = right - content_left - 10; - var left=parseInt((416 - width) / 2); // 左边界 - // 高度 - var height = 32*(length+2), bottom = 208+height/2; - if (length%2==0) bottom+=16; - var choice_top = bottom-height+56; + return { left: left, right: right, width: width, content_left: content_left, validWidth: validWidth }; +} - var id=null, name=null, image=null, icon=null, iconHeight=32, animate=null; - - var contents = null; - var content_left = left + 15; - var validWidth = width-(content_left-left)-10; - - if (core.isset(content)) { - // 获得name, image, icon - var info = this.getTitleAndIcon(content); - content = core.replaceText(info.content); - var realContent = content.replace(/(\r|\\r)(\[.*?])?/g, "").replace(/(\\i)(\[.*?])?/g, "啊1"); - 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; - validWidth = width-(content_left-left)-10 - contents = core.splitLines('ui', realContent, validWidth, 'bold 15px '+globalFont); - - // content部分高度 - var cheight=0; - // 如果含有标题,标题高度 - if (name!=null) cheight+=25; - cheight += contents.length*20; - height+=cheight; +ui.prototype._drawChoices_getVerticalPosition = function (titleInfo, choices, hPos) { + var length = choices.length; + var height = 32 * (length + 2), bottom = this.HPIXEL + height / 2; + if (length % 2 == 0) bottom += 16; + var choice_top = bottom - height + 56; + if (titleInfo.content) { + var realContent = this._getRealContent(titleInfo.content); + var lines = core.splitLines('ui', realContent, hPos.validWidth, this._buildFont(15, true)); + if (titleInfo.title) height += 25; + height += lines.length * 20; } - var top = bottom-height; + return {top: bottom - height, height: height, bottom: bottom, choice_top: choice_top }; +} - core.clearMap('ui'); - if (isWindowSkin) { - core.setAlpha('ui', 0.85); - this.drawWindowSkin(background,'ui',left,top,width,height); - } - else { - core.fillRect('ui', left, top, width, height, background); - core.strokeRect('ui', left - 1, top - 1, width + 1, height + 1, borderColor, 2); - } - core.setAlpha('ui', 1); +ui.prototype._drawChoices_drawTitle = function (titleInfo, hPos, vPos) { + if (!titleInfo.content) return; + var content_top = vPos.top + 21; + if (titleInfo.title != null) { + core.setTextAlign('ui', 'center'); - // 如果有内容 - if (core.isset(contents)) { + content_top = vPos.top + 41; + var title_offset = hPos.left+hPos.width/2; + // 动画 - var content_top = top + 35; + if (titleInfo.icon != null) { + title_offset += 12; + core.strokeRect('ui', hPos.left + 15 - 1, vPos.top + 30 - 1, 34, titleInfo.height + 2, '#DDDDDD', 2); + core.status.boxAnimateObjs = []; + core.status.boxAnimateObjs.push({ + 'bgx': hPos.left + 15, 'bgy': vPos.top + 30, 'bgWidth': 32, 'bgHeight': titleInfo.height, + 'x': hPos.left + 15, 'y': vPos.top + 30, 'height': titleInfo.height, 'animate': titleInfo.animate, + 'image': titleInfo.image, 'pos': titleInfo.icon * titleInfo.height + }); + core.drawBoxAnimate(); + }; - if (core.isset(id)) { - core.setTextAlign('ui', 'center'); - - content_top = top+55; - var title_offset = left+width/2; - // 动画 - - if (id=='hero' || core.isset(icon)) - title_offset += 12; - - if (id == 'hero') { - var heroHeight = core.material.icons.hero.height; - core.strokeRect('ui', left + 15 - 1, top + 30 - 1, 34, heroHeight+2, '#DDDDDD', 2); - core.fillText('ui', name, title_offset, top + 27, titleColor, 'bold 19px '+globalFont); - core.clearMap('ui', left + 15, top + 30, 32, heroHeight); - core.fillRect('ui', left + 15, top + 30, 32, heroHeight, core.material.groundPattern); - var heroIcon = core.material.icons.hero['down']; - core.drawImage('ui', core.material.images.hero, heroIcon.stop * 32, heroIcon.loc *heroHeight, 32, heroHeight, left+15, top+30, 32, heroHeight); - } - else { - core.fillText('ui', name, title_offset, top + 27, titleColor, 'bold 19px '+globalFont); - if (core.isset(icon)) { - core.strokeRect('ui', left + 15 - 1, top + 30 - 1, 34, iconHeight + 2, '#DDDDDD', 2); - core.status.boxAnimateObjs = []; - core.status.boxAnimateObjs.push({ - 'bgx': left + 15, 'bgy': top + 30, 'bgWidth': 32, 'bgHeight': iconHeight, - 'x': left+15, 'y': top+30, 'height': iconHeight, 'animate': animate, - 'image': image, - 'pos': icon*iconHeight - }); - core.drawBoxAnimate(); - } - } - } - - core.setFont('ui', 'bold 15px '+globalFont); - this.__drawText('ui', content, content_left, content_top, validWidth, textColor, 20, 15, 0); + core.fillText('ui', titleInfo.title, title_offset, vPos.top + 27, + core.arrayToRGBA(core.status.textAttribute.title), 'bold 19px '+core.status.globalAttribute.font); } + core.setTextAlign('ui', 'left'); + this.drawTextContent('ui', titleInfo.content, { + left: hPos.content_left, top: content_top, maxWidth: hPos.validWidth, + fontSize: 15, lineHeight: 20, bold: true + }); +} + +ui.prototype._drawChoices_drawChoices = function (choices, isWindowSkin, hPos, vPos) { // 选项 core.setTextAlign('ui', 'center'); + core.setFont('ui', "bold 17px " + core.status.globalAttribute.font); for (var i = 0; i < choices.length; i++) { - var color = choices[i].color || textColor; + var color = choices[i].color || core.status.textAttribute.text; if (color instanceof Array) color = core.arrayToRGBA(color); core.setFillStyle('ui', color); - var offset = 208; + var offset = this.HPIXEL; if (core.isset(choices[i].icon)) { var iconInfo = this._getDrawableIconInfo(choices[i].icon), image = iconInfo[0], icon = iconInfo[1]; if (image != null) { - core.drawImage('ui', image, 0, 32*icon, 32, 32, - 208 - choices[i].width/2, choice_top + 32*i - 17, 22, 22); + core.drawImage('ui', image, 0, 32 * icon, 32, 32, + this.HPIXEL - choices[i].width/2, vPos.choice_top + 32*i - 17, 22, 22); offset += 14; } } - core.fillText('ui', choices[i].text, offset, choice_top + 32 * i, null, "bold 17px "+globalFont); + core.fillText('ui', choices[i].text, offset, vPos.choice_top + 32 * i, color); } if (choices.length>0) { - if (!core.isset(core.status.event.selection)) core.status.event.selection=0; - while (core.status.event.selection<0) core.status.event.selection+=choices.length; - while (core.status.event.selection>=choices.length) core.status.event.selection-=choices.length; + core.status.event.selection = core.status.event.selection || 0; + while (core.status.event.selection < 0) core.status.event.selection += choices.length; + while (core.status.event.selection >= choices.length) core.status.event.selection -= choices.length; var len = choices[core.status.event.selection].width; if (isWindowSkin) - this.drawWindowSelector(background, 208-len/2-5, choice_top + 32 * core.status.event.selection - 20, len+10, 28); + this.drawWindowSelector(core.material.images.images[core.status.textAttribute.background], + this.HPIXEL - len/2 - 5, vPos.choice_top + 32 * core.status.event.selection - 20, len + 10, 28); else - core.strokeRect('ui', 208-len/2-5, choice_top + 32 * core.status.event.selection - 20, len+10, 28, "#FFD700", 2); + core.strokeRect('ui', this.HPIXEL - len/2 - 5, vPos.choice_top + 32 * core.status.event.selection - 20, + len+10, 28, "#FFD700", 2); } - return; -} - -////// 文本图片化 ////// -ui.prototype.textImage = function (content) { - content = content || ""; - - // 获得颜色的盒子等信息 - var textAttribute = core.status.textAttribute || core.initStatus.textAttribute; - var textfont = textAttribute.textfont || 16; - var offset = textAttribute.offset || 15; - var textColor = core.arrayToRGBA(textAttribute.text); - - var font = textfont+"px "+core.status.globalAttribute.font; - if (textAttribute.bold) font = "bold "+font; - var contents = core.splitLines('ui', content), lines = contents.length; - - // 计算总高度,按1.4倍行距计算 - var width = 416, height = textfont * 1.4 * lines; - var tempCanvas = core.bigmap.tempCanvas; - tempCanvas.canvas.width = width; - tempCanvas.canvas.height = height; - tempCanvas.clearRect(0, 0, width, height); - tempCanvas.font = font; - tempCanvas.fillStyle = textColor; - - // 全部绘制 - var currH = textfont; - for (var i = 0; i < lines; ++i) { - var text = contents[i]; - tempCanvas.fillText(text, offset, currH); - currH += 1.4 * textfont; - } - - return tempCanvas.canvas; } ////// 绘制一个确认/取消的警告页面 ////// ui.prototype.drawConfirmBox = function (text, yesCallback, noCallback) { core.lockControl(); + text = core.replaceText(text || ""); core.status.event.id = 'confirmBox'; core.status.event.data = {'yes': yesCallback, 'no': noCallback}; core.status.event.ui = text; + if (core.status.event.selection != 0) core.status.event.selection = 1; + this.clearUI(); - if (!core.isset(core.status.event.selection) || core.status.event.selection>1) core.status.event.selection=1; - if (core.status.event.selection<0) core.status.event.selection=0; - - core.clearSelector(); - - var background = core.status.textAttribute.background; - var isWindowSkin = false; - if (typeof background == 'string') { - background = core.material.images.images[background]; - if (core.isset(background) && background.width==192 && background.height==128) isWindowSkin = true; - else background = core.initStatus.textAttribute.background; - } - if (!isWindowSkin) background = core.arrayToRGBA(background); - var borderColor = core.status.globalAttribute.borderColor; - var textColor = core.arrayToRGBA(core.status.textAttribute.text); - - var globalFont = core.status.globalAttribute.font; - core.setFont('ui', "bold 19px "+globalFont); - - var contents = text.split('\n'); - var lines = contents.length; - var max_length = 0; - for (var i in contents) { - max_length = Math.max(max_length, core.calWidth('ui', contents[i])); - } - - var left = Math.min(208 - 40 - parseInt(max_length / 2), 100); - var top = 140 - (lines-1)*30; - var right = 416 - left, bottom = 416 - 140, width = right - left, height = bottom - top; - - core.clearMap('ui'); - if (isWindowSkin) { - core.setAlpha('ui', 0.85); - this.drawWindowSkin(background,'ui',left,top,width,height); - } - else { - core.fillRect('ui', left, top, width, height, background); - core.strokeRect('ui', left - 1, top - 1, width + 1, height + 1, borderColor, 2); - } - core.setAlpha('ui', 1); + core.setFont('ui', this._buildFont(19, true)); + var contents = text.split("\n"); + var rect = this._drawConfirmBox_getRect(contents); + var isWindowSkin = this._drawTextBox_drawBackground({}, {}, rect, rect); core.setTextAlign('ui', 'center'); + core.setFillStyle('ui', core.arrayToRGBA(core.status.textAttribute.text)) for (var i in contents) { - core.fillText('ui', contents[i], 208, top + 50 + i*30, textColor); + core.fillText('ui', contents[i], this.HPIXEL, rect.top + 50 + i*30); } - core.fillText('ui', "确定", 208 - 38, bottom - 35, null, "bold 17px "+globalFont); - core.fillText('ui', "取消", 208 + 38, bottom - 35); - + core.fillText('ui', "确定", this.HPIXEL - 38, rect.bottom - 35, null, this._buildFont(17, true)); + core.fillText('ui', "取消", this.HPIXEL + 38, rect.bottom - 35); var len=core.calWidth('ui', "确定"); - - var strokeLeft = 208 + (76*core.status.event.selection-38) - parseInt(len/2) - 5; + var strokeLeft = this.HPIXEL + (76*core.status.event.selection-38) - parseInt(len/2) - 5; if (isWindowSkin) - this.drawWindowSelector(background, strokeLeft, bottom-35-20, len+10, 28); + this.drawWindowSelector(core.status.textAttribute.background, strokeLeft, rect.bottom-35-20, len+10, 28); else - core.strokeRect('ui', strokeLeft, bottom-35-20, len+10, 28, "#FFD700", 2); + core.strokeRect('ui', strokeLeft, rect.bottom-35-20, len+10, 28, "#FFD700", 2); } +ui.prototype._drawConfirmBox_getRect = function (contents) { + var max_width = contents.reduce(function (pre, curr) { + return Math.max(pre, core.calWidth('ui', curr)); + }, 0); + var left = Math.min(this.HPIXEL - 40 - parseInt(max_width / 2), 100), right = this.PIXEL - left; + var top = this.HPIXEL - 68 - (contents.length-1)*30, bottom = this.HPIXEL + 68; + return { top: top, left: left, bottom: bottom, right: right, width: right - left, height: bottom - top }; +} + ////// 绘制系统设置界面 ////// ui.prototype.drawSwitchs = function() { core.status.event.id = 'switchs'; - var choices = [ "背景音乐: "+(core.musicStatus.bgmStatus ? "[ON]" : "[OFF]"), "背景音效: "+(core.musicStatus.soundStatus ? "[ON]" : "[OFF]"), @@ -1321,7 +1106,6 @@ ui.prototype.drawSwitchs = function() { ////// 绘制系统菜单栏 ////// ui.prototype.drawSettings = function () { core.status.event.id = 'settings'; - this.drawChoices(null, [ "系统设置", "虚拟键盘", "浏览地图", "绘图模式", "同步存档", "游戏信息", "返回标题", "返回游戏" ]); @@ -1329,68 +1113,37 @@ ui.prototype.drawSettings = function () { ////// 绘制快捷商店选择栏 ////// ui.prototype.drawQuickShop = function () { - core.status.event.id = 'selectShop'; - - var shopList = core.status.shops, keys = Object.keys(shopList).filter(function (shopId) {return shopList[shopId].visited || !shopList[shopId].mustEnable}); + var shopList = core.status.shops, keys = Object.keys(shopList).filter(function (shopId) { + return shopList[shopId].visited || !shopList[shopId].mustEnable + }); var choices = keys.map(function (shopId) { return {"text": shopList[shopId].textInList, "color": shopList[shopId].visited?null:"#999999"}; }); - choices.push("返回游戏"); this.drawChoices(null, choices); } ////// 绘制等待界面 ////// ui.prototype.drawWaiting = function(text) { - core.lockControl(); core.status.event.id = 'waiting'; - core.clearSelector(); - - var background = core.status.textAttribute.background; - var isWindowSkin = false; - if (typeof background == 'string') { - background = core.material.images.images[background]; - if (core.isset(background) && background.width==192 && background.height==128) isWindowSkin = true; - else background = core.initStatus.textAttribute.background; - } - if (!isWindowSkin) background = core.arrayToRGBA(background); - var borderColor = core.status.globalAttribute.borderColor; - var textColor = core.arrayToRGBA(core.status.textAttribute.text); - - var globalFont = core.status.globalAttribute.font; - var text_length = core.calWidth('ui', text, "bold 19px "+globalFont); - - var right = Math.max(text_length+50, 220); - var left = 208-parseInt(right/2), top = 208 - 32 - 16, bottom = 416 - 2 * top; - - core.clearMap('ui'); - if (isWindowSkin) { - core.setAlpha('ui', 0.85); - this.drawWindowSkin(background,'ui',left,top,right,bottom); - } - else { - core.fillRect('ui', left, top, right, bottom, background); - core.strokeRect('ui', left - 1, top - 1, right + 1, bottom + 1, borderColor, 2); - } - core.setAlpha('ui', 1); - + text = core.replaceText(text || ""); + var text_length = core.calWidth('ui', text, this._buildFont(19, true)); + var width = Math.max(text_length + 80, 220), left = this.HPIXEL - parseInt(width / 2), right = left + width; + var top = this.HPIXEL - 48, height = 96, bottom = top + height; + this._drawTextBox_drawBackground({}, {}, {left: left, right: right}, {top: top, bottom: bottom}); core.setTextAlign('ui', 'center'); - core.fillText('ui', text, 208, top + 56, textColor); - + core.fillText('ui', text, this.HPIXEL, top + 56, core.arrayToRGBA(core.status.textAttribute.text)); } ////// 绘制存档同步界面 ////// ui.prototype.drawSyncSave = function () { - core.status.event.id = 'syncSave'; - this.drawChoices(null, [ "同步存档到服务器", "从服务器加载存档", "存档至本地文件", "从本地文件读档", "回放当前录像", "下载当前录像", "清空本地存档", "返回主菜单" ]); - } ////// 绘制存档同步选择页面 ////// @@ -1435,44 +1188,36 @@ ui.prototype.drawGameInfo = function () { ////// 绘制分页 ////// ui.prototype.drawPagination = function (page, totalPage, top) { // if (totalPage 1) - core.fillText('ui', '上一页', 208 - 80, top*32+19); + core.fillText('ui', '上一页', this.HPIXEL - 80, top*32+19); if (page < totalPage) - core.fillText('ui', '下一页', 208 + 80, top*32+19); + core.fillText('ui', '下一页', this.HPIXEL + 80, top*32+19); } ////// 绘制键盘光标 ////// ui.prototype.drawCursor = function () { - - if (!core.isset(core.status.automaticRoute.cursorX)) - core.status.automaticRoute.cursorX=core.getHeroLoc('x'); - if (core.status.automaticRoute.cursorX<0) core.status.automaticRoute.cursorX=0; - if (core.status.automaticRoute.cursorX>12) core.status.automaticRoute.cursorX=12; - if (!core.isset(core.status.automaticRoute.cursorY)) - core.status.automaticRoute.cursorY=core.getHeroLoc('y'); - if (core.status.automaticRoute.cursorY<0) core.status.automaticRoute.cursorY=0; - if (core.status.automaticRoute.cursorY>12) core.status.automaticRoute.cursorY=12; - + var automaticRoute = core.status.automaticRoute; + if (automaticRoute.cursorX == null) + automaticRoute.cursorX = core.getHeroLoc('x'); + if (automaticRoute.cursorY == null) + automaticRoute.cursorY = core.getHeroLoc('y'); + automaticRoute.cursorX = core.clamp(automaticRoute.cursorX, 0, this.LAST); core.status.event.id = 'cursor'; core.lockControl(); - - core.clearMap('ui'); - core.setAlpha('ui', 1); - + core.clearUI(); var width = 4; - core.strokeRect('ui', 32*core.status.automaticRoute.cursorX+width/2, 32*core.status.automaticRoute.cursorY+width/2, + core.strokeRect('ui', 32*automaticRoute.cursorX+width/2, 32*automaticRoute.cursorY+width/2, 32-width, 32-width, '#FFD700', width); } @@ -1481,209 +1226,263 @@ ui.prototype.drawCursor = function () { ui.prototype.drawBook = function (index) { var floorId = core.floorIds[(core.status.event.ui||{}).index] || core.status.floorId; var enemys = core.enemys.getCurrentEnemys(floorId); - - core.clearSelector(); + core.clearUI(); core.clearMap('data'); + if (this._drawBook_drawBackground(floorId, enemys)) return; + index = core.clamp(index, 0, enemys.length - 1); + var perpage = this.HSIZE, page = parseInt(index / perpage) + 1; + var totalPage = parseInt((enemys.length - 1) / perpage) + 1; + core.status.event.data = index; + var start = (page - 1) * perpage, end = Math.min(page * perpage, enemys.length); + enemys = enemys.slice(start, end); + + for (var i = 0; i < enemys.length; i++) { + this._drawBook_drawOne(floorId, i, enemys[i]); + } + + if (index - start >= 0 && index - start < enemys.length) { + core.strokeRect('ui', 10, 62 * (index - start) + 13, this.PIXEL - 10 * 2, 62, '#FFD700'); + } + + core.drawBoxAnimate(); + this.drawPagination(page, totalPage); + core.fillText('ui', '返回游戏', this.PIXEL - 46, this.PIXEL - 13,'#DDDDDD', this._buildFont(15, true)); +} + +ui.prototype._drawBook_drawBackground = function (floorId, enemys) { // 生成groundPattern core.maps.generateGroundPattern(floorId); core.setFillStyle('ui', core.material.groundPattern); - core.fillRect('ui', 0, 0, 416, 416); + core.fillRect('ui', 0, 0, this.PIXEL, this.PIXEL); core.setAlpha('ui', 0.6); core.setFillStyle('ui', '#000000'); - core.fillRect('ui', 0, 0, 416, 416); + core.fillRect('ui', 0, 0, this.PIXEL, this.PIXEL); core.setAlpha('ui', 1); - core.setTextAlign('ui', 'left'); - var globalFont = core.status.globalAttribute.font; - core.setFont('ui', 'bold 15px '+globalFont); - if (enemys.length == 0) { - core.fillText('ui', "本层无怪物", 83, 222, '#999999', "bold 50px "+globalFont); - // 退出 core.setTextAlign('ui', 'center'); - core.fillText('ui', '返回游戏', 370, 403,'#DDDDDD', 'bold 15px '+globalFont); - return; + core.fillText('ui', "本层无怪物", this.HPIXEL, this.HPIXEL + 14, '#999999', this._buildFont(50, true)); + core.fillText('ui', '返回游戏', this.PIXEL - 46, this.PIXEL - 13,'#DDDDDD', this._buildFont(15, true)); + return true; } + return false; +} - if (index<0) index=0; - if (index>=enemys.length) index=enemys.length-1; - var perpage = 6; - var page=parseInt(index/perpage)+1; - var totalPage = parseInt((enemys.length - 1) / perpage) + 1; - core.status.event.data = index; - var start = (page - 1) * perpage, end = Math.min(page * perpage, enemys.length); +ui.prototype._drawBook_drawOne = function (floorId, index, enemy) { + // --- 区域规划:每个区域总高度为62,宽度为 PIXEL + var top = 62 * index + 12; // 最上面margin是12px + // 横向规划: + // 22 + 42 = 64 是头像框 + this._drawBook_drawBox(index, enemy, top); + // 剩余 PIXEL - 64 的宽度,按照 10 : 9 : 8 : 8 的比例划分 + var left = 64, total_width = this.PIXEL - left; + var name_width = total_width * 10 / 35, + col1_width = total_width * 9 / 35, col1_offset = left + name_width, + col2_width = total_width * 8 / 35, col2_offset = col1_offset + col2_width, + col3_width = total_width * 8 / 35, col3_offset = col2_offset + col3_width; + this._drawBook_drawNameCol(index, enemy, top, left, name_width); - enemys = enemys.slice(start, end); - core.status.boxAnimateObjs = []; - for (var i = 0; i < enemys.length; i++) { - // 边框 - var enemy = enemys[i]; - core.strokeRect('ui', 22, 62 * i + 22, 42, 42, '#DDDDDD', 2); + // 第二行:金币、加点、经验 + var second_line = []; + if (core.flags.enableMoney) second_line.push(["金币", core.formatBigNumber(enemy.money || 0)]); + if (core.flags.enableAddPoint) second_line.push(["加点", core.formatBigNumber(enemy.point || 0)]); + if (core.flags.enableExperience && second_line.length < 2) + second_line.push(["经验", core.formatBigNumber(enemy.experience || 0)]); + var cnt = second_line.length; - var cls = 'enemys'; - if (core.isset(core.material.icons.enemy48[enemy.id])) - cls = 'enemy48'; - var height = cls=='enemy48'?48:32; - var animate = cls=='enemy48'?4:2; + this._drawBook_drawCol1(index, enemy, top, col1_offset, col1_width, second_line); + this._drawBook_drawCol2(index, enemy, top, col2_offset, col2_width, second_line); + this._drawBook_drawCol3(index, enemy, top, col3_offset, col3_width); - // 怪物 - core.status.boxAnimateObjs.push({ - 'bgx': 22, 'bgy': 62 * i + 22, 'bgWidth': 42, 'bgHeight': 42, - 'x': 27, 'y': 62 * i + 27, 'height': 32, 'animate': animate, - 'image': core.material.images[cls], - 'pos': core.material.icons[cls][enemy.id] * height - }); + // get damage offset + var damageOffset = col1_offset + (col1_width + col2_width + col3_width) / 2 - 12; + if (cnt == 1) damageOffset = col2_offset + (col2_width + col3_width) / 2 - 12; + else if (cnt == 2) damageOffset = col3_offset + col3_width / 2 - 12; + this._drawBook_drawDamage(index, enemy, top, damageOffset); +} - // 数据 - core.setTextAlign('ui', 'center'); +ui.prototype._drawBook_drawBox = function (index, enemy, top) { + // 横向:22+42;纵向:10 + 42 + 10(正好居中);内部图像 32x32 + var border_top = top + 10, border_left = 22; + var img_top = border_top + 5, img_left = border_left + 5; + core.strokeRect('ui', 22, border_top, 42, 42, '#DDDDDD', 2); + var blockInfo = core.getBlockInfo(enemy.id); + core.status.boxAnimateObjs.push({ + 'bgx': border_left, 'bgy': border_top, 'bgWidth': 42, 'bgHeight': 42, + 'x': img_left, 'y': img_top, 'height': 32, 'animate': blockInfo.animate, + 'image': blockInfo.image, 'pos': blockInfo.posY * blockInfo.height + }); +} - if (enemy.specialText=='') { - core.fillText('ui', enemy.name, 115, 62 * i + 47, '#DDDDDD', 'bold 17px '+globalFont); - } - else { - core.fillText('ui', enemy.name, 115, 62 * i + 40, '#DDDDDD', 'bold 17px '+globalFont); - core.fillText('ui', enemy.specialText, 115, 62 * i + 62, '#FF6A6A', 'bold 15px '+globalFont); - } - core.setTextAlign('ui', 'left'); - core.fillText('ui', '生命', 165, 62 * i + 32, '#DDDDDD', '13px '+globalFont); - core.fillText('ui', core.formatBigNumber(enemy.hp||0), 195, 62 * i + 32, '#DDDDDD', 'bold 13px '+globalFont); - core.fillText('ui', '攻击', 255, 62 * i + 32, '#DDDDDD', '13px '+globalFont); - core.fillText('ui', core.formatBigNumber(enemy.atk||0), 285, 62 * i + 32, '#DDDDDD', 'bold 13px '+globalFont); - core.fillText('ui', '防御', 335, 62 * i + 32, '#DDDDDD', '13px '+globalFont); - core.fillText('ui', core.formatBigNumber(enemy.def||0), 365, 62 * i + 32, '#DDDDDD', 'bold 13px '+globalFont); - - var expOffset = 165, line_cnt=0; - if (core.flags.enableMoney) { - core.fillText('ui', '金币', 165, 62 * i + 50, '#DDDDDD', '13px '+globalFont); - core.fillText('ui', core.formatBigNumber(enemy.money||0), 195, 62 * i + 50, '#DDDDDD', 'bold 13px '+globalFont); - expOffset = 255; - line_cnt++; - } - - // 加点 - if (core.flags.enableAddPoint) { - core.setTextAlign('ui', 'left'); - core.fillText('ui', '加点', expOffset, 62 * i + 50, '#DDDDDD', '13px '+globalFont); - core.fillText('ui', core.formatBigNumber(enemy.point||0), expOffset + 30, 62 * i + 50, '#DDDDDD', 'bold 13px '+globalFont); - expOffset = 255; - line_cnt++; - } - - if (core.flags.enableExperience && line_cnt<2) { - core.setTextAlign('ui', 'left'); - core.fillText('ui', '经验', expOffset, 62 * i + 50, '#DDDDDD', '13px '+globalFont); - core.fillText('ui', core.formatBigNumber(enemy.experience||0), expOffset + 30, 62 * i + 50, '#DDDDDD', 'bold 13px '+globalFont); - line_cnt++; - } - - var damageOffset = 281; - if (line_cnt==1) damageOffset=326; - if (line_cnt==2) damageOffset=361; - - core.setTextAlign('ui', 'center'); - - var damage = enemy.damage; - var color = '#FFFF00'; - if (damage == null) { - damage = '无法战斗'; - color = '#FF0000'; - } - else { - if (damage >= core.status.hero.hp) color = '#FF0000'; - if (damage<=0) color = '#00FF00'; - - damage = core.formatBigNumber(damage); - if (core.enemys.hasSpecial(enemy, 19)) - damage += "+"; - if (core.enemys.hasSpecial(enemy, 21)) - damage += "-"; - if (core.enemys.hasSpecial(enemy, 11)) - damage += "^"; - } - if (enemy.notBomb) - damage += "[b]"; - core.fillText('ui', damage, damageOffset, 62 * i + 50, color, 'bold 13px '+globalFont); - - core.setTextAlign('ui', 'left'); - - core.fillText('ui', '临界', 165, 62 * i + 68, '#DDDDDD', '13px '+globalFont); - core.fillText('ui', core.formatBigNumber(enemy.critical||0), 195, 62 * i + 68, '#DDDDDD', 'bold 13px '+globalFont); - core.fillText('ui', '减伤', 255, 62 * i + 68, '#DDDDDD', '13px '+globalFont); - core.fillText('ui', core.formatBigNumber(enemy.criticalDamage||0), 285, 62 * i + 68, '#DDDDDD', 'bold 13px '+globalFont); - core.fillText('ui', '1防', 335, 62 * i + 68, '#DDDDDD', '13px '+globalFont); - core.fillText('ui', core.formatBigNumber(enemy.defDamage||0), 365, 62 * i + 68, '#DDDDDD', 'bold 13px '+globalFont); - - if (index == start+i) { - core.strokeRect('ui', 10, 62 * i + 13, 416-10*2, 62, '#FFD700'); - } - - } - core.drawBoxAnimate(); - this.drawPagination(page, totalPage, 12); +ui.prototype._drawBook_drawNameCol = function (index, enemy, top, left, width) { + // 绘制第零列(名称和特殊属性) + // 如果需要添加自己的比如怪物的称号等,也可以在这里绘制 core.setTextAlign('ui', 'center'); - // 退出 - core.fillText('ui', '返回游戏', 370, 403,'#DDDDDD', 'bold 15px '+globalFont); + if (enemy.specialText=='') { + core.fillText('ui', enemy.name, left + width / 2, + top + 35, '#DDDDDD', this._buildFont(17, true)); + } + else { + core.fillText('ui', enemy.name, left + width / 2, + top + 28, '#DDDDDD', this._buildFont(17, true)); + core.fillText('ui', enemy.specialText, left + width / 2, + top + 50, '#FF6A6A', this._buildFont(15, true)); + } +} + +ui.prototype._drawBook_drawCol1 = function (index, enemy, top, left, width, second_line) { + // 绘制第一列 + core.setTextAlign('ui', 'left'); + var b13 = this._buildFont(13, true), f13 = this._buildFont(13, false); + core.fillText('ui', '生命', left, top + 20, '#DDDDDD', f13); + core.fillText('ui', core.formatBigNumber(enemy.hp||0), left + 30, top + 20, null, b13); + if (second_line.length>0) { + var one = second_line.shift(); + core.fillText('ui', one[0], left, top + 38, '#DDDDDD', f13); + core.fillText('ui', one[1], left + 30, top + 38, null, b13); + } + core.fillText('ui', '临界', left, top + 56, '#DDDDDD', f13); + core.fillText('ui', core.formatBigNumber(enemy.critical||0), left + 30, top + 56, null, b13); +} + +ui.prototype._drawBook_drawCol2 = function (index, enemy, top, left, width, second_line) { + // 绘制第二列 + core.setTextAlign('ui', 'left'); + var b13 = this._buildFont(13, true), f13 = this._buildFont(13, false); + core.fillText('ui', '攻击', left, top + 20, '#DDDDDD', f13); + core.fillText('ui', core.formatBigNumber(enemy.atk||0), left + 30, top + 20, null, b13); + if (second_line.length>0) { + var one = second_line.shift(); + core.fillText('ui', one[0], left, top + 38, '#DDDDDD', f13); + core.fillText('ui', one[1], left + 30, top + 38, null, b13); + } + core.fillText('ui', '减伤', left, top + 56, '#DDDDDD', f13); + core.fillText('ui', core.formatBigNumber(enemy.criticalDamage||0), left + 30, top + 56, null, b13); +} + +ui.prototype._drawBook_drawCol3 = function (index, enemy, top, left, width) { + // 绘制第三列 + core.setTextAlign('ui', 'left'); + var b13 = this._buildFont(13, true), f13 = this._buildFont(13, false); + core.fillText('ui', '防御', left, top + 20, '#DDDDDD', f13); + core.fillText('ui', core.formatBigNumber(enemy.def||0), left + 30, top + 20, null, b13); + core.fillText('ui', '1防', left, top + 56, '#DDDDDD', f13); + core.fillText('ui', core.formatBigNumber(enemy.defDamage||0), left + 30, top + 56, null, b13); +} + +ui.prototype._drawBook_drawDamage = function (index, enemy, top, damageOffset) { + core.setTextAlign('ui', 'center'); + var damage = enemy.damage, color = '#FFFF00'; + if (damage == null) { + damage = '无法战斗'; + color = '#FF0000'; + } + else { + if (damage >= core.status.hero.hp) color = '#FF0000'; + if (damage <= 0) color = '#00FF00'; + damage = core.formatBigNumber(damage); + if (core.enemys.hasSpecial(enemy, 19)) damage += "+"; + if (core.enemys.hasSpecial(enemy, 21)) damage += "-"; + if (core.enemys.hasSpecial(enemy, 11)) damage += "^"; + } + if (enemy.notBomb) damage += "[b]"; + core.fillText('ui', damage, damageOffset, top + 38, color, this._buildFont(13, true)); } ////// 绘制怪物属性的详细信息 ////// ui.prototype.drawBookDetail = function (index) { + var info = this._drawBookDetail_getInfo(index), enemy = info[0]; + var content = info[1].join("\n"); + core.status.event.id = 'book-detail'; + clearInterval(core.interval.tipAnimate); + core.clearMap('data'); + + var left = 10, width = this.PIXEL - 2 * left, right = left + width; + var content_left = left + 25, validWidth = right - content_left - 13; + var contents = core.splitLines("data", content, validWidth, this._buildFont(16, false)); + var height = Math.max(24 * contents.length + 55, 80), top = (this.PIXEL - height) / 2, bottom = top + height; + + core.setAlpha('data', 0.9); + core.fillRect('data', left, top, width, height, '#000000'); + core.setAlpha('data', 1); + core.strokeRect('data', left - 1, top - 1, width + 1, height + 1, + core.status.globalAttribute.borderColor, 2); + + this._drawBookDetail_drawContent(enemy, contents, {top: top, content_left: content_left, bottom: bottom}); +} + +ui.prototype._drawBookDetail_getInfo = function (index) { var floorId = core.floorIds[(core.status.event.ui||{}).index] || core.status.floorId; var enemys = core.enemys.getCurrentEnemys(floorId); - if (enemys.length==0) return; - if (index<0) index=0; - if (index>=enemys.length) index=enemys.length-1; - + index = core.clamp(index, 0, enemys.length - 1); var enemy = enemys[index], enemyId = enemy.id; - var hints=core.enemys.getSpecialHint(enemyId); - var damageInfo = core.enemys.getDamageInfo(enemy, null, null, null, floorId); + var texts=core.enemys.getSpecialHint(enemyId); + if (texts.length == 0) texts.push("该怪物无特殊属性。"); + texts.push(""); + this._drawBookDetail_getTexts(enemy, floorId, texts); + return [enemy, texts]; +} - if (hints.length==0) - hints.push("该怪物无特殊属性。"); +ui.prototype._drawBookDetail_getTexts = function (enemy, floorId, texts) { + // --- 模仿临界计算器 + this._drawBookDetail_mofang(enemy, texts); + // --- 吸血怪最低生命值 + this._drawBookDetail_vampire(enemy, texts); + // --- 仇恨伤害 + this._drawBookDetail_hatred(enemy, texts); + // --- 战斗回合数,临界表 + this._drawBookDetail_turnAndCriticals(enemy, floorId, texts); +} +ui.prototype._drawBookDetail_mofang = function (enemy, texts) { // 模仿临界计算器 if (core.enemys.hasSpecial(enemy.special, 10)) { var hp = enemy.hp; var delta = core.status.hero.atk - core.status.hero.def; if (delta0) { - hints.push(""); - hints.push("模仿临界计算器:(当前攻防差"+core.formatBigNumber(delta)+")"); - var arr = []; - (function () { - var last=0, start=0; - for (var i=1;i=0) { var x1 = text.substring(0, index+1); - core.fillText('data', x1, content_left, content_top, '#FF6A6A', 'bold 16px '+globalFont); + core.fillText('data', x1, pos.content_left, content_top, '#FF6A6A', this._buildFont(16, true)); var len=core.calWidth('data', x1); - core.fillText('data', text.substring(index+1), content_left+len, content_top, '#FFFFFF', '16px '+globalFont); + core.fillText('data', text.substring(index+1), pos.content_left+len, content_top, '#FFFFFF', this._buildFont(16, false)); } else { - core.fillText('data', contents[i], content_left, content_top, '#FFFFFF', '16px '+globalFont); + core.fillText('data', contents[i], pos.content_left, content_top, '#FFFFFF', this._buildFont(16, false)); } content_top+=24; } - - core.fillText('data', '<点击任意位置继续>', 270, top+height-13, '#CCCCCC', '13px '+globalFont); } ////// 绘制楼层传送器 ////// ui.prototype.drawFly = function(page) { - core.status.event.data = page; - var floorId = core.floorIds[page]; var title = core.status.maps[floorId].title; - core.clearMap('ui'); core.setAlpha('ui', 0.85); - core.fillRect('ui', 0, 0, 416, 416, '#000000'); + core.fillRect('ui', 0, 0, this.PIXEL, this.PIXEL, '#000000'); core.setAlpha('ui', 1); core.setTextAlign('ui', 'center'); - var globalFont = core.status.globalAttribute.font - core.fillText('ui', '楼层跳跃', 208, 60, '#FFFFFF', "bold 28px "+globalFont); - core.fillText('ui', '返回游戏', 208, 403, '#FFFFFF', "bold 15px "+globalFont) - core.fillText('ui', title, 356, 247, '#FFFFFF', "bold 19px "+globalFont); + core.fillText('ui', '楼层跳跃', this.HPIXEL, 60, '#FFFFFF', this._buildFont(28, true)); + core.fillText('ui', '返回游戏', this.HPIXEL, this.PIXEL - 13, null, this._buildFont(15, true)) + core.fillText('ui', title, this.PIXEL - 60, this.HPIXEL + 39, null, this._buildFont(19, true)); + var middle = this.HPIXEL + 39; if (core.actions._getNextFlyFloor(1) != page) { - core.fillText('ui', '▲', 356, 247 - 64, '#FFFFFF', "17px "+globalFont); - core.fillText('ui', '▲', 356, 247 - 96, '#FFFFFF', "17px "+globalFont); - core.fillText('ui', '▲', 356, 247 - 96 - 7, '#FFFFFF', "17px "+globalFont); + core.fillText('ui', '▲', this.PIXEL - 60, middle - 64, null, this._buildFont(17, false)); + core.fillText('ui', '▲', this.PIXEL - 60, middle - 96,); + core.fillText('ui', '▲', this.PIXEL - 60, middle - 96 - 7); } if (core.actions._getNextFlyFloor(-1) != page) { - core.fillText('ui', '▼', 356, 247 + 64, '#FFFFFF', "17px "+globalFont); - core.fillText('ui', '▼', 356, 247 + 96, '#FFFFFF', "17px "+globalFont); - core.fillText('ui', '▼', 356, 247 + 96 + 7, '#FFFFFF', "17px "+globalFont); + core.fillText('ui', '▼', this.PIXEL - 60, middle + 64, null, this._buildFont(17, false)); + core.fillText('ui', '▼', this.PIXEL - 60, middle + 96); + core.fillText('ui', '▼', this.PIXEL - 60, middle + 96 + 7); } - core.strokeRect('ui', 20, 100, 273, 273, '#FFFFFF', 2); - - core.drawThumbnail(floorId, null, null, {ctx: 'ui', x: 20, y: 100, size: 273}); + var size = this.PIXEL - 143; + core.strokeRect('ui', 20, 100, size, size, '#FFFFFF', 2); + core.drawThumbnail(floorId, null, null, {ctx: 'ui', x: 20, y: 100, size: size}); } ////// 绘制中心对称飞行器 @@ -1844,100 +1618,94 @@ ui.prototype.drawShop = function (shopId) { ui.prototype.drawMaps = function (index, x, y) { core.lockControl(); core.status.event.id = 'viewMaps'; - - if (!core.isset(index)) { - core.status.event.data = null; - core.clearSelector(); - - core.fillRect('ui', 0, 0, 416, 416, 'rgba(0,0,0,0.4)'); - - core.strokeRect('ui', 66, 2, 284, 60, "#FFD700", 4); - core.strokeRect('ui', 2, 66, 60, 284); - core.strokeRect('ui', 66, 416-62, 284, 60); - core.strokeRect('ui', 416-62, 66, 60, 284); - core.strokeRect('ui', 66, 66, 284, 92); - core.strokeRect('ui', 66, 32*8+2, 284, 92); - core.setTextAlign('ui', 'center'); - core.fillText('ui', "上移地图 [W]", 208, 38, '#FFD700', '20px Arial'); - core.fillText('ui', "下移地图 [S]", 208, 390); - - core.strokeRect('ui', 2, 2, 28, 28); - core.fillText('ui', 'V', 16, 24); - core.strokeRect('ui', 2, 416-30, 28, 28); - core.fillText('ui', 'M', 16, 408); - core.strokeRect('ui', 416-30, 2, 28, 28); - core.fillText('ui', 'Z', 400, 24); - - var top = 150; - core.fillText('ui', "左", 32, top); - core.fillText('ui', "移", 32, top+32); - core.fillText('ui', "地", 32, top+32*2); - core.fillText('ui', "图", 32, top+32*3); - core.fillText('ui', "[A]", 32, top+32*4); - core.fillText('ui', "右", 384, top); - core.fillText('ui', "移", 384, top+32); - core.fillText('ui', "地", 384, top+32*2); - core.fillText('ui', "图", 384, top+32*3); - core.fillText('ui', "[D]", 384, top+32*4); - - core.fillText('ui', "前张地图 [▲ / PGUP]", 208, 64+54); - core.fillText('ui', "后张地图 [▼ / PGDN]", 208, 32*8+54); - - core.fillText('ui', "退出 [ESC / ENTER]", 208, 208+8); - core.fillText('ui', "[X] 可查看怪物手册", 285, 208+40, null, '13px Arial'); - - return; - } - - var damage = (core.status.event.data||{}).damage, paint = (core.status.event.data||{}).paint; - var all = (core.status.event.data||{}).all; - if (core.isset(index.damage)) damage=index.damage; - if (core.isset(index.paint)) paint=index.paint; - if (core.isset(index.all)) all=index.all; - - if (core.isset(index.index)) { - x=index.x; - y=index.y; - index=index.index; - } - - if (index<0) index=0; - if (index>=core.floorIds.length) index=core.floorIds.length-1; - var floorId = core.floorIds[index], mw = core.floors[floorId].width, mh = core.floors[floorId].height; - if (!core.isset(x)) x = parseInt(mw/2); - if (!core.isset(y)) y = parseInt(mh/2); - if (x<6) x=6; - if (x>mw-7) x=mw-7; - if (y<6) y=6; - if (y>mh-7) y=mh-7; - - core.status.event.data = {"index": index, "x": x, "y": y, "damage": damage, "paint": paint, "all": all}; - + this.clearUI(); + if (index == null) return this._drawMaps_drawHint(); clearTimeout(core.interval.tipAnimate); - core.clearSelector(); core.status.checkBlock.cache = {}; - core.drawThumbnail(floorId, null, {damage: damage}, {ctx: 'ui', centerX: x, centerY: y, all: all}); - + var data = this._drawMaps_buildData(index, x, y); + core.drawThumbnail(data.floorId, null, {damage: data.damage}, + {ctx: 'ui', centerX: data.x, centerY: data.y, all: data.all}); // 绘图 - if (core.status.event.data.paint) { - var offsetX = core.clamp(x-6, 0, mw-13), offsetY = core.clamp(y-6, 0, mh-13); - var value = core.paint[floorId]; - if (core.isset(value)) value = lzw_decode(value).split(","); - core.utils.decodeCanvas(value, 32*mw, 32*mh); - core.drawImage('ui', core.bigmap.tempCanvas.canvas, offsetX*32, offsetY*32, 416, 416, 0, 0, 416, 416); + if (data.paint) { + var offsetX = 32 * (data.x - this.HSIZE), offsetY = 32 * (data.y - this.HSIZE); + var value = core.paint[data.floorId]; + if (value) value = lzw_decode(value).split(","); + core.utils.decodeCanvas(value, 32 * data.mw, 32 * data.mh); + core.drawImage('ui', core.bigmap.tempCanvas.canvas, offsetX * 32, offsetY * 32, + this.PIXEL, this.PIXEL, 0, 0, this.PIXEL, this.PIXEL); } - core.clearMap('data'); core.setTextAlign('data', 'left'); core.setFont('data', '16px Arial'); - - var text = core.status.maps[floorId].title; - if (!all && (mw>13 || mh>13)) text+=" ["+(x-6)+","+(y-6)+"]"; + var text = core.status.maps[data.floorId].title; + if (!data.all && (data.mw>this.SIZE || data.mh>this.SIZE)) + text+=" ["+(data.x-this.HSIZE)+","+(data.y-this.HSIZE)+"]"; var textX = 16, textY = 18, width = textX + core.calWidth('data', text) + 16, height = 42; core.fillRect('data', 5, 5, width, height, 'rgba(0,0,0,0.4)'); core.fillText('data', text, textX + 5, textY + 15, 'rgba(255,255,255,0.6)'); } +ui.prototype._drawMaps_drawHint = function () { + core.fillRect('ui', 0, 0, this.PIXEL, this.PIXEL, 'rgba(0,0,0,0.4)'); + core.setTextAlign('ui', 'center'); + var stroke = function (left, top, width, height, fillStyle, lineWidth) { + core.strokeRect('ui', left*32+2, top*32+2, width*32-4, height*32-4, fillStyle, lineWidth); + } + var per = this.HSIZE - 4; + stroke(per, 0, 9, per, '#FFD700', 4); // up + stroke(0, per, per, 9); // left + stroke(per, this.SIZE - per, 9, per); // down + stroke(this.SIZE - per, per, per, 9); // right + stroke(per, per, 9, 3); // prev + stroke(per, this.SIZE - per - 3, 9, 3); // next + stroke(0, 0, per-1, per-1); // left top + stroke(this.SIZE-(per - 1), 0, per-1, per-1); // right top + stroke(0, this.SIZE-(per-1), per-1, per-1); // left bottom + + core.setTextBaseline('ui', 'middle'); + core.fillText('ui', "上移地图 [W]", this.HPIXEL, per * 16, '#FFD700', '20px Arial'); + core.fillText('ui', "下移地图 [S]", this.HPIXEL, this.PIXEL - per * 16); + core.fillText('ui', 'V', (per-1)*16, (per-1)*16); + core.fillText('ui', 'Z', this.PIXEL - (per-1)*16, (per-1)*16); + core.fillText('ui', 'M', (per-1)*16, this.PIXEL - (per-1)*16); + + var top = this.HPIXEL - 66, left = per * 16, right = this.PIXEL - left; + var lt = ["左", "移", "地", "图", "[A]"], rt = ["右", "移", "地", "图", "[D]"]; + for (var i = 0; i < 5; ++i) { + core.fillText("ui", lt[i], left, top + 32 * i); + core.fillText("ui", rt[i], right, top + 32 * i); + } + core.fillText('ui', "前张地图 [▲ / PGUP]", this.HPIXEL, 32 * per + 48); + core.fillText('ui', "后张地图 [▼ / PGDN]", this.HPIXEL, this.PIXEL - (32 * per + 48)); + + core.fillText('ui', "退出 [ESC / ENTER]", this.HPIXEL, this.HPIXEL); + core.fillText('ui', "[X] 可查看怪物手册", this.HPIXEL + 77, this.HPIXEL + 32, null, '13px Arial'); + + core.setTextBaseline('ui', 'alphabetic'); +} + +ui.prototype._drawMaps_buildData = function (index, x, y) { + var damage = (core.status.event.data||{}).damage; + var paint = (core.status.event.data||{}).paint; + var all = (core.status.event.data||{}).all; + if (index.damage != null) damage=index.damage; + if (index.paint != null) paint=index.paint; + if (index.all != null) all=index.all; + if (index.index != null) { x=index.x; y=index.y; index=index.index; } + index = core.clamp(index, 0, core.floorIds.length-1); + if (damage == null) damage = true; // 浏览地图默认开显伤好了 + + var floorId = core.floorIds[index], mw = core.floors[floorId].width, mh = core.floors[floorId].height; + if (x == null) x = parseInt(mw / 2); + if (y == null) y = parseInt(mh / 2); + x = core.clamp(x, this.HSIZE, mw - this.HSIZE - 1); + y = core.clamp(y, this.HSIZE, mh - this.HSIZE - 1); + + core.status.event.data = {index: index, x: x, y: y, floorId: floorId, mw: mw, mh: mh, + damage: damage, paint: paint, all: all }; + return core.status.event.data; +} + ////// 绘制道具栏 ////// ui.prototype.drawToolbox = function(index) { // 设定eventdata @@ -2403,41 +2171,19 @@ ui.prototype.drawSLPanel = function(index, refresh) { ui.prototype.drawKeyBoard = function () { core.lockControl(); core.status.event.id = 'keyBoard'; + core.clearUI(); - core.clearSelector(); - - var left = 16, top = 48, width = 416 - 2 * left, height = 416 - 2 * top; - - var background = core.status.textAttribute.background; - var isWindowSkin = false; - if (typeof background == 'string') { - background = core.material.images.images[background]; - if (core.isset(background) && background.width==192 && background.height==128) isWindowSkin = true; - else background = core.initStatus.textAttribute.background; - } - if (!isWindowSkin) background = core.arrayToRGBA(background); - var borderColor = core.status.globalAttribute.borderColor; - var titleColor = core.arrayToRGBA(core.status.textAttribute.title); - var textColor = core.arrayToRGBA(core.status.textAttribute.text); - - core.clearMap('ui'); - if (isWindowSkin) { - core.setAlpha('ui', 0.85); - this.drawWindowSkin(background,'ui',left,top,width,height); - } - else { - core.fillRect('ui', left, top, width, height, background); - core.strokeRect('ui', left - 1, top - 1, width + 1, height + 1, borderColor, 2); - } - core.setAlpha('ui', 1); + var width = 384, height = 320; + var left = (this.PIXEL - width) / 2, right = left + width; + var top = (this.PIXEL - height) / 2, bottom = top + height; + var isWindowSkin = this._drawTextBox_drawBackground({}, {}, {left:left, right:right}, {top:top, bottom: bottom}); core.setTextAlign('ui', 'center'); - var globalFont = core.status.globalAttribute.font; - core.fillText('ui', "虚拟键盘", 208, top+35, titleColor, "bold 22px "+globalFont); - - core.setFont('ui', '17px '+globalFont); - core.setFillStyle('ui', textColor); - var offset = 128-9; + core.setFillStyle('ui', core.arrayToRGBA(core.status.textAttribute.title)); + core.fillText('ui', '虚拟键盘', this.HPIXEL, top + 35, null, this._buildFont(22, true)); + core.setFont('ui', this._buildFont(17, false)); + core.setFillStyle('ui', core.arrayToRGBA(core.status.textAttribute.text)); + var offset = this.HPIXEL - 89; var lines = [ ["F1","F2","F3","F4","F5","F6","F7","F8","F9","10","11"], @@ -2451,17 +2197,17 @@ ui.prototype.drawKeyBoard = function () { lines.forEach(function (line) { for (var i=0;i0) t+=atk+"攻"; - if (def>0) t+=def+"防"; - if (mdef>0) t+=mdef+"魔防"; - if (t!="") ext[id]=t; - } - - total.count[id]++; - total.add.hp+=hp; - total.add.atk+=atk; - total.add.def+=def; - total.add.mdef+=mdef; - if (floorId==core.status.floorId) { - current.count[id]++; - current.add.hp+=hp; - current.add.atk+=atk; - current.add.def+=def; - current.add.mdef+=mdef; - } - } - } - }) - }) - - var getText = function (type, data) { - var text = type+"地图中:\n"; - text += "共有怪物"+data.monster.count+"个"; - if (core.flags.enableMoney) text+=",总金币数"+data.monster.money; - if (core.flags.enableExperience) text+=",总经验数"+data.monster.experience; - if (core.flags.enableAddPoint) text+=",总加点数"+data.monster.point; - text+="。\n"; - - var prev = ""; - ids.forEach(function (key) { - var value = data.count[key]; - if (value==0) return; - var c = cls[key]; - if (c!=prev) { - if (prev != "") text += "。"; - text += "\n"; - } - else - text += ","; - prev = c; - var name = null; - if (key=='yellowDoor') name="黄门"; - else if (key=='blueDoor') name="蓝门"; - else if (key=='redDoor') name="红门"; - else if (key=='greenDoor') name="绿门"; - else if (key=='steelDoor') name="铁门"; - else name=core.material.items[key].name; - text+=name+value+"个"; - if (core.isset(ext[key])) - text+="("+ext[key]+")"; - }) - - if (prev!="") text+="。"; - text+="\n\n"; - text+="共加生命值"+core.formatBigNumber(data.add.hp)+"点,攻击" - +core.formatBigNumber(data.add.atk)+"点,防御" - +core.formatBigNumber(data.add.def)+"点,魔防" - +core.formatBigNumber(data.add.mdef)+"点。"; - return text; - } - var formatTime = function (time) { return core.setTwoDigits(parseInt(time/3600000)) +":"+core.setTwoDigits(parseInt(time/60000)%60) +":"+core.setTwoDigits(parseInt(time/1000)%60); } - var statistics = core.status.hero.statistics; core.drawText([ - getText("全塔", total), - getText("当前", current), + this._drawStatistics_generateText(obj, "全塔", obj.total), + this._drawStatistics_generateText(obj, "当前", obj.current), "当前总步数:"+core.status.hero.steps+",当前游戏时长:"+formatTime(statistics.currTime) +",总游戏时长"+formatTime(statistics.totalTime) +"。\n瞬间移动次数:"+statistics.moveDirectly+",共计少走"+statistics.ignoreSteps+"步。" @@ -2652,10 +2242,148 @@ ui.prototype.drawStatistics = function () { +",领域/夹击/阻击/血网伤害"+core.formatBigNumber(statistics.extraDamage)+"点。", "\t[说明]1. 地图数据统计的效果仅模拟当前立刻获得该道具的效果。\n2. 不会计算“不可被浏览地图”的隐藏层的数据。\n" + "3. 不会计算任何通过事件得到的道具(显示事件、改变图块、或直接增加道具等)。\n"+ - "4. 在自定义道具(例如其他宝石)后,需在ui.js的drawStatistics中注册,不然不会进行统计。\n"+ + "4. 在自定义道具(例如其他宝石)后,需在脚本编辑的drawStatistics中注册,不然不会进行统计。\n"+ "5. 所有统计信息仅供参考,如有错误,概不负责。" ]) +} +ui.prototype._drawStatistics_buildObj = function () { + // 数据统计要统计如下方面: + // 1. 当前全塔剩余下的怪物数量,总金币数,总经验数,总加点数 + // 2. 当前全塔剩余的黄蓝红铁门数量,和对应的钥匙数量 + // 3. 当前全塔剩余的三种宝石数量,血瓶数量,装备数量;总共增加的攻防生命值 + // 4. 当前层的上述信息 + // 5. 当前已走的步数;瞬间移动的步数,瞬间移动的次数(和少走的步数);游戏时长 + // 6. 当前已恢复的生命值;当前总伤害、战斗伤害、阻激夹域血网伤害、中毒伤害。 + var ori = this.uidata.drawStatistics(); + var ids = ori.filter(function (e) { + return e.endsWith("Door") || core.material.items[e]; + }); + var cnt = {}, cls = {}, ext = {}; + ids.forEach(function (e) { + if (e.endsWith("Door")) cls[e] = "doors"; + else cls[e] = core.material.items[e].cls; + cnt[e] = 0; + }) + var order = ["doors", "keys", "items", "tools", "constants", "equips"]; + ids.sort(function (a, b) { + var c1 = order.indexOf(cls[a]), c2 = order.indexOf(cls[b]); + if (c1==c2) return ori.indexOf(a)-ori.indexOf(b); + return c1-c2; + }); + var obj = { + 'monster': { + 'count': 0, 'money': 0, 'experience': 0, 'point': 0, + }, + 'count': cnt, + 'add': { + 'hp': 0, 'atk': 0, 'def': 0, 'mdef': 0 + } + }; + return {ids: ids, cls: cls, ext: ext, total: core.clone(obj), current: core.clone(obj)}; +} + +ui.prototype._drawStatistics_add = function (floorId, obj, x1, x2, value) { + obj.total[x1][x2] += value || 0; + if (floorId == core.status.floorId) + obj.current[x1][x2] += value || 0; +} + +ui.prototype._drawStatistics_floorId = function (floorId, obj) { + var floor = core.status.maps[floorId], blocks = floor.blocks; + // 隐藏层不给看 + if (floor.cannotViewMap && floorId!=core.status.floorId) return; + blocks.forEach(function (block) { + if (block.disable) return; + var event = block.event; + if (event.cls.indexOf("enemy")==0) { + core.ui._drawStatistics_enemy(floorId, event.id, obj); + } + else { + var id = event.id; + if (obj.total.count[id] != null) + core.ui._drawStatistics_items(floorId, floor, id, obj); + } + }) +} + +ui.prototype._drawStatistics_enemy = function (floorId, id, obj) { + var enemy = core.material.enemys[id]; + this._drawStatistics_add(floorId, obj, 'monster', 'money', enemy.money); + this._drawStatistics_add(floorId, obj, 'monster', 'experience', enemy.experience); + this._drawStatistics_add(floorId, obj, 'monster', 'point', enemy.point); + this._drawStatistics_add(floorId, obj, 'monster', 'count', 1); +} + +ui.prototype._drawStatistics_items = function (floorId, floor, id, obj) { + var hp=0, atk=0, def=0, mdef=0; + if (obj.cls[id]=='items' && id!='superPotion') { + var temp = core.clone(core.status.hero); + core.setFlag("__statistics__", true); + var ratio = floor.item_ratio||1; + try { eval(core.items.itemEffect[id]); } + catch (e) {} + hp = core.status.hero.hp - temp.hp; + atk = core.status.hero.atk - temp.atk; + def = core.status.hero.def - temp.def; + mdef = core.status.hero.mdef - temp.mdef; + core.status.hero = temp; + } + else if (obj.cls[id]=='equips') { + var values = core.material.items[id].equip || {}; + atk = values.atk || 0; + def = values.def || 0; + mdef = values.mdef || 0; + } + if (id.indexOf('sword')==0 || id.indexOf('shield')==0 || obj.cls[id]=='equips') { + var t = ""; + if (atk > 0) t += atk + "攻"; + if (def > 0) t += def + "防"; + if (mdef > 0) t += mdef + "魔防"; + if (t != "") obj.ext[id] = t; + } + this._drawStatistics_add(floorId, obj, 'count', id, 1); + this._drawStatistics_add(floorId, obj, 'add', 'hp', hp); + this._drawStatistics_add(floorId, obj, 'add', 'atk', atk); + this._drawStatistics_add(floorId, obj, 'add', 'def', def); + this._drawStatistics_add(floorId, obj, 'add', 'mdef', mdef); +} + +ui.prototype._drawStatistics_generateText = function (obj, type, data) { + var text = type+"地图中:\n"; + text += "共有怪物"+data.monster.count+"个"; + if (core.flags.enableMoney) text+=",总金币数"+data.monster.money; + if (core.flags.enableExperience) text+=",总经验数"+data.monster.experience; + if (core.flags.enableAddPoint) text+=",总加点数"+data.monster.point; + text+="。\n"; + + var prev = ""; + obj.ids.forEach(function (key) { + var value = data.count[key]; + if (value==0) return; + if (obj.cls[key] != prev) { + if (prev != "") text += "。"; + text += "\n"; + } + else text += ","; + prev = obj.cls[key]; + text+=core.ui._drawStatistics_getName(key)+value+"个"; + if (obj.ext[key]) + text+="("+obj.ext[key]+")"; + }) + if (prev!="") text+="。"; + + text+="\n\n"; + text+="共加生命值"+core.formatBigNumber(data.add.hp)+"点,攻击" + +core.formatBigNumber(data.add.atk)+"点,防御" + +core.formatBigNumber(data.add.def)+"点,魔防" + +core.formatBigNumber(data.add.mdef)+"点。"; + return text; +} + +ui.prototype._drawStatistics_getName = function (key) { + return {"yellowDoor": "黄门", "blueDoor": "蓝门", "redDoor": "红门", "greenDoor": "绿门", + "steelDoor": "铁门"}[key] || core.material.items[key].name; } ////// 绘制“关于”界面 ////// @@ -2665,44 +2393,45 @@ ui.prototype.drawAbout = function () { ////// 绘制“画图”界面 ////// ui.prototype.drawPaint = function () { - core.drawText( "\t[进入绘图模式]你可以在此页面上任意进行绘图和标记操作。\nM键可以进入或退出此模式。\n\n"+ "绘图的内容会自动保存,且以页面为生命周期,和存读档无关,重新开始游戏或读档后绘制的内容仍有效,但刷新页面就会消失。\n"+ "你可以将绘制内容保存到文件,也可以从文件读取保存的绘制内容。\n"+ "浏览地图页面可以按楼传按钮或M键来开启/关闭该层的绘图显示。\n\n更多功能请详见文档-元件-绘图模式。", - function () { - core.drawTip("打开绘图模式,现在可以任意在界面上绘图标记"); - - core.lockControl(); - core.status.event.id = 'paint'; - core.status.event.data = {"x": null, "y": null, "erase": false}; - - core.clearSelector(); - core.createCanvas('paint', -core.bigmap.offsetX, -core.bigmap.offsetY, 32*core.bigmap.width, 32*core.bigmap.height, 95); - - // 将已有的内容绘制到route上 - var value = core.paint[core.status.floorId]; - if (core.isset(value)) value = lzw_decode(value).split(","); - core.utils.decodeCanvas(value, 32*core.bigmap.width, 32*core.bigmap.height); - core.drawImage('paint', core.bigmap.tempCanvas.canvas, 0, 0); - - core.setLineWidth('paint', 3); - core.setStrokeStyle('paint', '#FF0000'); - - core.statusBar.image.keyboard.style.opacity = 0; - core.statusBar.image.shop.style.opacity = 0; - - core.statusBar.image.book.src = core.statusBar.icons.paint.src; - core.statusBar.image.fly.src = core.statusBar.icons.erase.src; - core.statusBar.image.toolbox.src = core.statusBar.icons.empty.src; - core.statusBar.image.settings.src = core.statusBar.icons.exit.src; - core.statusBar.image.book.style.opacity = 1; - core.statusBar.image.fly.style.opacity = 1; - } + this._drawPaint_draw ); } +ui.prototype._drawPaint_draw = function () { + core.drawTip("打开绘图模式,现在可以任意在界面上绘图标记"); + + core.lockControl(); + core.status.event.id = 'paint'; + core.status.event.data = {"x": null, "y": null, "erase": false}; + + core.clearSelector(); + core.createCanvas('paint', -core.bigmap.offsetX, -core.bigmap.offsetY, 32*core.bigmap.width, 32*core.bigmap.height, 95); + + // 将已有的内容绘制到route上 + var value = core.paint[core.status.floorId]; + if (core.isset(value)) value = lzw_decode(value).split(","); + core.utils.decodeCanvas(value, 32*core.bigmap.width, 32*core.bigmap.height); + core.drawImage('paint', core.bigmap.tempCanvas.canvas, 0, 0); + + core.setLineWidth('paint', 3); + core.setStrokeStyle('paint', '#FF0000'); + + core.statusBar.image.keyboard.style.opacity = 0; + core.statusBar.image.shop.style.opacity = 0; + + core.statusBar.image.book.src = core.statusBar.icons.paint.src; + core.statusBar.image.fly.src = core.statusBar.icons.erase.src; + core.statusBar.image.toolbox.src = core.statusBar.icons.empty.src; + core.statusBar.image.settings.src = core.statusBar.icons.exit.src; + core.statusBar.image.book.style.opacity = 1; + core.statusBar.image.fly.style.opacity = 1; +} + ////// 绘制帮助页面 ////// ui.prototype.drawHelp = function () { core.clearSelector(); @@ -2710,7 +2439,8 @@ ui.prototype.drawHelp = function () { core.status.event.id = 'help'; core.lockControl(); core.setAlpha('ui', 1); - core.drawImage('ui', core.material.images.keyboard, 0, 0); + core.fillRect('ui', 0, 0, this.PIXEL, this.PIXEL, '#FFFFFF'); + core.drawImage('ui', core.material.images.keyboard, 32 * (this.HSIZE - 6), 32 * (this.HSIZE - 6)); } else { core.drawText([ 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; } diff --git a/project/functions.js b/project/functions.js index 64fc7537..64e05bf8 100644 --- a/project/functions.js +++ b/project/functions.js @@ -34,6 +34,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = var globalFlags = core.getFlag("globalFlags", {}); for (var key in globalFlags) core.flags[key] = globalFlags[key]; + core._init_sys_flags(); // 初始化界面,状态栏等 core.resize(); core.updateGlobalAttribute(); diff --git a/styles.css b/styles.css index 34bed2c4..a1d6649e 100644 --- a/styles.css +++ b/styles.css @@ -312,7 +312,7 @@ p#name { } #ui { - z-index: 160; + z-index: 140; } #data {