素材 #15

Merged
Ghost merged 1 commits from why_ga into main 2026-09-01 19:02:03 +08:00
7 changed files with 104 additions and 10 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 96 KiB

+104 -10
View File
@@ -32,16 +32,51 @@ body { background: #0a0e17; overflow: hidden; font-family: 'Microsoft YaHei', sa
display: flex; align-items: center; gap: 10px; display: flex; align-items: center; gap: 10px;
} }
#topBar .title img { width: 34px; height: 34px; border-radius: 7px; box-shadow: 0 0 12px rgba(74,175,255,.5); } #topBar .title img { width: 34px; height: 34px; border-radius: 7px; box-shadow: 0 0 12px rgba(74,175,255,.5); }
#topBar .worldNameWrap {
position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
display: flex; align-items: center; gap: 10px;
pointer-events: auto;
}
#topBar .title .worldName { #topBar .title .worldName {
font-size: 22px; font-weight: 700; color: #cfe1f3; -webkit-text-fill-color: #cfe1f3; font-size: 22px; font-weight: 700; color: #cfe1f3; -webkit-text-fill-color: #cfe1f3;
pointer-events: auto;
position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
white-space: nowrap; white-space: nowrap;
padding: 4px 14px; border: 1.5px solid rgba(139,92,246,.55); border-radius: 8px; padding: 4px 14px; border: 1.5px solid rgba(139,92,246,.55); border-radius: 8px;
background: rgba(10,14,23,.75); box-shadow: 0 0 12px rgba(139,92,246,.2); background: rgba(10,14,23,.75); box-shadow: 0 0 12px rgba(139,92,246,.2);
} }
#topBar .title .worldName.editable { cursor: pointer; padding: 2px 8px; border-radius: 5px; transition: background .15s; } #topBar .title .worldName.editable { cursor: pointer; padding: 2px 8px; border-radius: 5px; transition: background .15s; }
#topBar .title .worldName.editable:hover { background: rgba(255,255,255,.08); } #topBar .title .worldName.editable:hover { background: rgba(255,255,255,.08); }
/* 测试阶段金币编辑器(世界名称右侧) */
#topBar .goldEditor {
display: none;
align-items: center; gap: 6px;
padding: 4px 10px; border-radius: 8px;
background: rgba(10,14,23,.75);
border: 1.5px solid rgba(255,193,7,.45);
box-shadow: 0 0 12px rgba(255,193,7,.15);
font-size: 13px; color: #ffe082;
white-space: nowrap;
}
#topBar .goldEditor .ge-current { font-weight: 700; min-width: 36px; text-align: right; }
#topBar .goldEditor .ge-input {
width: 64px; height: 24px; padding: 0 6px;
background: rgba(0,0,0,.35); border: 1px solid rgba(255,193,7,.4);
border-radius: 5px; color: #ffe082; font-size: 12px; font-weight: 600;
outline: none; text-align: center;
}
#topBar .goldEditor .ge-input:focus { border-color: rgba(255,193,7,.8); }
#topBar .goldEditor .ge-btn {
width: 24px; height: 24px; border-radius: 5px; border: none;
font-size: 15px; font-weight: 700; line-height: 1; cursor: pointer;
display: inline-flex; align-items: center; justify-content: center;
transition: transform .12s, filter .12s;
}
#topBar .goldEditor .ge-btn:active { transform: scale(0.92); }
#topBar .goldEditor .ge-plus { background: rgba(76,175,80,.25); color: #81c784; }
#topBar .goldEditor .ge-plus:hover { background: rgba(76,175,80,.4); }
#topBar .goldEditor .ge-minus { background: rgba(239,83,80,.25); color: #ef5350; }
#topBar .goldEditor .ge-minus:hover { background: rgba(239,83,80,.4); }
#topBar .goldEditor .ge-hint { font-size: 10px; color: #b0a070; }
.worldName-input { .worldName-input {
background: transparent; border: 1px solid rgba(124,199,255,.6); color: #cfe1f3; background: transparent; border: 1px solid rgba(124,199,255,.6); color: #cfe1f3;
font-size: 15px; font-weight: 600; padding: 2px 6px; border-radius: 5px; width: 180px; font-size: 15px; font-weight: 600; padding: 2px 6px; border-radius: 5px; width: 180px;
@@ -738,7 +773,7 @@ body { background: #0a0e17; overflow: hidden; font-family: 'Microsoft YaHei', sa
#sceneToolbar .top-icon{width:40px;height:40px;font-size:19px;} #sceneToolbar .top-icon{width:40px;height:40px;font-size:19px;}
} }
@media (max-width:420px){ @media (max-width:420px){
#topBar .title .worldName{display:none;} #topBar .title .worldNameWrap{display:none;}
#bottomBar .bb-btn{padding:7px 9px;font-size:11px;} #bottomBar .bb-btn{padding:7px 9px;font-size:11px;}
#worldExpBarWrap{width:280px;gap:5px;} #worldExpBarWrap{width:280px;gap:5px;}
#worldExpBarWrap .we-title{display:none;} #worldExpBarWrap .we-title{display:none;}
@@ -859,7 +894,20 @@ body { background: #0a0e17; overflow: hidden; font-family: 'Microsoft YaHei', sa
<div id="worldFrame"><span class="wf-tl"></span><span class="wf-tr"></span><span class="wf-bl"></span><span class="wf-br"></span></div> <div id="worldFrame"><span class="wf-tl"></span><span class="wf-tr"></span><span class="wf-bl"></span><span class="wf-br"></span></div>
<div id="topBar"> <div id="topBar">
<span class="title"><span class="brand">宇森</span><span class="worldName editable" id="worldName" title="点击编辑世界名称">加载中…</span></span> <span class="title">
<span class="brand">宇森</span>
<span class="worldNameWrap">
<span class="worldName editable" id="worldName" title="点击编辑世界名称">加载中…</span>
<span class="goldEditor" id="goldEditor" title="测试专用:调整角色金币">
<span>🪙</span>
<span class="ge-current" id="goldCurrent">0</span>
<input type="number" class="ge-input" id="goldInput" value="1000" min="1" step="1">
<button class="ge-btn ge-plus" id="goldPlus" type="button">+</button>
<button class="ge-btn ge-minus" id="goldMinus" type="button">−</button>
<span class="ge-hint">测试</span>
</span>
</span>
</span>
<div class="topRight"> <div class="topRight">
<span class="coords" id="coords">坐标: (0, 0)</span> <span class="coords" id="coords">坐标: (0, 0)</span>
<div class="timeInfo" title="世界时间"> <div class="timeInfo" title="世界时间">
@@ -1875,13 +1923,13 @@ const MICRO_BUILD_EXTRA = [
{ id: 'temple', cat: 'build', icon: 'assets/buildings/spring/temple/temple_l.png?v=4', name: '神庙', desc: '供奉信仰的场所,提升居民精神状态与领地声望。', flat: false, w: 3, h: 3, statLevel: 1, statHp: 160, statYield: { prestige: 3 }, costGold: 100 }, { id: 'temple', cat: 'build', icon: 'assets/buildings/spring/temple/temple_l.png?v=4', name: '神庙', desc: '供奉信仰的场所,提升居民精神状态与领地声望。', flat: false, w: 3, h: 3, statLevel: 1, statHp: 160, statYield: { prestige: 3 }, costGold: 100 },
{ id: 'clinic', cat: 'build', icon: 'assets/buildings/spring/clinic/clinic_l.png?v=5', name: '医务室', desc: '诊治伤病,恢复居民生命值。', flat: false, w: 2, h: 2, statLevel: 1, statHp: 100, statYield: { heal: 2 }, costGold: 55 }, { id: 'clinic', cat: 'build', icon: 'assets/buildings/spring/clinic/clinic_l.png?v=5', name: '医务室', desc: '诊治伤病,恢复居民生命值。', flat: false, w: 2, h: 2, statLevel: 1, statHp: 100, statYield: { heal: 2 }, costGold: 55 },
{ id: 'restaurant', cat: 'build', icon: 'assets/buildings/spring/restaurant/restaurant_l.png?v=5',name: '酒馆', desc: '烹制料理,为居民提供饱食与心情加成。', flat: false, w: 2, h: 3, statLevel: 1, statHp: 95, statYield: { satiety: 3 }, costGold: 45 }, { id: 'restaurant', cat: 'build', icon: 'assets/buildings/spring/restaurant/restaurant_l.png?v=5',name: '酒馆', desc: '烹制料理,为居民提供饱食与心情加成。', flat: false, w: 2, h: 3, statLevel: 1, statHp: 95, statYield: { satiety: 3 }, costGold: 45 },
{ id: 'pasture', cat: 'business', icon: 'assets/buildings/spring/pasture/pasture_l.png?v=13', name: '牧场', desc: '放养牲畜,稳定产出肉奶类资源。', flat: false, w: 4, h: 4, statLevel: 1, statHp: 105, statYield: { meat: 2, milk: 1 }, costGold: 70 }, { id: 'pasture', cat: 'business', icon: 'assets/buildings/spring/pasture/pasture_l.png?v=17', name: '牧场', desc: '放养牲畜,稳定产出肉奶类资源。', flat: false, w: 4, h: 4, statLevel: 1, statHp: 105, statYield: { meat: 2, milk: 1 }, costGold: 70 },
{ id: 'blackmarket', cat: 'build', icon: 'assets/buildings/spring/blackmarket/blackmarket_l.png?v=7',name:'商城', desc: '灰色交易点,可换取稀有物资但伴随风险。', flat: false, w: 2, h: 2, statLevel: 1, statHp: 80, statYield: { rare: 1 }, costGold: 120 }, { id: 'blackmarket', cat: 'build', icon: 'assets/buildings/spring/blackmarket/blackmarket_l.png?v=7',name:'商城', desc: '灰色交易点,可换取稀有物资但伴随风险。', flat: false, w: 2, h: 2, statLevel: 1, statHp: 80, statYield: { rare: 1 }, costGold: 120 },
{ id: 'farmland', cat: 'business', icon: 'assets/buildings/spring/farmland/farmland.png?v=202608251713', name: '农田', desc: '春季播种的耕地,定期产出粮食作物。', flat: true, w: 2, h: 2, statLevel: 1, statHp: 60, statYield: { food: 3 }, costGold: 10 }, { id: 'farmland', cat: 'business', icon: 'assets/buildings/spring/farmland/farmland.png?v=202608251713', name: '农田', desc: '春季播种的耕地,定期产出粮食作物。', flat: true, w: 2, h: 2, statLevel: 1, statHp: 60, statYield: { food: 3 }, costGold: 10 },
{ id: 'well', cat: 'build', icon: 'assets/buildings/default/props/well_l.png', name: '水井', desc: '汲取地下水的圆井,保障饮水与灌溉。', flat: false, w: 2, h: 2, statLevel: 1, statHp: 90, statYield: { water: 2 }, costGold: 15 }, { id: 'well', cat: 'build', icon: 'assets/buildings/default/props/well_l.png', name: '水井', desc: '汲取地下水的圆井,保障饮水与灌溉。', flat: false, w: 2, h: 2, statLevel: 1, statHp: 90, statYield: { water: 2 }, costGold: 15 },
{ id: 'school', cat: 'build', icon: 'assets/buildings/spring/school/school_l.png?v=6', name: '学堂', desc: '授业解惑之所,研读典籍提升领地科研与基础教学产出。', flat: false, w: 3, h: 2, statLevel: 1, statHp: 100, statYield: { research: 3, prestige: 1 }, costGold: 90 }, { id: 'school', cat: 'build', icon: 'assets/buildings/spring/school/school_l.png?v=16', name: '学堂', desc: '授业解惑之所,研读典籍提升领地科研与基础教学产出。', flat: false, w: 3, h: 2, statLevel: 1, statHp: 100, statYield: { research: 3, prestige: 1 }, costGold: 90 },
{ id: 'library', cat: 'build', icon: 'assets/buildings/spring/library/library_l.png?v=5', name: '图书馆', desc: '收藏典籍与卷轴,提升领地科研与知识产出。', flat: false, w: 2, h: 3, statLevel: 1, statHp: 110, statYield: { research: 4 }, costGold: 110 }, { id: 'library', cat: 'build', icon: 'assets/buildings/spring/library/library_l.png?v=5', name: '图书馆', desc: '收藏典籍与卷轴,提升领地科研与知识产出。', flat: false, w: 2, h: 3, statLevel: 1, statHp: 110, statYield: { research: 4 }, costGold: 110 },
{ id: 'barracks', cat: 'build', icon: 'assets/buildings/spring/barracks/barracks_l.png?v=6', name: '兵营', desc: '训练士兵与储备武备的军事建筑,提升领地军事产出。', flat: false, w: 3, h: 3, statLevel: 1, statHp: 130, statYield: { military: 4 }, costGold: 130 }, { id: 'barracks', cat: 'build', icon: 'assets/buildings/spring/barracks/barracks_l.png?v=9', name: '兵营', desc: '训练士兵与储备武备的军事建筑,提升领地军事产出。', flat: false, w: 3, h: 3, statLevel: 1, statHp: 130, statYield: { military: 4 }, costGold: 130 },
{ id: 'guild', cat: 'build', icon: 'assets/buildings/spring/guild/guild_l.png?v=4', name: '公会', desc: '冒险者与住民集结之所,可发布委托与招募成员。', flat: false, w: 2, h: 2, statLevel: 1, statHp: 140, statYield: { prestige: 2, coin: 1 }, costGold: 100 }, { id: 'guild', cat: 'build', icon: 'assets/buildings/spring/guild/guild_l.png?v=4', name: '公会', desc: '冒险者与住民集结之所,可发布委托与招募成员。', flat: false, w: 2, h: 2, statLevel: 1, statHp: 140, statYield: { prestige: 2, coin: 1 }, costGold: 100 },
{ id: 'village', cat: 'build', icon: 'assets/buildings/spring/village/village_l.png?v=5', name: '村庄', desc: '族群聚落的核心,提升人口上限与基础产出。', flat: false, w: 3, h: 3, statLevel: 1, statHp: 150, statYield: { population: 6, food: 1 }, costGold: 200 }, { id: 'village', cat: 'build', icon: 'assets/buildings/spring/village/village_l.png?v=5', name: '村庄', desc: '族群聚落的核心,提升人口上限与基础产出。', flat: false, w: 3, h: 3, statLevel: 1, statHp: 150, statYield: { population: 6, food: 1 }, costGold: 200 },
// 生物分类:9 种族角色(点击进入"点地面放置"模式,不进入建筑模式) // 生物分类:9 种族角色(点击进入"点地面放置"模式,不进入建筑模式)
@@ -2082,6 +2130,7 @@ async function microLoadGame() {
}); });
} }
microRenderCharHud(); microRenderCharHud();
updateGoldEditorDisplay();
} catch (e) { /* 离线兜底:不阻塞微观世界 */ } } catch (e) { /* 离线兜底:不阻塞微观世界 */ }
} }
@@ -2138,6 +2187,48 @@ function microRenderCharHud() {
</div> </div>
<span style="font-size:11px;color:#9fb0c0;white-space:nowrap;">${exp}/${expMax} (${pct}%)</span> <span style="font-size:11px;color:#9fb0c0;white-space:nowrap;">${exp}/${expMax} (${pct}%)</span>
</div>`; </div>`;
updateGoldEditorDisplay();
}
// 顶部金币编辑器:测试阶段调试角色金币
function updateGoldEditorDisplay() {
const editor = document.getElementById('goldEditor');
const current = document.getElementById('goldCurrent');
if (!editor || !current) return;
if (!microChar) { editor.style.display = 'none'; return; }
editor.style.display = 'inline-flex';
current.textContent = Math.floor(microChar.gold || 0);
}
async function changeGoldEditor(delta) {
if (!microChar) { microToast('角色未加载,无法修改金币'); return; }
const input = document.getElementById('goldInput');
const val = parseInt(input.value, 10) || 0;
if (val <= 0) { microToast('请输入正整数'); return; }
const next = Math.max(0, Math.floor((microChar.gold || 0) + delta * val));
try {
const r = await API.saveChar({ gold: next });
if (r && r.ok && r.char) {
microChar.gold = r.char.gold;
updateGoldEditorDisplay();
microRenderCharHud();
microToast(`金币已调整为 🪙${microChar.gold}`);
} else {
microToast('金币保存失败:' + (r && r.error ? r.error : '未知错误'));
}
} catch (e) {
microToast('网络错误,金币未保存');
}
}
function initGoldEditor() {
const plus = document.getElementById('goldPlus');
const minus = document.getElementById('goldMinus');
const input = document.getElementById('goldInput');
if (plus) plus.addEventListener('click', () => changeGoldEditor(1));
if (minus) minus.addEventListener('click', () => changeGoldEditor(-1));
if (input) input.addEventListener('keydown', (e) => {
if (e.key === 'Enter') { e.preventDefault(); changeGoldEditor(1); }
});
updateGoldEditorDisplay();
} }
// ============ 任务系统(新手主线,后端驱动) ============ // ============ 任务系统(新手主线,后端驱动) ============
@@ -2199,6 +2290,7 @@ async function fetchTasks() {
microChar.gold = r.char.gold; microChar.gold = r.char.gold;
} }
microRenderCharHud(); microRenderCharHud();
updateGoldEditorDisplay();
} }
} }
} catch (e) { /* 离线兜底 */ } } catch (e) { /* 离线兜底 */ }
@@ -2437,13 +2529,14 @@ function microDrawPlaced(ctx, b, it, cell, ew, eh) {
// 3/4 立绘建筑:按 rot 切换 _r/_l 视角;180/270 做水平翻转表示背面,取消 canvas 整体旋转 // 3/4 立绘建筑:按 rot 切换 _r/_l 视角;180/270 做水平翻转表示背面,取消 canvas 整体旋转
// 尺寸贴合占位地块:底宽 = 占位格宽,与格子边缘对齐; // 尺寸贴合占位地块:底宽 = 占位格宽,与格子边缘对齐;
// 图片脚底对齐 footprint 菱形最下方顶点,避免建筑“浮”在占地左上角。 // 图片脚底对齐 footprint 菱形最下方顶点,避免建筑“浮”在占地左上角。
const dim = Math.max(ew, eh); // 立绘本宽 = 等距菱形真实水平跨度 (ew+eh)*cell/2。
const w = cell * dim; // 建筑底宽 = 占位格宽 // 正方形时 = max(ew,eh)*cell(与旧逻辑一致);矩形时比 max 更窄,使底座精确齐平菱形左右顶点,不再溢出绿格。
const w = (ew + eh) * cell / 2;
const h = w / 0.85; // 维持原宽高比(建筑立绘偏高) const h = w / 0.85; // 维持原宽高比(建筑立绘偏高)
const flip = (rot === 180 || rot === 270); const flip = (rot === 180 || rot === 270);
ctx.save(); ctx.save();
ctx.scale(flip ? -1 : 1, 1); ctx.scale(flip ? -1 : 1, 1);
ctx.drawImage(img, -w / 2, eh * cell / 4 - h, w, h); ctx.drawImage(img, -w / 2, (ew + eh) * cell / 8 - h, w, h); // 脚底对齐菱形最下顶点
ctx.restore(); ctx.restore();
} }
return; return;
@@ -7521,6 +7614,7 @@ if (typeof fitWorld === 'function') fitWorld();
if (wnEl) wnEl.textContent = local || '我的世界'; if (wnEl) wnEl.textContent = local || '我的世界';
} }
fetchTasks(); // 登录即拉取新手主线任务(主世界初次进入也要触发,不只进地块时) fetchTasks(); // 登录即拉取新手主线任务(主世界初次进入也要触发,不只进地块时)
initGoldEditor(); // 初始化测试阶段金币编辑器
const backdrop = document.getElementById('uaBackdrop'); const backdrop = document.getElementById('uaBackdrop');
const closeBtn = document.getElementById('uaClose'); const closeBtn = document.getElementById('uaClose');
const setMenuOpen = (open) => { const setMenuOpen = (open) => {