Skip to content

Commit 3a00a7d

Browse files
author
warasugitewara
committed
v1.0.4-beta: Add demand meter UI display and toggle functionality
1 parent bb4535a commit 3a00a7d

File tree

3 files changed

+202
-1
lines changed

3 files changed

+202
-1
lines changed

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<body>
1010
<div id="app">
1111
<div id="gameContainer">
12-
<h1>Easy Cities 2D (ver.1.0.3)</h1>
12+
<h1>Easy Cities 2D (ver.1.0.4-beta)</h1>
1313
<canvas id="gameCanvas" width="1024" height="1024"></canvas>
1414
</div>
1515
<div id="ui-container"></div>

src/style.css

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,3 +1189,122 @@ body {
11891189
background: linear-gradient(135deg, #2a5a5a, #1a3a3a);
11901190
box-shadow: 0 0 10px rgba(0, 191, 255, 0.5);
11911191
}
1192+
1193+
/* デマンドメーター(デスクトップ) */
1194+
.demand-meter-container {
1195+
position: absolute;
1196+
top: 140px;
1197+
left: 20px;
1198+
background: rgba(0, 0, 0, 0.8);
1199+
border: 2px solid #ff9800;
1200+
border-radius: 8px;
1201+
padding: 12px;
1202+
pointer-events: auto;
1203+
box-shadow: 0 0 15px rgba(255, 152, 0, 0.3);
1204+
z-index: 101;
1205+
min-width: 200px;
1206+
}
1207+
1208+
.demand-meter {
1209+
display: flex;
1210+
align-items: center;
1211+
gap: 8px;
1212+
margin-bottom: 8px;
1213+
}
1214+
1215+
.demand-meter:last-child {
1216+
margin-bottom: 0;
1217+
}
1218+
1219+
.demand-label {
1220+
font-size: 18px;
1221+
min-width: 25px;
1222+
}
1223+
1224+
.demand-bar {
1225+
flex: 1;
1226+
height: 20px;
1227+
background: rgba(255, 152, 0, 0.2);
1228+
border: 1px solid #ff9800;
1229+
border-radius: 4px;
1230+
overflow: hidden;
1231+
position: relative;
1232+
}
1233+
1234+
.demand-fill {
1235+
height: 100%;
1236+
background: linear-gradient(90deg, #ff9800, #ffb74d);
1237+
transition: width 0.3s ease;
1238+
}
1239+
1240+
.demand-value {
1241+
min-width: 35px;
1242+
text-align: right;
1243+
color: #ffb74d;
1244+
font-weight: bold;
1245+
font-size: 12px;
1246+
}
1247+
1248+
.btn-toggle-demand {
1249+
position: absolute;
1250+
bottom: 30px;
1251+
right: 50%;
1252+
transform: translateX(70px);
1253+
padding: 12px 16px;
1254+
background: linear-gradient(135deg, #ff9800, #ff7043);
1255+
color: #000;
1256+
border: none;
1257+
border-radius: 6px;
1258+
cursor: pointer;
1259+
font-size: 16px;
1260+
font-weight: bold;
1261+
box-shadow: 0 0 15px rgba(255, 152, 0, 0.5);
1262+
transition: all 0.2s;
1263+
pointer-events: auto;
1264+
}
1265+
1266+
.btn-toggle-demand:hover {
1267+
transform: translateX(70px) scale(1.05);
1268+
box-shadow: 0 0 25px rgba(255, 152, 0, 0.8);
1269+
}
1270+
1271+
/* デマンドメーター(モバイル) */
1272+
.demand-meter-container-mobile {
1273+
background: rgba(255, 152, 0, 0.1);
1274+
border-top: 2px solid #ff9800;
1275+
padding: 8px;
1276+
margin-top: 8px;
1277+
}
1278+
1279+
.demand-meter-mobile {
1280+
display: flex;
1281+
justify-content: space-between;
1282+
align-items: center;
1283+
padding: 4px 0;
1284+
font-size: 12px;
1285+
color: #ffb74d;
1286+
}
1287+
1288+
.demand-meter-mobile span {
1289+
display: flex;
1290+
gap: 8px;
1291+
}
1292+
1293+
.btn-toggle-demand-mobile {
1294+
width: 100%;
1295+
padding: 10px;
1296+
background: linear-gradient(135deg, #ff9800, #ff7043);
1297+
color: #000;
1298+
border: none;
1299+
border-radius: 4px;
1300+
cursor: pointer;
1301+
font-size: 13px;
1302+
font-weight: bold;
1303+
margin-top: 8px;
1304+
transition: all 0.2s;
1305+
}
1306+
1307+
.btn-toggle-demand-mobile:active {
1308+
transform: scale(0.95);
1309+
box-shadow: 0 0 10px rgba(255, 152, 0, 0.5);
1310+
}

src/ui.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,34 @@ export class UIManager {
140140
<span class="stat-value" id="stat-water">0%</span>
141141
</div>
142142
</div>
143+
<div class="demand-meter-container-mobile" id="demand-meter-container-mobile" style="display: none;">
144+
<div class="demand-meter-mobile">
145+
<span>🏘️ <span id="demand-value-residential-mobile">50</span></span>
146+
</div>
147+
<div class="demand-meter-mobile">
148+
<span>🏪 <span id="demand-value-commercial-mobile">50</span></span>
149+
</div>
150+
<div class="demand-meter-mobile">
151+
<span>🏭 <span id="demand-value-industrial-mobile">50</span></span>
152+
</div>
153+
</div>
143154
`;
144155
tabContent.appendChild(statsTab);
145156

157+
// ステータスタブにトグルボタンを追加
158+
const toggleDemandBtn = document.createElement('button');
159+
toggleDemandBtn.id = 'btn-toggle-demand-mobile';
160+
toggleDemandBtn.className = 'btn-toggle-demand-mobile';
161+
toggleDemandBtn.textContent = '📊 需要メーター';
162+
toggleDemandBtn.addEventListener('click', () => {
163+
const container = document.getElementById('demand-meter-container-mobile');
164+
if (container) {
165+
container.style.display = container.style.display === 'none' ? 'block' : 'none';
166+
this.engine.state.showDemandMeters = container.style.display !== 'none';
167+
}
168+
});
169+
statsTab.appendChild(toggleDemandBtn);
170+
146171
// 建設タブ
147172
const buildTab = document.createElement('div');
148173
buildTab.className = 'mobile-tab-pane';
@@ -368,6 +393,30 @@ export class UIManager {
368393
<span class="stat-value" id="stat-water">0%</span>
369394
</div>
370395
</div>
396+
<div class="demand-meter-container" id="demand-meter-container" style="display: none;">
397+
<div class="demand-meter">
398+
<span class="demand-label">🏘️</span>
399+
<div class="demand-bar">
400+
<div class="demand-fill" id="demand-residential" style="width: 50%"></div>
401+
</div>
402+
<span class="demand-value" id="demand-value-residential">50</span>
403+
</div>
404+
<div class="demand-meter">
405+
<span class="demand-label">🏪</span>
406+
<div class="demand-bar">
407+
<div class="demand-fill" id="demand-commercial" style="width: 50%"></div>
408+
</div>
409+
<span class="demand-value" id="demand-value-commercial">50</span>
410+
</div>
411+
<div class="demand-meter">
412+
<span class="demand-label">🏭</span>
413+
<div class="demand-bar">
414+
<div class="demand-fill" id="demand-industrial" style="width: 50%"></div>
415+
</div>
416+
<span class="demand-value" id="demand-value-industrial">50</span>
417+
</div>
418+
</div>
419+
<button id="btn-toggle-demand" class="btn-toggle-demand" title="需要メーター表示">📊</button>
371420
`;
372421
container.appendChild(dashboard);
373422

@@ -611,13 +660,46 @@ export class UIManager {
611660
document.getElementById('stat-international')!.textContent = Math.round(this.engine.state.internationalLevel).toString();
612661
document.getElementById('stat-power')!.textContent = Math.round(this.engine.state.powerSupplyRate).toString() + '%';
613662
document.getElementById('stat-water')!.textContent = Math.round(this.engine.state.waterSupplyRate).toString() + '%';
663+
664+
// デマンドメーター表示(デスクトップ)
665+
if (this.engine.state.showDemandMeters) {
666+
const residentialDemand = Math.round(this.engine.state.residentialDemand);
667+
const commercialDemand = Math.round(this.engine.state.commercialDemand);
668+
const industrialDemand = Math.round(this.engine.state.industrialDemand);
669+
670+
const resFill = document.getElementById('demand-residential') as HTMLElement;
671+
const comFill = document.getElementById('demand-commercial') as HTMLElement;
672+
const indFill = document.getElementById('demand-industrial') as HTMLElement;
673+
674+
if (resFill) resFill.style.width = Math.max(0, Math.min(100, residentialDemand)) + '%';
675+
if (comFill) comFill.style.width = Math.max(0, Math.min(100, commercialDemand)) + '%';
676+
if (indFill) indFill.style.width = Math.max(0, Math.min(100, industrialDemand)) + '%';
677+
678+
document.getElementById('demand-value-residential')!.textContent = residentialDemand.toString();
679+
document.getElementById('demand-value-commercial')!.textContent = commercialDemand.toString();
680+
document.getElementById('demand-value-industrial')!.textContent = industrialDemand.toString();
681+
682+
// モバイル版
683+
document.getElementById('demand-value-residential-mobile')!.textContent = residentialDemand.toString();
684+
document.getElementById('demand-value-commercial-mobile')!.textContent = commercialDemand.toString();
685+
document.getElementById('demand-value-industrial-mobile')!.textContent = industrialDemand.toString();
686+
}
614687
}
615688

616689
private attachEventListeners(): void {
617690
// GUI表示/非表示トグル
618691
document.getElementById('btn-toggle-gui')?.addEventListener('click', () => this.toggleGUI());
619692
document.getElementById('btn-close-gui')?.addEventListener('click', () => this.toggleGUI());
620693

694+
// デマンドメーター トグル(デスクトップ)
695+
document.getElementById('btn-toggle-demand')?.addEventListener('click', () => {
696+
const container = document.getElementById('demand-meter-container');
697+
if (container) {
698+
container.style.display = container.style.display === 'none' ? 'block' : 'none';
699+
this.engine.state.showDemandMeters = container.style.display !== 'none';
700+
}
701+
});
702+
621703
// 時間制御ボタン
622704
document.getElementById('btn-pause')?.addEventListener('click', () => this.setGameSpeed(0));
623705
document.getElementById('btn-slow')?.addEventListener('click', () => this.setGameSpeed(0.5));

0 commit comments

Comments
 (0)