diff --git a/index.html b/index.html
index 957ad73..5be5cff 100644
--- a/index.html
+++ b/index.html
@@ -4,7 +4,7 @@
 
     
-        
-        
-            
请稍候...
-            
-                
-                    
-                    
资源即将开始加载
-                    
HTML5魔塔游戏平台,享受更多魔塔游戏:
https://h5mota.com/
-                
-            
-            
-            
-                
-                    
![]()
-                    
-                
-                
-                    
![]()
-                    
-                
-                
-                    
![]()
-                    
-                
-                
-                    
![]()
-                    
-                
-                
-                    
![]()
-                    
-                
-                
-                    
![]()
-                    
-                
-                
-                    
![]()
-                    
-                
-                
-                    
![]()
-                    
-                
-                
-                    
![]()
-                    
-                
-                
-                    
![]()
-                    
-                
-                
-                    
![]()
-                    
-                
-                
-                    
![]()
-                    
-                
-                
-                    
![]()
-                    
-                
-                
-                    
-                    
-                    
-                    
-                
-                
-                    
-                    
-                    
-                
-                
-                    
-                    
-                    
-                
-
-                
-                
-            
-            
-            
-                
-                
-                
-                
-                
-                
-                
-                
-                
-                
-                
-                
-                
-            
+        
     
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();
     }