Update auto-scaling to match new DOM; introduce a landscape layout with more vertical space
This commit is contained in:
parent
83f0ac9813
commit
602f16be8c
52
index.html
52
index.html
@ -136,34 +136,34 @@
|
|||||||
</main>
|
</main>
|
||||||
<main id="player" hidden>
|
<main id="player" hidden>
|
||||||
<div id="player-main">
|
<div id="player-main">
|
||||||
<div class="controls">
|
<div id="player-controls">
|
||||||
<div class="play-controls">
|
<button class="control-pause" type="button" title="pause">
|
||||||
<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>
|
||||||
<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"><kbd>p</kbd></span></button>
|
||||||
<span class="keyhint"><kbd>p</kbd></span></button>
|
<button class="control-restart" type="button" title="restart">
|
||||||
<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>
|
||||||
<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>
|
<button class="control-undo" type="button" title="undo">
|
||||||
<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>
|
||||||
<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>
|
<button class="control-rewind" type="button" title="rewind">
|
||||||
<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>
|
||||||
<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"><kbd>z</kbd></span></button>
|
||||||
<span class="keyhint"><kbd>z</kbd></span></button>
|
<div class="radio-faux-button-set">
|
||||||
<label><input class="control-turn-based" type="checkbox"> Turn-based mode</label>
|
<label><input class="control-turn-based" type="checkbox"> <span>Turn <br>based <br>mode</span></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"><kbd>q</kbd></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"><kbd>e</kbd></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"><kbd>c</kbd></span></button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="player-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"><kbd>q</kbd></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"><kbd>e</kbd></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"><kbd>c</kbd></span></button>
|
||||||
|
</div>
|
||||||
<section id="player-game-area">
|
<section id="player-game-area">
|
||||||
<div class="level"><!-- level canvas and any overlays go here --></div>
|
<div class="level"><!-- level canvas and any overlays go here --></div>
|
||||||
<div class="overlay-message">
|
<div class="overlay-message">
|
||||||
|
|||||||
87
js/main.js
87
js/main.js
@ -414,7 +414,7 @@ class Player extends PrimaryView {
|
|||||||
// 1: turn-based mode, at the start of a tic
|
// 1: turn-based mode, at the start of a tic
|
||||||
// 2: turn-based mode, in mid-tic, with the game frozen waiting for input
|
// 2: turn-based mode, in mid-tic, with the game frozen waiting for input
|
||||||
this.turn_mode = 0;
|
this.turn_mode = 0;
|
||||||
this.turn_based_checkbox = this.root.querySelector('.controls .control-turn-based');
|
this.turn_based_checkbox = this.root.querySelector('.control-turn-based');
|
||||||
this.turn_based_checkbox.checked = false;
|
this.turn_based_checkbox.checked = false;
|
||||||
this.turn_based_checkbox.addEventListener('change', ev => {
|
this.turn_based_checkbox.addEventListener('change', ev => {
|
||||||
if (this.turn_based_checkbox.checked) {
|
if (this.turn_based_checkbox.checked) {
|
||||||
@ -432,19 +432,19 @@ class Player extends PrimaryView {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Bind buttons
|
// Bind buttons
|
||||||
this.pause_button = this.root.querySelector('.controls .control-pause');
|
this.pause_button = this.root.querySelector('.control-pause');
|
||||||
this.pause_button.addEventListener('click', ev => {
|
this.pause_button.addEventListener('click', ev => {
|
||||||
this.toggle_pause();
|
this.toggle_pause();
|
||||||
ev.target.blur();
|
ev.target.blur();
|
||||||
});
|
});
|
||||||
this.restart_button = this.root.querySelector('.controls .control-restart');
|
this.restart_button = this.root.querySelector('.control-restart');
|
||||||
this.restart_button.addEventListener('click', ev => {
|
this.restart_button.addEventListener('click', ev => {
|
||||||
new ConfirmOverlay(this.conductor, "Abandon this attempt and try again?", () => {
|
new ConfirmOverlay(this.conductor, "Abandon this attempt and try again?", () => {
|
||||||
this.restart_level();
|
this.restart_level();
|
||||||
}).open();
|
}).open();
|
||||||
ev.target.blur();
|
ev.target.blur();
|
||||||
});
|
});
|
||||||
this.undo_button = this.root.querySelector('.controls .control-undo');
|
this.undo_button = this.root.querySelector('.control-undo');
|
||||||
this.undo_button.addEventListener('click', ev => {
|
this.undo_button.addEventListener('click', ev => {
|
||||||
let player_cell = this.level.player.cell;
|
let player_cell = this.level.player.cell;
|
||||||
// Keep undoing until (a) we're on another cell and (b) we're not sliding, i.e. we're
|
// Keep undoing until (a) we're on another cell and (b) we're not sliding, i.e. we're
|
||||||
@ -469,7 +469,7 @@ class Player extends PrimaryView {
|
|||||||
this._redraw();
|
this._redraw();
|
||||||
ev.target.blur();
|
ev.target.blur();
|
||||||
});
|
});
|
||||||
this.rewind_button = this.root.querySelector('.controls .control-rewind');
|
this.rewind_button = this.root.querySelector('.control-rewind');
|
||||||
this.rewind_button.addEventListener('click', ev => {
|
this.rewind_button.addEventListener('click', ev => {
|
||||||
if (this.state === 'rewinding') {
|
if (this.state === 'rewinding') {
|
||||||
this.set_state('playing');
|
this.set_state('playing');
|
||||||
@ -480,19 +480,19 @@ class Player extends PrimaryView {
|
|||||||
});
|
});
|
||||||
// Game actions
|
// Game actions
|
||||||
// TODO do these need buttons?? feel like they're not discoverable otherwise
|
// TODO do these need buttons?? feel like they're not discoverable otherwise
|
||||||
this.drop_button = this.root.querySelector('.actions .action-drop');
|
this.drop_button = this.root.querySelector('#player-actions .action-drop');
|
||||||
this.drop_button.addEventListener('click', ev => {
|
this.drop_button.addEventListener('click', ev => {
|
||||||
// Use the set of "buttons pressed between tics" because it's cleared automatically;
|
// Use the set of "buttons pressed between tics" because it's cleared automatically;
|
||||||
// otherwise these will stick around forever
|
// otherwise these will stick around forever
|
||||||
this.current_keys_new.add('q');
|
this.current_keys_new.add('q');
|
||||||
ev.target.blur();
|
ev.target.blur();
|
||||||
});
|
});
|
||||||
this.cycle_button = this.root.querySelector('.actions .action-cycle');
|
this.cycle_button = this.root.querySelector('#player-actions .action-cycle');
|
||||||
this.cycle_button.addEventListener('click', ev => {
|
this.cycle_button.addEventListener('click', ev => {
|
||||||
this.current_keys_new.add('e');
|
this.current_keys_new.add('e');
|
||||||
ev.target.blur();
|
ev.target.blur();
|
||||||
});
|
});
|
||||||
this.swap_button = this.root.querySelector('.actions .action-swap');
|
this.swap_button = this.root.querySelector('#player-actions .action-swap');
|
||||||
this.swap_button.addEventListener('click', ev => {
|
this.swap_button.addEventListener('click', ev => {
|
||||||
this.current_keys_new.add('c');
|
this.current_keys_new.add('c');
|
||||||
ev.target.blur();
|
ev.target.blur();
|
||||||
@ -1878,58 +1878,41 @@ class Player extends PrimaryView {
|
|||||||
if (style['display'] === 'none')
|
if (style['display'] === 'none')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let is_portrait = !! style.getPropertyValue('--is-portrait');
|
let is_portrait = window.matchMedia('(orientation: portrait)').matches;
|
||||||
// The base size is the size of the canvas, i.e. the viewport size times the tile size --
|
// The base size is the size of the canvas, i.e. the viewport size times the tile size --
|
||||||
// but note that we have 2x4 extra tiles for the inventory depending on layout
|
// but note that we have 2x4 extra tiles for the inventory depending on layout, plus half a
|
||||||
|
// tile's worth of padding around the game area, plus a quarter tile spacing
|
||||||
let base_x, base_y;
|
let base_x, base_y;
|
||||||
if (is_portrait) {
|
if (is_portrait) {
|
||||||
base_x = this.renderer.tileset.size_x * this.renderer.viewport_size_x;
|
base_x = this.renderer.tileset.size_x * (this.renderer.viewport_size_x + 0.5);
|
||||||
base_y = this.renderer.tileset.size_y * (this.renderer.viewport_size_y + 2);
|
base_y = this.renderer.tileset.size_y * (this.renderer.viewport_size_y + 2.75);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
base_x = this.renderer.tileset.size_x * (this.renderer.viewport_size_x + 4);
|
base_x = this.renderer.tileset.size_x * (this.renderer.viewport_size_x + 4.75);
|
||||||
base_y = this.renderer.tileset.size_y * this.renderer.viewport_size_y;
|
base_y = this.renderer.tileset.size_y * (this.renderer.viewport_size_y + 0.5);
|
||||||
}
|
}
|
||||||
// Unfortunately, finding the available space is a little tricky. The container is a CSS
|
// The element hierarchy is: the root is a wrapper that takes up the entire flex cell;
|
||||||
// flex item, and the flex cell doesn't correspond directly to any element, so there's no
|
// within that is the main player element which contains everything; and within that is the
|
||||||
// way for us to query its size directly. We also have various stuff up top and down below
|
// game area which is the part we can scale. The available space is the size of the root,
|
||||||
// that shouldn't count as available space. So instead we take a rough guess by adding up:
|
// but minus the size of the controls and whatnot placed around it, which are the difference
|
||||||
// - the space currently taken up by the canvas
|
// between the player container and the game area
|
||||||
let avail_x = this.renderer.canvas.offsetWidth;
|
let player = this.root.querySelector('#player-main');
|
||||||
let avail_y = this.renderer.canvas.offsetHeight;
|
let game_area = this.root.querySelector('#player-game-area');
|
||||||
// - the space currently taken up by the inventory, depending on orientation
|
let avail_x = this.root.offsetWidth - (player.offsetWidth - game_area.offsetWidth);
|
||||||
if (is_portrait) {
|
let avail_y = this.root.offsetHeight - (player.offsetHeight - game_area.offsetHeight);
|
||||||
avail_y += this.inventory_el.offsetHeight;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
avail_x += this.inventory_el.offsetWidth;
|
|
||||||
}
|
|
||||||
// - the difference between the size of the play area and the size of our root (which will
|
|
||||||
// add in any gap around the player, e.g. if the controls stretch the root to be wider)
|
|
||||||
let root_rect = this.root.getBoundingClientRect();
|
|
||||||
let player_rect = this.root.querySelector('#player-game-area').getBoundingClientRect();
|
|
||||||
avail_x += root_rect.width - player_rect.width;
|
|
||||||
avail_y += root_rect.height - player_rect.height;
|
|
||||||
// ...minus the width of the debug panel, if visible
|
// ...minus the width of the debug panel, if visible
|
||||||
if (this.debug.enabled) {
|
if (this.debug.enabled) {
|
||||||
avail_x -= this.root.querySelector('#player-debug').getBoundingClientRect().width;
|
avail_x -= this.root.querySelector('#player-debug').getBoundingClientRect().width;
|
||||||
}
|
}
|
||||||
// - the margins around our root, which consume all the extra space
|
// If there's already a scrollbar, the extra scrolled space is unavailable
|
||||||
let margin_x = parseFloat(style['margin-left']) + parseFloat(style['margin-right']);
|
avail_x -= Math.max(0, document.body.scrollWidth - document.body.clientWidth);
|
||||||
let margin_y = parseFloat(style['margin-top']) + parseFloat(style['margin-bottom']);
|
avail_y -= Math.max(0, document.body.scrollHeight - document.body.clientHeight);
|
||||||
avail_x += margin_x;
|
|
||||||
avail_y += margin_y;
|
|
||||||
// If those margins are zero, by the way, we risk being too big for the viewport already,
|
|
||||||
// and we need to subtract any extra scroll on the body
|
|
||||||
if (margin_x === 0 || margin_y === 0) {
|
|
||||||
avail_x -= document.body.scrollWidth - document.body.clientWidth;
|
|
||||||
avail_y -= document.body.scrollHeight - document.body.clientHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
let dpr = window.devicePixelRatio || 1.0;
|
let dpr = window.devicePixelRatio || 1.0;
|
||||||
// Divide to find the biggest scale that still fits. But don't exceed 90% of the available
|
// Divide to find the biggest scale that still fits. Leave a LITTLE wiggle room for pixel
|
||||||
// space, or it'll feel cramped (except on small screens, where being too small HURTS).
|
// rounding and breathing (except on small screens, where being too small REALLY hurts), but
|
||||||
let maxfrac = is_portrait ? 1 : 0.9;
|
// not too much since there's already a flex gap between the game and header/footer
|
||||||
|
let maxfrac = is_portrait ? 1 : 0.99;
|
||||||
let scale = Math.floor(maxfrac * dpr * Math.min(avail_x / base_x, avail_y / base_y));
|
let scale = Math.floor(maxfrac * dpr * Math.min(avail_x / base_x, avail_y / base_y));
|
||||||
if (scale <= 1) {
|
if (scale <= 1) {
|
||||||
scale = 1;
|
scale = 1;
|
||||||
@ -3534,9 +3517,9 @@ class Conductor {
|
|||||||
if (this.current) {
|
if (this.current) {
|
||||||
this.current.deactivate();
|
this.current.deactivate();
|
||||||
}
|
}
|
||||||
this.splash.activate();
|
|
||||||
this.current = this.splash;
|
this.current = this.splash;
|
||||||
document.body.setAttribute('data-mode', 'splash');
|
document.body.setAttribute('data-mode', 'splash');
|
||||||
|
this.splash.activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_to_editor() {
|
switch_to_editor() {
|
||||||
@ -3547,9 +3530,9 @@ class Conductor {
|
|||||||
this.editor.load_level(this.stored_level);
|
this.editor.load_level(this.stored_level);
|
||||||
this.loaded_in_editor = true;
|
this.loaded_in_editor = true;
|
||||||
}
|
}
|
||||||
this.editor.activate();
|
|
||||||
this.current = this.editor;
|
this.current = this.editor;
|
||||||
document.body.setAttribute('data-mode', 'editor');
|
document.body.setAttribute('data-mode', 'editor');
|
||||||
|
this.editor.activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_to_player() {
|
switch_to_player() {
|
||||||
@ -3560,9 +3543,11 @@ class Conductor {
|
|||||||
this.player.load_level(this.stored_level);
|
this.player.load_level(this.stored_level);
|
||||||
this.loaded_in_player = true;
|
this.loaded_in_player = true;
|
||||||
}
|
}
|
||||||
this.player.activate();
|
|
||||||
this.current = this.player;
|
this.current = this.player;
|
||||||
document.body.setAttribute('data-mode', 'player');
|
document.body.setAttribute('data-mode', 'player');
|
||||||
|
// Activate last, so any DOM inspection (ahem, auto-scaling) already sees the effects of
|
||||||
|
// data-mode revealing the header
|
||||||
|
this.player.activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
reload_all_options() {
|
reload_all_options() {
|
||||||
|
|||||||
280
style.css
280
style.css
@ -5,6 +5,7 @@ html {
|
|||||||
body {
|
body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -201,8 +202,8 @@ svg.svg-icon {
|
|||||||
.radio-faux-button-set > label > input:checked + span {
|
.radio-faux-button-set > label > input:checked + span {
|
||||||
background: hsl(225, 80%, 50%);
|
background: hsl(225, 80%, 50%);
|
||||||
box-shadow:
|
box-shadow:
|
||||||
inset 0 1px 0 1px hsl(225, 10%, 20%),
|
inset 0 0 1px 1px hsl(225, 50%, 40%),
|
||||||
inset 0 -0em 2em 0.5em hsl(225, 50%, 30%),
|
inset 0 -0.125em 0.5em 0.25em hsl(225, 50%, 30%),
|
||||||
0 1px 1px hsl(225, 10%, 10%);
|
0 1px 1px hsl(225, 10%, 10%);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,7 +434,7 @@ body > header {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5em;
|
gap: 0.5em;
|
||||||
|
|
||||||
padding: 0.5em;
|
padding: 0.25em 0.5em;
|
||||||
line-height: 1.125;
|
line-height: 1.125;
|
||||||
}
|
}
|
||||||
body > header h1 {
|
body > header h1 {
|
||||||
@ -453,6 +454,7 @@ body > header > nav {
|
|||||||
}
|
}
|
||||||
body > header button {
|
body > header button {
|
||||||
font-size: 0.75em;
|
font-size: 0.75em;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
body > header h1 a {
|
body > header h1 a {
|
||||||
color: inherit !important;
|
color: inherit !important;
|
||||||
@ -899,15 +901,149 @@ ol.packtest-summary > li {
|
|||||||
* debug panel can use that to sit against the right edge; absolute positioning excludes
|
* debug panel can use that to sit against the right edge; absolute positioning excludes
|
||||||
* margins, so if it were positioned as a child of THIS element, it would be stuffed into the
|
* margins, so if it were positioned as a child of THIS element, it would be stuffed into the
|
||||||
* game area (oops!) */
|
* game area (oops!) */
|
||||||
display: flex;
|
/* It does also make auto-sizing easier! */
|
||||||
flex-direction: column;
|
/* Default to a landscape layout, with the buttons on the left */
|
||||||
|
display: grid;
|
||||||
|
grid:
|
||||||
|
"buttons game actions"
|
||||||
|
"buttons game actions"
|
||||||
|
". music music"
|
||||||
|
/ 1fr auto 1fr
|
||||||
|
;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
gap: 0.5em;
|
gap: 0.5em;
|
||||||
margin: auto; /* center in both directions baby */
|
margin: auto; /* center in both directions baby */
|
||||||
}
|
}
|
||||||
|
#player-controls,
|
||||||
|
#player-actions {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
gap: 0.25em;
|
||||||
|
}
|
||||||
|
#player-controls {
|
||||||
|
grid-area: buttons;
|
||||||
|
align-self: start;
|
||||||
|
}
|
||||||
|
#player-controls button,
|
||||||
|
#player-actions button svg {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
#player-controls button {
|
||||||
|
padding: 0.5em;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
#player-controls .radio-faux-button-set {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
#player-actions {
|
||||||
|
grid-area: actions;
|
||||||
|
align-self: end;
|
||||||
|
}
|
||||||
|
#player-actions button {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#player-actions button svg {
|
||||||
|
display: block;
|
||||||
|
margin: 0.125em auto;
|
||||||
|
}
|
||||||
|
#player-music {
|
||||||
|
grid-area: music;
|
||||||
|
margin: 0 calc(var(--tile-width) * var(--scale) / 4);
|
||||||
|
text-transform: lowercase;
|
||||||
|
color: #909090;
|
||||||
|
}
|
||||||
|
/* Key hints are placed on the sides */
|
||||||
|
#player button {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
#player button .keyhint {
|
||||||
|
font-size: 1rem;
|
||||||
|
position: absolute;
|
||||||
|
top: 1.25em;
|
||||||
|
margin: auto;
|
||||||
|
color: #404040;
|
||||||
|
}
|
||||||
|
#player-controls button .keyhint {
|
||||||
|
left: -2em;
|
||||||
|
}
|
||||||
|
#player-actions button .keyhint {
|
||||||
|
right: -2em;
|
||||||
|
}
|
||||||
|
#player button:disabled .keyhint {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
@media (orientation: portrait) {
|
||||||
|
/* On a portrait screen, put the controls on top */
|
||||||
|
#player-main {
|
||||||
|
grid:
|
||||||
|
"buttons actions"
|
||||||
|
"game game"
|
||||||
|
"music music"
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#player-controls,
|
||||||
|
#player-actions {
|
||||||
|
flex-direction: row;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
#player-controls button,
|
||||||
|
#player-actions button svg {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
#player-controls button {
|
||||||
|
padding: 0.25em 0.5em;
|
||||||
|
line-height: 1.33;
|
||||||
|
}
|
||||||
|
/* Hackily remove the <br>s in "turn based mode" */
|
||||||
|
#player-controls .radio-faux-button-set br {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#player-actions {
|
||||||
|
justify-content: end;
|
||||||
|
}
|
||||||
|
#player-actions button svg {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0.125em;
|
||||||
|
}
|
||||||
|
#player button .keyhint {
|
||||||
|
top: -2em;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (orientation: portrait) and (max-width: 800px) {
|
||||||
|
/* On a /small/ portrait screen, also put the controls in two rows */
|
||||||
|
#player-main {
|
||||||
|
grid:
|
||||||
|
"buttons"
|
||||||
|
"actions"
|
||||||
|
"game"
|
||||||
|
"music"
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#player-controls,
|
||||||
|
#player-actions {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
#player .keyhint {
|
||||||
|
/* Hide key hints; there's nowhere to put them and they take up surprisingly a lot of space */
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (max-width: 800px) {
|
||||||
|
#player-music {
|
||||||
|
font-size: 0.875em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#player-game-area {
|
#player-game-area {
|
||||||
|
grid-area: game;
|
||||||
|
/* don't stretch if the buttons or music blow out somehow */
|
||||||
|
justify-self: center;
|
||||||
|
align-self: center;
|
||||||
|
|
||||||
isolation: isolate;
|
isolation: isolate;
|
||||||
align-self: center; /* don't stretch if the buttons or music blow out somehow */
|
|
||||||
display: grid;
|
display: grid;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
grid:
|
grid:
|
||||||
@ -919,22 +1055,19 @@ ol.packtest-summary > li {
|
|||||||
/* Need explicit min-content to force the hint to wrap */
|
/* Need explicit min-content to force the hint to wrap */
|
||||||
/ min-content min-content
|
/ min-content min-content
|
||||||
;
|
;
|
||||||
column-gap: 2em;
|
column-gap: calc(var(--tile-width) * var(--scale) / 4);
|
||||||
row-gap: 0.5em;
|
row-gap: calc(var(--tile-height) * var(--scale) / 4);
|
||||||
|
|
||||||
padding: 1em;
|
padding: calc(var(--tile-height) * var(--scale) / 4) calc(var(--tile-width) * var(--scale) / 4);
|
||||||
background: hsl(225, 10%, 20%);
|
background: hsl(225, 10%, 20%);
|
||||||
box-shadow: 0 0.25em 1em black;
|
box-shadow: 0 0.25em 1em black;
|
||||||
}
|
}
|
||||||
#player > .controls {
|
|
||||||
order: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.level {
|
.level {
|
||||||
grid-area: level;
|
grid-area: level;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
border: 2px solid black;
|
outline: 2px solid black;
|
||||||
}
|
}
|
||||||
.level canvas {
|
.level canvas {
|
||||||
display: block;
|
display: block;
|
||||||
@ -956,8 +1089,6 @@ ol.packtest-summary > li {
|
|||||||
height: 0;
|
height: 0;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
/* Copy the canvas's border width too */
|
|
||||||
border: 2px solid transparent;
|
|
||||||
|
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
font-size: calc(0.5 * var(--tile-width) * var(--scale));
|
font-size: calc(0.5 * var(--tile-width) * var(--scale));
|
||||||
@ -1080,7 +1211,7 @@ dl.score-chart .-sum {
|
|||||||
.time h3,
|
.time h3,
|
||||||
.bonus h3 {
|
.bonus h3 {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
font-size: 1.25em;
|
font-size: 1.5em;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
color: hsl(225, 20%, 90%);
|
color: hsl(225, 20%, 90%);
|
||||||
}
|
}
|
||||||
@ -1148,6 +1279,8 @@ dl.score-chart .-sum {
|
|||||||
* parent happens to be. Magic! */
|
* parent happens to be. Magic! */
|
||||||
height: 0;
|
height: 0;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
|
width: 0;
|
||||||
|
min-width: 100%;
|
||||||
}
|
}
|
||||||
#player-game-area > .player-hint-wrapper.--visible {
|
#player-game-area > .player-hint-wrapper.--visible {
|
||||||
display: initial;
|
display: initial;
|
||||||
@ -1185,50 +1318,29 @@ dl.score-chart .-sum {
|
|||||||
background: #0009;
|
background: #0009;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
#player .actions {
|
|
||||||
display: flex;
|
|
||||||
gap: 0.5em;
|
|
||||||
}
|
|
||||||
#player .actions button {
|
|
||||||
flex: 1;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
#player-music {
|
@media (orientation: portrait) {
|
||||||
grid-area: music;
|
#player-game-area {
|
||||||
margin: 0 1em;
|
/* Rearrange the grid to be vertical */
|
||||||
text-transform: lowercase;
|
grid:
|
||||||
color: #909090;
|
"level level"
|
||||||
}
|
"chips inventory" calc((var(--tile-height) * var(--scale) * 2 - 1em) / 3)
|
||||||
|
"time inventory" calc((var(--tile-height) * var(--scale) * 2 - 1em) / 3)
|
||||||
#player .controls {
|
"bonus inventory" calc((var(--tile-height) * var(--scale) * 2 - 1em) / 3)
|
||||||
grid-area: controls;
|
/ 1fr min-content
|
||||||
display: flex;
|
;
|
||||||
gap: 0.25em;
|
}
|
||||||
justify-content: space-between;
|
#player .inventory {
|
||||||
}
|
/* stick me in the center right */
|
||||||
#player button {
|
place-self: center end;
|
||||||
position: relative;
|
}
|
||||||
}
|
#player-game-area > .player-hint-wrapper {
|
||||||
#player button .keyhint {
|
/* Overlay hints on the inventory area */
|
||||||
position: absolute;
|
grid-row: chips / bonus;
|
||||||
left: 0;
|
grid-column: level;
|
||||||
right: 0;
|
z-index: 1;
|
||||||
top: -2em;
|
font-size: calc(var(--tile-height) * var(--scale) / 2.5);
|
||||||
margin: auto;
|
}
|
||||||
color: #404040;
|
|
||||||
}
|
|
||||||
#player button:disabled .keyhint {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.play-controls {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.25em;
|
|
||||||
}
|
|
||||||
.play-controls {
|
|
||||||
align-self: start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Debug stuff */
|
/* Debug stuff */
|
||||||
@ -1413,56 +1525,6 @@ body.--debug #player-debug {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@media (max-width: 800px) {
|
|
||||||
#player {
|
|
||||||
/* sentinel for js */
|
|
||||||
--is-portrait: 1;
|
|
||||||
/* The play area isn't necessarily the biggest thing any more, and it's ugly when stretched */
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
#player .controls {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
#player-game-area {
|
|
||||||
/* Rearrange the grid to be vertical */
|
|
||||||
grid:
|
|
||||||
"level level"
|
|
||||||
"chips inventory" calc((var(--tile-height) * var(--scale) * 2 - 1em) / 3)
|
|
||||||
"time inventory" calc((var(--tile-height) * var(--scale) * 2 - 1em) / 3)
|
|
||||||
"bonus inventory" calc((var(--tile-height) * var(--scale) * 2 - 1em) / 3)
|
|
||||||
/* FIXME ideally the first column would be 1fr so the hearts/time have space, but that
|
|
||||||
* allows hints to grow to the entire width of the window, which incredibly sucks. i
|
|
||||||
* don't know how to get around this except by giving the grid a fixed width, which i
|
|
||||||
* guess wouldn't be that hard */
|
|
||||||
/ min-content min-content
|
|
||||||
;
|
|
||||||
row-gap: 0.5em;
|
|
||||||
column-gap: 1em;
|
|
||||||
|
|
||||||
padding: 0.5em;
|
|
||||||
}
|
|
||||||
#player .inventory {
|
|
||||||
/* stick me in the center right */
|
|
||||||
place-self: center end;
|
|
||||||
}
|
|
||||||
#player-game-area > .player-hint-wrapper {
|
|
||||||
/* Overlay hints on the inventory area */
|
|
||||||
grid-row: chips / bonus;
|
|
||||||
grid-column: level;
|
|
||||||
z-index: 1;
|
|
||||||
font-size: calc(var(--tile-height) * var(--scale) / 2.5);
|
|
||||||
}
|
|
||||||
#player .keyhint {
|
|
||||||
/* Hide key hints, they take up surprisingly a lot of space */
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
#player-music {
|
|
||||||
/* Stack the title/artist on the volume, since they don't fit well side by side */
|
|
||||||
font-size: 0.875em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************************************/
|
/**************************************************************************************************/
|
||||||
/* Editor */
|
/* Editor */
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user