From a8800838d4ff2e3c577577450193132c478f50a2 Mon Sep 17 00:00:00 2001 From: "Eevee (Evelyn Woods)" Date: Thu, 24 Dec 2020 03:38:13 -0700 Subject: [PATCH] Add a loading and error screen; also include compat CSS oops --- index.html | 48 +++++++++++---- js/main.js | 120 +++++++++++++++++++++++++++++++++++-- style.css | 169 +++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 297 insertions(+), 40 deletions(-) diff --git a/index.html b/index.html index aa2b87e..89fb1b1 100644 --- a/index.html +++ b/index.html @@ -12,7 +12,8 @@ - + + @@ -44,12 +45,11 @@
-

Lexy's Labyrinth

-

— a game by eevee

+

Lexy's Labyrinth

+

— an open source game by eevee

@@ -73,16 +73,41 @@
-
+
+

oops!

+

Sorry, the game was unable to load at all.

+

If you have JavaScript partly or wholly blocked, I salute you! ...but this is an interactive game and cannot work without it.

+
+
+

...loading...

+
+ Lexy walking +
+
+ +

Lexy's Labyrinth

an unapproved Chip's Challenge emulator

-

Welcome to Lexy's Labyrinth, an open source puzzle game that is curiously similar to — but legally distinct from — the Atari classic Chip's Challenge!

+

Welcome to Lexy's Labyrinth, an open source puzzle game that is curiously similar to — but legally distinct from! — the Atari classic Chip's Challenge. It's been lovingly crafted from scratch with completely new art, sounds, and music; it lets you undo your mistakes; and it's the only way to play Chip's Challenge 2 levels on Linux, Mac, or a phone!

Pick a level pack to get started! You can also load and play any levels you've got lying around, or brave the level editor and make one of your own.

-

If you're not familiar with the game, read up on how to play. You can also get more technical details or report bugs on GitHub, find out more about Chip's Challenge via the Bit Busters Club fansite, or support this endeavor (and other things I do) on Patreon.

+
+
@@ -91,16 +116,15 @@
-

Load other levels

-

Load and play any levels you have on hand, including the original levels. Supports CCL/DAT, C2G, and individual C2Ms (though scores aren't saved for those). Find more on the Bit Busters Club set list.

+

Other levels

+

You can load custom levels as well — CCL/DAT, C2G, or individual C2Ms (though scores aren't saved for those).

You can also drag and drop files or directories into this window.

-

If you still have the original Microsoft "BOWEP" game lying around, you can play the Chip's Challenge 1 levels by loading CHIPS.DAT.

-

If you own the Steam versions of Chip's Challenge 1 (free!) or Chip's Challenge 2 ($5 last I checked), you can play those too, even on Linux or Mac:

+

To play the original levels, you can load CHIPS.DAT from the ancient Microsoft port, or load the Steam levels as follows:

  1. Right-click the game in Steam and choose Properties. On the Local Files tab, click Browse local files.
  2. Open the data folder, then games.
  3. diff --git a/js/main.js b/js/main.js index dcefea8..2be723e 100644 --- a/js/main.js +++ b/js/main.js @@ -1683,6 +1683,102 @@ const BUILTIN_LEVEL_PACKS = [{ ident: 'cclp3', title: "Chip's Challenge Level Pack 3", desc: "A tough challenge, by and for veteran players.", +/* + * TODO: this is tricky. it's a massive hodgepodge of levels mostly made by individual people... +}, { + path: 'levels/CCLP3.ccl', + ident: 'jblp1', + title: "JBLP1", + author: 'jb', + desc: "\"Meant to be simple and straightforward in the spirit of the original game, though the difficulty peak is ultimately a bit higher.\"", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "Pit of 100 Tiles", + author: 'ajmiam', + desc: "A tough challenge, by and for veteran players.", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "The Other 100 Tiles", + author: 'ajmiam', + desc: "A tough challenge, by and for veteran players.", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "JoshL5", + desc: "A tough challenge, by and for veteran players.", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "JoshL6", + desc: "A tough challenge, by and for veteran players.", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "JoshL7", + desc: "A tough challenge, by and for veteran players.", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "Neverstopgaming", + desc: "A tough challenge, by and for veteran players.", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "Ultimate Chip 4", + desc: "A tough challenge, by and for veteran players.", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "Ultimate Chip 5", + desc: "A tough challenge, by and for veteran players.", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "Ultimate Chip 6", + desc: "A tough challenge, by and for veteran players.", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "Walls of CCLP 1", + desc: "A tough challenge, by and for veteran players.", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "Walls of CCLP 3", + desc: "A tough challenge, by and for veteran players.", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "Walls of CCLP 4", + desc: "A tough challenge, by and for veteran players.", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "TS0", + desc: "A tough challenge, by and for veteran players.", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "TS1", + desc: "A tough challenge, by and for veteran players.", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "TS2", + desc: "A tough challenge, by and for veteran players.", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "Chip56", + desc: "A tough challenge, by and for veteran players.", +}, { + path: 'levels/CCLP3.ccl', + ident: 'cclp3', + title: "kidsfair", + desc: "A tough challenge, by and for veteran players.", + */ }]; class Splash extends PrimaryView { @@ -2555,9 +2651,6 @@ class Conductor { this.player = new Player(this); // Bind the header buttons - document.querySelector('#main-about').addEventListener('click', ev => { - new AboutOverlay(this).open(); - }); document.querySelector('#main-options').addEventListener('click', ev => { new OptionsOverlay(this).open(); }); @@ -2633,6 +2726,7 @@ class Conductor { }); this.update_nav_buttons(); + document.querySelector('#loading').setAttribute('hidden', ''); this.switch_to_splash(); } @@ -2891,4 +2985,22 @@ async function main() { } } -main(); +(async () => { + try { + await main(); + } + catch (e) { + let failed = document.getElementById('failed'); + document.getElementById('loading').setAttribute('hidden', ''); + failed.removeAttribute('hidden'); + document.body.setAttribute('data-mode', 'failed'); + + failed.appendChild(mk('p', + "I did manage to capture this error, which you might be able to ", + mk('a', {href: 'https://github.com/eevee/lexys-labyrinth'}, "report somewhere"), + ":", + )); + failed.appendChild(mk('pre.stack-trace', e.toString(), "\n\n", (e.stack ?? "").replace(/^/mg, " "))); + throw e; + } +})(); diff --git a/style.css b/style.css index d4ca4ad..8c98bcb 100644 --- a/style.css +++ b/style.css @@ -19,6 +19,7 @@ body { --panel-bg-color: hsl(225, 10%, 20%); --button-bg-color: hsl(225, 10%, 25%); --button-bg-hover-color: hsl(225, 15%, 30%); + --generic-bg-hover-on-white: hsl(225, 60%, 85%); } /* Generic element styling */ @@ -31,7 +32,8 @@ input[type=range] { margin: 0.125em; vertical-align: middle; } -button { +button, +.radio-faux-button-set > label > input + span { font-size: inherit; padding: 0.25em 0.5em; font-family: inherit; @@ -45,12 +47,12 @@ button { text-transform: lowercase; cursor: pointer; } -button:hover { +button:hover, +.radio-faux-button-set > label:hover > input + span { background: var(--button-bg-hover-color); } -button:active { - box-shadow: - inset 0 0 2px 1px hsl(225, 10%, 33%); +button:active, +.radio-faux-button-set > label:active > input + span { transform: translateY(1px); /* Need this for the editor's tool help things and i'm not questioning it */ z-index: 1; @@ -143,6 +145,40 @@ svg.svg-icon { fill-rule: evenodd; } +/* Set of radio buttons in a row, styled like buttons */ +/* (you know, like /actual/ radio buttons) */ +/* Button-esque styling is shared with the button definition above */ +.radio-faux-button-set { + display: flex; + margin: 0.5em 0; +} +.radio-faux-button-set > label { + flex: 1; +} +.radio-faux-button-set > label > input { + display: none; +} +.radio-faux-button-set > label > input + span { + display: block; + border-radius: 0; + text-align: center; +} +.radio-faux-button-set > label:first-child > input + span { + border-top-left-radius: 0.25em; + border-bottom-left-radius: 0.25em; +} +.radio-faux-button-set > label:last-child > input + span { + border-top-right-radius: 0.25em; + border-bottom-right-radius: 0.25em; +} +.radio-faux-button-set > label > input:checked + span { + background: hsl(225, 80%, 50%); + box-shadow: + inset 0 1px 0 1px hsl(225, 10%, 20%), + inset 0 -0em 2em 0.5em hsl(225, 50%, 30%), + 0 1px 1px hsl(225, 10%, 10%); +} + /* Overlay styling */ .overlay { display: flex; @@ -266,12 +302,42 @@ table.level-browser tbody tr { cursor: pointer; } table.level-browser tbody tr:hover { - background: hsl(225, 60%, 85%); + background: var(--generic-hover-bg-on-white); } table.level-browser tbody tr:nth-child(10n) td { border-bottom: 2px solid hsl(225, 20%, 80%); } +/* Compat dialog */ +.dialog-compat { + max-width: 60em; +} +ul.compat-flags > li { + padding: 0.125em; +} +ul.compat-flags > li.-checked { + background: hsl(225, 60%, 90%); +} +ul.compat-flags > li:hover { + background: var(--generic-bg-hover-on-white); +} +ul.compat-flags > li > label { + display: flex; + align-items: center; + gap: 0.25em; +} +ul.compat-flags > li > label > span.-desc { + flex: 1; +} +img.compat-icon, +.compat-icon-gap { + display: inline-block; + width: 32px; + height: 32px; + vertical-align: middle; +} + + /* Options dialog */ .dialog-options { height: 60%; @@ -334,24 +400,6 @@ label.option .option-label { } } -/* Bits and pieces */ -img.compat-icon { - margin: 0 0.25em 0.125em; - vertical-align: middle; -} -.compat-lynx, -.compat-ms { - font-size: 0.75em; - display: inline-block; - margin: 0 0.25em; - padding: 0.25em; - line-height: 1; - vertical-align: middle; - color: white; - background: gray; - border-radius: 0.25em; -} - /**************************************************************************************************/ /* Main page structure */ @@ -382,7 +430,19 @@ body > header > nav { body > header button { font-size: 0.75em; } +body > header h1 a { + color: inherit !important; + text-decoration: none !important; +} +body[data-mode=failed] #header-pack, +body[data-mode=failed] #header-level, +body[data-mode=failed] #header-main > nav, +body[data-mode=loading] #header-pack, +body[data-mode=loading] #header-level, +body[data-mode=loading] #header-main > nav { + display: none; +} body[data-mode=splash] #header-pack, body[data-mode=splash] #header-level { display: none; @@ -391,6 +451,50 @@ body[data-mode=editor] #player-edit, body[data-mode=player] #editor-play { display: none; } +#failed, +#loading { + margin: auto; + text-align: center; +} +#loading { + font-size: 2em; +} +.scrolling-sidewalk { + height: 32px; + width: 50vw; + margin: auto; + background: url(icons/tool-bg-selected.png) repeat; + animation: scrolling-sidewalk linear 0.4s infinite; + /* + box-shadow: + inset 5vw 0 5vw -5vw black, + inset -5vw 0 5vw -5vw black; + */ + mask: linear-gradient(to right, transparent 0, #ffffff40 10%, white 20%, white 80%, #ffffff40 90%, transparent 100%); +} +.scrolling-sidewalk > img { + display: block; + margin: auto; +} +@keyframes scrolling-sidewalk { + 0% { + background-position: 0px 0px; + } + 100% { + background-position: -32px 0px; + } +} +pre.stack-trace { + overflow: auto; + width: 90vw; + max-width: 50em; + padding: 0.5em; + margin: 1em auto; + white-space: pre; + text-align: left; + background: hsl(345, 20%, 10%); + border: 3px double hsl(345, 75%, 20%); +} #header-main { order: 3; @@ -422,9 +526,16 @@ body[data-mode=player] #editor-play { #splash { display: grid; + grid: + "header header header" + "intro stock upload" + "links stock yours" + / 1fr 1fr 1fr + ; grid: "header header header" "intro intro intro" + "links links links" "stock upload yours" / 1fr 1fr 1fr ; @@ -487,6 +598,12 @@ body[data-mode=player] #editor-play { grid-area: intro; font-size: 20px; } +#splash > #splash-links { + grid-area: links; +} +#splash > #splash-links ul.normal-list li { + margin: 0.5em 0; +} #splash > #splash-stock-levels { grid-area: stock; } @@ -517,6 +634,10 @@ body[data-mode=player] #editor-play { #splash > header h1 { font-size: 2em; } + /* No need to boost the font size here */ + #splash > #splash-intro { + font-size: inherit; + } } button.level-pack-button {