A room you can share by link, a code you can type, and a name to be called
Multiplayer setup moves out of a canvas modal and a prompt() dialog into one menu screen: your name, the two ways to host, and the friend's code. The socket opens from the menu and the game stays parked behind the overlay until the room fills — netHooks.paired takes the court one line before netStart writes to it — so the room code can carry a real SHARE button and a wrong code is a typo you fix rather than a CONNECTION LOST card over a match that never began. The name is the world board's name (stats.saveName), crosses on the existing look message, and the scoreboard finally names the person instead of CPU. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ad258ace97
commit
425c18dcb6
7 files changed
+255
-75
No files matched your search
+76
-12
@@ -155,7 +155,7 @@ if (location.hostname !== 'splatter-tennis.wuwi.one') {
|
||||
/* ONE overlay, four panels, swapped by #intro[data-stage]. Keeping the backdrop and the card frame
|
||||
alive across every screen is the point — a screen that unmounts the whole overlay flashes the
|
||||
court through between menus. */
|
||||
#splash, #setup, #stats, #ranks, #newbest, #secret, #bosses, #stmode, #stsub, #bracket { display: none; }
|
||||
#splash, #setup, #stats, #ranks, #newbest, #secret, #bosses, #stmode, #stsub, #bracket, #vs { display: none; }
|
||||
#intro[data-stage="splash"] #splash { display: flex; flex-direction: column; flex: 1; }
|
||||
/* flex COLUMN, not block: it is what lets the footer's margin-top:auto reach the bottom of a
|
||||
screen whose content does not fill it */
|
||||
@@ -167,6 +167,7 @@ if (location.hostname !== 'splatter-tennis.wuwi.one') {
|
||||
#intro[data-stage="secret"] #secret,
|
||||
#intro[data-stage="bosses"] #bosses,
|
||||
#intro[data-stage="bracket"] #bracket,
|
||||
#intro[data-stage="vs"] #vs,
|
||||
#intro[data-stage="newbest"] #newbest { display: flex; flex-direction: column; flex: 1;
|
||||
animation: drop 0.3s ease-out; }
|
||||
/* the overlay is HIDDEN during play, not removed: a restart puts it straight back, and the
|
||||
@@ -400,21 +401,53 @@ if (location.hostname !== 'splatter-tennis.wuwi.one') {
|
||||
.rkrow span { flex: 1; min-width: 0; font: 400 11px Silkscreen, monospace; color: var(--cream);
|
||||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.rkrow i { font: 400 11px Silkscreen, monospace; font-style: normal; color: var(--dim); }
|
||||
/* ---- the name prompt. It is the only screen in the game that asks for typing, so the field is
|
||||
deliberately big, centred and already focused: on a phone this appears with the keyboard
|
||||
rising under it and there is no room for a second tap to find the input. */
|
||||
/* ---- typed fields. Two screens ask for typing — the name prompt and the netplay lobby — and
|
||||
both want the same field: big, centred, acid on the panel, no rounded corners anywhere near it.
|
||||
One class, two size overrides. */
|
||||
.cent { text-align: center; }
|
||||
.tin { display: block; width: 100%; box-sizing: border-box; margin: 0 auto;
|
||||
padding: 12px 10px; background: var(--solid); border: 2px solid var(--line);
|
||||
border-radius: 0; color: var(--acid); font: 700 16px Silkscreen, monospace;
|
||||
letter-spacing: 3px; text-align: center; text-transform: uppercase;
|
||||
-webkit-appearance: none; -webkit-tap-highlight-color: transparent; }
|
||||
.tin:focus { outline: none; border-color: var(--acid); }
|
||||
.tin::placeholder { color: var(--dim); letter-spacing: 2px; font-size: 12px; }
|
||||
#newbest h2 { font-size: 30px; margin-bottom: 6px; }
|
||||
#nbScore { margin: 0 0 22px; font: 400 11px Silkscreen, monospace; color: var(--dim);
|
||||
letter-spacing: 1px; }
|
||||
#nbScore b { color: var(--acid); font-weight: 400; }
|
||||
#nbName { display: block; width: 100%; box-sizing: border-box; margin: 0 auto 10px;
|
||||
padding: 14px 10px; background: var(--solid); border: 2px solid var(--line);
|
||||
border-radius: 0; color: var(--acid); font: 700 20px Silkscreen, monospace;
|
||||
letter-spacing: 3px; text-align: center; text-transform: uppercase;
|
||||
-webkit-appearance: none; -webkit-tap-highlight-color: transparent; }
|
||||
#nbName:focus { outline: none; border-color: var(--acid); }
|
||||
#nbName::placeholder { color: var(--dim); letter-spacing: 2px; font-size: 14px; }
|
||||
#nbName { margin-bottom: 10px; padding: 14px 10px; font-size: 20px; }
|
||||
#nbName::placeholder { font-size: 14px; }
|
||||
/* ---- THE NETPLAY LOBBY. Everything the mode needs before there is a court: who you are, the
|
||||
two ways to host, and the friend's code. The room you are waiting in replaces the picker in
|
||||
place (#vsWait), so the code and the SHARE button stand where the buttons were. */
|
||||
#vsErr:empty { display: none; }
|
||||
#vsErr { margin: 10px 0 0; padding: 8px; border: 2px solid #6e2a24; background: rgba(110,42,36,0.22);
|
||||
font: 400 10px Silkscreen, monospace; color: var(--bad); letter-spacing: 1px;
|
||||
text-align: center; }
|
||||
#vs .btn { margin-bottom: 8px; }
|
||||
/* the room takes the whole screen the picker had: the code floats in the middle band and CANCEL
|
||||
sits under your thumb, same three-band anchoring as every other screen */
|
||||
#vsWait { display: flex; flex-direction: column; flex: 1; }
|
||||
#vsWait[hidden] { display: none; }
|
||||
.joinrow { display: flex; gap: 8px; align-items: stretch; }
|
||||
.joinrow .tin { flex: 1; letter-spacing: 8px; }
|
||||
/* JOIN is the act, not a label beside a box: the crimson plate every primary button in the game
|
||||
wears, and NO padding of its own — the row stretches it to exactly the field's height, which
|
||||
its own 13px padding could only ever approximate. */
|
||||
/* #vs .btn's margin-bottom outranks a bare .joinrow .btn — and a margin on a stretched flex item
|
||||
is exactly the 8px the button was coming up short by */
|
||||
#vs .joinrow .btn { flex: none; width: 104px; margin: 0; padding: 0 6px; background: var(--red);
|
||||
border-color: #69201c; color: #f6e7dc; font: 400 22px Bangers, cursive;
|
||||
letter-spacing: 2px; }
|
||||
/* the code is the biggest thing on the screen — it is read aloud across a room as often as it is
|
||||
shared, and a four-letter code you have to squint at is the whole friction being removed */
|
||||
#vsBig { margin: 4px 0 20px; font: 700 42px Silkscreen, monospace; color: var(--acid);
|
||||
letter-spacing: 10px; text-indent: 10px; }
|
||||
#vsMsg { margin-top: 12px; }
|
||||
/* the h3 rows are label-left/hint-right everywhere else; this one has no hint and sits over a
|
||||
centred code, so it centres too (text-align cannot reach it — the row is a flex box) */
|
||||
#vsWHdr { justify-content: center; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -509,6 +542,37 @@ if (location.hostname !== 'splatter-tennis.wuwi.one') {
|
||||
<button class="btn big" id="cupGo" disabled>ENTER THE DRAW</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- VS A FRIEND. The whole lobby: your name (the world board's name — one name per player),
|
||||
the host's one decision, and the friend's code. #vsWait replaces the picker in place once
|
||||
a socket is open, so the room code and its SHARE button stand where the buttons were and
|
||||
the game stays parked behind this overlay until the room fills (main.js, THE LOBBY). -->
|
||||
<div id="vs">
|
||||
<div class="hdr"><button class="chev" id="vsBack">‹</button><h2>VS A FRIEND</h2></div>
|
||||
<div id="vsPick">
|
||||
<h3>01 · YOUR NAME<span>ON THEIR SCOREBOARD</span></h3>
|
||||
<input id="vsName" class="tin" maxlength="12" placeholder="YOUR NAME" autocomplete="off"
|
||||
autocapitalize="characters" spellcheck="false">
|
||||
<h3>02 · HOST A MATCH<span>THEY COME TO YOU</span></h3>
|
||||
<button class="btn" id="vsHostC">CLASSIC TENNIS</button>
|
||||
<button class="btn" id="vsHostD">DEATH MATCH</button>
|
||||
<h3>OR JOIN THEIRS<span>WITH THEIR CODE</span></h3>
|
||||
<div class="joinrow">
|
||||
<input id="vsCode" class="tin" maxlength="4" placeholder="CODE" autocomplete="off"
|
||||
autocapitalize="characters" spellcheck="false">
|
||||
<button class="btn" id="vsJoin">JOIN</button>
|
||||
</div>
|
||||
<p id="vsErr"></p>
|
||||
</div>
|
||||
<div id="vsWait" hidden>
|
||||
<div class="mid cent">
|
||||
<h3 id="vsWHdr" class="cent">ROOM CODE</h3>
|
||||
<p id="vsBig">····</p>
|
||||
<button class="btn big" id="vsShare">SHARE THE LINK</button>
|
||||
<p class="none cent" id="vsMsg">WAITING FOR THEM TO JOIN</p>
|
||||
</div>
|
||||
<div class="foot bare"><button class="btn" id="vsCancel">CANCEL</button></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- BODY COUNT. Every row in here is built by stats.js from the run records in localStorage. -->
|
||||
<div id="stats">
|
||||
<div class="hdr"><button class="chev" id="stBack">‹</button><h2 id="stTitle">BODY COUNT</h2></div>
|
||||
@@ -581,6 +645,6 @@ if (location.hostname !== 'splatter-tennis.wuwi.one') {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" src="src/main.js?v=265"></script>
|
||||
<script type="module" src="src/main.js?v=266"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user