diff --git a/index.html b/index.html index 957ad73..5be5cff 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - + HTML5魔塔 @@ -19,135 +19,14 @@ -
-
- -
+
- -
-

请稍候...

-
-
-
-
-
-

资源即将开始加载

-

HTML5魔塔游戏平台,享受更多魔塔游戏:
https://h5mota.com/

-
-
-
-

-

-

-
-
-
- -

-
-
- -

-
-
- -

-
-
- -

-
-
- -

-
-
- -

-
-
- -

-
-
- -

-
-
- -

-
-
- -

-
-
- -

-
-
- -

-
-
- -

-
-
- - - - -
-
- - - -
-
- - - -
- - - -
-
- - - - - - - - - - - - - - - - -

-
-
-
-
- - - - - - - - - - 此浏览器不支持HTML5 - -
+
+ + + 此浏览器不支持HTML5 + +
diff --git a/public/libs/actions.js b/public/libs/actions.js index 4019cbd..947a135 100644 --- a/public/libs/actions.js +++ b/public/libs/actions.js @@ -763,26 +763,17 @@ actions.prototype._sys_onup = function (x, y, px, py) { }; ////// 获得点击事件相对左上角的坐标 ////// -actions.prototype._getClickLoc = function (x, y) { - var statusBar = { x: 0, y: 0 }; - var size = 32; - size = size * core.domStyle.scale; +actions.prototype._getClickLoc = function (x, y, isClient = false) { + var size = 32 * core.domStyle.scale; - if (core.domStyle.isVertical) { - statusBar.x = 3; - statusBar.y = - core.dom.statusBar.offsetHeight + - 3 + - 32 * core.values.statusCanvasRowsOnMobile; + if (!isClient) { + return { x, y, size }; } else { - statusBar.x = core.dom.statusBar.offsetWidth + 3; - statusBar.y = 3; + const ele = core.dom.gameDraw; + const left = ele.offsetLeft; + const top = ele.offsetTop; + return { x: x - left, y: y - top, size }; } - - var left = core.dom.gameGroup.offsetLeft + statusBar.x; - var top = core.dom.gameGroup.offsetTop + statusBar.y; - var loc = { x: Math.max(x - left), y: Math.max(y - top, 0), size: size }; - return loc; }; ////// 滑动鼠标滚轮时的操作 ////// diff --git a/public/libs/control.js b/public/libs/control.js index 494dea8..a4afba9 100644 --- a/public/libs/control.js +++ b/public/libs/control.js @@ -47,7 +47,6 @@ control.prototype._init = function () { this.registerReplayAction('ignoreInput', this._replayAction_ignoreInput); this.registerReplayAction('no', this._replayAction_no); // --- 注册系统的resize - this.registerResize('gameGroup', this._resize_gameGroup); this.registerResize('canvas', this._resize_canvas); }; @@ -251,14 +250,10 @@ control.prototype.showStartAnimate = function (noAnimate, callback) { Mota.r(() => { Mota.require('var', 'fixedUi').open('start'); }); - // core.hideWithAnimate(core.dom.startTop, 20, function () { - // core.control._showStartAnimate_finished(false, callback); - // }); }; control.prototype._showStartAnimate_resetDom = function () { core.status.played = false; - core.dom.gameGroup.style.display = 'none'; core.clearStatus(); core.clearMap('all'); // 重置音量 @@ -267,7 +262,6 @@ control.prototype._showStartAnimate_resetDom = function () { }; control.prototype._showStartAnimate_finished = function (start, callback) { - core.dom.startTop.style.display = 'none'; main.selectedButton = null; if (start) core.startGame(); if (callback) callback(); @@ -275,9 +269,7 @@ control.prototype._showStartAnimate_finished = function (start, callback) { ////// 隐藏游戏开始界面 ////// control.prototype.hideStartAnimate = function (callback) { - core.dom.startPanel.style.display = 'none'; callback?.(); - // core.hideWithAnimate(core.dom.startPanel, 20, callback); }; ////// 游戏是否已经开始 ////// @@ -931,6 +923,7 @@ control.prototype.setHeroOpacity = function ( ////// 设置画布偏移 control.prototype.setGameCanvasTranslate = function (canvas, x, y) { + // Deprecated. Use RenderItem.transform instead. var c = core.dom.gameCanvas[canvas]; x = x * core.domStyle.scale; y = y * core.domStyle.scale; @@ -968,22 +961,7 @@ control.prototype.setGameCanvasTranslate = function (canvas, x, y) { ////// 加减画布偏移 control.prototype.addGameCanvasTranslate = function (x, y) { - for (var ii = 0, canvas; (canvas = core.dom.gameCanvas[ii]); ii++) { - var id = canvas.getAttribute('id'); - if (id == 'ui' || id == 'data') continue; // UI层和data层不移动 - var offsetX = x, - offsetY = y; - if (core.bigmap.canvas.indexOf(id) >= 0) { - if (core.bigmap.v2) { - offsetX -= core.bigmap.offsetX - 32 * core.bigmap.posX + 32; - offsetY -= core.bigmap.offsetY - 32 * core.bigmap.posY + 32; - } else { - offsetX -= core.bigmap.offsetX; - offsetY -= core.bigmap.offsetY; - } - } - core.control.setGameCanvasTranslate(id, offsetX, offsetY); - } + // Deprecated. Use RenderItem.transform instead. }; ////// 更新视野范围 ////// @@ -2670,11 +2648,13 @@ control.prototype.getStatusLabel = function (name) { ////// 设置某个属性的增幅值 ////// control.prototype.setBuff = function (name, value) { + core.status.hero.buff[name] ??= 1; core.status.hero.buff[name] = value; }; ////// 加减某个属性的增幅值 ////// control.prototype.addBuff = function (name, value) { + core.status.hero.buff[name] ??= 1; core.status.hero.buff[name] += value; }; @@ -2893,9 +2873,11 @@ control.prototype.getMappedName = function (name) { ////// 更改天气效果 ////// control.prototype.setWeather = function (type, level) { // Deprecated. Use WeatherController API instead. - const controller = Mota.require('module', 'Weather').controller; - controller.clearWeather(); - if (type !== null && type !== void 0) controller.activate(type, level); + Mota.r(() => { + const controller = Mota.require('module', 'Weather').controller; + controller.clearWeather(); + if (type !== null && type !== void 0) controller.activate(type, level); + }); }; ////// 注册一个天气 ////// @@ -3101,17 +3083,7 @@ control.prototype.setDisplayScale = function (delta) { ////// 清空状态栏 ////// control.prototype.clearStatusBar = function () { - if (main.mode === 'editor') return; - Object.keys(core.statusBar).forEach(function (e) { - if (core.statusBar[e].innerHTML != null) { - core.statusBar[e].innerHTML = ' '; - core.statusBar[e].removeAttribute('_style'); - core.statusBar[e].removeAttribute('_value'); - } - }); - core.statusBar.image.book.style.opacity = 0.3; - if (!core.flags.equipboxButton) - core.statusBar.image.fly.style.opacity = 0.3; + // Deprecated. }; ////// 更新状态栏 ////// @@ -3183,110 +3155,54 @@ control.prototype._doResize = function (obj) { ////// 屏幕分辨率改变后重新自适应 ////// control.prototype.resize = function () { - if (main.mode == 'editor') return; - var clientWidth = main.dom.body.clientWidth, - clientHeight = main.dom.body.clientHeight; - var BORDER = 3; - var extendToolbar = core.flags.extendToolbar; - var BAR_WIDTH = extendToolbar ? 0 : Math.round(core._PY_ * 0.31); + if (main.mode === 'editor') return; + const width = window.innerWidth; + const height = window.innerHeight; - var horizontalMaxRatio = - (clientHeight - 2 * BORDER - (extendToolbar ? BORDER : 0)) / - (core._PY_ + (extendToolbar ? 38 : 0)); + const auto = Mota.require('var', 'mainSetting').getValue('autoScale', true); - if ( - clientWidth - 3 * BORDER >= core._PX_ + BAR_WIDTH || - (clientWidth > clientHeight && horizontalMaxRatio < 1) - ) { + if (window.innerWidth >= 600) { // 横屏 core.domStyle.isVertical = false; - core.domStyle.availableScale = []; + const maxScale = Math.min(width / core._PX_, height / core._PY_); [1, 1.25, 1.5, 1.75, 2, 2.25, 2.5].forEach(function (v) { - if ( - clientWidth - 3 * BORDER >= v * (core._PX_ + BAR_WIDTH) && - horizontalMaxRatio >= v - ) { + if (v < maxScale) { core.domStyle.availableScale.push(v); } }); - if (core.domStyle.availableScale.indexOf(core.domStyle.scale) < 0) { - core.domStyle.scale = Math.min(1, horizontalMaxRatio); + if (!core.domStyle.availableScale.includes(core.domStyle.scale)) { + core.domStyle.scale = 1; } + core.dom.gameDraw.style.top = '0'; } else { // 竖屏 core.domStyle.isVertical = true; - core.domStyle.scale = Math.min((clientWidth - 2 * BORDER) / core._PX_); + core.domStyle.scale = window.innerWidth / core._PX_; core.domStyle.availableScale = []; - extendToolbar = false; - BAR_WIDTH = Math.round(core._PX_ * 0.3); + core.dom.gameDraw.style.top = '10vh'; } - var statusCanvas = core.flags.statusCanvas, - statusCanvasRows = core.values.statusCanvasRowsOnMobile || 3; - var col = statusCanvas ? statusCanvasRows : Math.ceil(5 / 3); + if (!core.domStyle.isVertical) { + const height = window.innerHeight; + const width = window.innerWidth; + const maxScale = Math.min(height / core._PY_, width / core._PX_); + const target = Number((Math.floor(maxScale * 4) / 4).toFixed(2)); + core.domStyle.scale = target - 0.25; + } - var globalAttribute = - core.status.globalAttribute || core.initStatus.globalAttribute; + const pw = core._PX_ * core.domStyle.scale; + const ph = core._PY_ * core.domStyle.scale; + core.dom.gameDraw.style.width = `${pw}px`; + core.dom.gameDraw.style.height = `${ph}px`; - var obj = { - clientWidth: clientWidth, - clientHeight: clientHeight, - BORDER: BORDER, - BAR_WIDTH: BAR_WIDTH, - TOOLBAR_HEIGHT: 38, - outerWidth: core._PX_ * core.domStyle.scale + 2 * BORDER, - outerHeight: core._PY_ * core.domStyle.scale + 2 * BORDER, - globalAttribute: globalAttribute, - border: - '3px ' + core.arrayToRGBA(globalAttribute.borderColor) + ' solid', - col: col, - statusBarHeightInVertical: core.domStyle.isVertical - ? (32 * col + 6) * core.domStyle.scale + 2 * BORDER - : 0, - toolbarHeightInVertical: core.domStyle.isVertical - ? 38 * core.domStyle.scale + 2 * BORDER - : 0, - extendToolbar: extendToolbar, - is15x15: false - }; - - this._doResize(obj); + this._doResize({}); this.setToolbarButton(); core.updateStatusBar(); }; control.prototype._resize_gameGroup = function (obj) { - var gameGroup = core.dom.gameGroup; - var totalWidth, totalHeight; - if (core.domStyle.isVertical) { - totalWidth = obj.outerWidth; - totalHeight = - obj.outerHeight + - obj.statusBarHeightInVertical + - obj.toolbarHeightInVertical; - } else { - totalWidth = - obj.outerWidth + - obj.BAR_WIDTH * core.domStyle.scale + - (obj.extendToolbar ? 0 : obj.BORDER); - totalHeight = obj.outerHeight; - } - gameGroup.style.width = totalWidth + 'px'; - gameGroup.style.height = totalHeight + 'px'; - gameGroup.style.left = (obj.clientWidth - totalWidth) / 2 + 'px'; - gameGroup.style.top = - (obj.clientHeight - totalHeight) / 2 + - (core.domStyle.isVertical ? totalHeight / 8 : 0) + - 'px'; - // floorMsgGroup - var floorMsgGroup = core.dom.floorMsgGroup; - floorMsgGroup.style = obj.globalAttribute.floorChangingStyle; - floorMsgGroup.style.width = obj.outerWidth - 2 * obj.BORDER + 'px'; - floorMsgGroup.style.height = totalHeight - 2 * obj.BORDER + 'px'; - floorMsgGroup.style.fontSize = 16 * core.domStyle.scale + 'px'; - // startPanel - core.dom.startPanel.style.fontSize = 16 * core.domStyle.scale + 'px'; + // Deprecated. }; control.prototype._resize_canvas = function (obj) { @@ -3300,26 +3216,6 @@ control.prototype._resize_canvas = function (obj) { core.resizeCanvas(ctx, core._PX_, core._PY_); } - core.dom.gif.style.width = innerWidth; - core.dom.gif.style.height = innerHeight; - core.dom.gif2.style.width = innerWidth; - core.dom.gif2.style.height = innerHeight; - core.dom.gameDraw.style.width = innerWidth; - core.dom.gameDraw.style.height = innerHeight; - core.dom.gameDraw.style.top = obj.statusBarHeightInVertical + 'px'; - core.dom.gameDraw.style.right = 0; - core.dom.gameDraw.style.boxSizing = 'content-box'; - // resize bigmap - core.bigmap.canvas.forEach(function (cn) { - var ratio = core.canvas[cn].canvas.hasAttribute('isHD') - ? core.domStyle.scale * devicePixelRatio - : 1; - core.canvas[cn].canvas.style.width = - (core.canvas[cn].canvas.width / ratio) * core.domStyle.scale + 'px'; - core.canvas[cn].canvas.style.height = - (core.canvas[cn].canvas.height / ratio) * core.domStyle.scale + - 'px'; - }); // resize dynamic canvas if (!core.isPlaying()) { for (var name in core.dymCanvas) { diff --git a/public/libs/core.js b/public/libs/core.js index f81fe94..74c2c89 100644 --- a/public/libs/core.js +++ b/public/libs/core.js @@ -111,7 +111,7 @@ function core() { hdCanvas: ['damage', 'ui', 'data'] }; this.bigmap = { - canvas: ['bg', 'event', 'event2', 'fg', 'damage'], + canvas: [], offsetX: 0, // in pixel offsetY: 0, posX: 0, // @@ -376,8 +376,6 @@ core.prototype._init_flags = function () { core.firstData = core.clone(core.data.firstData); this._init_sys_flags(); - core.dom.versionLabel.innerText = core.firstData.version; - core.dom.logoLabel.innerText = core.firstData.title; document.title = core.firstData.title + ' - HTML5魔塔'; (core.firstData.shops || []).forEach(function (t) { core.initStatus.shops[t.id] = t; diff --git a/public/libs/events.js b/public/libs/events.js index c1b0a35..c9a0dda 100644 --- a/public/libs/events.js +++ b/public/libs/events.js @@ -24,7 +24,6 @@ events.prototype.resetGame = function (hero, hard, floorId, maps, values) { ////// 游戏开始事件 ////// events.prototype.startGame = function (hard, seed, route, callback) { hard = hard || ''; - core.dom.gameGroup.style.display = 'block'; if (!main.replayChecking) { Mota.require('var', 'fixedUi').closeByName('start'); } @@ -34,7 +33,6 @@ events.prototype.startGame = function (hard, seed, route, callback) { // 无动画的开始游戏 if (core.flags.startUsingCanvas || route != null) { - core.dom.startPanel.style.display = 'none'; this._startGame_start(hard, seed, route, callback); } else { core.hideStartAnimate(function () { @@ -62,7 +60,6 @@ events.prototype._startGame_start = function (hard, seed, route, callback) { var todo = []; if (core.flags.startUsingCanvas) { core.hideStatusBar(); - core.dom.musicBtn.style.display = 'block'; core.push(todo, core.firstData.startCanvas); } core.push(todo, { @@ -146,7 +143,6 @@ events.prototype.gameOver = function (ending, fromReplay, norank) { if (!core.status.extraEvent) { core.clearMap('all'); core.deleteAllCanvas(); - core.dom.gif2.innerHTML = ''; core.setWeather(); } core.ui.closePanel(); @@ -783,7 +779,6 @@ events.prototype.changeFloor = function ( floorId = info.floorId; info.locked = core.status.lockControl; - core.dom.floorNameLabel.innerText = core.status.maps[floorId].title; core.lockControl(); core.stopAutomaticRoute(); core.clearContinueAutomaticRoute(); @@ -820,7 +815,6 @@ events.prototype._changeFloor_getInfo = function ( if (main.mode != 'play' || core.isReplaying()) time = 0; if (time == null) time = core.values.floorChangeTime; - time /= 20; return { floorId: floorId, @@ -869,15 +863,17 @@ events.prototype._changeFloor_beforeChange = function (info, callback) { this._changeFloor_playSound(); // 需要 setTimeout 执行,不然会出错 window.setTimeout(function () { - if (info.time == 0) core.events._changeFloor_changing(info, callback); - else - core.showWithAnimate( - core.dom.floorMsgGroup, - info.time / 2, - function () { - core.events._changeFloor_changing(info, callback); - } - ); + if (info.time === 0 || main.replayChecking) { + core.events._changeFloor_changing(info, callback); + } else { + const Render = Mota.require('module', 'Render').MotaRenderer; + const main = Render.get('render-main'); + const change = main.getElementById('floor-change'); + change.setTitle(core.floors[info.floorId]?.title ?? ''); + change.showChange(info.time / 2).then(() => { + core.events._changeFloor_changing(info, callback); + }); + } }, 25); }; @@ -900,15 +896,16 @@ events.prototype._changeFloor_changing = function (info, callback) { core.drawHero(); core.setFlag('__lockViewport__', __lockViewport__); - if (info.time == 0) this._changeFloor_afterChange(info, callback); - else - core.hideWithAnimate( - core.dom.floorMsgGroup, - info.time / 4, - function () { - core.events._changeFloor_afterChange(info, callback); - } - ); + if (info.time === 0 || main.replayChecking) { + this._changeFloor_afterChange(info, callback); + } else { + const Render = Mota.require('module', 'Render').MotaRenderer; + const main = Render.get('render-main'); + const change = main.getElementById('floor-change'); + change.hideChange(info.time / 2).then(() => { + core.events._changeFloor_afterChange(info, callback); + }); + } }; events.prototype._changeFloor_afterChange = function (info, callback) { @@ -3418,7 +3415,6 @@ events.prototype.load = function (fromUserAction) { offset = saveIndex - 5 * page; // 游戏开始前读档 if (!core.isPlaying()) { - core.dom.startPanel.style.display = 'none'; core.clearStatus(); core.clearMap('all'); core.status.event = { id: 'load', data: null }; @@ -4206,20 +4202,7 @@ events.prototype._scaleImage_scale = function (ctx, scaleInfo, callback) { ////// 绘制或取消一张gif图片 ////// events.prototype.showGif = function (name, x, y) { - name = core.getMappedName(name); - var image = core.material.images.images[name]; - if (image) { - var gif = new Image(); - gif.src = image.src; - gif.style.position = 'absolute'; - gif.style.left = x * core.domStyle.scale + 'px'; - gif.style.top = y * core.domStyle.scale + 'px'; - gif.style.width = image.width * core.domStyle.scale + 'px'; - gif.style.height = image.height * core.domStyle.scale + 'px'; - core.dom.gif2.appendChild(gif); - } else { - core.dom.gif2.innerHTML = ''; - } + // Deprecated. }; ////// 淡入淡出音乐 ////// diff --git a/public/libs/loader.js b/public/libs/loader.js index fab081d..58936e4 100644 --- a/public/libs/loader.js +++ b/public/libs/loader.js @@ -13,14 +13,10 @@ function loader() { loader.prototype._init = function () {}; ////// 设置加载进度条进度 ////// -loader.prototype._setStartProgressVal = function (val) { - core.dom.startTopProgress.style.width = val + '%'; -}; +loader.prototype._setStartProgressVal = function (val) {}; ////// 设置加载进度条提示文字 ////// -loader.prototype._setStartLoadTipText = function (text) { - core.dom.startTopLoadTips.innerText = text; -}; +loader.prototype._setStartLoadTipText = function (text) {}; loader.prototype._load = function (callback) { if (main.useCompress) { diff --git a/public/libs/maps.js b/public/libs/maps.js index 5e34571..f88bde0 100644 --- a/public/libs/maps.js +++ b/public/libs/maps.js @@ -1960,16 +1960,7 @@ maps.prototype._getFloorImages = function (floorId) { }; maps.prototype._drawFloorImages_gif = function (image, dx, dy) { - core.dom.gif.innerHTML = ''; - var gif = new Image(); - gif.src = image.src; - gif.style.position = 'absolute'; - gif.style.left = dx * core.domStyle.scale + 'px'; - gif.style.top = dy * core.domStyle.scale + 'px'; - gif.style.width = image.width * core.domStyle.scale + 'px'; - gif.style.height = image.height * core.domStyle.scale + 'px'; - core.dom.gif.appendChild(gif); - return; + // Deprecated. }; maps.prototype._drawFloorImage = function ( diff --git a/public/libs/ui.js b/public/libs/ui.js index 88af564..ee2e4d5 100644 --- a/public/libs/ui.js +++ b/public/libs/ui.js @@ -50,7 +50,6 @@ ui.prototype.clearMap = function (name, x, y, width, height) { core.canvas[m].canvas.height + 32 ); } - core.dom.gif.innerHTML = ''; core.removeGlobalAnimate(); core.deleteCanvas(function (one) { return one.startsWith('_bigImage_'); @@ -3759,85 +3758,7 @@ ui.prototype._drawSLPanel_drawRecords = function (n) { }; ui.prototype._drawKeyBoard = function () { - core.lockControl(); - core.status.event.id = 'keyBoard'; - core.clearUI(); - core.playSound('打开界面'); - - var offset = core._WIDTH_ % 2 == 0 ? 16 : 0; - - var width = 384, - height = 320; - var left = (core._PX_ - width) / 2 + offset, - right = left + width; - var top = (core._PY_ - height) / 2 + (core._HEIGHT_ % 2 == 0 ? 16 : 0), - bottom = top + height; - - var isWindowSkin = this.drawBackground(left, top, right, bottom); - core.setTextAlign('ui', 'center'); - core.setFillStyle('ui', core.arrayToRGBA(core.status.textAttribute.title)); - core.fillText( - 'ui', - '虚拟键盘', - core._PX_ / 2 + offset, - top + 35, - null, - this._buildFont(22, true) - ); - core.setFont('ui', this._buildFont(17, false)); - core.setFillStyle('ui', core.arrayToRGBA(core.status.textAttribute.text)); - var now = core._PY_ / 2 - 89 + (core._HEIGHT_ % 2 == 0 ? 16 : 0); - - var lines = [ - ['F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', '10', '11'], - ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'], - ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'], - ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'], - ['Z', 'X', 'C', 'V', 'B', 'N', 'M'], - ['-', '=', '[', ']', '\\', ';', "'", ',', '.', '/', '`'], - ['ES', 'TA', 'CA', 'SH', 'CT', 'AL', 'SP', 'BS', 'EN', 'DE'] - ]; - - lines.forEach(function (line) { - for (var i = 0; i < line.length; i++) { - core.fillText( - 'ui', - line[i], - core._PX_ / 2 + 32 * (i - 5) + offset, - now - ); - } - now += 32; - }); - - core.fillText( - 'ui', - '返回游戏', - core._PX_ / 2 + 128 + offset, - now - 3, - '#FFFFFF', - this._buildFont(15, true) - ); - - if (isWindowSkin) - this._drawWindowSelector( - core.status.textAttribute.background, - core._PX_ / 2 + 92 + offset, - now - 22, - 72, - 27 - ); - else - core.strokeRoundRect( - 'ui', - core._PX_ / 2 + 92 + offset, - now - 22, - 72, - 27, - 6, - core.status.globalAttribute.selectColor, - 2 - ); + // Deprecated. }; ////// 绘制“数据统计”界面 ////// @@ -4145,7 +4066,7 @@ ui.prototype.createCanvas = function (name, x, y, width, height, z) { newCanvas.style.pointerEvents = 'none'; core.dymCanvas[name] = newCanvas.getContext('2d'); core.maps._setHDCanvasSize(core.dymCanvas[name], width, height); - core.dom.gameDraw.appendChild(newCanvas); + // core.dom.gameDraw.appendChild(newCanvas); return core.dymCanvas[name]; }; @@ -4223,7 +4144,7 @@ ui.prototype.deleteCanvas = function (name) { } if (!core.dymCanvas[name]) return null; - core.dom.gameDraw.removeChild(core.dymCanvas[name].canvas); + // core.dom.gameDraw.removeChild(core.dymCanvas[name].canvas); delete core.dymCanvas[name]; }; diff --git a/public/main.js b/public/main.js index 671e67b..982b07a 100644 --- a/public/main.js +++ b/public/main.js @@ -22,55 +22,10 @@ function main() { this.dom = { body: document.body, - gameGroup: document.getElementById('gameGroup'), - mainTips: document.getElementById('mainTips'), - musicBtn: document.getElementById('musicBtn'), - enlargeBtn: document.createElement('img'), - startPanel: document.getElementById('startPanel'), - startTop: document.getElementById('startTop'), - startTopProgressBar: document.getElementById('startTopProgressBar'), - startTopProgress: document.getElementById('startTopProgress'), - startTopLoadTips: document.getElementById('startTopLoadTips'), - floorMsgGroup: document.getElementById('floorMsgGroup'), - logoLabel: document.getElementById('logoLabel'), - versionLabel: document.getElementById('versionLabel'), - floorNameLabel: document.getElementById('floorNameLabel'), - statusBar: document.getElementById('statusBar'), - status: document.getElementsByClassName('status'), - tools: document.getElementsByClassName('tools'), + game: document.getElementById('game'), + gameDraw: document.getElementById('game-draw'), gameCanvas: document.getElementsByClassName('gameCanvas'), - gif: document.getElementById('gif'), - gif2: document.getElementById('gif2'), - gameDraw: document.getElementById('gameDraw'), - startButtons: document.getElementById('startButtons'), - playGame: document.getElementById('playGame'), - loadGame: document.getElementById('loadGame'), - replayGame: document.getElementById('replayGame'), - levelChooseButtons: document.getElementById('levelChooseButtons'), data: document.getElementById('data'), - statusLabels: document.getElementsByClassName('statusLabel'), - statusTexts: document.getElementsByClassName('statusText'), - floorCol: document.getElementById('floorCol'), - nameCol: document.getElementById('nameCol'), - lvCol: document.getElementById('lvCol'), - hpmaxCol: document.getElementById('hpmaxCol'), - hpCol: document.getElementById('hpCol'), - manaCol: document.getElementById('manaCol'), - atkCol: document.getElementById('atkCol'), - defCol: document.getElementById('defCol'), - mdefCol: document.getElementById('mdefCol'), - moneyCol: document.getElementById('moneyCol'), - expCol: document.getElementById('expCol'), - upCol: document.getElementById('upCol'), - keyCol: document.getElementById('keyCol'), - pzfCol: document.getElementById('pzfCol'), - debuffCol: document.getElementById('debuffCol'), - skillCol: document.getElementById('skillCol'), - hard: document.getElementById('hard'), - statusCanvas: document.getElementById('statusCanvas'), - statusCanvasCtx: document - .getElementById('statusCanvas') - .getContext('2d'), inputDiv: document.getElementById('inputDiv'), inputMessage: document.getElementById('inputMessage'), inputBox: document.getElementById('inputBox'), @@ -115,37 +70,7 @@ function main() { ]; this.statusBar = { - image: { - floor: document.getElementById('img-floor'), - name: document.getElementById('img-name'), - lv: document.getElementById('img-lv'), - hpmax: document.getElementById('img-hpmax'), - hp: document.getElementById('img-hp'), - mana: document.getElementById('img-mana'), - atk: document.getElementById('img-atk'), - def: document.getElementById('img-def'), - mdef: document.getElementById('img-mdef'), - money: document.getElementById('img-money'), - exp: document.getElementById('img-exp'), - up: document.getElementById('img-up'), - skill: document.getElementById('img-skill'), - book: document.getElementById('img-book'), - fly: document.getElementById('img-fly'), - toolbox: document.getElementById('img-toolbox'), - keyboard: document.getElementById('img-keyboard'), - shop: document.getElementById('img-shop'), - save: document.getElementById('img-save'), - load: document.getElementById('img-load'), - settings: document.getElementById('img-settings'), - btn1: document.getElementById('img-btn1'), - btn2: document.getElementById('img-btn2'), - btn3: document.getElementById('img-btn3'), - btn4: document.getElementById('img-btn4'), - btn5: document.getElementById('img-btn5'), - btn6: document.getElementById('img-btn6'), - btn7: document.getElementById('img-btn7'), - btn8: document.getElementById('img-btn8') - }, + image: {}, icons: { floor: 0, name: null, @@ -183,31 +108,7 @@ function main() { btn6: 32, btn7: 33, btn8: 34 - }, - floor: document.getElementById('floor'), - name: document.getElementById('name'), - lv: document.getElementById('lv'), - hpmax: document.getElementById('hpmax'), - hp: document.getElementById('hp'), - mana: document.getElementById('mana'), - atk: document.getElementById('atk'), - def: document.getElementById('def'), - mdef: document.getElementById('mdef'), - money: document.getElementById('money'), - exp: document.getElementById('exp'), - up: document.getElementById('up'), - skill: document.getElementById('skill'), - yellowKey: document.getElementById('yellowKey'), - blueKey: document.getElementById('blueKey'), - redKey: document.getElementById('redKey'), - greenKey: document.getElementById('greenKey'), - poison: document.getElementById('poison'), - weak: document.getElementById('weak'), - curse: document.getElementById('curse'), - pickaxe: document.getElementById('pickaxe'), - bomb: document.getElementById('bomb'), - fly: document.getElementById('fly'), - hard: document.getElementById('hard') + } }; this.floors = {}; this.canvas = {}; @@ -353,7 +254,6 @@ main.prototype.loadAsync = async function (mode, callback) { main.setMainTipsText('正在加载楼层文件...'); if (main.useCompress) { await main.loadScript(`project/floors.min.js?v=${main.version}`); - main.dom.mainTips.style.display = 'none'; } else { await new Promise(res => { main.loadScript( @@ -362,7 +262,6 @@ main.prototype.loadAsync = async function (mode, callback) { }&id=${main.floorIds.join(',')}` ).then( () => { - main.dom.mainTips.style.display = 'none'; main.supportBunch = true; res(); }, @@ -372,7 +271,6 @@ main.prototype.loadAsync = async function (mode, callback) { main.loadScript(`project/floors/${v}.js`) ) ); - main.dom.mainTips.style.display = 'none'; res(); } ); @@ -419,78 +317,27 @@ main.prototype.loadAsync = async function (mode, callback) { let auto = Mota.require('var', 'mainSetting').getValue('autoScale', true); if (auto && !core.domStyle.isVertical) { - try { - Mota.Plugin.require('utils_g').maxGameScale(1); - requestAnimationFrame(() => { - var style = getComputedStyle(main.dom.gameGroup); - var height = parseFloat(style.height); - if (height > window.innerHeight * 0.95) { - core.control.setDisplayScale(-1); - if (!core.isPlaying() && core.flags.enableHDCanvas) { - core.domStyle.ratio = Math.max( - window.devicePixelRatio || 1, - core.domStyle.scale - ); - core.resize(); - } - } - }); - } catch {} + const height = window.innerHeight; + const width = window.innerWidth; + const maxScale = Math.min(height / core._PY_, width / core._PX_); + const target = Number((Math.floor(maxScale * 4) / 4).toFixed(2)); + core.domStyle.scale = target - 0.25; } + if (core.domStyle.isVertical) { + core.domStyle.scale = window.innerWidth / core._PX_; + } + Mota.r(() => { + Mota.require('module', 'Render').MotaOffscreenCanvas2D.refreshAll(); + }); }; ////// 加载过程提示 ////// -main.prototype.setMainTipsText = function (text) { - main.dom.mainTips.innerHTML = text; -}; +main.prototype.setMainTipsText = function (text) {}; -main.prototype.createOnChoiceAnimation = function () { - var borderColor = - main.dom.startButtonGroup.style.caretColor || 'rgb(255, 215, 0)'; - // get rgb value - var rgb = - /^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*\d+\s*)?\)$/.exec( - borderColor - ); - if (rgb != null) { - var value = rgb[1] + ', ' + rgb[2] + ', ' + rgb[3]; - var style = document.createElement('style'); - style.type = 'text/css'; - var keyFrames = - 'onChoice { ' + - '0% { border-color: rgba(' + - value + - ', 0.9); } ' + - '50% { border-color: rgba(' + - value + - ', 0.3); } ' + - '100% { border-color: rgba(' + - value + - ', 0.9); } ' + - '}'; - style.innerHTML = - '@-webkit-keyframes ' + keyFrames + ' @keyframes ' + keyFrames; - document.body.appendChild(style); - } -}; +main.prototype.createOnChoiceAnimation = function () {}; ////// 创建字体 ////// -main.prototype.importFonts = function (fonts) { - if (!(fonts instanceof Array) || fonts.length == 0) return; - var style = document.createElement('style'); - style.type = 'text/css'; - var html = ''; - fonts.forEach(function (font) { - html += - '@font-face { font-family: "' + - font + - '"; src: url("project/fonts/' + - font + - '.ttf") format("truetype"); }'; - }); - style.innerHTML = html; - document.body.appendChild(style); -}; +main.prototype.importFonts = function (fonts) {}; main.prototype.listen = function () { ////// 窗口大小变化时 ////// @@ -515,9 +362,6 @@ main.prototype.listen = function () { } }; - ////// 在界面上放开某按键时 ////// - main.dom.body.addEventListener('keyup', function (e) {}); - ////// 开始选择时 ////// main.dom.body.onselectstart = function () { return false; @@ -527,7 +371,7 @@ main.prototype.listen = function () { main.dom.data.onmousedown = function (e) { try { e.stopPropagation(); - var loc = core.actions._getClickLoc(e.clientX, e.clientY); + var loc = core.actions._getClickLoc(e.offsetX, e.offsetY); if (loc == null) return; core.ondown(loc); } catch (ee) { @@ -538,7 +382,7 @@ main.prototype.listen = function () { ////// 鼠标移动时 ////// main.dom.data.onmousemove = function (e) { try { - var loc = core.actions._getClickLoc(e.clientX, e.clientY); + var loc = core.actions._getClickLoc(e.offsetX, e.offsetY); if (loc == null) return; core.onmove(loc); } catch (ee) { @@ -549,7 +393,7 @@ main.prototype.listen = function () { ////// 鼠标放开时 ////// main.dom.data.onmouseup = function (e) { try { - var loc = core.actions._getClickLoc(e.clientX, e.clientY); + var loc = core.actions._getClickLoc(e.offsetX, e.offsetY); if (loc == null) return; core.onup(loc); } catch (ee) { @@ -573,7 +417,8 @@ main.prototype.listen = function () { e.preventDefault(); var loc = core.actions._getClickLoc( e.targetTouches[0].clientX, - e.targetTouches[0].clientY + e.targetTouches[0].clientY, + true ); if (loc == null) return; main.lastTouchLoc = loc; @@ -589,7 +434,8 @@ main.prototype.listen = function () { e.preventDefault(); var loc = core.actions._getClickLoc( e.targetTouches[0].clientX, - e.targetTouches[0].clientY + e.targetTouches[0].clientY, + true ); if (loc == null) return; main.lastTouchLoc = loc; @@ -612,218 +458,6 @@ main.prototype.listen = function () { } }; - ////// 点击状态栏中的怪物手册时 ////// - main.statusBar.image.book.onclick = function (e) { - e.stopPropagation(); - - if (core.isReplaying()) { - core.triggerReplay(); - return; - } - - if (core.isPlaying()) core.openBook(true); - }; - - ////// 点击状态栏中的楼层传送器/装备栏时 ////// - main.statusBar.image.fly.onclick = function (e) { - e.stopPropagation(); - - // 播放录像时 - if (core.isReplaying()) { - core.stopReplay(); - return; - } - - if (core.isPlaying()) { - if (!core.flags.equipboxButton) { - core.useFly(true); - } else { - core.openEquipbox(true); - } - } - }; - - ////// 点击状态栏中的工具箱时 ////// - main.statusBar.image.toolbox.onclick = function (e) { - e.stopPropagation(); - - if (core.isReplaying()) { - core.rewindReplay(); - return; - } - - if (core.isPlaying()) { - core.openToolbox(core.status.event.id != 'equipbox'); - } - }; - - ////// 双击状态栏中的工具箱时 ////// - main.statusBar.image.toolbox.ondblclick = function (e) { - e.stopPropagation(); - - if (core.isReplaying()) { - return; - } - - if (core.isPlaying()) core.openEquipbox(true); - }; - - ////// 点击状态栏中的虚拟键盘时 ////// - main.statusBar.image.keyboard.onclick = function (e) { - e.stopPropagation(); - - if (core.isReplaying()) { - core.control._replay_book(); - return; - } - - if (core.isPlaying()) core.openKeyBoard(true); - }; - - ////// 点击状态栏中的快捷商店时 ////// - main.statusBar.image.shop.onclick = function (e) { - e.stopPropagation(); - - if (core.isReplaying()) { - core.control._replay_viewMap(); - return; - } - - if (core.isPlaying()) core.openQuickShop(true); - }; - - ////// 点击金币时也可以开启快捷商店 ////// - main.statusBar.image.money.onclick = function (e) { - e.stopPropagation(); - - if (core.isPlaying()) core.openQuickShop(true); - }; - - ////// 点击楼梯图标也可以浏览地图 ////// - main.statusBar.image.floor.onclick = function (e) { - e.stopPropagation(); - - if ( - core && - core.isPlaying() && - !core.isMoving() && - !core.status.lockControl - ) { - core.ui._drawViewMaps(); - } - }; - - ////// 点击状态栏中的存档按钮时 ////// - main.statusBar.image.save.onclick = function (e) { - e.stopPropagation(); - - if (core.isReplaying()) { - core.speedDownReplay(); - return; - } - - if (core.isPlaying()) core.save(true); - }; - - ////// 点击状态栏中的读档按钮时 ////// - main.statusBar.image.load.onclick = function (e) { - e.stopPropagation(); - - if (core.isReplaying()) { - core.speedUpReplay(); - return; - } - - if (core.isPlaying()) core.load(true); - }; - - ////// 点击状态栏中的系统菜单时 ////// - main.statusBar.image.settings.onclick = function (e) { - e.stopPropagation(); - - if (core.isReplaying()) { - core.control._replay_SL(); - return; - } - - if (core.isPlaying()) core.openSettings(true); - }; - - ////// 点击工具栏时 ////// - main.dom.hard.onclick = function () { - core.control.setToolbarButton(!core.domStyle.toolbarBtn); - }; - - ////// 手机端的按钮1-7 ////// - // main.statusBar.image.btn1.onclick = function (e) { - // e.stopPropagation(); - // core.onkeyUp({ - // keyCode: 49, - // altKey: core.getLocalStorage('altKey') - // }); - // }; - - // main.statusBar.image.btn2.onclick = function (e) { - // e.stopPropagation(); - // core.onkeyUp({ - // keyCode: 50, - // altKey: core.getLocalStorage('altKey') - // }); - // }; - - // main.statusBar.image.btn3.onclick = function (e) { - // e.stopPropagation(); - // core.onkeyUp({ - // keyCode: 51, - // altKey: core.getLocalStorage('altKey') - // }); - // }; - - // main.statusBar.image.btn4.onclick = function (e) { - // e.stopPropagation(); - // core.onkeyUp({ - // keyCode: 52, - // altKey: core.getLocalStorage('altKey') - // }); - // }; - - // main.statusBar.image.btn5.onclick = function (e) { - // e.stopPropagation(); - // core.onkeyUp({ - // keyCode: 53, - // altKey: core.getLocalStorage('altKey') - // }); - // }; - - // main.statusBar.image.btn6.onclick = function (e) { - // e.stopPropagation(); - // core.onkeyUp({ - // keyCode: 54, - // altKey: core.getLocalStorage('altKey') - // }); - // }; - - // main.statusBar.image.btn7.onclick = function (e) { - // e.stopPropagation(); - // core.onkeyUp({ - // keyCode: 55, - // altKey: core.getLocalStorage('altKey') - // }); - // }; - - // main.statusBar.image.btn8.onclick = function (e) { - // e.stopPropagation(); - // if (core.getLocalStorage('altKey')) { - // core.removeLocalStorage('altKey'); - // core.drawTip('Alt模式已关闭。'); - // main.statusBar.image.btn8.style.filter = ''; - // } else { - // core.setLocalStorage('altKey', true); - // core.drawTip('Alt模式已开启;此模式下1~7按钮视为Alt+1~7。'); - // main.statusBar.image.btn8.style.filter = 'sepia(1) contrast(1.5)'; - // } - // }; - window.onblur = function () { if (core && core.control) { try { diff --git a/public/project/functions.js b/public/project/functions.js index 3f9a4e6..419f9c2 100644 --- a/public/project/functions.js +++ b/public/project/functions.js @@ -102,7 +102,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = { if (!noexit) { core.clearMap('all'); // 清空全地图 core.deleteAllCanvas(); // 删除所有创建的画布 - core.dom.gif2.innerHTML = ''; } reason = core.replaceText(reason); core.drawText( @@ -391,37 +390,10 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = { }); }, updateStatusBar: function () { - // 更新状态栏 - // 检查等级 core.events.checkLvUp(); - - // 如果是自定义添加的状态栏,也需要在这里进行设置显示的数值 - - // 难度 - if (core.statusBar.hard.innerText != core.status.hard) { - core.statusBar.hard.innerText = core.status.hard; - } - var hardColor = core.getFlag('__hardColor__', 'red'); - if (core.statusBar.hard.getAttribute('_style') != hardColor) { - core.statusBar.hard.style.color = hardColor; - core.statusBar.hard.setAttribute('_style', hardColor); - } - // 更新全地图显伤 core.updateDamage(); - - if (main.replayChecking) return; - - // 已学习的技能 - // if ( - // core.plugin.skillTree.getSkillLevel(11) > 0 && - // (core.status.hero.special?.num ?? []).length > 0 - // ) { - // mota.plugin.ui.showStudiedSkill.value = true; - // } else { - // mota.plugin.ui.showStudiedSkill.value = false; - // } }, moveOneStep: function (callback) { // 勇士每走一步后执行的操作。callback为行走完毕后的回调 @@ -433,10 +405,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = { // 增加步数 core.status.hero.steps++; - // 更新跟随者状态,并绘制 - core.updateFollowers(); - core.drawHero(); - // 从v2.7开始,每一步行走不会再刷新状态栏。 // 如果有特殊要求(如每走一步都加buff之类),可手动取消注释下面这一句: // core.updateStatusBar(true); diff --git a/public/styles.css b/public/styles.css index 7764fd8..31b1596 100644 --- a/public/styles.css +++ b/public/styles.css @@ -17,344 +17,12 @@ body { align-items: center; } -#gameGroup { - position: absolute; - box-sizing: border-box; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - background-color: #000; -} - -#mainTips { - color: #fff; - font-size: 0.8em; - position: fixed; - top: 10px; - left: 10px; - z-index: 370; -} - -#musicBtn { - position: absolute; - bottom: 3px; - right: -20%; - cursor: pointer; - z-index: 400; - display: none; -} - -#startPanel { - opacity: 0; - width: 150%; - height: 100%; - position: absolute; - top: 0; - left: -25%; - background-color: #000; - overflow: hidden; - z-index: 300; -} - -#startTop { - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - background-color: #000; - z-index: 350; -} - -#startTopProgressBar { - width: 90%; - height: 5%; - margin: 0 5%; - position: absolute; - top: 5%; - background-color: #fff; - z-index: 15; -} - -#startTopProgress { - width: 0%; - height: 100%; - background-color: #666; -} - -#startTopLoadTips { - color: #fff; - font-size: 0.6em; - position: absolute; - top: 10%; - left: 5%; - z-index: 15; -} - -#startTopHint { - color: #66ccff; - position: absolute; - bottom: 0; - left: 5%; - z-index: 15; - font-size: 1.1em; -} - -#startBackground { - position: absolute; - top: 50%; - left: 50%; - height: 100%; - width: auto; - transform: translate(-50%, -50%); - z-index: 260; - object-fit: cover; - filter: sepia(30%) contrast(70%); -} - -#startLogo { - position: absolute; - z-index: 290; - left: 0; - right: 0; - margin-left: auto; - margin-right: auto; - margin-top: 8%; - max-width: 100%; - color: transparent; - text-align: center; - font: 4em 'normal'; - font-weight: 200; - background-image: linear-gradient( - to right, - rgb(0, 0, 0), - rgb(44, 44, 44), - rgb(136, 0, 214), - rgb(0, 2, 97), - rgb(0, 2, 97) - ); - background-clip: text; - -webkit-background-clip: text; - text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5), - -1px -1px 3px rgba(255, 255, 255, 0.3), 5px 5px 5px rgba(0, 0, 0, 0.4); - filter: brightness(1.8); - user-select: none; -} - -#startTitle { - position: absolute; - z-index: 280; -} - -#startButtonGroup { - width: 25%; - position: absolute; - text-align: center; - font-size: 1.4em; - font-family: 'normal'; - display: none; - z-index: 310; - bottom: 0; - margin-bottom: 7%; - left: 30%; - transform: translateX(-50%); - padding: 15px 25px; - text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.4), - 0px 0px 1px rgba(255, 255, 255, 0.3); -} - -#playGame { +#game-draw { position: relative; - left: 10%; - color: transparent; - background-image: linear-gradient( - to bottom, - rgb(255, 255, 255), - rgb(0, 255, 255) - ); - background-clip: text; - -webkit-background-clip: text; } -#loadGame { - position: relative; - left: 5%; - color: transparent; - background-image: linear-gradient( - to bottom, - rgb(255, 255, 255), - rgb(0, 255, 55) - ); - background-clip: text; - -webkit-background-clip: text; -} - -#replayGame { - position: relative; - - color: transparent; - background-image: linear-gradient( - to bottom, - rgb(255, 255, 255), - rgb(255, 251, 0) - ); - background-clip: text; - -webkit-background-clip: text; -} - -#startButtons { - display: block; -} - -#levelChooseButtons { - display: none; -} - -span#hard { - background-image: linear-gradient( - to bottom, - rgb(255, 255, 255), - rgb(255, 0, 0) - ); -} - -#levelChooseButtons span { - color: transparent; - background-clip: text; - -webkit-background-clip: text; -} - -.startButton { - width: 100%; - margin: 0; - font-weight: bold; - display: block; - cursor: pointer; - border-color: transparent; - border-width: 2px; - border-style: solid; - border-radius: 6px; - transition: box-shadow 0.3s linear, transform 0.2s ease-out; - box-shadow: 0px 0px 7px rgba(0, 0, 0, 0.4); - transform: scale(1); -} - -.onChoiceAnimate { - animation: onChoice 2s ease-in-out 0s infinite normal none running; -} - -#floorMsgGroup { - top: 3px; - right: 3px; +#game-draw > * { position: absolute; - text-align: center; - display: none; - color: transparent; - background-color: #000; - z-index: 230; - user-select: none; -} - -#logoLabel { - margin-top: 8%; - font: bold 3em STXingkai; - margin-left: auto; - margin-right: auto; -} - -#versionLabel { - margin-top: -3%; - font-size: 1.2em; - font-weight: bold; -} - -#floorNameLabel { - margin-top: 30px; - font-size: 1.6em; - font-weight: bold; -} - -#statusBar { - position: absolute; - box-sizing: border-box; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - background: black; - z-index: 185; - display: none; - top: 0; - left: 0; - padding: 3px; -} -#statusBar .status { - user-select: none; - position: relative; - display: block; - float: left; - width: 100%; -} -.status img { - vertical-align: middle; - width: auto; - height: 100%; - max-height: 1.6em; -} -#statusBar span { - user-select: none; - font: bold italic 1.1em Verdana; - display: inline; -} -#statusBar p { - user-select: none; - display: inline-block; - vertical-align: middle; - width: 60%; - margin: 0; - color: white; - font: bold italic 1.1em Verdana; - white-space: nowrap; -} -#toolBar { - position: absolute; - z-index: 210; - box-sizing: border-box; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - display: none; - padding: 3px; - border-top: 2px solid #ddd9; - margin-right: 3px; -} -#toolBar .tools { - position: relative; - display: block; - float: left; -} - -p#hard { - user-select: none; - width: 6em; - vertical-align: middle; - display: inline-block; - color: red; - font: bold normal 1.1em 'Arial Black'; - text-align: center; - margin: 0 6px 6px 0; - word-break: keep-all; -} - -span#poison, -span#weak, -span#curse, -span#pickaxe, -span#bomb, -span#fly { - user-select: none; - font-style: normal; - font-size: 1em; -} - -p#name { - font-style: normal; } .gameCanvas { @@ -364,55 +32,6 @@ p#name { -webkit-box-sizing: border-box; } -#gif { - z-index: 20; - position: absolute; - overflow: hidden; -} - -#gif2 { - z-index: 90; - position: absolute; - overflow: hidden; -} - -#gameDraw { - position: absolute; - background: #000000; - overflow: hidden; - z-index: 185; - margin: 3px; -} - -#bg { - z-index: 10; -} - -#event { - z-index: 30; -} - -#hero { - /* display: none; */ - z-index: 40; -} - -#event2 { - z-index: 50; -} - -#fg { - z-index: 60; -} - -#damage { - z-index: 65; -} - -#animate { - z-index: 70; -} - #curtain { z-index: 125; } @@ -425,14 +44,6 @@ p#name { z-index: 170; } -.no-anti-aliasing { - image-rendering: pixelated; -} - -/* .draw-canvas { - filter: contrast(120%) brightness(80%); -} */ - #inputDiv { display: none; width: 100%; @@ -537,85 +148,3 @@ p#name { transform: rotate(45deg) translate(-3px, -3px); } } - -#startImageBackgroundDiv { - display: none; - width: 100%; - height: 100%; - position: fixed; - z-index: 10000; -} - -#startImageDiv { - width: 100%; - height: 100%; - position: fixed; - background: black; - opacity: 1; -} - -#startImageLogo { - opacity: 0; - max-width: 60%; - max-height: 60%; - position: fixed; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); -} - -.startImageAnimation { - -webkit-animation: startImage 4s ease-in-out 1s forwards 1; - animation: startImage 4s ease-in-out 1s forwards 1; -} - -@-webkit-keyframes startImage { - 0% { - opacity: 0; - } - 60% { - opacity: 1; - } - 100% { - opacity: 0; - } -} - -@keyframes startImage { - 0% { - opacity: 0; - } - 60% { - opacity: 1; - } - 100% { - opacity: 0; - } -} - -.startImageDivAnimation { - -webkit-animation: startImageDivDisappear 2s ease-in-out 5s forwards 1; - animation: startImageDivDisappear 2s ease-in-out 5s forwards 1; -} - -@-webkit-keyframes startImageDivDisappear { - 0% { - opacity: 1; - } - 100% { - opacity: 0; - } -} - -@keyframes startImageDivDisappear { - 0% { - opacity: 1; - } - 100% { - opacity: 0; - } -} - -.hide { - display: none; -} diff --git a/src/core/fx/canvas2d.ts b/src/core/fx/canvas2d.ts index 355d030..0e65bc9 100644 --- a/src/core/fx/canvas2d.ts +++ b/src/core/fx/canvas2d.ts @@ -1,7 +1,4 @@ -import { parseCss } from '@/plugin/utils'; import { EventEmitter } from 'eventemitter3'; -import { CSSObj } from '../interface'; -import { isWebGL2Supported } from './webgl'; interface OffscreenCanvasEvent { /** 当被动触发resize时(例如core.domStyle.scale变化、窗口大小变化)时触发,使用size函数并不会触发 */ @@ -29,10 +26,15 @@ export class MotaOffscreenCanvas2D extends EventEmitter { /** 更新标识符,如果发生变化则说明画布被动清空 */ symbol: number = 0; - constructor(alpha: boolean = true) { + /** + * 创建一个新的离屏画布 + * @param alpha 是否启用透明度通道 + * @param canvas 指定画布,不指定时会自动创建一个新画布 + */ + constructor(alpha: boolean = true, canvas?: HTMLCanvasElement) { super(); - this.canvas = document.createElement('canvas'); + this.canvas = canvas ?? document.createElement('canvas'); this.ctx = this.canvas.getContext('2d', { alpha })!; this.width = this.canvas.width / devicePixelRatio; this.height = this.canvas.height / devicePixelRatio; @@ -45,8 +47,9 @@ export class MotaOffscreenCanvas2D extends EventEmitter { */ size(width: number, height: number) { let ratio = this.highResolution ? devicePixelRatio : 1; - if (this.autoScale && this.highResolution) { - ratio *= core.domStyle.scale; + const scale = core.domStyle.scale; + if (this.autoScale) { + ratio *= scale; } this.scale = ratio; this.canvas.width = width * ratio; @@ -56,6 +59,10 @@ export class MotaOffscreenCanvas2D extends EventEmitter { this.ctx.setTransform(1, 0, 0, 1, 0, 0); this.ctx.scale(ratio, ratio); this.ctx.imageSmoothingEnabled = this.antiAliasing; + if (this.canvas.isConnected) { + this.canvas.style.width = `${width * scale}px`; + this.canvas.style.height = `${height * scale}px`; + } } /** @@ -100,7 +107,7 @@ export class MotaOffscreenCanvas2D extends EventEmitter { } /** - * 复制一个离屏Canvas2D对象或Canvas2D对象,一般用于缓存等操作 + * 复制一个离屏Canvas2D对象,一般用于缓存等操作 * @param canvas 被复制的MotaOffscreenCanvas2D对象 * @returns 复制结果 */ @@ -118,220 +125,20 @@ export class MotaOffscreenCanvas2D extends EventEmitter { ); return newCanvas; } -} -export class MotaOffscreenCanvasGL2 extends EventEmitter { - static support: boolean = isWebGL2Supported(); - static list: Set = new Set(); - - canvas: HTMLCanvasElement; - gl: WebGL2RenderingContext; - - width: number; - height: number; - - /** 是否自动跟随样板的core.domStyle.scale进行缩放 */ - autoScale: boolean = false; - /** 是否是高清画布 */ - highResolution: boolean = true; - - scale: number = 1; - - /** 更新标识符,如果发生变化则说明画布被动清空 */ - symbol: number = 0; - - constructor() { - super(); - - this.canvas = document.createElement('canvas'); - this.gl = this.canvas.getContext('webgl2')!; - this.width = this.canvas.width / devicePixelRatio; - this.height = this.canvas.height / devicePixelRatio; - } - - /** - * 设置画布的大小 - */ - size(width: number, height: number) { - let ratio = this.highResolution ? devicePixelRatio : 1; - if (this.autoScale && this.highResolution) { - ratio *= core.domStyle.scale; - } - this.scale = ratio; - this.canvas.width = width * ratio; - this.canvas.height = height * ratio; - this.width = width; - this.height = height; - } - - /** - * 设置当前画布是否跟随样板的 core.domStyle.scale 一同进行缩放 - */ - withGameScale(auto: boolean) { - this.autoScale = auto; - this.size(this.width, this.height); - } - - /** - * 设置当前画布是否为高清画布 - */ - setHD(hd: boolean) { - this.highResolution = hd; - this.size(this.width, this.height); - } - - /** - * 删除这个画布 - */ - delete() { - MotaOffscreenCanvasGL2.list.delete(this); - } -} - -export class MotaCanvas2D extends MotaOffscreenCanvas2D { - static map: Map = new Map(); - - id: string = ''; - - x: number = 0; - y: number = 0; - - private mounted: boolean = false; - private target!: HTMLElement; - /** 是否自动跟随样板的core.domStyle.scale进行缩放 */ - autoScale: boolean = false; - /** 是否是高清画布 */ - highResolution: boolean = true; - - constructor( - id: string = '', - setTarget: boolean = true, - alpha: boolean = true - ) { - super(); - - this.id = id; - if (setTarget) this.target = core.dom.gameDraw; - this.canvas = document.createElement('canvas'); - this.canvas.id = id; - this.ctx = this.canvas.getContext('2d', { alpha })!; - this.width = this.canvas.width / devicePixelRatio; - this.height = this.canvas.height / devicePixelRatio; - - this.canvas.style.position = 'absolute'; - - MotaCanvas2D.map.set(this.id, this); - } - - /** - * 修改画布的挂载目标,如果已经被挂载,那么会被重新挂载至新的目标元素 - * @param target 画布将被挂载的目标 - */ - setTarget(target: HTMLElement) { - this.target = target; - if (this.mounted) { - this.unmount(); - this.mount(); - } - } - - /** - * 设置画布的大小 - */ - size(width: number, height: number) { - let ratio = this.highResolution ? devicePixelRatio : 1; - if (this.autoScale) { - const scale = core.domStyle.scale; - if (this.highResolution) ratio *= scale; - this.canvas.style.width = `${width * scale}px`; - this.canvas.style.height = `${height * scale}px`; - } else { - this.canvas.style.width = `${width}px`; - this.canvas.style.height = `${height}px`; - } - this.scale = ratio; - this.canvas.width = width * ratio; - this.canvas.height = height * ratio; - this.width = width; - this.height = height; - this.ctx.setTransform(1, 0, 0, 1, 0, 0); - this.ctx.scale(ratio, ratio); - } - - /** - * 设置画布的位置 - */ - pos(x: number, y: number) { - this.canvas.style.left = `${x}px`; - this.canvas.style.top = `${y}px`; - this.x = x; - this.y = y; - } - - /** - * 设置画布的css - * @param css 要设置成的css - */ - css(css: string | CSSObj) { - const s = typeof css === 'string' ? parseCss(css) : css; - for (const [key, value] of Object.entries(s)) { - this.canvas.style[key as CanParseCss] = value; - } - } - - /** - * 删除这个画布 - */ - delete() { - super.delete(); - this.unmount(); - MotaCanvas2D.map.delete(this.id); - } - - /** - * 将这个画布添加至游戏画布 - */ - mount() { - if (!this.mounted) { - this.mounted = true; - this.target.appendChild(this.canvas); - } - } - - /** - * 将这个画布从页面上移除 - */ - unmount() { - if (this.mounted) { - this.mounted = false; - this.canvas.remove(); - } - } - - /** - * 类似于 Symbol.for - */ - static for(id: string, setTarget?: boolean) { - const canvas = this.map.get(id); - return canvas ?? new MotaCanvas2D(id, setTarget); + static refreshAll() { + this.list.forEach(v => { + if (v.autoScale) { + v.size(v.width, v.height); + v.symbol++; + v.emit('resize'); + } + }); } } window.addEventListener('resize', () => { requestAnimationFrame(() => { - MotaOffscreenCanvas2D.list.forEach(v => { - if (v.autoScale) { - v.size(v.width, v.height); - v.symbol++; - v.emit('resize'); - } - }); - MotaOffscreenCanvasGL2.list.forEach(v => { - if (v.autoScale) { - v.size(v.width, v.height); - v.symbol++; - v.emit('resize'); - } - }); + MotaOffscreenCanvas2D.refreshAll(); }); }); diff --git a/src/core/fx/portal.ts b/src/core/fx/portal.ts deleted file mode 100644 index 1a78e19..0000000 --- a/src/core/fx/portal.ts +++ /dev/null @@ -1,241 +0,0 @@ -import { Ticker } from 'mutate-animate'; -import { MotaCanvas2D } from '@/core/fx/canvas2d'; -import { MotaSettingItem, mainSetting } from '@/core/main/setting'; - -// 苍蓝殿左上角区域的传送门机制的绘制部分,传送部分看 src/game/machanism/misc.ts - -interface DrawingPortal { - color: string; - x: number; - y: number; - particles: PortalParticle[]; - /** v表示竖向,h表示横向 */ - type: 'v' | 'h'; - /** 上一次新增粒子的时间 */ - lastParticle: number; -} - -interface PortalParticle { - fx: number; - fy: number; - totalTime: number; - time: number; - tx: number; - ty: number; - r: number; -} - -const MAX_PARTICLES = 10; -const PARTICLE_LAST = 2000; -const PARTICLE_INTERVAL = PARTICLE_LAST / MAX_PARTICLES; - -const color: string[] = ['#0f0', '#ff0', '#0ff', '#fff', '#f0f']; - -const drawing: DrawingPortal[] = []; -const ticker = new Ticker(); - -let canvas: MotaCanvas2D; -let ctx: CanvasRenderingContext2D; -let particleSetting: MotaSettingItem; - -let lastTime = 0; -// Mota.require('var', 'loading').once('coreInit', () => { -// canvas = MotaCanvas2D.for('@portal'); -// ctx = canvas.ctx; -// canvas.mount(); -// canvas.css(`z-index: 51`); -// canvas.withGameScale(true); -// canvas.pos(0, 0); -// canvas.size(480, 480); -// canvas.on('resize', () => { -// canvas.css(`z-index: 51`); -// }); -// particleSetting = mainSetting.getSetting('fx.portalParticle')!; -// ticker.add(tickPortal); -// }); - -// Mota.require('var', 'hook').on('changingFloor', id => { -// drawPortals(id); -// }); - -let needDraw = false; -function tickPortal(time: number) { - const last = lastTime; - lastTime = time; - const p = particleSetting.value; - - if (!core.isPlaying() || drawing.length === 0) return; - if (!p && !needDraw) return; - - needDraw = false; - - ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); - ctx.lineCap = 'round'; - ctx.lineWidth = 3; - ctx.shadowOffsetX = 0; - ctx.shadowOffsetY = 0; - if (p) { - ctx.shadowBlur = 8; - } else { - ctx.shadowBlur = 0; - } - - drawing.forEach(v => { - const { color, x, y, type, lastParticle, particles } = v; - - ctx.strokeStyle = color; - ctx.fillStyle = color; - ctx.globalAlpha = 1; - ctx.shadowColor = color; - if (type === 'v') { - ctx.beginPath(); - ctx.moveTo(x, y - 14); - ctx.lineTo(x, y + 30); - ctx.stroke(); - } else { - ctx.beginPath(); - ctx.moveTo(x + 2, y); - ctx.lineTo(x + 30, y); - ctx.stroke(); - } - - if (p) { - // 绘制粒子效果 - let needDelete = false; - const dt = time - last; - - particles.forEach(v => { - const { fx, fy, tx, ty, time: t, totalTime, r } = v; - const progress = t / totalTime; - const nx = (tx - fx) * progress + fx; - const ny = (ty - fy) * progress + fy; - v.time += dt; - - if (progress > 1) { - needDelete = true; - return; - } else if (progress > 0.75) { - ctx.globalAlpha = (1 - progress) * 4; - } else if (progress < 0.25) { - ctx.globalAlpha = progress * 4; - } else { - ctx.globalAlpha = 1; - } - - ctx.beginPath(); - ctx.arc(nx, ny, r, 0, Math.PI * 2); - ctx.closePath(); - ctx.fill(); - }); - if (needDelete) { - particles.shift(); - } - if ( - time - lastParticle >= PARTICLE_INTERVAL && - particles.length < MAX_PARTICLES - ) { - // 添加新粒子 - const direction = Math.random(); - const k = Math.random() / 2 - 0.3; - const verticle = Math.floor(Math.random() * 8 + 8); - const r = Math.random() * 2; - v.lastParticle = time; - if (direction > 0.5) { - // 左边 | 上边 - if (type === 'h') { - const fx = Math.floor(Math.random() * 24 + x + 4); - particles.push({ - fx: fx, - fy: y - 1, - tx: verticle * k + fx + 4, - ty: -verticle + y - 1, - r: r, - time: 0, - totalTime: PARTICLE_LAST - }); - } else { - const fy = Math.floor(Math.random() * 44 + y - 14); - particles.push({ - fy: fy, - fx: x - 1, - ty: verticle * k + fy + 4, - tx: -verticle + x - 1, - r: r, - time: 0, - totalTime: PARTICLE_LAST - }); - } - } else { - // 右边 | 下边 - if (type === 'h') { - const fx = Math.floor(Math.random() * 24 + x + 4); - particles.push({ - fx: fx, - fy: y + 1, - tx: verticle * k + fx + 4, - ty: verticle + y - 1, - r: r, - time: 0, - totalTime: PARTICLE_LAST - }); - } else { - const fy = Math.floor(Math.random() * 44 + y - 14); - particles.push({ - fy: fy, - fx: x + 1, - ty: verticle * k + fy + 4, - tx: verticle + x + 1, - r: r, - time: 0, - totalTime: PARTICLE_LAST - }); - } - } - } - } - }); -} - -/** - * 绘制传送门 - * @param floorId 要绘制传送门的楼层 - */ -export function drawPortals(floorId: FloorIds) { - drawing.splice(0); - const p = Mota.require('module', 'Mechanism').BluePalace.portals[floorId]; - if (!p) return; - p.forEach((v, i) => { - const c = color[i % color.length]; - const { fx, fy, tx, ty, dir, toDir } = v; - - let x1 = fx * 32; - let y1 = fy * 32; - let x2 = tx * 32; - let y2 = ty * 32; - - if (dir === 'down') y1 += 32; - else if (dir === 'right') x1 += 32; - - if (toDir === 'down') y2 += 32; - else if (toDir === 'right') x2 += 32; - - drawing.push({ - x: x1, - y: y1, - type: dir === 'left' || dir === 'right' ? 'v' : 'h', - color: c, - particles: [], - lastParticle: lastTime - }); - - drawing.push({ - x: x2, - y: y2, - type: toDir === 'left' || toDir === 'right' ? 'v' : 'h', - color: c, - particles: [], - lastParticle: lastTime - }); - }); - needDraw = true; -} diff --git a/src/core/fx/shadow.ts b/src/core/fx/shadow.ts index 7dd6bcd..fb1ed7a 100644 --- a/src/core/fx/shadow.ts +++ b/src/core/fx/shadow.ts @@ -990,7 +990,7 @@ export class Shadow { } static mount() { - core.dom.gameDraw.appendChild(this.canvas); + // core.dom.gameDraw.appendChild(this.canvas); } /** diff --git a/src/core/index.ts b/src/core/index.ts index 96314fb..4dd9596 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -60,8 +60,6 @@ import { ResourceController } from './loader/controller'; import { logger } from './common/logger'; import { Danmaku } from './main/custom/danmaku'; import * as Shadow from './fx/shadow'; -import { MotaCanvas2D } from './fx/canvas2d'; -import * as portal from './fx/portal'; import { MotaRenderer } from './render/render'; import { Container } from './render/container'; import { Sprite } from './render/sprite'; @@ -77,6 +75,7 @@ import * as Animation from 'mutate-animate'; import './render/index'; import * as RenderUtils from './render/utils'; import '@/module'; +import { MotaOffscreenCanvas2D } from './fx/canvas2d'; // ----- 类注册 Mota.register('class', 'AudioPlayer', AudioPlayer); @@ -95,7 +94,6 @@ Mota.register('class', 'UiController', UiController); Mota.register('class', 'MComponent', MComponent); Mota.register('class', 'ResourceController', ResourceController); Mota.register('class', 'Danmaku', Danmaku); -Mota.register('class', 'MotaCanvas2D', MotaCanvas2D); // ----- 函数注册 Mota.register('fn', 'm', m); Mota.register('fn', 'unwrapBinary', unwarpBinary); @@ -151,9 +149,7 @@ Mota.register('module', 'UIComponents', { }); Mota.register('module', 'MCGenerator', MCGenerator); Mota.register('module', 'Shadow', Shadow); -Mota.register('module', 'Effect', { - Portal: portal -}); +Mota.register('module', 'Effect', {}); Mota.register('module', 'Render', { texture, MotaRenderer, @@ -166,6 +162,7 @@ Mota.register('module', 'Render', { Layer, LayerGroupFloorBinder, Camera, + MotaOffscreenCanvas2D, Utils: RenderUtils }); Mota.register('module', 'Action', { diff --git a/src/core/main/custom/hotkey.ts b/src/core/main/custom/hotkey.ts index 5ad77eb..d8d0325 100644 --- a/src/core/main/custom/hotkey.ts +++ b/src/core/main/custom/hotkey.ts @@ -428,31 +428,6 @@ document.addEventListener('keyup', e => { } } else { // polyfill样板 - if ( - main.dom.startPanel.style.display == 'block' && - (main.dom.startButtons.style.display == 'block' || - main.dom.levelChooseButtons.style.display == 'block') - ) { - if (e.keyCode == 38 || e.keyCode == 33) - // up/pgup - main.selectButton((main.selectedButton || 0) - 1); - else if (e.keyCode == 40 || e.keyCode == 34) - // down/pgdn - main.selectButton((main.selectedButton || 0) + 1); - else if (e.keyCode == 67 || e.keyCode == 13 || e.keyCode == 32) - // C/Enter/Space - main.selectButton(main.selectedButton); - else if ( - e.keyCode == 27 && - main.dom.levelChooseButtons.style.display == 'block' - ) { - // ESC - core.showStartAnimate(true); - e.preventDefault(); - } - e.stopPropagation(); - return; - } if (main.dom.inputDiv.style.display == 'block') { if (e.keyCode == 13) { setTimeout(function () { diff --git a/src/core/main/custom/toolbar.ts b/src/core/main/custom/toolbar.ts index 0834f55..e3e40be 100644 --- a/src/core/main/custom/toolbar.ts +++ b/src/core/main/custom/toolbar.ts @@ -389,11 +389,13 @@ Mota.require('var', 'hook').on('reset', () => { Mota.require('var', 'hook').once('reset', () => { const mainStorage = GameStorage.for(GameStorage.fromGame('main')); mainStorage.read(); - if (!mainStorage.getValue('played', false)) { + if (mainStorage.getValue('played', false)) { mainStorage.setValue('played', true); - const defaultsTool = - CustomToolbar.list.find(v => v.id === '@defaults') ?? - new CustomToolbar('@defaults', true); + let defaultsTool = CustomToolbar.list.find(v => v.id === '@defaults'); + const hasDefaults = !!defaultsTool; + if (!defaultsTool) { + defaultsTool = new CustomToolbar('@defaults', true); + } defaultsTool.closeAll(); defaultsTool.items = reactive([]); defaultsTool.add({ @@ -417,38 +419,25 @@ Mota.require('var', 'hook').once('reset', () => { 'minimap' ] }); - // 计算位置 - if (isMobile) { - // 手机端显示在最下方 - defaultsTool.setPos(25, window.innerHeight - 100); - defaultsTool.setSize(window.innerWidth - 50, 100); - } else { - // 电脑显示在屏幕右方 - const x = window.innerWidth / 2 + core.domStyle.scale * 240 + 75; - defaultsTool.setPos(x, window.innerHeight / 2 + 100); - defaultsTool.setSize(window.innerWidth - x - 75, 200); - } + // 计算位置,显示在游戏画面下方 + // if (!hasDefaults) { + // const gameGroup = core.dom.gameGroup; + // const bottom = gameGroup.offsetTop + gameGroup.offsetHeight - 3; + // const left = gameGroup.offsetLeft + 3; + // const width = gameGroup.offsetWidth - 6; + + // if (isMobile) { + // // 手机端显示在最下方 + // defaultsTool.setPos(16, window.innerHeight - 32); + // defaultsTool.setSize(bottom, 35); + // } else { + // // 电脑显示在屏幕右方 + // defaultsTool.setPos(left, bottom); + // defaultsTool.setSize(width, 70); + // } + // } defaultsTool.show(); CustomToolbar.save(); } }); - -window.addEventListener('resize', () => { - requestAnimationFrame(() => { - const defaultsTool = CustomToolbar.list.find(v => v.id === '@defaults'); - if (!defaultsTool) return; - // 计算位置 - if (isMobile) { - // 手机端显示在最下方 - defaultsTool.setPos(25, window.innerHeight - 100); - defaultsTool.setSize(window.innerWidth - 50, 100); - } else { - // 电脑显示在屏幕右方 - const x = window.innerWidth / 2 + core.domStyle.scale * 240 + 75; - defaultsTool.setPos(x, window.innerHeight / 2 + 100); - defaultsTool.setSize(window.innerWidth - x - 75, 200); - } - defaultsTool.refresh(true); - }); -}); diff --git a/src/core/main/setting.ts b/src/core/main/setting.ts index 3f36638..db3a8e9 100644 --- a/src/core/main/setting.ts +++ b/src/core/main/setting.ts @@ -355,16 +355,6 @@ function handleScreenSetting( } else if (key === 'heroDetail') { // 勇士显伤 core.drawHero(); - } else if (key === 'antiAlias') { - // 抗锯齿 - for (const canvas of core.dom.gameCanvas) { - if (core.domStyle.hdCanvas.includes(canvas.id)) continue; - if (n) { - canvas.classList.remove('no-anti-aliasing'); - } else { - canvas.classList.add('no-anti-aliasing'); - } - } } else if (key === 'fontSize') { // 字体大小 root.style.fontSize = `${n}px`; @@ -434,9 +424,8 @@ mainSetting .register('itemDetail', '宝石血瓶显伤', true, COM.Boolean) .register('heroDetail', '勇士显伤', false, COM.Boolean) .register('transition', '界面动画', false, COM.Boolean) - .register('antiAlias', '抗锯齿', false, COM.Boolean) .register('fontSize', '字体大小', 16, COM.Number, [2, 48, 1]) - .register('fontSizeStatus', '状态栏字体', 16, COM.Number, [2, 48, 1]) + .register('fontSizeStatus', '状态栏字体', 16, COM.Number, [10, 300, 10]) .register('smoothView', '平滑镜头', true, COM.Boolean) .register('criticalGem', '临界显示方式', false, COM.Boolean) .setDisplayFunc('criticalGem', value => (value ? '宝石数' : '攻击')) @@ -501,7 +490,6 @@ loading.once('coreInit', () => { 'screen.itemDetail': !!storage.getValue('screen.itemDetail', true), 'screen.heroDetail': !!storage.getValue('screen.heroDetail', false), 'screen.transition': !!storage.getValue('screen.transition', false), - 'screen.antiAlias': !!storage.getValue('screen.antiAlias', false), 'screen.fontSize': storage.getValue('screen.fontSize', isMobile ? 9 : 16), 'screen.smoothView': !!storage.getValue('screen.smoothView', true), 'screen.criticalGem': !!storage.getValue('screen.criticalGem', false), diff --git a/src/core/render/index.ts b/src/core/render/index.ts index f889456..7545869 100644 --- a/src/core/render/index.ts +++ b/src/core/render/index.ts @@ -12,27 +12,33 @@ import { LayerGroupHalo } from '@/plugin/fx/halo'; import { FloorViewport } from './preset/viewport'; import { Container } from './container'; import { PopText } from '@/plugin/fx/pop'; +import { FloorChange } from '@/plugin/fallback'; let main: MotaRenderer; Mota.require('var', 'loading').once('coreInit', () => { const render = new MotaRenderer(); main = render; - render.mount(); render.hide(); const mapDraw = new Container(); const layer = new LayerGroup(); const pop = new PopText('static'); + const floorChange = new FloorChange('static'); mapDraw.id = 'map-draw'; layer.id = 'layer-main'; pop.id = 'pop-main'; + floorChange.id = 'floor-change'; mapDraw.setHD(true); mapDraw.setAntiAliasing(false); mapDraw.size(core._PX_, core._PY_); - + floorChange.size(480, 480); + floorChange.setHD(true); + floorChange.setZIndex(10); + floorChange.setTips(tips); pop.setZIndex(80); + ['bg', 'bg2', 'event', 'fg', 'fg2'].forEach(v => { layer.addLayer(v as FloorLayer); }); @@ -61,6 +67,7 @@ Mota.require('var', 'loading').once('coreInit', () => { render.appendChild(mapDraw); mapDraw.appendChild(layer); layer.appendChild(pop); + mapDraw.appendChild(floorChange); console.log(render); }); @@ -71,3 +78,37 @@ Mota.require('var', 'hook').on('reset', () => { Mota.require('var', 'hook').on('restart', () => { main.hide(); }); + +const tips = [ + '按下C可以查看鼠标位置怪物临界', + '按下E可以查看鼠标位置怪物属性', + '将鼠标移动到光环怪上以查看其产生的光环', + '字体太大?试试在背包的系统设置里面调整字体大小吧!', + '字体太小?试试在背包的系统设置里面调整字体大小吧!', + '按键不合心意?试试在背包的系统设置里面自定义快捷键', + '拖动状态栏左上角可以移动状态栏哦!', + '拖动状态栏右下角可以缩放状态栏哦!', + '按下M键,鼠标位置的怪物的信息就会被你看光啦!', + '咱就是说,要不要试一下工具栏的最后一个按钮?', + '要不要试试工具栏倒数第二个按钮呢?', + '想自定义工具栏?去背包的系统设置看看吧!', + '冷知识:临界界面可以拖动滚动条来查看减伤情况', + '可以用滚轮或者双指缩放小地图!', + '楼传的最左侧一栏可以选择区域!', + '冷知识:装备栏左栏最上面可以修改装备排序', + '冷冷冷知识:装备栏左栏最上面右侧可以更改顺序或倒序', + '第一章使用跳跃技能可是要扣血的!要注意!', + '按H查看本游戏的百科全书', + '给别人炫耀一下自己的成就点吧!虽然不能记榜(', + '抱团属性会在怪物右上角显示加成数量!', + '乾坤挪移属性绘制怪物左上角显示“乾”字!', + '电脑端可以试试按F11全屏游玩!', + '手机端要不试试横屏玩?', + '不在楼梯边也可以使用楼传!', + '技能树的右下角可以切换章节!', + '开启自动切换技能就会自动帮你选择最优技能了!', + '魔塔不仅有撤回,还有恢复,按W或6就可以了!', + '觉得卡顿?可以去试着设置里面关闭一些特性!', + '从第二章开始,怪物负伤量不会超过其生命的1/4', + '生命回复不会超过防御的十分之一' +]; diff --git a/src/core/render/item.ts b/src/core/render/item.ts index 12b1bb8..2d67d13 100644 --- a/src/core/render/item.ts +++ b/src/core/render/item.ts @@ -123,6 +123,8 @@ export interface ERenderItemEvent { beforeRender: [transform: Transform]; afterRender: [transform: Transform]; destroy: []; + /** 当这个元素被点击时触发 */ + clickCapture: [x: number, y: number, type: number, ev: MouseEvent]; } interface TickerDelegation { diff --git a/src/core/render/render.ts b/src/core/render/render.ts index bab6d2b..5a9188b 100644 --- a/src/core/render/render.ts +++ b/src/core/render/render.ts @@ -1,4 +1,5 @@ -import { MotaCanvas2D } from '../fx/canvas2d'; +import { logger } from '../common/logger'; +import { MotaOffscreenCanvas2D } from '../fx/canvas2d'; import { Container } from './container'; import { RenderItem } from './item'; import { Transform } from './transform'; @@ -6,7 +7,7 @@ import { Transform } from './transform'; export class MotaRenderer extends Container { static list: Map = new Map(); - target: MotaCanvas2D; + target!: MotaOffscreenCanvas2D; protected needUpdate: boolean = false; readonly isRoot: boolean = true; @@ -14,11 +15,15 @@ export class MotaRenderer extends Container { constructor(id: string = 'render-main') { super('static', false); - this.target = new MotaCanvas2D(id); + const canvas = document.getElementById(id) as HTMLCanvasElement; + if (!canvas) { + logger.error(19); + return; + } + this.target = new MotaOffscreenCanvas2D(true, canvas); this.size(core._PX_, core._PY_); this.target.withGameScale(true); this.target.size(core._PX_, core._PY_); - this.target.css(`z-index: 100`); this.target.setAntiAliasing(false); this.setAnchor(0.5, 0.5); @@ -72,13 +77,6 @@ export class MotaRenderer extends Container { return null; } - /** - * 添加至游戏画面 - */ - mount() { - this.target.mount(); - } - destroy() { MotaRenderer.list.delete(this.id); } diff --git a/src/data/logger.json b/src/data/logger.json index ebb1189..40f5b9c 100644 --- a/src/data/logger.json +++ b/src/data/logger.json @@ -18,6 +18,7 @@ "16": "Cannot find log message for $1 code $2.", "17": "Cannot use shader program for shader element that does not belong to it.", "18": "Cannot delete shader program for shader element that does not belong to it.", + "19": "Cannot create MotaRenderer instance for nonexistent canvas.", "1101": "Shadow extension needs 'floor-hero' extension as dependency.", "1201": "Floor-damage extension needs 'floor-binder' extension as dependency.", "1301": "Portal extension need 'floor-binder' extension as dependency.", diff --git a/src/data/settings.json b/src/data/settings.json index 1e15419..dc6c1f8 100644 --- a/src/data/settings.json +++ b/src/data/settings.json @@ -10,9 +10,6 @@ "是否展示当一个ui界面,如怪物手册等的打开与关闭时的动画。当此项开启时,", "所有界面被打开或关闭时都会展示动画,否则会直接展示出来" ], - "antiAlias": [ - "是否开启抗锯齿。开启后,画面会变得不那么锐利,观感更加舒适;关闭后,可以更好地展现出像素感,同时部分像素错误也不会出现。" - ], "fontSize": [ "在各种 ui 界面中显示的文字大小,范围为 2 - 48。注意,字体过大可能会引起 ui 布局发生错误" ], diff --git a/src/game/system.ts b/src/game/system.ts index aceb992..6edf198 100644 --- a/src/game/system.ts +++ b/src/game/system.ts @@ -24,8 +24,6 @@ import type * as damage from './enemy/damage'; import type { Logger } from '@/core/common/logger'; import type { Danmaku } from '@/core/main/custom/danmaku'; import type * as misc from './mechanism/misc'; -import type { MotaCanvas2D } from '@/core/fx/canvas2d'; -import type * as portal from '@/core/fx/portal'; import type { texture } from '@/core/render/cache'; import type { MotaRenderer } from '@/core/render/render'; import type { Container } from '@/core/render/container'; @@ -42,6 +40,7 @@ import type { Camera } from '@/core/render/camera'; import type * as Animation from 'mutate-animate'; import type * as RenderUtils from '@/core/render/utils'; import type { WeatherController } from '@/module/weather/weather'; +import type { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d'; interface ClassInterface { // 渲染进程与游戏进程通用 @@ -62,7 +61,6 @@ interface ClassInterface { SoundEffect: typeof SoundEffect; SoundController: typeof SoundController; BgmController: typeof BgmController; - MotaCanvas2D: typeof MotaCanvas2D; Danmaku: typeof Danmaku; // todo: 放到插件 ShaderEffect: typeof ShaderEffect; // 定义于游戏进程,渲染进程依然可用 @@ -110,9 +108,7 @@ interface ModuleInterface { MiscData: typeof misc.MiscData; HeroSkill: typeof misc.HeroSkill; }; - Effect: { - Portal: typeof portal; - }; + Effect: {}; Render: { texture: typeof texture; MotaRenderer: typeof MotaRenderer; @@ -125,6 +121,7 @@ interface ModuleInterface { Layer: typeof Layer; LayerGroupFloorBinder: typeof LayerGroupFloorBinder; Camera: typeof Camera; + MotaOffscreenCanvas2D: typeof MotaOffscreenCanvas2D; Utils: typeof RenderUtils; }; State: { diff --git a/src/module/weather/cloud.ts b/src/module/weather/cloud.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/module/weather/sun.ts b/src/module/weather/sun.ts new file mode 100644 index 0000000..f050565 --- /dev/null +++ b/src/module/weather/sun.ts @@ -0,0 +1,18 @@ +import { Shader, ShaderProgram } from '@/core/render/shader'; +import { IWeather, WeatherController } from './weather'; + +export class SunWeather implements IWeather { + static id: string = 'sun'; + + activate(): void {} + + frame(): void {} + + deactivate(): void {} +} + +WeatherController.register(SunWeather); + +class SunShader extends Shader { + protected override postDraw(gl: WebGL2RenderingContext): void {} +} diff --git a/src/plugin/fallback.ts b/src/plugin/fallback.ts new file mode 100644 index 0000000..c4de780 --- /dev/null +++ b/src/plugin/fallback.ts @@ -0,0 +1,108 @@ +import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d'; +import { RenderItem, RenderItemPosition } from '@/core/render/item'; +import { Transform } from '@/core/render/transform'; + +// 渲染端的向后兼容用,会充当两个版本间过渡的作用 +export class FloorChange extends RenderItem { + private tips: string[] = []; + /** 当前小贴士 */ + private usingTip: string = ''; + /** 透明度 */ + private alpha: number = 0; + private title: string = ''; + + constructor(type: RenderItemPosition) { + super(type, false); + } + + /** + * 设置楼传过程中的小贴士 + */ + setTips(tip: string[]) { + this.tips = tip; + } + + /** + * 设置标题 + */ + setTitle(title: string) { + this.title = title; + } + + /** + * 显示楼层切换的从透明变黑的动画 + * @param time 动画时长 + */ + showChange(time: number) { + const length = this.tips.length; + const tip = this.tips[Math.floor(Math.random() * length)] ?? ''; + this.usingTip = tip; + + return new Promise(res => { + const start = Date.now(); + const id = this.delegateTicker( + () => { + const dt = Date.now() - start; + const progress = dt / time; + if (progress > 1) { + this.alpha = 1; + this.removeTicker(id); + } else { + this.alpha = progress; + } + this.update(); + }, + 10000, + res + ); + }); + } + + /** + * 显示楼层切换从黑到透明的动画 + * @param time 动画时长 + */ + async hideChange(time: number) { + return new Promise(res => { + const start = Date.now(); + const id = this.delegateTicker( + () => { + const dt = Date.now() - start; + const progress = dt / time; + if (progress > 1) { + this.removeTicker(id); + this.alpha = 0; + } else { + this.alpha = 1 - progress; + } + this.update(); + }, + 10000, + res + ); + }); + } + + protected render( + canvas: MotaOffscreenCanvas2D, + transform: Transform + ): void { + if (this.alpha === 0) return; + const ctx = canvas.ctx; + ctx.globalAlpha = this.alpha; + ctx.fillStyle = '#000'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + ctx.textAlign = 'center'; + ctx.fillStyle = '#fff'; + ctx.font = '32px "normal"'; + ctx.fillText(this.title, canvas.width / 2, canvas.height * 0.4); + ctx.font = '16px "normal"'; + if (this.usingTip.length > 0) { + ctx.fillText( + '小贴士:' + this.usingTip, + canvas.width / 2, + canvas.height * 0.75 + ); + } + } +} diff --git a/src/plugin/game/fiveLayer.ts b/src/plugin/game/fiveLayer.ts index f4531f5..6ff0fa7 100644 --- a/src/plugin/game/fiveLayer.ts +++ b/src/plugin/game/fiveLayer.ts @@ -17,22 +17,23 @@ function createCanvas(name, zIndex) { } export function init() { - var bg2Canvas = createCanvas('bg2', 20); - var fg2Canvas = createCanvas('fg2', 63); // 大地图适配 - core.bigmap.canvas = [ - 'bg2', - 'fg2', - 'bg', - 'event', - 'event2', - 'fg', - 'damage' - ]; + core.initStatus.bg2maps = {}; core.initStatus.fg2maps = {}; if (main.mode == 'editor') { + var bg2Canvas = createCanvas('bg2', 20); + var fg2Canvas = createCanvas('fg2', 63); + core.bigmap.canvas = [ + 'bg2', + 'fg2', + 'bg', + 'event', + 'event2', + 'fg', + 'damage' + ]; /*插入编辑器的图层 不做此步新增图层无法在编辑器显示*/ // 编辑器图层覆盖优先级 eui > efg > fg(前景层) > event2(48*32图块的事件层) > event(事件层) > bg(背景层) // 背景层2(bg2) 插入事件层(event)之前(即bg与event之间) diff --git a/src/plugin/game/ui.ts b/src/plugin/game/ui.ts index e1a75bb..d873d97 100644 --- a/src/plugin/game/ui.ts +++ b/src/plugin/game/ui.ts @@ -35,30 +35,30 @@ export function init() { // todo: 多个状态栏分离与控制 control.prototype.showStatusBar = function () { if (main.mode == 'editor') return; + const CustomToolbar = Mota.require('class', 'CustomToolbar'); + const defaultsTool = CustomToolbar.get('@defaults'); core.removeFlag('hideStatusBar'); if (!fixedUi.hasName('statusBar')) { fixedUi.open('statusBar'); } + defaultsTool?.show(); }; control.prototype.hideStatusBar = function (showToolbox) { if (main.mode == 'editor') return; + const CustomToolbar = Mota.require('class', 'CustomToolbar'); + const defaultsTool = CustomToolbar.get('@defaults'); // 如果原本就是隐藏的,则先显示 if (!core.domStyle.showStatusBar) this.showStatusBar(); if (core.isReplaying()) showToolbox = true; fixedUi.closeByName('statusBar'); + if (!showToolbox) { + defaultsTool?.closeAll(); + } - var toolItems = core.dom.tools; core.setFlag('hideStatusBar', true); core.setFlag('showToolbox', showToolbox || null); - if ( - (!core.domStyle.isVertical && !core.flags.extendToolbar) || - !showToolbox - ) { - for (var i = 0; i < toolItems.length; ++i) - toolItems[i].style.display = 'none'; - } }; } diff --git a/src/plugin/index.ts b/src/plugin/index.ts index 0c4146c..610bfe7 100644 --- a/src/plugin/index.ts +++ b/src/plugin/index.ts @@ -2,7 +2,6 @@ import * as fly from './ui/fly'; import * as chase from './chase'; import * as completion from './completion'; import * as pop from './pop'; -import * as frag from './fx/frag'; import * as use from './use'; import * as gameCanvas from './fx/gameCanvas'; import * as animateController from './animateController'; @@ -14,7 +13,6 @@ Mota.Plugin.register('fly_r', fly); Mota.Plugin.register('chase_r', chase); Mota.Plugin.register('completion_r', completion, completion.init); Mota.Plugin.register('pop_r', pop, pop.init); -Mota.Plugin.register('frag_r', frag, frag.init); Mota.Plugin.register('use_r', use); Mota.Plugin.register('gameCanvas_r', gameCanvas); Mota.Plugin.register( diff --git a/src/types/core.d.ts b/src/types/core.d.ts index d60383f..f18029a 100644 --- a/src/types/core.d.ts +++ b/src/types/core.d.ts @@ -939,21 +939,25 @@ interface Core extends Pick { readonly material: Material; /** + * @deprecated * 计时器(样板的神秘操作 */ readonly timeout: Timeout; /** + * @deprecated * 定时器 */ readonly interval: Interval; /** + * @deprecated * 全局动画信息 */ readonly animateFrame: AnimateFrame; /** + * @deprecated * 音乐状态 */ readonly musicStatus: Readonly; @@ -964,11 +968,13 @@ interface Core extends Pick { readonly platform: Readonly; /** + * @deprecated * dom样式 */ readonly domStyle: Readonly; /** + * @deprecated * 大地图信息 */ readonly bigmap: CoreBigmap; @@ -989,6 +995,7 @@ interface Core extends Pick { readonly initStatus: DeepReadonly; /** + * @deprecated * 所有的自定义画布 */ readonly dymCanvas: Record; diff --git a/src/ui/start.vue b/src/ui/start.vue index 2d70107..ec9d6b1 100644 --- a/src/ui/start.vue +++ b/src/ui/start.vue @@ -155,7 +155,6 @@ async function clickStartButton(id: string) { core.startGame(id === 'easy' ? 'easy' : 'hard'); } if (id === 'load-game') { - core.dom.gameGroup.style.display = 'block'; start.style.top = '200vh'; core.load(); }