Spruce up stock pack list with previews, progress bar
This commit is contained in:
parent
bb7c468174
commit
3aec2b1fe6
@ -2235,7 +2235,7 @@ export class Level extends LevelInterface {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let time = Math.ceil((this.time_remaining ?? 0) / 20);
|
let time = Math.ceil((this.time_remaining ?? 0) / TICS_PER_SECOND);
|
||||||
return {
|
return {
|
||||||
time: time,
|
time: time,
|
||||||
abstime: this.tic_counter,
|
abstime: this.tic_counter,
|
||||||
|
|||||||
44
js/main.js
44
js/main.js
@ -1941,35 +1941,41 @@ class Player extends PrimaryView {
|
|||||||
|
|
||||||
const BUILTIN_LEVEL_PACKS = [{
|
const BUILTIN_LEVEL_PACKS = [{
|
||||||
path: 'levels/lexys-lessons.zip',
|
path: 'levels/lexys-lessons.zip',
|
||||||
|
preview: 'levels/previews/lexys-lessons.png',
|
||||||
ident: "Lexy's Lessons",
|
ident: "Lexy's Lessons",
|
||||||
title: "Lexy's Lessons (WIP)",
|
title: "Lexy's Lessons (WIP)",
|
||||||
desc: "A set of beginner levels that introduces every mechanic in Chip's Challenge 2, made specifically for Lexy's Labyrinth!",
|
desc: "A set of beginner levels that introduces every mechanic in Chip's Challenge 2, made specifically for Lexy's Labyrinth!",
|
||||||
}, {
|
}, {
|
||||||
path: 'levels/CC2LP1.zip',
|
path: 'levels/CC2LP1.zip',
|
||||||
|
preview: 'levels/previews/cc2lp1.png',
|
||||||
ident: 'Chips Challenge 2 Level Pack 1',
|
ident: 'Chips Challenge 2 Level Pack 1',
|
||||||
title: "Chip's Challenge 2 Level Pack 1",
|
title: "Chip's Challenge 2 Level Pack 1",
|
||||||
desc: "Thoroughly demonstrates what Chip's Challenge 2 is capable of. Fair, but doesn't hold your hand; you'd better have at least a passing familiarity with the CC2 elements.",
|
desc: "Thoroughly demonstrates what Chip's Challenge 2 is capable of. Fair, but doesn't hold your hand; you'd better have at least a passing familiarity with the CC2 elements.",
|
||||||
url: 'https://wiki.bitbusters.club/Chip%27s_Challenge_2_Level_Pack_1',
|
url: 'https://wiki.bitbusters.club/Chip%27s_Challenge_2_Level_Pack_1',
|
||||||
}, {
|
}, {
|
||||||
path: 'levels/CCLP1.ccl',
|
path: 'levels/CCLP1.ccl',
|
||||||
|
preview: 'levels/previews/cclp1.png',
|
||||||
ident: 'cclp1',
|
ident: 'cclp1',
|
||||||
title: "Chip's Challenge Level Pack 1",
|
title: "Chip's Challenge Level Pack 1",
|
||||||
desc: "Designed like a direct replacement for Chip's Challenge 1, with introductory levels for new players and a gentle difficulty curve.",
|
desc: "Designed like a direct replacement for Chip's Challenge 1, with introductory levels for new players and a gentle difficulty curve.",
|
||||||
url: 'https://wiki.bitbusters.club/Chip%27s_Challenge_Level_Pack_1',
|
url: 'https://wiki.bitbusters.club/Chip%27s_Challenge_Level_Pack_1',
|
||||||
}, {
|
}, {
|
||||||
path: 'levels/CCLP4.ccl',
|
path: 'levels/CCLP4.ccl',
|
||||||
|
preview: 'levels/previews/cclp4.png',
|
||||||
ident: 'cclp4',
|
ident: 'cclp4',
|
||||||
title: "Chip's Challenge Level Pack 4",
|
title: "Chip's Challenge Level Pack 4",
|
||||||
desc: "Moderately difficult, but not unfair.",
|
desc: "Moderately difficult, but not unfair.",
|
||||||
url: 'https://wiki.bitbusters.club/Chip%27s_Challenge_Level_Pack_4',
|
url: 'https://wiki.bitbusters.club/Chip%27s_Challenge_Level_Pack_4',
|
||||||
}, {
|
}, {
|
||||||
path: 'levels/CCLXP2.ccl',
|
path: 'levels/CCLXP2.ccl',
|
||||||
|
preview: 'levels/previews/cclxp2.png',
|
||||||
ident: 'cclxp2',
|
ident: 'cclxp2',
|
||||||
title: "Chip's Challenge Level Pack 2-X",
|
title: "Chip's Challenge Level Pack 2-X",
|
||||||
desc: "The first community pack released, tricky and rough around the edges.",
|
desc: "The first community pack released, tricky and rough around the edges.",
|
||||||
url: 'https://wiki.bitbusters.club/Chip%27s_Challenge_Level_Pack_2_(Lynx)',
|
url: 'https://wiki.bitbusters.club/Chip%27s_Challenge_Level_Pack_2_(Lynx)',
|
||||||
}, {
|
}, {
|
||||||
path: 'levels/CCLP3.ccl',
|
path: 'levels/CCLP3.ccl',
|
||||||
|
preview: 'levels/previews/cclp3.png',
|
||||||
ident: 'cclp3',
|
ident: 'cclp3',
|
||||||
title: "Chip's Challenge Level Pack 3",
|
title: "Chip's Challenge Level Pack 3",
|
||||||
desc: "A tough challenge, by and for veteran players.",
|
desc: "A tough challenge, by and for veteran players.",
|
||||||
@ -2253,7 +2259,12 @@ class Splash extends PrimaryView {
|
|||||||
button.disabled = true;
|
button.disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let li = mk('li.--unplayed', {'data-ident': ident}, button);
|
let li = mk('li.--unplayed', {'data-ident': ident});
|
||||||
|
if (packdef && packdef.preview) {
|
||||||
|
li.append(mk('img.-preview', {src: packdef.preview}));
|
||||||
|
}
|
||||||
|
li.append(button);
|
||||||
|
|
||||||
let forget_button = mk('button.-forget', {type: 'button'}, "Forget");
|
let forget_button = mk('button.-forget', {type: 'button'}, "Forget");
|
||||||
forget_button.addEventListener('click', ev => {
|
forget_button.addEventListener('click', ev => {
|
||||||
new ConfirmOverlay(this.conductor, `Clear all your progress for ${title}? This can't be undone.`, () => {
|
new ConfirmOverlay(this.conductor, `Clear all your progress for ${title}? This can't be undone.`, () => {
|
||||||
@ -2268,6 +2279,13 @@ class Splash extends PrimaryView {
|
|||||||
}
|
}
|
||||||
}).open();
|
}).open();
|
||||||
});
|
});
|
||||||
|
li.append(mk('div.-progress',
|
||||||
|
mk('div.-levels'),
|
||||||
|
mk('span.-score'),
|
||||||
|
mk('span.-time'),
|
||||||
|
forget_button,
|
||||||
|
));
|
||||||
|
|
||||||
if (packdef) {
|
if (packdef) {
|
||||||
let p = mk('p', packdef.desc);
|
let p = mk('p', packdef.desc);
|
||||||
if (packdef.url) {
|
if (packdef.url) {
|
||||||
@ -2275,12 +2293,7 @@ class Splash extends PrimaryView {
|
|||||||
}
|
}
|
||||||
li.append(p);
|
li.append(p);
|
||||||
}
|
}
|
||||||
li.append(mk('div.-progress',
|
|
||||||
mk('span.-score'),
|
|
||||||
mk('span.-time'),
|
|
||||||
mk('span.-levels'),
|
|
||||||
forget_button,
|
|
||||||
));
|
|
||||||
this.played_pack_elements[ident] = li;
|
this.played_pack_elements[ident] = li;
|
||||||
return li;
|
return li;
|
||||||
}
|
}
|
||||||
@ -2322,19 +2335,19 @@ class Splash extends PrimaryView {
|
|||||||
}
|
}
|
||||||
progress.querySelector('.-score').textContent = score;
|
progress.querySelector('.-score').textContent = score;
|
||||||
|
|
||||||
// This stuff isn't available in old saves
|
let level_el = progress.querySelector('.-levels');
|
||||||
if (packinfo.total_levels === undefined) {
|
if (packinfo.total_levels === undefined) {
|
||||||
|
// This stuff isn't available in old saves
|
||||||
progress.querySelector('.-time').textContent = "";
|
progress.querySelector('.-time').textContent = "";
|
||||||
progress.querySelector('.-levels').textContent = "";
|
progress.querySelector('.-levels').textContent = "";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO not used: total_abstime, aidless_levels
|
progress.querySelector('.-time').textContent = util.format_duration(packinfo.total_abstime / TICS_PER_SECOND, 2);
|
||||||
progress.querySelector('.-time').textContent = util.format_duration(packinfo.total_time);
|
|
||||||
let levels = `${packinfo.cleared_levels}/${packinfo.total_levels}`;
|
let levels = `${packinfo.cleared_levels}/${packinfo.total_levels}`;
|
||||||
if (packinfo.cleared_levels === packinfo.total_levels) {
|
levels = `cleared ${packinfo.cleared_levels} of ${packinfo.total_levels} levels, ${packinfo.aidless_levels}★ without aid`;
|
||||||
levels += '★';
|
level_el.textContent = levels;
|
||||||
}
|
level_el.style.setProperty('--cleared', packinfo.cleared_levels / packinfo.total_levels);
|
||||||
progress.querySelector('.-levels').textContent = levels;
|
level_el.style.setProperty('--aidless', packinfo.aidless_levels / packinfo.total_levels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3354,7 +3367,8 @@ class LevelBrowserOverlay extends DialogOverlay {
|
|||||||
// Main storage:
|
// Main storage:
|
||||||
// packs:
|
// packs:
|
||||||
// total_score
|
// total_score
|
||||||
// total_time
|
// total_time -- FIXME this is nonsense lol, it's time left on the clock
|
||||||
|
// total_abstime
|
||||||
// total_levels
|
// total_levels
|
||||||
// cleared_levels
|
// cleared_levels
|
||||||
// aidless_levels
|
// aidless_levels
|
||||||
|
|||||||
BIN
levels/previews/cc2lp1.png
Normal file
BIN
levels/previews/cc2lp1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
BIN
levels/previews/cclp1.png
Normal file
BIN
levels/previews/cclp1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
BIN
levels/previews/cclp3.png
Normal file
BIN
levels/previews/cclp3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.2 KiB |
BIN
levels/previews/cclp4.png
Normal file
BIN
levels/previews/cclp4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
BIN
levels/previews/cclxp2.png
Normal file
BIN
levels/previews/cclxp2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
BIN
levels/previews/lexys-lessons.png
Normal file
BIN
levels/previews/lexys-lessons.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
105
style.css
105
style.css
@ -208,12 +208,15 @@ svg.svg-icon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.button-row {
|
.button-row {
|
||||||
display: flex;
|
display: grid;
|
||||||
|
/* Put the buttons in a row most of the time, but change to a column when out of space */
|
||||||
|
grid: auto-flow auto / repeat(auto-fit, minmax(10em, 1fr));
|
||||||
gap: 0.5em;
|
gap: 0.5em;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
|
margin: 0.5em 0;
|
||||||
}
|
}
|
||||||
.button-row > button {
|
.button-row > button {
|
||||||
flex: 1;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Overlay styling */
|
/* Overlay styling */
|
||||||
@ -556,12 +559,12 @@ pre.stack-trace {
|
|||||||
"header header"
|
"header header"
|
||||||
"links links"
|
"links links"
|
||||||
"stock yours"
|
"stock yours"
|
||||||
/ 1fr 1fr
|
/ 3fr minmax(18em, 1fr)
|
||||||
;
|
;
|
||||||
gap: 1em;
|
gap: 1em;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 1em 10%;
|
padding: 1em 7.5%;
|
||||||
margin: auto 0;
|
margin: auto 0;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
@ -701,21 +704,17 @@ pre.stack-trace {
|
|||||||
.played-pack-list {
|
.played-pack-list {
|
||||||
|
|
||||||
}
|
}
|
||||||
.played-pack-list > li {
|
#splash-stock-levels .played-pack-list {
|
||||||
margin-bottom: 1em;
|
display: grid;
|
||||||
|
grid: auto-flow auto / repeat(auto-fill, minmax(320px, 1fr)); /* 10x10 */
|
||||||
|
gap: 1em;
|
||||||
|
margin: 1em 0;
|
||||||
}
|
}
|
||||||
.played-pack-list p {
|
.played-pack-list .-preview {
|
||||||
margin: 0 0.5em;
|
display: block;
|
||||||
color: #e8e8e8;
|
height: 320px;
|
||||||
}
|
margin: auto;
|
||||||
.played-pack-list .-progress {
|
object-fit: none;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5em;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
.played-pack-list > li.--unplayed .-progress {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
.played-pack-list > li > button {
|
.played-pack-list > li > button {
|
||||||
font-size: 1.25em;
|
font-size: 1.25em;
|
||||||
@ -735,18 +734,72 @@ pre.stack-trace {
|
|||||||
.played-pack-list > li > button:enabled:hover {
|
.played-pack-list > li > button:enabled:hover {
|
||||||
background: hsl(225, 40%, 30%);
|
background: hsl(225, 40%, 30%);
|
||||||
}
|
}
|
||||||
.played-pack-list .-progress > .-score,
|
.played-pack-list p {
|
||||||
.played-pack-list .-progress > .-time,
|
color: #c0c0c0;
|
||||||
.played-pack-list .-progress > .-levels {
|
font-style: italic;
|
||||||
flex: 2;
|
|
||||||
}
|
}
|
||||||
.played-pack-list .-progress > button {
|
.played-pack-list .-progress {
|
||||||
flex: 1;
|
display: grid;
|
||||||
|
grid:
|
||||||
|
"levels levels levels"
|
||||||
|
"score time button"
|
||||||
|
/ 2fr 2fr 1fr
|
||||||
|
;
|
||||||
|
gap: 0.5em;
|
||||||
|
margin: 0.5em 0;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.played-pack-list > li.--unplayed .-progress {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.played-pack-list .-progress > .-levels {
|
||||||
|
grid-area: levels;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
padding: 0.25em;
|
||||||
|
border: 1px solid hsl(225, 25%, 40%);
|
||||||
|
text-shadow: 0 1px 1px black;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.played-pack-list .-progress > .-levels::before,
|
||||||
|
.played-pack-list .-progress > .-levels::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
z-index: -1;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
.played-pack-list .-progress > .-levels::before {
|
||||||
|
width: calc(var(--cleared) * 100%);
|
||||||
|
background: hsl(225, 25%, 30%);
|
||||||
|
}
|
||||||
|
.played-pack-list .-progress > .-levels::after {
|
||||||
|
width: calc(var(--aidless) * 100%);
|
||||||
|
background: hsl(225, 25%, 40%);
|
||||||
|
}
|
||||||
|
.played-pack-list .-progress > .-score {
|
||||||
|
grid-area: score;
|
||||||
|
}
|
||||||
|
.played-pack-list .-progress > .-time {
|
||||||
|
grid-area: time;
|
||||||
|
}
|
||||||
|
.played-pack-list .-progress > .-levels {
|
||||||
|
grid-area: levels;
|
||||||
|
}
|
||||||
|
.played-pack-list .-progress > .-score::before {
|
||||||
|
content: "Score: ";
|
||||||
|
color: #909090;
|
||||||
|
}
|
||||||
|
.played-pack-list .-progress > .-time::before {
|
||||||
|
content: "Time: ";
|
||||||
|
color: #909090;
|
||||||
}
|
}
|
||||||
.played-pack-list .-editor-status {
|
.played-pack-list .-editor-status {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5em;
|
gap: 0.5em;
|
||||||
margin: 0 0.5em;
|
margin: 0.5em 0 1em;
|
||||||
}
|
}
|
||||||
.played-pack-list .-editor-status > .-level-count {
|
.played-pack-list .-editor-status > .-level-count {
|
||||||
flex: auto;
|
flex: auto;
|
||||||
@ -1777,7 +1830,7 @@ body.--debug #player-debug {
|
|||||||
|
|
||||||
.editor-level-browser {
|
.editor-level-browser {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid: auto-flow auto / repeat(auto-fill, minmax(13em, 1fr)); /* 12em preview wdith + padding */
|
grid: auto-flow auto / repeat(auto-fill, minmax(13em, 1fr)); /* 12em preview width + padding */
|
||||||
gap: 0.5em;
|
gap: 0.5em;
|
||||||
width: 70vw;
|
width: 70vw;
|
||||||
/* seems to go into the parent's right padding fsr, i guess because the scrollbar is there */
|
/* seems to go into the parent's right padding fsr, i guess because the scrollbar is there */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user