diff --git a/_server/functions.comment.js b/_server/functions.comment.js index 9b8c79dd..fc21ae17 100644 --- a/_server/functions.comment.js +++ b/_server/functions.comment.js @@ -31,11 +31,17 @@ var functions_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = "_lint": true, "_data": "游戏失败事件" }, + "changingFloor": { + "_leaf": true, + "_type": "textarea", + "_lint": true, + "_data": "正在切换楼层过程中的操作\n此函数的执行时间是在切换楼层过程中屏幕完全变黑的一刻" + }, "afterChangeFloor": { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "转换楼层结束的事件" + "_data": "转换楼层结束的事件\n此函数会在整个楼层切换完全结束后执行" }, "addPoint": { "_leaf": true, diff --git a/docs/api.md b/docs/api.md index bba4bba2..e908bcbd 100644 --- a/docs/api.md +++ b/docs/api.md @@ -184,12 +184,6 @@ core.trigger(x, y) [异步] 触发某个地点的事件。 -core.clearMap(mapName) -清空某个画布图层。 -mapName可为'bg', 'event', 'hero', 'event2', 'fg', 'damage', 'animate', 'weather', 'ui', 'data', 'all'之一。 -如果mapName为'all',则为清空所有画布;否则只清空对应的画布。 - - core.drawBlock(block) 重绘某个图块。block应为core.status.thisMap.blocks中的一项。 @@ -473,6 +467,86 @@ core.maps.removeBlockByIds(floorId, ids) ui.js主要用来进行UI窗口的绘制,比如对话框、怪物手册、楼传器、存读档界面等等。 +core.ui.getContextByName(name) +根据画布名找到一个画布的context;支持系统画布和自定义画布。如果不存在画布返回null。 + + +core.clearMap(name) +清空某个画布图层。 +name为画布名,可以是系统画布之一,也可以是任意自定义动态创建的画布名。 +如果name也可以是'all',若为all则为清空所有系统画布。 + + +core.ui.fillText(name, text, x, y, style, font) +在某个画布上绘制一段文字。 +name为画布名,可以是系统画布之一,也可以是任意自定义动态创建的画布名。(下同) +text为要绘制的文本,x,y为要绘制的坐标,style可选为绘制的样式,font可选为绘制的字体。 + + +core.ui.fillBoldText(canvas, text, style, x, y, font) +在某个画布上绘制一个描黑边的文字。 +canvas为要绘制的画布的context,text为文本,style为颜色样式,x,y坐标,font可选为要绘制的字体。 + + +core.ui.fillRect(name, x, y, width, height, style) +绘制一个矩形。style可选为绘制样式。 + + +core.ui.strokeRect(name, x, y, width, height, style) +绘制一个矩形的边框。 + + +core.ui.drawLine(name, x1, y1, x2, y2, style, lineWidth) +绘制一条线。lineWidth可选为线宽。 + + +core.ui.drawArrow(name, x1, y1, x2, y2, style, lineWidth) +绘制一个箭头。 + + +core.ui.setFont(name, font) / core.ui.setLineWidth(name, lineWidth) +设置一个画布的字体/线宽。 + + +core.ui.setAlpha(name, font) / core.ui.setOpacity(name, font) +设置一个画布的绘制不透明度和画布本身的不透明度。 +两者区别如下: + - setAlpha是设置"接下来绘制的内容的不透明度",不会对已经绘制的内容产生影响。比如setAlpha('ui', 0.5)则会在接下来的绘制中使用0.5的不透明度。 + - setOpacity是设置"画布本身的不透明度",已经绘制的内容也会产生影响。比如我已经在UI层绘制了一段文字,再setOpacity则也会看起来变得透明。 +尽量不要对系统画布使用setOpacity(因为会对已经绘制的内容产生影响),自定义创建的画布则不受此限制。 + + +core.ui.setFillStyle(name, style) / core.ui.setStrokeStype(name, style) +设置一个画布的填充样式/描边样式。 + + +core.ui.createCanvas(name, x, y, width, height, zIndex) +动态创建一个画布。name为要创建的画布名,如果已存在则会直接取用当前存在的。 +x,y为创建的画布相对窗口左上角的像素坐标,width,height为创建的长宽。 +zIndex为创建的纵向高度(关系到画布之间的覆盖),z值高的将覆盖z值低的;系统画布的z值可在个性化中查看。 +创建一个画布后,可以通过 core.dymCanvas[name] 进行调用。 + + +core.ui.findCanvas(name) +寻找一个自定义画布的索引;如果存在该画布则返回对应的索引,不存在画布则返回-1。 + + +core.ui.relocateCanvas(name, x, y) +重新定位一个自定义画布。 + + +core.ui.resizeCanvas(name, x, y) +重新设置一个自定义画布的大小。 + + +core.ui.deleteCanvas(name) +删除一个自定义画布。 + + +core.ui.deleteAllCanvas() +清空所有的自定义画布。 + + core.ui.drawThumbnail(floorId, canvas, blocks, x, y, size, heroLoc, heroIcon) 绘制一个缩略图,比如楼传器界面,存读档界面等情况。 floorId为目标楼层ID,canvas为要绘制到的图层,blocks为要绘制的所有图块。 diff --git a/docs/event.md b/docs/event.md index a16a6737..438ee9e7 100644 --- a/docs/event.md +++ b/docs/event.md @@ -2198,8 +2198,8 @@ if (core.getFlag("door",0)==2) { var replaying = core.status.replay.replaying; core.stopReplay(); core.waitHeroToStop(function() { - core.removeGlobalAnimate(0,0,true); - core.clearMap('all'); core.clearMap('curtain'); // 清空全地图 + core.clearMap('all'); // 清空全地图 + core.deleteAllCanvas(); core.drawText([ "\t[恭喜通关]你的分数是${status:hp}。" ], function () { diff --git a/docs/personalization.md b/docs/personalization.md index f88c49a2..ac67729c 100644 --- a/docs/personalization.md +++ b/docs/personalization.md @@ -8,21 +8,45 @@ HTML5魔塔是使用画布(canvas)来绘制,存在若干个图层,它们之间有一个覆盖关系,后面的图层将覆盖前面的图层。 -所有图层从低往高依次如下:(加[B]的代表该层是大地图) +所有图层从低往高依次如下:(加[B]的代表该层是大地图,[D]代表由系统按需动态创建,z-index代表该层的纵向高度) -- bg**[B]**:背景层;绘制背景图层素材bgmap,和背景贴图 -- event**[B]**:事件层;所有事件(道具、墙壁、NPC、怪物等)都绘制在这一层进行处理 -- hero:勇士层;主要用来绘制勇士 -- event2**[B]**:事件2层;本层主要用来绘制48x32的图片素材的上半部分(避免和勇士错位) -- fg**[B]**:前景层;绘制前景图层素材fgmap,和前景贴图 -- damage**[B]**:显伤层;主要用来绘制怪物显伤和领域显伤 -- animate:动画层;主要用来绘制动画。 -- weather:天气层;主要用来绘制天气(雨/雪/雾) -- route**[B]**:路线层;主要用来绘制勇士的行走路线图,也用来绘制图块的淡入/淡出效果,图块的移动等。 -- curtain:色调层;用来控制当前楼层的画面色调 -- image:图片层;主要用来绘制显示图片;该层之所以在curtain层上是为了可以在全黑时贴大头像图 -- ui:UI层;用来绘制一切UI窗口,如剧情文本、怪物手册、楼传器、系统菜单等等 -- data:数据层;用来绘制一些顶层的或更新比较快的数据,如左上角的提示,战斗界面中数据的变化等等。 +- bg**[B]**:背景层;绘制背景图层素材bgmap,和背景贴图 (z-index: 10) +- event**[B]**:事件层;所有事件(道具、墙壁、NPC、怪物等)都绘制在这一层进行处理 (z-index: 30) +- hero:勇士层;主要用来绘制勇士 (z-index: 40) +- event2**[B]**:事件2层;本层主要用来绘制48x32的图片素材的上半部分(避免和勇士错位) (z-index: 50) +- fg**[B]**:前景层;绘制前景图层素材fgmap,和前景贴图 (z-index: 60) +- damage**[B]**:显伤层;主要用来绘制怪物显伤和领域显伤 (z-index: 65) +- animate:动画层;主要用来绘制动画。 (z-index: 70) +- weather**[D]**:天气层;主要用来绘制天气(雨/雪/雾) (z-index: 80) +- route**[D]**:路线层;主要用来绘制勇士的行走路线图。 (z-index: 95) +- paint**[D]**:绘图层;主要用来进行绘图模式。(z-index: 95) +- curtain:色调层;用来控制当前楼层的画面色调 (z-index: 100) +- ui:UI层;用来绘制一切UI窗口,如剧情文本、怪物手册、楼传器、系统菜单等等 (z-index: 160) +- data:数据层;用来绘制一些顶层的或更新比较快的数据,如左上角的提示,战斗界面中数据的变化等等。 (z-index: 170) + +### 动态创建canvas + +从V2.5.3开始,可以在H5样板中任意动态创建canvas并进行使用。 + +使用`core.createCanvas(name, x, y, w, h, z)`来动态创建一个画布。 + +其中name为动态canvas名称,x,y,w,h为创建的画布相对窗口左上角的像素坐标和长宽,z为画布的纵向高度。 + +例如:`core.createCanvas('test', 10, 20, 100, 200, 74)` 创建了一个名为test的画布,其左上角相对窗口的像素坐标为(10,20),宽100高200,纵向高度74(在动画层和天气层之间)。 + +可以通过 `core.dymCanvas[name]` 来获得该画布的context;例如 `core.dymCanvas.test` 就是我们上面创建的画布的context,然后进行操作。 + +也可以简单的使用`core.fillText()`, `core.fillRect()`, `core.strokeRect()`等等对画布进行任意绘制。 + +``` js +core.fillText('test', '这是一段文字', 10, 30, '#FF0000', '16px Verdana'); // 绘制一段文本 +``` + +使用 `core.deleteCanvas(name)` 删除一个动态创建的画布,例如 `core.deleteCanvas('test')`。 + +`core.deleteAllCanvas()`可以删除所有动态创建的画布,`core.relocateCanvas(name, x, y)`和`core.resizeCanvas(name, x, y)`可以对画布的位置和大小进行改变。 + +更多详细API请参见[API列表](api)。 ## 自定义素材 diff --git a/editor-mobile.html b/editor-mobile.html index 1026c9dc..36dfd637 100644 --- a/editor-mobile.html +++ b/editor-mobile.html @@ -440,8 +440,6 @@ - - 此浏览器不支持HTML5 diff --git a/editor.html b/editor.html index 7f865e9b..bd022f4f 100644 --- a/editor.html +++ b/editor.html @@ -425,8 +425,6 @@ - - 此浏览器不支持HTML5 diff --git a/index.html b/index.html index 028c5a6a..fcf9b278 100644 --- a/index.html +++ b/index.html @@ -140,8 +140,6 @@ - - 此浏览器不支持HTML5 diff --git a/libs/actions.js b/libs/actions.js index f41f52dc..ab8abb3a 100644 --- a/libs/actions.js +++ b/libs/actions.js @@ -341,7 +341,7 @@ actions.prototype.ondown = function (loc) { } core.status.downTime = new Date(); - core.clearMap('route'); + core.deleteCanvas('route'); var pos={'x':x,'y':y} core.status.stepPostfix=[]; core.status.stepPostfix.push(pos); @@ -409,8 +409,7 @@ actions.prototype.onup = function () { var posy=core.status.stepPostfix[0].y; core.status.stepPostfix=[]; if (!core.status.lockControl) { - core.clearMap('route'); - core.canvas.route.restore(); + core.clearMap('ui'); } // 长按 @@ -2612,8 +2611,8 @@ actions.prototype.ondownPaint = function (x, y) { x+=core.bigmap.offsetX; y+=core.bigmap.offsetY; if (!core.status.event.data.erase) { - core.canvas.route.beginPath(); - core.canvas.route.moveTo(x, y); + core.dymCanvas.paint.beginPath(); + core.dymCanvas.paint.moveTo(x, y); } core.status.event.data.x = x; core.status.event.data.y = y; @@ -2624,12 +2623,12 @@ actions.prototype.onmovePaint = function (x, y) { x+=core.bigmap.offsetX; y+=core.bigmap.offsetY; if (core.status.event.data.erase) { - core.clearMap('route', x-10, y-10, 20, 20); + core.clearMap('paint', x-10, y-10, 20, 20); return; } var midx = (core.status.event.data.x+x)/2, midy = (core.status.event.data.y+y)/2; - core.canvas.route.quadraticCurveTo(midx, midy, x, y); - core.canvas.route.stroke(); + core.dymCanvas.paint.quadraticCurveTo(midx, midy, x, y); + core.dymCanvas.paint.stroke(); core.status.event.data.x = x; core.status.event.data.y = y; } @@ -2638,7 +2637,7 @@ actions.prototype.onupPaint = function () { core.status.event.data.x = null; core.status.event.data.y = null; // 保存 - core.paint[core.status.floorId] = LZString.compress(core.utils.encodeCanvas(core.canvas.route).join(",")); + core.paint[core.status.floorId] = LZString.compress(core.utils.encodeCanvas(core.dymCanvas.paint).join(",")); } actions.prototype.setPaintMode = function (mode) { @@ -2650,8 +2649,8 @@ actions.prototype.setPaintMode = function (mode) { } actions.prototype.clearPaint = function () { - core.clearMap('route'); - core.paint[core.status.floorId] = null; + core.clearMap('paint'); + delete core.paint[core.status.floorId]; core.drawTip("已清空绘图内容"); } @@ -2683,18 +2682,18 @@ actions.prototype.loadPaint = function () { core.paint[floorId] = LZString.compress(obj.paint[floorId]); } - core.clearMap('route'); + core.clearMap('paint'); var value = core.paint[core.status.floorId]; if (core.isset(value)) value = LZString.decompress(value).split(","); core.utils.decodeCanvas(value, 32*core.bigmap.width, 32*core.bigmap.height); - core.canvas.route.drawImage(core.bigmap.tempCanvas.canvas, 0, 0); + core.canvas.paint.drawImage(core.bigmap.tempCanvas.canvas, 0, 0); core.drawTip("读取绘图文件成功"); }) } actions.prototype.exitPaint = function () { - core.clearMap('route'); + core.deleteCanvas('paint'); core.ui.closePanel(); core.statusBar.image.shop.style.opacity = 1; core.updateStatusBar(); diff --git a/libs/control.js b/libs/control.js index 8f94e572..54bbfcd7 100644 --- a/libs/control.js +++ b/libs/control.js @@ -46,13 +46,6 @@ control.prototype.setRequestAnimationFrame = function () { core.animateFrame.speed = core.values.animateSpeed; - var scan = { - 'up': {'x': 0, 'y': -1}, - 'left': {'x': -1, 'y': 0}, - 'down': {'x': 0, 'y': 1}, - 'right': {'x': 1, 'y': 0} - }; - var draw = function(timestamp) { core.animateFrame.globalTime = core.animateFrame.globalTime||timestamp; @@ -127,12 +120,27 @@ control.prototype.setRequestAnimationFrame = function () { // Animate if (timestamp-core.animateFrame.animateTime>50 && core.isset(core.status.animateObjs) && core.status.animateObjs.length>0) { core.clearMap('animate'); - core.status.animateObjs = core.status.animateObjs.filter(function (obj) { - return obj.index < obj.animate.frames.length; - }); - core.status.animateObjs.forEach(function (obj) { - core.maps.drawAnimateFrame(obj.animate, obj.centerX, obj.centerY, obj.index++); - }); + // 更新帧 + var animateObjs = []; + for (var i=0;i30) { + if (core.isPlaying() && timestamp-core.animateFrame.weather.time>30 && core.isset(core.dymCanvas.weather)) { + var ctx = core.dymCanvas.weather; var ox = core.bigmap.offsetX, oy = core.bigmap.offsetY; if (core.animateFrame.weather.type == 'rain' && core.animateFrame.weather.level > 0) { core.clearMap('weather'); - core.canvas.weather.strokeStyle = 'rgba(174,194,224,0.8)'; - core.canvas.weather.lineWidth = 1; - core.canvas.weather.lineCap = 'round'; + ctx.strokeStyle = 'rgba(174,194,224,0.8)'; + ctx.lineWidth = 1; + ctx.lineCap = 'round'; core.animateFrame.weather.nodes.forEach(function (p) { - core.canvas.weather.beginPath(); - core.canvas.weather.moveTo(p.x-ox, p.y-oy); - core.canvas.weather.lineTo(p.x + p.l * p.xs - ox, p.y + p.l * p.ys - oy); - core.canvas.weather.stroke(); + ctx.beginPath(); + ctx.moveTo(p.x-ox, p.y-oy); + ctx.lineTo(p.x + p.l * p.xs - ox, p.y + p.l * p.ys - oy); + ctx.stroke(); p.x += p.xs; p.y += p.ys; @@ -182,15 +191,14 @@ control.prototype.setRequestAnimationFrame = function () { }) - core.canvas.weather.fill(); + ctx.fill(); } else if (core.animateFrame.weather.type == 'snow' && core.animateFrame.weather.level > 0) { core.clearMap('weather'); - - core.canvas.weather.fillStyle = "rgba(255, 255, 255, 0.8)"; - core.canvas.weather.beginPath(); + ctx.fillStyle = "rgba(255, 255, 255, 0.8)"; + ctx.beginPath(); if (!core.isset(core.animateFrame.weather.data)) core.animateFrame.weather.data = 0; @@ -198,8 +206,8 @@ control.prototype.setRequestAnimationFrame = function () { var angle = core.animateFrame.weather.data; core.animateFrame.weather.nodes.forEach(function (p) { - core.canvas.weather.moveTo(p.x - ox, p.y - oy); - core.canvas.weather.arc(p.x - ox, p.y - oy, p.r, 0, Math.PI * 2, true); + ctx.moveTo(p.x - ox, p.y - oy); + ctx.arc(p.x - ox, p.y - oy, p.r, 0, Math.PI * 2, true); // update p.x += Math.sin(angle) * 2; @@ -224,7 +232,7 @@ control.prototype.setRequestAnimationFrame = function () { }) - core.canvas.weather.fill(); + ctx.fill(); } else if (core.animateFrame.weather.type == 'fog' && core.animateFrame.weather.level > 0) { @@ -233,7 +241,7 @@ control.prototype.setRequestAnimationFrame = function () { var w = 416, h = 416; core.setAlpha('weather', 0.5); core.animateFrame.weather.nodes.forEach(function (p) { - core.canvas.weather.drawImage(core.animateFrame.weather.fog, p.x - ox, p.y - oy, w, h); + ctx.drawImage(core.animateFrame.weather.fog, p.x - ox, p.y - oy, w, h); p.x += p.xs; p.y += p.ys; @@ -287,7 +295,7 @@ control.prototype.showStartAnimate = function (noAnimate, callback) { core.status.played = false; core.clearStatus(); core.clearMap('all'); - core.clearMap('curtain'); + core.deleteAllCanvas(); // 重置音量 core.events.setVolume(1, 0); @@ -355,6 +363,7 @@ control.prototype.clearStatus = function() { } core.status = {}; core.clearStatusBar(); + core.deleteAllCanvas(); core.status.played = false; core.events.setHeroIcon('hero.png', true); } @@ -431,7 +440,7 @@ control.prototype.restart = function(noAnimate) { ////// 清除自动寻路路线 ////// control.prototype.clearAutomaticRouteNode = function (x, y) { if (core.status.event.id==null) - core.canvas.route.clearRect(x * 32 + 5, y * 32 + 5, 27, 27); + core.clearMap('route', x * 32 + 5 - core.status.automaticRoute.offsetX, y * 32 + 5 - core.status.automaticRoute.offsetY, 27, 27); } ////// 停止自动寻路操作 ////// @@ -449,7 +458,7 @@ control.prototype.stopAutomaticRoute = function () { core.status.automaticRoute.lastDirection = null; core.stopHero(); if (core.status.automaticRoute.moveStepBeforeStop.length==0) - core.clearMap('route'); + core.deleteCanvas('route'); } ////// 继续剩下的自动寻路操作 ////// @@ -467,7 +476,7 @@ control.prototype.continueAutomaticRoute = function () { ////// 清空剩下的自动寻路列表 ////// control.prototype.clearContinueAutomaticRoute = function () { - core.clearMap('route'); + core.deleteCanvas('route'); core.status.automaticRoute.moveStepBeforeStop=[]; } @@ -551,93 +560,59 @@ control.prototype.setAutomaticRoute = function (destX, destY, stepPostfix) { return; } - var step = 0; - var tempStep = null; - var moveStep; - if (!(moveStep = core.automaticRoute(destX, destY))) { - if (destX == core.status.hero.loc.x && destY == core.status.hero.loc.y){ - moveStep=[]; - } else { - core.clearMap('route'); - return; - } + var moveStep = core.automaticRoute(destX, destY).concat(stepPostfix); + if (moveStep.length == 0) { + core.deleteCanvas('route'); + return; } - moveStep=moveStep.concat(stepPostfix); + core.status.automaticRoute.destX=destX; core.status.automaticRoute.destY=destY; - core.canvas.route.save(); - core.clearMap('route'); - core.canvas.route.fillStyle = '#bfbfbf'; - core.canvas.route.strokeStyle = '#bfbfbf'; - core.canvas.route.lineWidth = 8; + + // 计算绘制区域的宽高 + var sx = core.bigmap.width * 32, sy = core.bigmap.height * 32, dx = 0, dy = 0; + moveStep.forEach(function (t) { + sx = Math.min(sx, t.x * 32); dx = Math.max(dx, t.x * 32); + sy = Math.min(sy, t.y * 32); dy = Math.max(dy, t.y * 32); + }); + core.createCanvas('route', sx-core.bigmap.offsetX, sy-core.bigmap.offsetY, dx-sx+32, dy-sy+32, 95); + core.status.automaticRoute.offsetX = sx; + core.status.automaticRoute.offsetY = sy; + var ctx = core.dymCanvas['route']; + ctx.fillStyle = '#bfbfbf'; + ctx.strokeStyle = '#bfbfbf'; + ctx.lineWidth = 8; for (var m = 0; m < moveStep.length; m++) { - if (tempStep == null) { - step++; - tempStep = moveStep[m].direction; - } - else if (tempStep == moveStep[m].direction) { - step++; - } - else { - //core.status.automaticRoutingTemp.moveStep.push({'direction': tempStep, 'step': step}); - core.status.automaticRoute.autoStepRoutes.push({'direction': tempStep, 'step': step}); - step = 1; - tempStep = moveStep[m].direction; - } if (m == moveStep.length - 1) { - // core.status.automaticRoutingTemp.moveStep.push({'direction': tempStep, 'step': step}); - core.status.automaticRoute.autoStepRoutes.push({'direction': tempStep, 'step': step}); - core.canvas.route.fillRect(moveStep[m].x * 32 + 10, moveStep[m].y * 32 + 10, 12, 12); + ctx.fillRect(moveStep[m].x * 32 + 10 - sx, moveStep[m].y * 32 + 10 - sy, 12, 12); } else { - core.canvas.route.beginPath(); - if (core.isset(moveStep[m + 1]) && tempStep != moveStep[m + 1].direction) { - if (tempStep == 'up' && moveStep[m + 1].direction == 'left' || tempStep == 'right' && moveStep[m + 1].direction == 'down') { - core.canvas.route.moveTo(moveStep[m].x * 32 + 5, moveStep[m].y * 32 + 16); - core.canvas.route.lineTo(moveStep[m].x * 32 + 16, moveStep[m].y * 32 + 16); - core.canvas.route.lineTo(moveStep[m].x * 32 + 16, moveStep[m].y * 32 + 27); - } - else if (tempStep == 'up' && moveStep[m + 1].direction == 'right' || tempStep == 'left' && moveStep[m + 1].direction == 'down') { - core.canvas.route.moveTo(moveStep[m].x * 32 + 27, moveStep[m].y * 32 + 16); - core.canvas.route.lineTo(moveStep[m].x * 32 + 16, moveStep[m].y * 32 + 16); - core.canvas.route.lineTo(moveStep[m].x * 32 + 16, moveStep[m].y * 32 + 27); - } - else if (tempStep == 'left' && moveStep[m + 1].direction == 'up' || tempStep == 'down' && moveStep[m + 1].direction == 'right') { - core.canvas.route.moveTo(moveStep[m].x * 32 + 27, moveStep[m].y * 32 + 16); - core.canvas.route.lineTo(moveStep[m].x * 32 + 16, moveStep[m].y * 32 + 16); - core.canvas.route.lineTo(moveStep[m].x * 32 + 16, moveStep[m].y * 32 + 5); - } - else if (tempStep == 'right' && moveStep[m + 1].direction == 'up' || tempStep == 'down' && moveStep[m + 1].direction == 'left') { - core.canvas.route.moveTo(moveStep[m].x * 32 + 5, moveStep[m].y * 32 + 16); - core.canvas.route.lineTo(moveStep[m].x * 32 + 16, moveStep[m].y * 32 + 16); - core.canvas.route.lineTo(moveStep[m].x * 32 + 16, moveStep[m].y * 32 + 5); - } - core.canvas.route.stroke(); - continue; - } - switch (tempStep) { - case 'up': - case 'down': - core.canvas.route.beginPath(); - core.canvas.route.moveTo(moveStep[m].x * 32 + 16, moveStep[m].y * 32 + 5); - core.canvas.route.lineTo(moveStep[m].x * 32 + 16, moveStep[m].y * 32 + 27); - core.canvas.route.stroke(); - break; - case 'left': - case 'right': - core.canvas.route.beginPath(); - core.canvas.route.moveTo(moveStep[m].x * 32 + 5, moveStep[m].y * 32 + 16); - core.canvas.route.lineTo(moveStep[m].x * 32 + 27, moveStep[m].y * 32 + 16); - core.canvas.route.stroke(); - break; - } + ctx.beginPath(); + var cx = moveStep[m].x*32 +16 - sx, cy = moveStep[m].y*32+16 - sy; + var currDir = moveStep[m].direction, nextDir = moveStep[m+1].direction; + ctx.moveTo(cx-core.utils.scan[currDir].x*11, cy-core.utils.scan[currDir].y*11); + ctx.lineTo(cx, cy); + ctx.lineTo(cx+core.utils.scan[nextDir].x*11, cy+core.utils.scan[nextDir].y*11); + ctx.stroke(); } } - core.canvas.route.restore(); + + // 路线转autoStepRoutes + var step = 0, currStep = null; + moveStep.forEach(function (t) { + var dir = t.direction; + if (currStep == null || currStep == dir) { + step++; currStep = dir; + } + else { + core.status.automaticRoute.autoStepRoutes.push({'direction': currStep, 'step': step}); + step = 1; currStep = dir; + } + }); + core.status.automaticRoute.autoStepRoutes.push({'direction': currStep, 'step': step}); // 立刻移动 core.setAutoHeroMove(); - } ////// 自动寻路算法,找寻最优路径 ////// @@ -645,13 +620,7 @@ control.prototype.automaticRoute = function (destX, destY) { var fw = core.bigmap.width, fh = core.bigmap.height; var startX = core.getHeroLoc('x'); var startY = core.getHeroLoc('y'); - var scan = { - 'up': {'x': 0, 'y': -1}, - 'left': {'x': -1, 'y': 0}, - 'down': {'x': 0, 'y': 1}, - 'right': {'x': 1, 'y': 0} - }; - if (destX == startX && destY == startY) return false; + if (destX == startX && destY == startY) return []; var route = []; var queue = new PriorityQueue({comparator: function (a,b) { @@ -665,12 +634,12 @@ control.prototype.automaticRoute = function (destX, destY) { var curr = queue.dequeue(); var deep = curr.depth, nowX = curr.x, nowY = curr.y; - for (var direction in scan) { + for (var direction in core.utils.scan) { if (!core.canMoveHero(nowX, nowY, direction)) continue; - var nx = nowX + scan[direction].x; - var ny = nowY + scan[direction].y; + var nx = nowX + core.utils.scan[direction].x; + var ny = nowY + core.utils.scan[direction].y; if (nx<0 || nx>=fw || ny<0 || ny>=fh) continue; var nid = nx + fw * ny; @@ -705,15 +674,15 @@ control.prototype.automaticRoute = function (destX, destY) { if (core.isset(route[destX + fw * destY])) break; } if (!core.isset(route[destX + fw * destY])) { - return false; + return []; } var nowX = destX, nowY = destY; while (nowX != startX || nowY != startY) { var dir = route[nowX + fw * nowY]; ans.push({'direction': dir, 'x': nowX, 'y': nowY}); - nowX -= scan[dir].x; - nowY -= scan[dir].y; + nowX -= core.utils.scan[dir].x; + nowY -= core.utils.scan[dir].y; } ans.reverse(); @@ -722,7 +691,7 @@ control.prototype.automaticRoute = function (destX, destY) { ////// 显示离散的寻路点 ////// control.prototype.fillPosWithPoint = function (pos) { - core.fillRect('route', pos.x*32+12+core.bigmap.offsetX,pos.y*32+12+core.bigmap.offsetY,8,8, '#bfbfbf'); + core.fillRect('ui', pos.x*32+12,pos.y*32+12,8,8, '#bfbfbf'); } ////// 设置勇士的自动行走路线 ////// @@ -744,12 +713,6 @@ control.prototype.setHeroMoveInterval = function (direction, x, y, callback) { return; } core.status.heroMoving=1; - var scan = { - 'up': {'x': 0, 'y': -1}, - 'left': {'x': -1, 'y': 0}, - 'down': {'x': 0, 'y': 1}, - 'right': {'x': 1, 'y': 0} - }; var toAdd = 1; if (core.status.replay.speed>3) @@ -762,8 +725,8 @@ control.prototype.setHeroMoveInterval = function (direction, x, y, callback) { core.interval.heroMoveInterval = window.setInterval(function () { core.status.heroMoving+=toAdd; if (core.status.heroMoving>=8) { - core.setHeroLoc('x', x+scan[direction].x, true); - core.setHeroLoc('y', y+scan[direction].y, true); + core.setHeroLoc('x', x+core.utils.scan[direction].x, true); + core.setHeroLoc('y', y+core.utils.scan[direction].y, true); core.control.updateFollowers(); core.moveOneStep(); core.clearMap('hero'); @@ -779,23 +742,17 @@ control.prototype.setHeroMoveInterval = function (direction, x, y, callback) { control.prototype.moveAction = function (callback) { if (core.interval.openDoorAnimate!=null) return; // 开门判断 if (core.status.heroMoving>0) return; - var scan = { - 'up': {'x': 0, 'y': -1}, - 'left': {'x': -1, 'y': 0}, - 'down': {'x': 0, 'y': 1}, - 'right': {'x': 1, 'y': 0} - }; var direction = core.getHeroLoc('direction'); var x = core.getHeroLoc('x'); var y = core.getHeroLoc('y'); - var noPass = core.noPass(x + scan[direction].x, y + scan[direction].y), canMove = core.canMoveHero(); + var noPass = core.noPass(x + core.utils.scan[direction].x, y + core.utils.scan[direction].y), canMove = core.canMoveHero(); if (noPass || !canMove) { if (core.status.event.id!='ski') core.status.route.push(direction); core.status.automaticRoute.moveStepBeforeStop = []; core.status.automaticRoute.lastDirection = core.getHeroLoc('direction'); if (canMove) // 非箭头:触发 - core.trigger(x + scan[direction].x, y + scan[direction].y); + core.trigger(x + core.utils.scan[direction].x, y + core.utils.scan[direction].y); core.drawHero(direction, x, y); if (core.status.automaticRoute.moveStepBeforeStop.length==0) { @@ -851,7 +808,6 @@ control.prototype.turnHero = function(direction) { if (core.isset(direction)) { core.setHeroLoc('direction', direction); core.drawHero(); - core.clearMap('route'); core.status.route.push("turn:"+direction); return; } @@ -860,7 +816,6 @@ control.prototype.turnHero = function(direction) { else if (core.status.hero.loc.direction == 'down') core.status.hero.loc.direction = 'left'; else if (core.status.hero.loc.direction == 'left') core.status.hero.loc.direction = 'up'; core.drawHero(); - core.clearMap('route'); core.status.route.push("turn"); } @@ -879,14 +834,8 @@ control.prototype.moveHero = function (direction, callback) { if (core.hasFlag('debug') && core.status.ctrlDown) { if (core.status.heroMoving!=0) return; // 检测是否穿出去 - var scan = { - 'up': {'x': 0, 'y': -1}, - 'left': {'x': -1, 'y': 0}, - 'down': {'x': 0, 'y': 1}, - 'right': {'x': 1, 'y': 0} - }; direction = core.getHeroLoc('direction'); - var nx = core.getHeroLoc('x') + scan[direction].x, ny=core.getHeroLoc('y') + scan[direction].y; + var nx = core.getHeroLoc('x') + core.utils.scan[direction].x, ny=core.getHeroLoc('y') + core.utils.scan[direction].y; if (nx<0 || nx>=core.bigmap.width || ny<0 || ny>=core.bigmap.height) return; core.status.heroMoving=-1; @@ -936,12 +885,6 @@ control.prototype.eventMoveHero = function(steps, time, callback) { }); var step=0; - var scan = { - 'up': {'x': 0, 'y': -1}, - 'left': {'x': -1, 'y': 0}, - 'down': {'x': 0, 'y': 1}, - 'right': {'x': 1, 'y': 0} - }; var animate=window.setInterval(function() { var x=core.getHeroLoc('x'), y=core.getHeroLoc('y'); @@ -963,8 +906,8 @@ control.prototype.eventMoveHero = function(steps, time, callback) { } if (step == 8) { step = 0; - core.setHeroLoc('x', x + scan[direction].x, true); - core.setHeroLoc('y', y + scan[direction].y, true); + core.setHeroLoc('x', x + core.utils.scan[direction].x, true); + core.setHeroLoc('y', y + core.utils.scan[direction].y, true); core.control.updateFollowers(); moveSteps.shift(); } @@ -1090,6 +1033,8 @@ control.prototype.updateViewport = function() { core.bigmap.canvas.forEach(function(cn){ core.control.setGameCanvasTranslate(cn,-core.bigmap.offsetX,-core.bigmap.offsetY); }); + // ------ 路线 + core.relocateCanvas('route', core.status.automaticRoute.offsetX - core.bigmap.offsetX, core.status.automaticRoute.offsetY - core.bigmap.offsetY); } ////// 绘制勇士 ////// @@ -1097,19 +1042,12 @@ control.prototype.drawHero = function (direction, x, y, status, offset) { if (!core.isPlaying()) return; - var scan = { - 'up': {'x': 0, 'y': -1}, - 'left': {'x': -1, 'y': 0}, - 'down': {'x': 0, 'y': 1}, - 'right': {'x': 1, 'y': 0} - }; - if (!core.isset(x)) x = core.getHeroLoc('x'); if (!core.isset(y)) y = core.getHeroLoc('y'); status = status || 'stop'; direction = direction || core.getHeroLoc('direction'); offset = offset || 0; - var way = scan[direction]; + var way = core.utils.scan[direction]; var offsetX = way.x*offset; var offsetY = way.y*offset; var dx=offsetX==0?0:offsetX/Math.abs(offsetX), dy=offsetY==0?0:offsetY/Math.abs(offsetY); @@ -1144,8 +1082,8 @@ control.prototype.drawHero = function (direction, x, y, status, offset) { "img": core.material.images.images[t.img], "height": core.material.images.images[t.img].height/4, "heroIcon": heroIconArr[t.direction], - "posx": 32*t.x - core.bigmap.offsetX + (t.stop?0:scan[t.direction].x*offset), - "posy": 32*t.y - core.bigmap.offsetY + (t.stop?0:scan[t.direction].y*offset), + "posx": 32*t.x - core.bigmap.offsetX + (t.stop?0:core.utils.scan[t.direction].x*offset), + "posy": 32*t.y - core.bigmap.offsetY + (t.stop?0:core.utils.scan[t.direction].y*offset), "status": t.stop?"stop":status, "index": index++ }); @@ -1182,24 +1120,12 @@ control.prototype.getHeroLoc = function (itemName) { ////// 获得勇士面对位置的x坐标 ////// control.prototype.nextX = function(n) { - var scan = { - 'up': {'x': 0, 'y': -1}, - 'left': {'x': -1, 'y': 0}, - 'down': {'x': 0, 'y': 1}, - 'right': {'x': 1, 'y': 0} - }; - return core.getHeroLoc('x')+scan[core.getHeroLoc('direction')].x*(n||1); + return core.getHeroLoc('x')+core.utils.scan[core.getHeroLoc('direction')].x*(n||1); } ////// 获得勇士面对位置的y坐标 ////// control.prototype.nextY = function (n) { - var scan = { - 'up': {'x': 0, 'y': -1}, - 'left': {'x': -1, 'y': 0}, - 'down': {'x': 0, 'y': 1}, - 'right': {'x': 1, 'y': 0} - }; - return core.getHeroLoc('y')+scan[core.getHeroLoc('direction')].y*(n||1); + return core.getHeroLoc('y')+core.utils.scan[core.getHeroLoc('direction')].y*(n||1); } ////// 聚集跟随者 ////// @@ -1217,16 +1143,10 @@ control.prototype.gatherFollowers = function () { ////// 更新跟随者坐标 ////// control.prototype.updateFollowers = function () { if (!core.isset(core.status.hero.followers) || core.status.hero.followers.length==0) return; - var scan = { - 'up': {'x': 0, 'y': -1}, - 'left': {'x': -1, 'y': 0}, - 'down': {'x': 0, 'y': 1}, - 'right': {'x': 1, 'y': 0} - }; core.status.hero.followers.forEach(function (t) { if (!t.stop) { - t.x += scan[t.direction].x; - t.y += scan[t.direction].y; + t.x += core.utils.scan[t.direction].x; + t.y += core.utils.scan[t.direction].y; } }) @@ -1273,14 +1193,8 @@ control.prototype.checkBlock = function () { // 检查阻击事件 var snipe = []; if (!core.hasFlag("no_snipe")) { - var scan = { - 'up': {'x': 0, 'y': -1}, - 'left': {'x': -1, 'y': 0}, - 'down': {'x': 0, 'y': 1}, - 'right': {'x': 1, 'y': 0} - } - for (var direction in scan) { - var nx = x+scan[direction].x, ny=y+scan[direction].y; + for (var direction in core.utils.scan) { + var nx = x+core.utils.scan[direction].x, ny=y+core.utils.scan[direction].y; if (nx<0 || nx>=core.bigmap.width || ny<0 || ny>=core.bigmap.height) continue; var id=core.status.checkBlock.map[nx+core.bigmap.width*ny]; if (core.isset(id)) { @@ -1328,7 +1242,7 @@ control.prototype.checkBlock = function () { } snipe = snipe.filter(function (t) { var x=t.x, y=t.y, direction = t.direction; - var nx = x+scan[direction].x, ny=y+scan[direction].y; + var nx = x+core.utils.scan[direction].x, ny=y+core.utils.scan[direction].y; return nx>=0 && nx=0 && ny=core.bigmap.width||ny<0||ny>=core.bigmap.height) return; diff --git a/libs/maps.js b/libs/maps.js index dc360888..e4149a23 100644 --- a/libs/maps.js +++ b/libs/maps.js @@ -296,13 +296,7 @@ maps.prototype.canMoveHero = function(x,y,direction,floorId) { if (!check(core.getBlock(x,y,floorId),"cannotOut") || !check(getNumber(floorId,"bg",x,y),"cannotOut") || !check(getNumber(floorId,"fg",x,y),"cannotOut")) return false; - var scan = { - 'up': {'x': 0, 'y': -1}, - 'left': {'x': -1, 'y': 0}, - 'down': {'x': 0, 'y': 1}, - 'right': {'x': 1, 'y': 0} - }; - var nx = x+scan[direction].x, ny = y+scan[direction].y; + var nx = x+core.utils.scan[direction].x, ny = y+core.utils.scan[direction].y; // 检查目标点的cannotIn if (!check(core.getBlock(nx,ny,floorId),"cannotIn") || !check(getNumber(floorId,"bg",nx,ny),"cannotIn") || !check(getNumber(floorId,"fg",nx,ny),"cannotIn")) return false; @@ -474,21 +468,20 @@ maps.prototype.drawBgFgMap = function (floorId, canvas, name, animate) { } ////// 绘制某张地图 ////// -maps.prototype.drawMap = function (mapName, callback) { - mapName = mapName || core.status.floorId; - if (!core.isset(mapName)) { +maps.prototype.drawMap = function (floorId, callback) { + floorId = floorId || core.status.floorId; + if (!core.isset(floorId)) { if (core.isset(callback)) callback(); return; } core.clearMap('all'); - core.removeGlobalAnimate(null, null, true); var drawBg = function(){ - var width = core.floors[mapName].width || 13; - var height = core.floors[mapName].height || 13; + var width = core.floors[floorId].width || 13; + var height = core.floors[floorId].height || 13; - var groundId = (core.status.maps||core.floors)[mapName].defaultGround || "ground"; + var groundId = (core.status.maps||core.floors)[floorId].defaultGround || "ground"; var blockIcon = core.material.icons.terrains[groundId]; for (var x = 0; x < width; x++) { for (var y = 0; y < height; y++) { @@ -497,8 +490,8 @@ maps.prototype.drawMap = function (mapName, callback) { } var images = []; - if (core.isset(core.status.maps[mapName].images)) { - images = core.status.maps[mapName].images; + if (core.isset(core.status.maps[floorId].images)) { + images = core.status.maps[floorId].images; if (typeof images == 'string') { images = [[0, 0, images]]; } @@ -507,7 +500,7 @@ maps.prototype.drawMap = function (mapName, callback) { if (typeof t == 'string') t = [0,0,t]; var dx=parseInt(t[0]), dy=parseInt(t[1]), p=t[2]; if (core.isset(dx) && core.isset(dy) && - !core.hasFlag("floorimg_"+mapName+"_"+dx+"_"+dy) && + !core.hasFlag("floorimg_"+floorId+"_"+dx+"_"+dy) && core.isset(core.material.images.images[p])) { var image = core.material.images.images[p]; if (!t[3]) { @@ -537,8 +530,8 @@ maps.prototype.drawMap = function (mapName, callback) { } }); - core.maps.drawBgFgMap(mapName, core.canvas.bg, "bg", true); - core.maps.drawBgFgMap(mapName, core.canvas.fg, "fg", true); + core.maps.drawBgFgMap(floorId, core.canvas.bg, "bg", true); + core.maps.drawBgFgMap(floorId, core.canvas.fg, "fg", true); } if (main.mode=='editor'){ @@ -554,8 +547,8 @@ maps.prototype.drawMap = function (mapName, callback) { drawBg(); } - core.status.floorId = mapName; - core.status.thisMap = core.status.maps[mapName]; + core.status.floorId = floorId; + core.status.thisMap = core.status.maps[floorId]; var drawEvent = function(){ var mapData = core.status.maps[core.status.floorId]; @@ -838,7 +831,15 @@ maps.prototype.__initBlockCanvas = function (block, height, x, y) { damageCanvas = "blockDamage"+x+"_"+y; core.createCanvas(damageCanvas, 0, 0, 32, 32, 65); core.dymCanvas[damageCanvas].textAlign = 'left'; + core.dymCanvas[damageCanvas].font = "bold 11px Arial"; core.fillBoldText(core.dymCanvas[damageCanvas], damage, damageColor, 1, 31); + if (core.flags.displayCritical) { + var critical = core.enemys.nextCriticals(block.event.id); + if (critical.length>0) critical=critical[0]; + critical = core.formatBigNumber(critical[0], true); + if (critical == '???') critical = '?'; + core.fillBoldText(core.dymCanvas[damageCanvas], critical, '#FFFFFF', 1, 21); + } } return { "headCanvas": headCanvas, @@ -888,12 +889,6 @@ maps.prototype.moveBlock = function(x,y,steps,time,keep,callback) { }); var nowX=32*x, nowY=32*y, step=0; - var scan = { - 'up': {'x': 0, 'y': -1}, - 'left': {'x': -1, 'y': 0}, - 'down': {'x': 0, 'y': 1}, - 'right': {'x': 1, 'y': 0} - }; var animateValue = block.event.animate || 1, animateCurrent = isTileset?bx:0, animateTime = 0; var blockCanvas = this.__initBlockCanvas(block, height, x, y); @@ -946,8 +941,8 @@ maps.prototype.moveBlock = function(x,y,steps,time,keep,callback) { } } step++; - nowX+=scan[direction].x*2; - nowY+=scan[direction].y*2; + nowX+=core.utils.scan[direction].x*2; + nowY+=core.utils.scan[direction].y*2; // 移动 core.maps.__moveBlockCanvas(image, animateCurrent, by, height, nowX, nowY, opacity, headCanvas, bodyCanvas, damageCanvas); if (step==16) { @@ -1369,34 +1364,22 @@ maps.prototype.drawAnimate = function (name, x, y, callback) { return; } - clearInterval(core.interval.animateInterval); - // 开始绘制 var animate = core.material.animates[name], centerX = 32*x+16, centerY = 32*y+16; // 播放音效 core.playSound(animate.se); - // 异步绘制:使用requestAnimationFrame进行绘制 - if (!core.isset(callback)) { - core.status.animateObjs.push({"animate": animate, "centerX": centerX, "centerY": centerY, "index": 0}); - return; - } + var animateId = parseInt(Math.random() * 100000000); + core.status.animateObjs.push({ + "animate": animate, + "centerX": centerX, + "centerY": centerY, + "index": 0, + "id": animateId, + "callback": callback + }); - var index=0; - core.clearMap('animate'); - core.maps.drawAnimateFrame(animate, centerX, centerY, index++); - - core.interval.animateInterval = setInterval(function (t) { - if (index == animate.frames.length) { - clearInterval(core.interval.animateInterval); - core.clearMap('animate'); - core.setAlpha('animate', 1); - if (core.isset(callback)) callback(); - return; - } - core.clearMap('animate'); - core.maps.drawAnimateFrame(animate, centerX, centerY, index++); - }, 50); + core.animateFrame.asyncId[animateId] = true; } maps.prototype.setFloorImage = function (type, loc, floorId, callback) { diff --git a/libs/ui.js b/libs/ui.js index 76b97621..7a632dc9 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -17,179 +17,162 @@ ui.prototype.init = function () { ////////////////// 地图设置 +ui.prototype.getContextByName = function (name) { + if (core.isset(core.canvas[name])) + return core.canvas[name]; + if (core.isset(core.dymCanvas[name])) + return core.dymCanvas[name]; + return null; +} + ////// 清除地图 ////// -ui.prototype.clearMap = function (map, x, y, width, height) { - if (map == 'all') { +ui.prototype.clearMap = function (name, x, y, width, height) { + if (name == 'all') { for (var m in core.canvas) { - // 不擦除curtain层 - if (m=='curtain') continue; core.canvas[m].clearRect(0, 0, core.bigmap.width*32, core.bigmap.height*32); } core.dom.gif.innerHTML = ""; + core.removeGlobalAnimate(0,0,true); } else { - core.canvas[map].clearRect(x||0, y||0, width||core.bigmap.width*32, height||core.bigmap.height*32); + var ctx = this.getContextByName(name); + if (ctx) ctx.clearRect(x||0, y||0, width||ctx.canvas.width, height||ctx.canvas.height); } } ////// 在某个canvas上绘制一段文字 ////// -ui.prototype.fillText = function (map, text, x, y, style, font) { +ui.prototype.fillText = function (name, text, x, y, style, font) { if (core.isset(style)) { - core.setFillStyle(map, style); + core.setFillStyle(name, style); } if (core.isset(font)) { - core.setFont(map, font); + core.setFont(name, font); } - core.canvas[map].fillText(text, x, y); + var ctx = this.getContextByName(name); + if (ctx) ctx.fillText(text, x, y); } ////// 在某个canvas上绘制粗体 ////// -ui.prototype.fillBoldText = function (canvas, text, color, x, y, font) { +ui.prototype.fillBoldText = function (canvas, text, style, x, y, font) { if (core.isset(font)) canvas.font = font; canvas.fillStyle = '#000000'; canvas.fillText(text, x-1, y-1); canvas.fillText(text, x-1, y+1); canvas.fillText(text, x+1, y-1); canvas.fillText(text, x+1, y+1); - canvas.fillStyle = color; + canvas.fillStyle = style; canvas.fillText(text, x, y); } ////// 在某个canvas上绘制一个矩形 ////// -ui.prototype.fillRect = function (map, x, y, width, height, style) { +ui.prototype.fillRect = function (name, x, y, width, height, style) { if (core.isset(style)) { - core.setFillStyle(map, style); + core.setFillStyle(name, style); } - core.canvas[map].fillRect(x, y, width, height); + var ctx = this.getContextByName(name); + if (ctx) ctx.fillRect(x, y, width, height); } ////// 在某个canvas上绘制一个矩形的边框 ////// -ui.prototype.strokeRect = function (map, x, y, width, height, style, lineWidth) { +ui.prototype.strokeRect = function (name, x, y, width, height, style, lineWidth) { if (core.isset(style)) { - core.setStrokeStyle(map, style); + core.setStrokeStyle(name, style); } if (core.isset(lineWidth)) { - core.setLineWidth(map, lineWidth); + core.setLineWidth(name, lineWidth); } - core.canvas[map].strokeRect(x, y, width, height); + var ctx = this.getContextByName(name); + if (ctx) ctx.strokeRect(x, y, width, height); } ////// 在某个canvas上绘制一条线 ////// -ui.prototype.drawLine = function (map, x1, y1, x2, y2, style, lineWidth) { +ui.prototype.drawLine = function (name, x1, y1, x2, y2, style, lineWidth) { if (core.isset(style)) { - core.setStrokeStyle(map, style); + core.setStrokeStyle(name, style); } if (core.isset(lineWidth)) { - core.setLineWidth(map, lineWidth); + core.setLineWidth(name, lineWidth); + } + var ctx = this.getContextByName(name); + if (ctx) { + ctx.beginPath(); + ctx.moveTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.stroke(); } - core.canvas[map].beginPath(); - core.canvas[map].moveTo(x1, y1); - core.canvas[map].lineTo(x2, y2); - core.canvas[map].stroke(); } ////// 在某个canvas上绘制一个箭头 ////// -ui.prototype.drawArrow = function (map, x1, y1, x2, y2, style, lineWidth) { +ui.prototype.drawArrow = function (name, x1, y1, x2, y2, style, lineWidth) { if (x1==x2 && y1==y2) return; if (core.isset(style)) { - core.setStrokeStyle(map, style); + core.setStrokeStyle(name, style); } if (core.isset(lineWidth)) { - core.setLineWidth(map, lineWidth); + core.setLineWidth(name, lineWidth); + } + var ctx = this.getContextByName(name); + if (ctx) { + var head = 10; + var dx = x2-x1, dy=y2-y1; + var angle = Math.atan2(dy,dx); + ctx.beginPath(); + ctx.moveTo(x1,y1); + ctx.lineTo(x2, y2); + ctx.lineTo(x2-head*Math.cos(angle-Math.PI/6),y2-head*Math.sin(angle-Math.PI/6)); + ctx.moveTo(x2, y2); + ctx.lineTo(x2-head*Math.cos(angle+Math.PI/6),y2-head*Math.sin(angle+Math.PI/6)); + ctx.stroke(); } - var head = 10; - var dx = x2-x1, dy=y2-y1; - var angle = Math.atan2(dy,dx); - core.canvas[map].beginPath(); - core.canvas[map].moveTo(x1,y1); - core.canvas[map].lineTo(x2, y2); - core.canvas[map].lineTo(x2-head*Math.cos(angle-Math.PI/6),y2-head*Math.sin(angle-Math.PI/6)); - core.canvas[map].moveTo(x2, y2); - core.canvas[map].lineTo(x2-head*Math.cos(angle+Math.PI/6),y2-head*Math.sin(angle+Math.PI/6)); - core.canvas[map].stroke(); } ////// 设置某个canvas的文字字体 ////// -ui.prototype.setFont = function (map, font) { - core.canvas[map].font = font; +ui.prototype.setFont = function (name, font) { + var ctx = this.getContextByName(name); + if (ctx) ctx.font = font; } ////// 设置某个canvas的线宽度 ////// -ui.prototype.setLineWidth = function (map, lineWidth) { - if (map == 'all') { - for (var m in core.canvas) { - core.canvas[m].lineWidth = lineWidth; - } - } - core.canvas[map].lineWidth = lineWidth; +ui.prototype.setLineWidth = function (name, lineWidth) { + var ctx = this.getContextByName(name); + if (ctx) ctx.lineWidth = lineWidth; } ////// 保存某个canvas状态 ////// -ui.prototype.saveCanvas = function (map) { - core.canvas[map].save(); +ui.prototype.saveCanvas = function (name) { + var ctx = this.getContextByName(name); + if (ctx) ctx.save(); } ////// 加载某个canvas状态 ////// -ui.prototype.loadCanvas = function (map) { - core.canvas[map].restore(); -} - -////// 设置某个canvas边框属性 ////// -ui.prototype.setStrokeStyle = function (map, style) { - if (map == 'all') { - for (var m in core.canvas) { - core.canvas[m].strokeStyle = style; - } - } - else { - core.canvas[map].strokeStyle = style; - } +ui.prototype.loadCanvas = function (name) { + var ctx = this.getContextByName(name); + if (ctx) ctx.restore(); } ////// 设置某个canvas的alpha值 ////// -ui.prototype.setAlpha = function (map, alpha) { - if (map == 'all') { - for (var m in core.canvas) { - core.canvas[m].globalAlpha = alpha; - } - } - else core.canvas[map].globalAlpha = alpha; +ui.prototype.setAlpha = function (name, alpha) { + var ctx = this.getContextByName(name); + if (ctx) ctx.globalAlpha = alpha; } ////// 设置某个canvas的透明度;尽量不要使用本函数,而是全部换成setAlpha实现 ////// -ui.prototype.setOpacity = function (map, opacity) { - if (map == 'all') { - for (var m in core.canvas) { - core.canvas[m].canvas.style.opacity = opacity; - } - } - else if (core.isset(core.canvas[map])) { - core.canvas[map].canvas.style.opacity = opacity; - } - else if (core.isset(core.dymCanvas[map])) { - core.dymCanvas[map].canvas.style.opacity = opacity; - } - else - console.log("未找到"+map); +ui.prototype.setOpacity = function (name, opacity) { + var ctx = this.getContextByName(name); + if (ctx) ctx.canvas.style.opacity = opacity; } ////// 设置某个canvas的绘制属性(如颜色等) ////// -ui.prototype.setFillStyle = function (map, style) { - if (map == 'all') { - for (var m in core.canvas) { - core.canvas[m].fillStyle = style; - } - } - else if (core.isset(core.canvas[map])) { - core.canvas[map].fillStyle = style; - } - else if (core.isset(core.dymCanvas[map])) { - core.dymCanvas[map].fillStyle = style; -} - else - console.log("未找到"+map); +ui.prototype.setFillStyle = function (name, style) { + var ctx = this.getContextByName(name); + if (ctx) ctx.fillStyle = style; } +////// 设置某个canvas边框属性 ////// +ui.prototype.setStrokeStyle = function (name, style) { + var ctx = this.getContextByName(name); + if (ctx) ctx.strokeStyle = style; +} ///////////////// UI绘制 @@ -1833,8 +1816,7 @@ ui.prototype.drawMaps = function (index, x, y) { core.status.event.data = null; core.clearLastEvent(); - core.clearMap('animate'); - core.fillRect('animate', 0, 0, 416, 416, 'rgba(0,0,0,0.4)'); + 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); @@ -1874,8 +1856,6 @@ ui.prototype.drawMaps = function (index, x, y) { return; } - core.clearMap('animate'); - 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; @@ -1901,8 +1881,7 @@ ui.prototype.drawMaps = function (index, x, y) { core.status.event.data = {"index": index, "x": x, "y": y, "damage": damage, "paint": paint, "all": all}; clearTimeout(core.interval.tipAnimate); - core.clearMap('ui'); - core.setAlpha('ui', 1); + core.clearLastEvent(); this.drawThumbnail(floorId, 'ui', core.status.maps[floorId].blocks, 0, 0, 416, x, y); // 绘图 @@ -2739,18 +2718,16 @@ ui.prototype.drawPaint = function () { core.status.event.data = {"x": null, "y": null, "erase": false}; core.clearLastEvent(); - core.clearMap('route'); - - core.setAlpha('route', 1); + 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 = LZString.decompress(value).split(","); core.utils.decodeCanvas(value, 32*core.bigmap.width, 32*core.bigmap.height); - core.canvas.route.drawImage(core.bigmap.tempCanvas.canvas, 0, 0); + core.dymCanvas.paint.drawImage(core.bigmap.tempCanvas.canvas, 0, 0); - core.setLineWidth('route', 3); - core.setStrokeStyle('route', '#FF0000'); + core.setLineWidth('paint', 3); + core.setStrokeStyle('paint', '#FF0000'); core.statusBar.image.shop.style.opacity = 0; @@ -2796,6 +2773,14 @@ ui.prototype.drawHelp = function () { ////// canvas创建 ////// ui.prototype.createCanvas = function (name, x, y, width, height, z) { + // 如果画布已存在则直接调用 + var cv = this.findCanvas(name); + if (cv!=-1) { + this.relocateCanvas(name, x, y); + this.resizeCanvas(name, width, height); + core.dymCanvas[name].canvas.style.zIndex = z; + return; + } var newCanvas = document.createElement("canvas"); newCanvas.id = name; newCanvas.style.display = 'block'; diff --git a/libs/utils.js b/libs/utils.js index 5a356344..63e91eeb 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -7,6 +7,12 @@ utils.js 工具类 function utils() { this.init(); + this.scan = { + 'up': {'x': 0, 'y': -1}, + 'left': {'x': -1, 'y': 0}, + 'down': {'x': 0, 'y': 1}, + 'right': {'x': 1, 'y': 0} + }; } utils.prototype.init = function () { diff --git a/project/functions.js b/project/functions.js index 09ed1cdd..ecf7e223 100644 --- a/project/functions.js +++ b/project/functions.js @@ -58,8 +58,9 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = var replaying = core.status.replay.replaying; core.stopReplay(); core.waitHeroToStop(function() { - core.removeGlobalAnimate(0,0,true); - core.clearMap('all'); core.clearMap('curtain'); // 清空全地图 + core.clearMap('all'); // 清空全地图 + core.deleteAllCanvas(); // 删除所有创建的画布 + core.dom.gif2.innerHTML = ""; // 请注意: // 成绩统计时是按照hp进行上传并排名,因此光在这里改${status:hp}是无效的 // 如需按照其他的的分数统计方式,请先将hp设置为你的得分 @@ -83,9 +84,62 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = core.events.gameOver(null, replaying); }); }) +}, + "changingFloor": function (floorId, heroLoc, fromLoad) { + // 正在切换楼层过程中执行的操作;此函数的执行时间是“屏幕完全变黑“的那一刻 + // floorId为要切换到的楼层ID;heroLoc表示勇士切换到的位置;fromLoad表示是否是从读档造成的切换 + + // ---------- 此时还没有进行切换,当前floorId还是原来的 ---------- // + var currentId = core.status.floorId || null; // 获得当前的floorId,可能为null + // 可以对currentId进行判定,比如删除某些自定义图层等 + // if (currentId == 'MT0') { + // core.deleteAllCanvas(); + // } + + // 重置画布尺寸 + core.maps.resizeMap(floorId); + // 检查重生怪并重置 + if (!fromLoad) { + core.status.maps[floorId].blocks.forEach(function(block) { + if (block.disable && core.isset(block.event) && block.event.cls.indexOf('enemy')==0 && + core.enemys.hasSpecial(core.material.enemys[block.event.id].special, 23)) { + block.disable = false; + } + }); + } + // 设置勇士的位置 + core.status.hero.loc = heroLoc; + + // ---------- 重绘新地图;这一步将会设置core.status.floorId ---------- // + core.drawMap(floorId); + + // 切换楼层BGM + if (core.isset(core.status.maps[floorId].bgm)) { + var bgm = core.status.maps[floorId].bgm; + if (bgm instanceof Array) bgm = bgm[0]; + core.playBgm(bgm); + } + // 更改画面色调 + var color = core.getFlag('__color__', null); + if (!core.isset(color) && core.isset(core.status.maps[floorId].color)) + color = core.status.maps[floorId].color; + if (core.isset(color)) { + core.fillRect('curtain',0,0,416,416,core.arrayToRGBA(color)); + core.status.curtainColor = color; + } + // 更改天气 + var weather = core.getFlag('__weather__', null); + if (!core.isset(weather) && core.isset(core.status.maps[floorId].weather)) + weather = core.status.maps[floorId].weather; + if (core.isset(weather)) + core.setWeather(weather[0], weather[1]); + else core.setWeather(); + + // ...可以新增一些其他内容,比如创建个画布在右上角显示什么内容等等 + }, "afterChangeFloor": function (floorId, fromLoad) { - // 转换楼层结束的事件 + // 转换楼层结束的事件;此函数会在整个楼层切换完全结束后再执行 // floorId是切换到的楼层;fromLoad若为true则代表是从读档行为造成的楼层切换 // 每次抵达楼层时执行的事件 @@ -422,12 +476,12 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = var mon_hp = enemy.hp, mon_atk = enemy.atk, mon_def = enemy.def, mon_special = enemy.special; var mon_money = enemy.money, mon_experience = enemy.experience, mon_point = enemy.point; // 模仿 - if (this.hasSpecial(mon_special, 10)) { + if (core.hasSpecial(mon_special, 10)) { mon_atk = hero_atk; mon_def = hero_def; } // 坚固 - if (this.hasSpecial(mon_special, 3) && mon_def < hero_atk - 1) { + if (core.hasSpecial(mon_special, 3) && mon_def < hero_atk - 1) { mon_def = hero_atk - 1; } @@ -463,7 +517,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // TODO:可以在这里新增其他的怪物数据变化 // 比如仿攻(怪物攻击不低于勇士攻击): - // if (this.hasSpecial(mon_special, 27) && mon_atk < hero_atk) { + // if (core.hasSpecial(mon_special, 27) && mon_atk < hero_atk) { // mon_atk = hero_atk; // } // 也可以按需增加各种自定义内容(比如幻塔的魔杖效果等) @@ -511,14 +565,14 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = } // 如果是无敌属性,且勇士未持有十字架 - if (this.hasSpecial(mon_special, 20) && !core.hasItem("cross")) + if (core.hasSpecial(mon_special, 20) && !core.hasItem("cross")) return null; // 不可战斗 // 战前造成的额外伤害(可被魔防抵消) var init_damage = 0; // 吸血 - if (this.hasSpecial(mon_special, 11)) { + if (core.hasSpecial(mon_special, 11)) { var vampire_damage = hero_hp * enemy.value; // 如果有神圣盾免疫吸血等可以在这里写 @@ -536,28 +590,28 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 每回合怪物对勇士造成的战斗伤害 var per_damage = mon_atk - hero_def; // 魔攻:战斗伤害就是怪物攻击力 - if (this.hasSpecial(mon_special, 2)) per_damage = mon_atk; + if (core.hasSpecial(mon_special, 2)) per_damage = mon_atk; // 战斗伤害不能为负值 if (per_damage < 0) per_damage = 0; // 2连击 & 3连击 & N连击 - if (this.hasSpecial(mon_special, 4)) per_damage *= 2; - if (this.hasSpecial(mon_special, 5)) per_damage *= 3; - if (this.hasSpecial(mon_special, 6)) per_damage *= (enemy.n||4); + if (core.hasSpecial(mon_special, 4)) per_damage *= 2; + if (core.hasSpecial(mon_special, 5)) per_damage *= 3; + if (core.hasSpecial(mon_special, 6)) per_damage *= (enemy.n||4); // 每回合的反击伤害;反击是按照勇士的攻击次数来计算回合 var counterDamage = 0; - if (this.hasSpecial(mon_special, 8)) counterDamage += Math.floor(core.values.counterAttack * hero_atk); + if (core.hasSpecial(mon_special, 8)) counterDamage += Math.floor(core.values.counterAttack * hero_atk); // 先攻 - if (this.hasSpecial(mon_special, 1)) init_damage += per_damage; + if (core.hasSpecial(mon_special, 1)) init_damage += per_damage; // 破甲 - if (this.hasSpecial(mon_special, 7)) + if (core.hasSpecial(mon_special, 7)) init_damage += Math.floor(core.values.breakArmor * hero_def); // 净化 - if (this.hasSpecial(mon_special, 9)) + if (core.hasSpecial(mon_special, 9)) init_damage += Math.floor(core.values.purify * hero_mdef); // 勇士每回合对怪物造成的伤害 @@ -1113,14 +1167,9 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = }, "drawAbout": function() { // 绘制“关于”界面 - if (!core.isPlaying()) { - core.status.event = {'id': null, 'data': null}; - core.dom.startPanel.style.display = 'none'; - } - core.lockControl(); + core.ui.closePanel(); core.status.event.id = 'about'; - core.clearMap('ui'); var left = 48, top = 36, right = 416 - 2 * left, bottom = 416 - 2 * top; core.setAlpha('ui', 0.85); @@ -1207,8 +1256,11 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // core.plugin.drawLight(0.9, [[25,11,46],[105,121,88],[301,221,106]]); // 存在三个灯光效果,分别是中心(25,11)半径46,中心(105,121)半径88,中心(301,221)半径106。 // core.plugin.drawLight([0,0,255,0.3], [[25,11,46],[105,121,88,0.2]], 0.4); // 存在两个灯光效果,它们在内圈40%范围内保持全亮,且40%后才开始衰减。 this.drawLight = function (color, lights, lightDec) { - // 清空色调层;也可以修改成其它层比如animate层,或者用自己创建的canvas - var ctx = core.canvas.curtain; + // 清空色调层;也可以修改成其它层比如animate/weather层,或者用自己创建的canvas + var canvasName = 'curtain'; + var ctx = core.getContextByName(canvasName); + if (ctx == null) return; + ctx.mozImageSmoothingEnabled = false; ctx.webkitImageSmoothingEnabled = false; ctx.msImageSmoothingEnabled = false; diff --git a/styles.css b/styles.css index 8609eedb..5d6e9c08 100644 --- a/styles.css +++ b/styles.css @@ -286,14 +286,6 @@ p#name { z-index: 70; } -#weather { - z-index: 80; -} - -#route { - z-index: 95; -} - #curtain { z-index: 100; }