refactor: 完全修改dom结构

This commit is contained in:
unanmed 2024-11-19 22:28:48 +08:00
parent 4e21f60696
commit b87a2b3e2f
32 changed files with 370 additions and 1902 deletions

View File

@ -4,7 +4,7 @@
<head>
<meta http-equiv='content-type' content='text/html' charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=Edge, chrome=1'>
<meta name='author' content='ckcz123'>
<meta name='author' content='AncTe'>
<meta name='viewport'
content='width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=yes'>
<title>HTML5魔塔</title>
@ -19,135 +19,14 @@
</head>
<body>
<div id='startImageBackgroundDiv'>
<div id='startImageDiv'></div>
<img id='startImageLogo' />
</div>
<!-- injection -->
<div id="game">
<!-- injection -->
<div id='gameGroup'>
<p id='mainTips'>请稍候...</p>
<div id='startPanel'>
<div id='startTop'>
<div id='startTopProgressBar'>
<div id='startTopProgress'></div>
</div>
<p id='startTopLoadTips'>资源即将开始加载</p>
<p id='startTopHint'>HTML5魔塔游戏平台享受更多魔塔游戏<br />https://h5mota.com/</p>
</div>
</div>
<div id='floorMsgGroup'>
<p id='logoLabel'></p>
<p id='versionLabel'></p>
<p id='floorNameLabel'></p>
</div>
<div id='statusBar' class="clearfix">
<div class="status" id="floorCol">
<img id="img-floor">
<p class='statusLabel statusText' id='floor'></p>
</div>
<div class="status" id="nameCol">
<img id="img-name">
<p class='statusLabel statusText' id='name'></p>
</div>
<div class="status" id="lvCol">
<img id="img-lv">
<p class='statusLabel statusText' id='lv'></p>
</div>
<div class="status" id='hpmaxCol'>
<img id="img-hpmax">
<p class='statusLabel statusText' id='hpmax'></p>
</div>
<div class="status" id='hpCol'>
<img id="img-hp">
<p class='statusLabel statusText' id='hp'></p>
</div>
<div class="status" id='manaCol'>
<img id="img-mana">
<p class='statusLabel statusText' id='mana'></p>
</div>
<div class="status" id='atkCol'>
<img id="img-atk">
<p class='statusLabel statusText' id='atk'></p>
</div>
<div class="status" id='defCol'>
<img id="img-def">
<p class='statusLabel statusText' id='def'></p>
</div>
<div class="status" id="mdefCol">
<img id="img-mdef">
<p class='statusLabel statusText' id='mdef'></p>
</div>
<div class="status" id="moneyCol">
<img id="img-money">
<p class='statusLabel statusText' id='money'></p>
</div>
<div class="status" id="expCol">
<img id="img-exp">
<p class='statusLabel statusText' id='exp'></p>
</div>
<div class="status" id="upCol">
<img id="img-up">
<p class='statusLabel statusText' id='up'></p>
</div>
<div class="status" id="skillCol">
<img id="img-skill">
<p class='statusLabel statusText' id='skill' style='font-style: normal'></p>
</div>
<div class="status" id='keyCol'>
<span class='statusLabel' id='yellowKey' style="color:#FFCCAA"></span>
<span class='statusLabel' id='blueKey' style="color:#AAAADD"></span>
<span class='statusLabel' id='redKey' style="color:#FF8888"></span>
<span class='statusLabel' id='greenKey' style="color:#88FF88"></span>
</div>
<div class="status" id='pzfCol'>
<span class='statusLabel' id='pickaxe' style="color: #BC6E27"></span>
<span class='statusLabel' id='bomb' style="color: #FA14B9"></span>
<span class='statusLabel' id='fly' style="color: #8DB600"></span>
</div>
<div class="status" id="debuffCol">
<span class='statusLabel' id='poison' style="color: #AFFCA8;"></span>
<span class='statusLabel' id='weak' style="color: #FECCD0;"></span>
<span class='statusLabel' id='curse' style="color: #C2F4E7;"></span>
</div>
<!-- 状态栏canvas化 -->
<canvas id="statusCanvas" style="position: absolute; left: 0; top: 0;"></canvas>
</div>
<div id="toolBar" class="clearfix">
<img class="tools" id='img-book'>
<img class="tools" id='img-fly'>
<img class="tools" id='img-toolbox'>
<img class="tools" id='img-keyboard'>
<img class="tools" id='img-shop'>
<img class="tools" id='img-save'>
<img class="tools" id='img-load'>
<img class="tools" id='img-settings'>
<img class="tools" id='img-btn1' style='display:none'>
<img class="tools" id='img-btn2' style='display:none'>
<img class="tools" id='img-btn3' style='display:none'>
<img class="tools" id='img-btn4' style='display:none'>
<img class="tools" id='img-btn5' style='display:none'>
<img class="tools" id='img-btn6' style='display:none'>
<img class="tools" id='img-btn7' style='display:none'>
<img class="tools" id='img-btn8' style='display:none'>
<p class="statusLabel tools" id="hard"></p>
</div>
<div id="gameDraw">
<div id="gif"></div>
<div id="gif2"></div>
<canvas class='gameCanvas draw-canvas hide' id='bg'></canvas>
<canvas class='gameCanvas draw-canvas hide' id='event'></canvas>
<canvas class='gameCanvas draw-canvas hide' id='hero'></canvas>
<canvas class='gameCanvas draw-canvas hide' id='event2'></canvas>
<canvas class='gameCanvas draw-canvas hide' id='fg'></canvas>
<canvas class='gameCanvas hide' id='damage'></canvas>
<canvas class='gameCanvas hide' id='animate'></canvas>
<canvas class='gameCanvas' id='curtain'></canvas>
<canvas class='gameCanvas' id='ui'></canvas>
<canvas class='gameCanvas' id='data'>此浏览器不支持HTML5</canvas>
<div id="next"></div>
</div>
<div id="game-draw">
<canvas class='gameCanvas' id='curtain'></canvas>
<canvas class='gameCanvas' id='ui'></canvas>
<canvas class='gameCanvas' id='data'>此浏览器不支持HTML5</canvas>
<canvas id="render-main"></canvas>
<div id="next"></div>
</div>
</div>
<div id='inputDiv'>

View File

@ -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;
};
////// 滑动鼠标滚轮时的操作 //////

View File

@ -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 = '&nbsp;';
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) {

View File

@ -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;

View File

@ -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.
};
////// 淡入淡出音乐 //////

View File

@ -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) {

View File

@ -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 (

View File

@ -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];
};

View File

@ -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 {

View File

@ -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);

View File

@ -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;
}

View File

@ -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<OffscreenCanvasEvent> {
/** 更新标识符,如果发生变化则说明画布被动清空 */
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<OffscreenCanvasEvent> {
*/
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<OffscreenCanvasEvent> {
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<OffscreenCanvasEvent> {
}
/**
* Canvas2D对象或Canvas2D对象
* Canvas2D对象
* @param canvas MotaOffscreenCanvas2D对象
* @returns
*/
@ -118,220 +125,20 @@ export class MotaOffscreenCanvas2D extends EventEmitter<OffscreenCanvasEvent> {
);
return newCanvas;
}
}
export class MotaOffscreenCanvasGL2 extends EventEmitter<OffscreenCanvasEvent> {
static support: boolean = isWebGL2Supported();
static list: Set<MotaOffscreenCanvasGL2> = 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<string, MotaCanvas2D> = 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();
});
});

View File

@ -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;
}

View File

@ -990,7 +990,7 @@ export class Shadow {
}
static mount() {
core.dom.gameDraw.appendChild(this.canvas);
// core.dom.gameDraw.appendChild(this.canvas);
}
/**

View File

@ -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', {

View File

@ -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 () {

View File

@ -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);
});
});

View File

@ -355,16 +355,6 @@ function handleScreenSetting<T extends number | boolean>(
} 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),

View File

@ -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',
'生命回复不会超过防御的十分之一'
];

View File

@ -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 {

View File

@ -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<string, MotaRenderer> = 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);
}

View File

@ -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.",

View File

@ -10,9 +10,6 @@
"是否展示当一个ui界面如怪物手册等的打开与关闭时的动画。当此项开启时",
"所有界面被打开或关闭时都会展示动画,否则会直接展示出来"
],
"antiAlias": [
"是否开启抗锯齿。开启后,画面会变得不那么锐利,观感更加舒适;关闭后,可以更好地展现出像素感,同时部分像素错误也不会出现。"
],
"fontSize": [
"在各种 ui 界面中显示的文字大小,范围为 2 - 48。注意字体过大可能会引起 ui 布局发生错误"
],

View File

@ -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: {

View File

18
src/module/weather/sun.ts Normal file
View File

@ -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 {}
}

108
src/plugin/fallback.ts Normal file
View File

@ -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<void>(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<void>(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
);
}
}
}

View File

@ -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之间)

View File

@ -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';
}
};
}

View File

@ -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(

7
src/types/core.d.ts vendored
View File

@ -939,21 +939,25 @@ interface Core extends Pick<Main, CoreDataFromMain> {
readonly material: Material;
/**
* @deprecated
*
*/
readonly timeout: Timeout;
/**
* @deprecated
*
*/
readonly interval: Interval;
/**
* @deprecated
*
*/
readonly animateFrame: AnimateFrame;
/**
* @deprecated
*
*/
readonly musicStatus: Readonly<MusicStatus>;
@ -964,11 +968,13 @@ interface Core extends Pick<Main, CoreDataFromMain> {
readonly platform: Readonly<CorePlatform>;
/**
* @deprecated
* dom样式
*/
readonly domStyle: Readonly<DomStyle>;
/**
* @deprecated
*
*/
readonly bigmap: CoreBigmap;
@ -989,6 +995,7 @@ interface Core extends Pick<Main, CoreDataFromMain> {
readonly initStatus: DeepReadonly<InitGameStatus>;
/**
* @deprecated
*
*/
readonly dymCanvas: Record<string, CanvasRenderingContext2D>;

View File

@ -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();
}