Add tank stage 3 and per-stage entry links
Two stages were not much of a ladder. Add STAGE 3 · 강철 회랑: 31 steel cells the shells cannot pass, a double brick cap over the base and two narrow funnels into it, 8 enemies with 4 on the field. Getting to a later stage meant clearing the earlier ones. Read the stage from the URL (#3 or ?stage=3) at load and on hashchange, so the shell's nav chips and a plain link both land where they say. The stage buttons and key hints are built from STAGES, so a new stage needs no UI edit. Simulated 10 idle and 10 random-bot runs per stage: stage 3 leaves the base standing in 6 of 10 idle runs, and its 144 reachable cells keep the player out of a sealed pocket - an earlier layout had only 8. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+74
-16
@@ -62,6 +62,7 @@
|
||||
font-family:inherit;
|
||||
}
|
||||
.note{margin-top:12px;font-size:11px;color:#8e7a5f;line-height:1.7}
|
||||
.note code{color:#c0a87f;background:#2f251c;padding:0 3px;border-radius:3px}
|
||||
button{
|
||||
margin-top:14px; width:100%; cursor:pointer;
|
||||
background:linear-gradient(#9a6a35,#7a5026);
|
||||
@@ -70,8 +71,11 @@
|
||||
}
|
||||
button:hover{filter:brightness(1.1)}
|
||||
button:active{transform:translateY(1px); border-bottom-width:2px}
|
||||
.btns{display:flex; gap:8px}
|
||||
.btns button{background:linear-gradient(#5c4a34,#463725); border-color:#3a2c1c}
|
||||
.btns{display:flex; flex-wrap:wrap; gap:6px}
|
||||
.btns button{
|
||||
flex:0 0 calc(33.333% - 4px); margin-top:8px; padding:7px 0; font-size:12px;
|
||||
background:linear-gradient(#5c4a34,#463725); border-color:#3a2c1c;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -89,17 +93,15 @@
|
||||
<div><kbd>←</kbd><kbd>→</kbd><kbd>↑</kbd><kbd>↓</kbd> 이동</div>
|
||||
<div><kbd>Space</kbd> 발사</div>
|
||||
<div><kbd>P</kbd> 일시정지 <kbd>R</kbd> 다시시작</div>
|
||||
<div><kbd>1</kbd><kbd>2</kbd> 단계 직접 선택</div>
|
||||
<div id="stagekeys"></div>
|
||||
</div>
|
||||
<div class="note">
|
||||
갈색 벽돌은 포탄에 부서지고, 회색 강철은 부서지지 않습니다.
|
||||
기지가 파괴되거나 탱크 3대를 모두 잃으면 게임 오버.
|
||||
<br>1단계 적 4대 → 돌파 시 2단계(미로, 적 6대) 진입.
|
||||
</div>
|
||||
<div class="btns">
|
||||
<button id="b1">1단계</button>
|
||||
<button id="b2">2단계</button>
|
||||
<br>돌파하면 다음 단계로 넘어가고, 아래 버튼이나 <code>#2</code>·<code>#3</code>
|
||||
같은 주소로 각 단계에 바로 들어갈 수도 있습니다.
|
||||
</div>
|
||||
<div class="btns" id="stagebtns"></div>
|
||||
<button id="btn">현재 단계 다시 시작 (R)</button>
|
||||
</aside>
|
||||
</div>
|
||||
@@ -170,6 +172,28 @@ var STAGES=[
|
||||
"...B...BBB...B...",
|
||||
".S.B...BEB...B.S."
|
||||
]
|
||||
},
|
||||
{
|
||||
name:"STAGE 3 · 강철 회랑",
|
||||
maxOnField:4,
|
||||
enemies:["hunter","heavy","scout","hunter","heavy","guard","hunter","heavy"],
|
||||
map:[
|
||||
".................",
|
||||
".SSSSS.S.S.SSSSS.",
|
||||
".S.....B.B.....S.",
|
||||
".S.BBBBB.BBBBB.S.",
|
||||
"...B.........B...",
|
||||
".BBB.SSBSBSS.BBB.",
|
||||
".B...S.....S...B.",
|
||||
".B.B.S.BBB.S.B.B.",
|
||||
".B.B...B.B...B.B.",
|
||||
".B.BBBBB.BBBBB.B.",
|
||||
".B.....B.B.....B.",
|
||||
".BSSS...B...SSSB.",
|
||||
"...B.B.BBB.B.B...",
|
||||
".BBB...BBB...BBB.",
|
||||
"...B...BEB...B..."
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@@ -235,6 +259,11 @@ var cv=document.getElementById("cv"), ctx=cv.getContext("2d");
|
||||
var elE=document.getElementById("epips"), elP=document.getElementById("ppips");
|
||||
var elS=document.getElementById("score"), elK=document.getElementById("kills");
|
||||
var elStage=document.getElementById("stage");
|
||||
(function(){ /* 단계 키 안내 */
|
||||
var t="",i;
|
||||
for(i=1;i<=STAGES.length;i++) t+="<kbd>"+i+"</kbd>";
|
||||
document.getElementById("stagekeys").innerHTML=t+" 단계 직접 선택";
|
||||
})();
|
||||
|
||||
var grid, player, enemies, bullets, fx, spawns, enemyQueue;
|
||||
var state, msg, msg2, score, kills, livesLeft, shake, flashT, elapsed;
|
||||
@@ -278,7 +307,7 @@ function startStage(n,keep){
|
||||
spawnPlayer(0.4);
|
||||
fillEnemySpawns(0.9);
|
||||
state="ready"; msg=st.name; msg2="화면을 클릭한 뒤 방향키 · 스페이스";
|
||||
syncHud();
|
||||
syncHud(); syncUrl();
|
||||
}
|
||||
function reset(){ startStage(1,false); }
|
||||
|
||||
@@ -705,12 +734,20 @@ window.addEventListener("blur",function(){ held.length=0; });
|
||||
document.getElementById("btn").addEventListener("click",function(){
|
||||
audio(); startStage(state==="win"?1:stage,false); state="play"; msg=null;
|
||||
});
|
||||
document.getElementById("b1").addEventListener("click",function(){
|
||||
audio(); startStage(1,false); state="play"; msg=null;
|
||||
});
|
||||
document.getElementById("b2").addEventListener("click",function(){
|
||||
audio(); startStage(2,false); state="play"; msg=null;
|
||||
});
|
||||
(function(){ /* 단계 버튼은 STAGES 를 보고 만든다 */
|
||||
var box=document.getElementById("stagebtns");
|
||||
for(var i=1;i<=STAGES.length;i++){
|
||||
(function(n){
|
||||
var b=document.createElement("button");
|
||||
b.textContent=n+"단계";
|
||||
b.title=STAGES[n-1].name;
|
||||
b.addEventListener("click",function(){
|
||||
audio(); startStage(n,false); state="play"; msg=null;
|
||||
});
|
||||
box.appendChild(b);
|
||||
})(i);
|
||||
}
|
||||
})();
|
||||
cv.addEventListener("mousedown",function(){
|
||||
audio();
|
||||
try{ window.focus(); cv.focus(); }catch(e){} /* iframe 안에서도 키 입력을 받도록 */
|
||||
@@ -974,7 +1011,28 @@ function frame(ts){
|
||||
requestAnimationFrame(frame);
|
||||
}
|
||||
|
||||
reset();
|
||||
/* URL 로 단계 직접 진입: tank.html#3 또는 tank.html?stage=3 */
|
||||
function stageFromUrl(){
|
||||
var h=String(location.hash||"").replace(/^#\/?/,"");
|
||||
var m=h.match(/^(?:stage)?([0-9]+)$/);
|
||||
if(!m){
|
||||
var q=String(location.search||"").match(/[?&]stage=([0-9]+)/);
|
||||
if(q) m=[0,q[1]];
|
||||
}
|
||||
if(!m) return 0;
|
||||
var n=parseInt(m[1],10);
|
||||
return (n>=1 && n<=STAGES.length) ? n : 0;
|
||||
}
|
||||
function syncUrl(){
|
||||
/* 셸의 iframe 안에서는 주소의 주인이 셸이다. 단독으로 열렸을 때만 동기화한다 */
|
||||
try{ if(window.top===window) history.replaceState(null,"","#"+stage); }catch(e){}
|
||||
}
|
||||
/* 셸이 iframe 의 조각만 바꿀 때는 문서가 다시 읽히지 않으므로 hashchange 로 받는다 */
|
||||
window.addEventListener("hashchange",function(){
|
||||
startStage(stageFromUrl()||1,false);
|
||||
});
|
||||
|
||||
startStage(stageFromUrl()||1,false);
|
||||
requestAnimationFrame(frame);
|
||||
})();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user