- Include links for the stock packs - Show completion amount and total time for played packs - Expose a list of all other packs the player has played - Allow forgetting a pack - Jump to the current level when reopening a pack - Highlight the current level in the level browser, and scroll to it
392 lines
19 KiB
HTML
392 lines
19 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf8">
|
||
<title>Lexy's Labyrinth</title>
|
||
<link rel="stylesheet" type="text/css" href="style.css">
|
||
<link rel="shortcut icon" type="image/png" href="icon.png">
|
||
<script type="module" src="js/main.js"></script>
|
||
<meta name="og:type" content="website">
|
||
<meta name="og:image" content="https://c.eev.ee/lexys-labyrinth/og-preview.png">
|
||
<meta name="og:title" content="Lexy's Labyrinth">
|
||
<meta name="og:description" content="A (work in progress) reimplementation of Chip's Challenge 1 and 2, using entirely free assets.">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||
</head>
|
||
<body data-mode="failed">
|
||
<script>document.body.setAttribute('data-mode', 'loading');</script>
|
||
<svg id="svg-iconsheet">
|
||
<defs>
|
||
<!-- Actions -->
|
||
<g id="svg-icon-up">
|
||
<path d="M0,12 l8,-8 l8,8 z"></path>
|
||
</g>
|
||
<g id="svg-icon-right">
|
||
<use href="#svg-icon-up" transform="rotate(90 8 8)"></use>
|
||
</g>
|
||
<g id="svg-icon-down">
|
||
<use href="#svg-icon-up" transform="rotate(180 8 8)"></use>
|
||
</g>
|
||
<g id="svg-icon-left">
|
||
<use href="#svg-icon-up" transform="rotate(270 8 8)"></use>
|
||
</g>
|
||
<g id="svg-icon-drop">
|
||
<path d="M6,0 h4 v9 h3 l-5,5 h7 v2 h-14 v-2 h7 l-5,-5 h3"></path>
|
||
</g>
|
||
<g id="svg-icon-cycle">
|
||
<path d="M2,3 H11 V1 l4,4 -4,4 V7 H2 Z"></path>
|
||
<path d="M14,9 H5 V7 l-4,4 4,4 v-2 h9 z"></path>
|
||
</g>
|
||
<g id="svg-icon-swap">
|
||
<path d="m 7,1 h 2 l 1,1 V 6 L 9,7 v 4 L 8,11.5 7,11 V 7 L 6,6 V 2 Z"></path>
|
||
<path d="M 8,13 13,11 8,9 3,11 Z m 0,2 7,-3 V 11 L 8,8 1,11 v 1 z"></path>
|
||
<ellipse cx="5.5" cy="11" rx="0.75" ry="0.5"></ellipse>
|
||
</g>
|
||
</defs>
|
||
</svg>
|
||
<header id="header-main">
|
||
<img id="header-icon" src="icon.png" alt="">
|
||
<h1><a href="https://github.com/eevee/lexys-labyrinth">Lexy's Labyrinth</a></h1>
|
||
<p>— an <a href="https://github.com/eevee/lexys-labyrinth">open source</a> game by <a href="https://eev.ee/">eevee</a></p>
|
||
<nav>
|
||
<button id="main-options" type="button" disabled>options</button>
|
||
<button id="main-compat" type="button">compat mode: <output>lexy</output></button>
|
||
</nav>
|
||
</header>
|
||
<header id="header-pack">
|
||
<h2 id="level-pack-name">Chip's Challenge Level Pack 1</h2>
|
||
<nav>
|
||
<button id="main-test-pack" type="button">Bulk test</button>
|
||
<button id="main-change-pack" type="button">Change pack</button>
|
||
<button id="player-edit" type="button">Edit</button>
|
||
<button id="editor-play" type="button">Play</button>
|
||
</nav>
|
||
</header>
|
||
<header id="header-level">
|
||
<h3 id="level-name">Level 1 — Key Pyramid</h3>
|
||
<nav>
|
||
<button id="main-prev-level" type="button">
|
||
<svg class="svg-icon" viewBox="0 0 16 16" title="previous"><path d="M14,1 2,8 14,14 z"></svg>
|
||
</button>
|
||
<button id="main-choose-level" type="button">Level select</button>
|
||
<button id="main-next-level" type="button">
|
||
<svg class="svg-icon" viewBox="0 0 16 16" title="next"><path d="M2,1 14,8 2,14 z"></svg>
|
||
</button>
|
||
</nav>
|
||
</header>
|
||
<main id="failed">
|
||
<h1>oops!</h1>
|
||
<p>Sorry, the game was unable to load at all.</p>
|
||
<p>If you have JavaScript partly or wholly blocked, I salute you! ...but this is an interactive game and cannot work without it.</p>
|
||
</main>
|
||
<main id="loading" hidden>
|
||
<p>...loading...</p>
|
||
<div class="scrolling-sidewalk">
|
||
<img src="loading.gif" alt="Lexy walking">
|
||
</div>
|
||
</main>
|
||
<script>
|
||
// FIXME not quite good enough; we'll get loading forever if there's a syntax error in the js
|
||
document.querySelector('#failed').setAttribute('hidden', '');
|
||
document.querySelector('#loading').removeAttribute('hidden');
|
||
</script>
|
||
<main id="splash" hidden>
|
||
<div class="drag-overlay"></div>
|
||
<header>
|
||
<h1><img src="og-preview.png" alt="">Lexy's Labyrinth</h1>
|
||
<p>an unapproved Chip's Challenge emulator</p>
|
||
</header>
|
||
<section id="splash-intro">
|
||
<p><strong>Welcome</strong> to Lexy's Labyrinth, an open source puzzle game that is curiously similar to — but legally distinct from! — the Atari classic <a href="https://en.wikipedia.org/wiki/Chip%27s_Challenge">Chip's Challenge</a>. It's been lovingly crafted from scratch with completely new art, sounds, and music; it lets you undo your mistakes; and it's the <em>only</em> way to play Chip's Challenge 2 levels on Linux, Mac, or a phone!</p>
|
||
<p>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.</p>
|
||
</section>
|
||
<section id="splash-links">
|
||
<h2>More resources</h2>
|
||
<ul class="normal-list">
|
||
<li><a href="https://github.com/eevee/lexys-labyrinth/wiki/How-To-Play">How to play</a></li>
|
||
<li><a href="https://github.com/eevee/lexys-labyrinth">Source code and project details on GitHub</a></li>
|
||
<li><a href="https://patreon.com/eevee">Support this project (and others) on my Patreon</a></li>
|
||
<li><a href="https://bitbusters.club/">Bit Busters Club</a>, a fansite with an extensive <a href="https://wiki.bitbusters.club/Main_Page">wiki</a>, vastly more <a href="https://sets.bitbusters.club/">community levels</a>, speedrun records, and more</li>
|
||
<li><a href="https://store.steampowered.com/app/346850/Chips_Challenge_1/">Chip's Challenge 1</a> (free) and <a href="https://store.steampowered.com/app/348300/Chips_Challenge_2/">Chip's Challenge 2</a> ($5) on Steam</li>
|
||
<li><a href="http://www.niffler.co.uk/">Niffler</a>, the current publisher of Chip's Challenge and its spiritual sequel <a href="https://store.steampowered.com/app/262590/Chucks_Challenge_3D_2020/">Chuck's Challenge 3D</a></li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section id="splash-stock-levels">
|
||
<h2>Play community levels</h2>
|
||
<!-- populated by js -->
|
||
</section>
|
||
|
||
<section id="splash-upload-levels">
|
||
<h2>Other levels</h2>
|
||
<p>You can load custom levels as well — CCL/DAT, C2G, or individual C2Ms (though scores aren't saved for those).</p>
|
||
<!-- TODO zip files! -->
|
||
<p>You can also drag and drop files or directories into this window.</p>
|
||
<input id="splash-upload-file" type="file" accept=".dat,.ccl,.c2m,.ccs" multiple>
|
||
<input id="splash-upload-dir" type="file" webkitdirectory>
|
||
<button type="button" id="splash-upload-file-button" class="button-big">Load files</button>
|
||
<button type="button" id="splash-upload-dir-button" class="button-big">Load directory</button>
|
||
<p>To play the original levels, you can load <code>CHIPS.DAT</code> from the ancient Microsoft port, or load the Steam levels as follows:</p>
|
||
<ol class="normal-list">
|
||
<li>Right-click the game in Steam and choose <em>Properties</em>. On the <em>Local Files</em> tab, click <em>Browse local files</em>.</li>
|
||
<li>Open the <code>data</code> folder, then <code>games</code>.</li>
|
||
<li>You should see either a <code>cc1</code> or <code>cc2</code> folder. Drag it into this window, or load it with the button above.</li>
|
||
</ol>
|
||
</section>
|
||
|
||
<section id="splash-your-levels">
|
||
<h2>Make your own (WIP lol)</h2>
|
||
<p>Please note that the level editor is <strong>very</strong> unfinished, and doesn't even have undo yet. It may eat your work! Beware!</p>
|
||
<p><button type="button" id="splash-create-pack" class="button-big">New pack</button></p>
|
||
<p><button type="button" id="splash-create-level" class="button-big">New scratch level<br>(won't be saved!)</button></p>
|
||
</section>
|
||
</main>
|
||
<main id="player" hidden>
|
||
<div id="player-main">
|
||
<div class="controls">
|
||
<div class="play-controls">
|
||
<button class="control-pause" type="button" title="pause">
|
||
<svg class="svg-icon" viewBox="0 0 16 16"><path d="M2,1 h4 v14 h-4 z M10,1 h4 v14 h-4 z"></svg>
|
||
<span class="keyhint">p</span></button>
|
||
<button class="control-restart" type="button" title="restart">
|
||
<svg class="svg-icon" viewBox="0 0 16 16"><path d="M13,13 A 7,7 270 1,1 13,3 L15,1 15,7 9,7 11,5 A 4,4 270 1,0 11,11 z"></svg>
|
||
</button>
|
||
<button class="control-undo" type="button" title="undo">
|
||
<svg class="svg-icon" viewBox="0 0 16 16"><path d="M6,5 6,2 1,7 6,12 6,9 A 10,10 60 0,1 15,12 A 10,10 90 0,0 6,5"></svg>
|
||
</button>
|
||
<button class="control-rewind" type="button" title="rewind">
|
||
<svg class="svg-icon" viewBox="0 0 16 16"><path d="M1,8 7,2 7,14 z M9,8 15,2 15,14 z"></svg>
|
||
<span class="keyhint">z</span></button>
|
||
<label><input class="control-turn-based" type="checkbox"> Turn-based mode</label>
|
||
</div>
|
||
<div class="actions">
|
||
<button class="action-drop" type="button">
|
||
<svg class="svg-icon" viewBox="0 0 16 16"><use href="#svg-icon-drop"></use></svg>
|
||
drop <span class="keyhint">q</span></button>
|
||
<button class="action-cycle" type="button">
|
||
<svg class="svg-icon" viewBox="0 0 16 16"><use href="#svg-icon-cycle"></use></svg>
|
||
cycle <span class="keyhint">e</span></button>
|
||
<button class="action-swap" type="button">
|
||
<svg class="svg-icon" viewBox="0 0 16 16"><use href="#svg-icon-swap"></use></svg>
|
||
switch <span class="keyhint">c</span></button>
|
||
</div>
|
||
</div>
|
||
<section id="player-game-area">
|
||
<div class="level"><!-- level canvas and any overlays go here --></div>
|
||
<div class="overlay-message">
|
||
<h1 class="-top"></h1>
|
||
<div class="-middle"></div>
|
||
<p class="-bottom"></p>
|
||
<p class="-keyhint"></p>
|
||
</div>
|
||
<div class="message"></div>
|
||
<div class="chips">
|
||
<h3>Hearts</h3>
|
||
<output></output>
|
||
</div>
|
||
<div class="time">
|
||
<h3>Time</h3>
|
||
<output></output>
|
||
</div>
|
||
<div class="bonus">
|
||
<h3>Bonus</h3>
|
||
<output></output>
|
||
</div>
|
||
<div class="inventory"></div>
|
||
</section>
|
||
<div id="player-music">
|
||
<div id="player-music-left">
|
||
🎵 <a id="player-music-title">title</a> by <a id="player-music-author">author</a>
|
||
</div>
|
||
<div id="player-music-right">
|
||
<input id="player-music-volume" type="range" min="0" max="1" step="0.05" value="1">
|
||
<input id="player-music-unmute" type="checkbox" checked>
|
||
</div>
|
||
<audio loop preload="auto">
|
||
</div>
|
||
</div>
|
||
<form id="player-debug">
|
||
<h3>Time</h3>
|
||
<table class="-time-controls">
|
||
<tr>
|
||
<td><button type="button" class="-time-button" data-dt="-1">← 1 tic</button></td>
|
||
<td id="player-debug-time-tics">0</td>
|
||
<td>tics</td>
|
||
<td><button type="button" class="-time-button" data-dt="1">1 tic →</button></td>
|
||
</tr>
|
||
<tr>
|
||
<td><button type="button" class="-time-button" data-dt="-4">← 1 move</button></td>
|
||
<td id="player-debug-time-moves">0</td>
|
||
<td>moves</td>
|
||
<td><button type="button" class="-time-button" data-dt="4">1 move →</button></td>
|
||
</tr>
|
||
<tr>
|
||
<td><button type="button" class="-time-button" data-dt="-20">← 1 s</button></td>
|
||
<td id="player-debug-time-secs">0</td>
|
||
<td>seconds</td>
|
||
<td><button type="button" class="-time-button" data-dt="20">1 s →</button></td>
|
||
</tr>
|
||
</table>
|
||
<div class="-buttons" id="player-debug-time-buttons">
|
||
<!-- populated in js -->
|
||
</div>
|
||
<p>Game speed:
|
||
<select name="speed">
|
||
<option value="100">100× faster</option>
|
||
<option value="50">50× faster</option>
|
||
<option value="20">20× faster</option>
|
||
<option value="10">10× faster</option>
|
||
<option value="5">5× faster</option>
|
||
<option value="3">3× faster</option>
|
||
<option value="2">2× faster</option>
|
||
<option value="3/2">1½× faster</option>
|
||
<option value="1" selected>Normal speed</option>
|
||
<option value="1/2">2× slower</option>
|
||
<option value="1/3">3× slower</option>
|
||
<option value="1/4">4× slower</option>
|
||
</select>
|
||
</p>
|
||
|
||
<h3>Inventory</h3>
|
||
<div class="-inventory">
|
||
<!-- populated in js -->
|
||
</div>
|
||
|
||
<h3>Replay</h3>
|
||
<!-- TODO...
|
||
play back replay
|
||
record replay, including altering it from here
|
||
stop replay, without restarting the level
|
||
show progress in %, length in tics + time
|
||
browse replay? jump to any point? label points???
|
||
edit manually?
|
||
-->
|
||
<div class="-replay-columns">
|
||
<div id="player-debug-input"></div>
|
||
<div class="-replay-status">
|
||
<!-- This should be a fixed height and is always showing one of the following -->
|
||
<div class="-none">No replay in progress</div>
|
||
<div class="-playback">
|
||
<progress max="0" value="0"></progress>
|
||
<output>100%</output>
|
||
<span>0 tics (0:00s)</span>
|
||
<button disabled>Relinquish control</button>
|
||
</div>
|
||
<div class="-recording">Recording...</div>
|
||
</div>
|
||
</div>
|
||
<!-- js inserts a bunch of stuff here -->
|
||
|
||
<h3>Misc</h3>
|
||
<p>Viewport size:
|
||
<select id="player-debug-viewport">
|
||
<option value="default" selected>Standard</option>
|
||
<option value="12">12 × 12</option>
|
||
<option value="16">16 × 16</option>
|
||
<option value="24">24 × 24</option>
|
||
<option value="32">32 × 32</option>
|
||
<option value="max">Entire level</option>
|
||
</select>
|
||
</p>
|
||
<ul>
|
||
<li><label><input type="checkbox" name="show_actor_bboxes"> Show actor bounding boxes</label></li>
|
||
<li><label><input type="checkbox" name="disable_interpolation"> Disable interpolation</label></li>
|
||
<!--
|
||
<li><label><input type="checkbox" disabled> Show actor info</label></li>
|
||
<li><label><input type="checkbox" disabled> Freeze time for everything else</label></li>
|
||
<li><label><input type="checkbox" disabled> Player is immortal</label></li>
|
||
<li><label><input type="checkbox" disabled> Player ignores collision</label></li>
|
||
<li><label><input type="checkbox" disabled> Player levitates</label></li>
|
||
-->
|
||
</ul>
|
||
<div class="-buttons" id="player-debug-misc-buttons">
|
||
<!-- populated in js -->
|
||
</div>
|
||
<p>Tip: Middle-click to teleport.</p>
|
||
|
||
<!-- TODO?
|
||
- inspect with mouse
|
||
- list of actors, or currently pointed-to actor?
|
||
- activate something manually?
|
||
- click a button ingame?
|
||
- pan viewport (like editor)
|
||
- show connections, directions, other editor features
|
||
- look under anything
|
||
|
||
- other game info?
|
||
- count tiles?
|
||
- total hearts?
|
||
- total bonus flags?
|
||
-->
|
||
</form>
|
||
</main>
|
||
<main id="editor" hidden>
|
||
<header>
|
||
<!-- TODO
|
||
- close
|
||
- export
|
||
- delete??
|
||
|
||
- zoom
|
||
|
||
also deal with levels vs level /packs/ somehow, not sure how that'll work (including downloading them, yeargh?)
|
||
-->
|
||
</header>
|
||
<div class="editor-canvas">
|
||
<div class="-container">
|
||
<!-- level canvas and any overlays go here -->
|
||
<!-- the container is to allow them to scroll as a single unit -->
|
||
</div>
|
||
</div>
|
||
<nav class="controls">
|
||
<div id="editor-tile">
|
||
</div>
|
||
<!--
|
||
<p style>
|
||
Tip: Right click to color drop.<br>
|
||
Tip: Ctrl-click with terrain to replace only the current tile's terrain, rather than overwriting the whole tile.
|
||
</p>
|
||
|
||
<p>Layer: [all/auto] [terrain] [item] [actor] [overlay]</p>
|
||
|
||
<p>Actor direction: [north] [south] [east] [west]</p>
|
||
|
||
<p>[ ] Show connections</p>
|
||
<p>[ ] Toggle green objects</p>
|
||
<p>[ ] Show monster pathing</p>
|
||
<p>[ ] Show circuits???</p>
|
||
|
||
<pre>
|
||
Metadata:
|
||
xxx / yyy chips required
|
||
Time limit: [____]
|
||
Title: [__________]
|
||
Author: [__________]
|
||
map size
|
||
</pre>
|
||
-->
|
||
</nav>
|
||
<div class="palette"></div>
|
||
<!-- TODO:
|
||
controls
|
||
- play!
|
||
- object palette
|
||
- choose direction
|
||
- choose layer to /modify/: terrain, item, creature, overlay
|
||
- stack (place item atop whatever terrain), or replace (placing a tile overwrites the whole cell)
|
||
[XXX mode that allows arbitrary stacking of objects?]
|
||
- level metadata
|
||
- change size
|
||
|
||
XXX how do i handle thin walls? treat specially, allow drawing/erasing them along edges instead of tiles? ehh then you can't control which tile they're in though... but the game seems to prefer south+east so maybe that works...
|
||
|
||
hotkeys
|
||
- mod a tile on the board: rotate a creature, alter thin walls??
|
||
- "pick up" a tile
|
||
|
||
cool stuff
|
||
- set chip count by hand, set extra ones automatically
|
||
-->
|
||
</main>
|
||
</body>
|
||
</html>
|