Chose one of two main-menu backgrounds at launch
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 330 KiB |
+14
-6
@@ -35,9 +35,6 @@ html, body {
|
|||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
padding: 28px 34px;
|
padding: 28px 34px;
|
||||||
background:
|
|
||||||
radial-gradient(circle at 30% 0%, rgba(40, 70, 110, 0.25), transparent 60%),
|
|
||||||
#05070c;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.loading-overlay.hidden { display: none; }
|
.loading-overlay.hidden { display: none; }
|
||||||
@@ -91,14 +88,25 @@ html, body {
|
|||||||
}
|
}
|
||||||
#screen-menu.active, #screen-new.active, #screen-join.active, #screen-choose.active { display: flex; }
|
#screen-menu.active, #screen-new.active, #screen-join.active, #screen-choose.active { display: flex; }
|
||||||
|
|
||||||
/* The main menu sits on the game's key art, dimmed so the card stays legible;
|
/* The main menu sits on one of the game's key-art pieces, dimmed so the card
|
||||||
the setup, join and choose screens keep the plain gradient above. */
|
stays legible; the setup, join and choose screens keep the plain gradient
|
||||||
#screen-menu {
|
above. The piece is picked at launch (client/js/menu_background.js) by the
|
||||||
|
class on <body>, and the same art stays behind the boot log while the world
|
||||||
|
loads. The default below is also what paints before the script runs. */
|
||||||
|
#screen-menu,
|
||||||
|
.loading-overlay {
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at 50% 25%, rgba(60, 90, 140, 0.25), transparent 60%),
|
radial-gradient(circle at 50% 25%, rgba(60, 90, 140, 0.25), transparent 60%),
|
||||||
linear-gradient(180deg, rgba(5, 7, 12, 0.45), rgba(5, 7, 12, 0.85)),
|
linear-gradient(180deg, rgba(5, 7, 12, 0.45), rgba(5, 7, 12, 0.85)),
|
||||||
url("../assets/main_menu_background.png") center / cover no-repeat;
|
url("../assets/main_menu_background.png") center / cover no-repeat;
|
||||||
}
|
}
|
||||||
|
body.menu-bg-1 #screen-menu,
|
||||||
|
body.menu-bg-1 .loading-overlay {
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at 50% 25%, rgba(60, 90, 140, 0.25), transparent 60%),
|
||||||
|
linear-gradient(180deg, rgba(5, 7, 12, 0.45), rgba(5, 7, 12, 0.85)),
|
||||||
|
url("../assets/main_menu_background2.png") center / cover no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
.menu-card {
|
.menu-card {
|
||||||
width: 380px;
|
width: 380px;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
import { Network } from "./net.js";
|
import { Network } from "./net.js";
|
||||||
import { GameScreen } from "./game_screen.js";
|
import { GameScreen } from "./game_screen.js";
|
||||||
import { bootLog } from "./loading.js";
|
import { bootLog } from "./loading.js";
|
||||||
|
import { chooseMenuBackground } from "./menu_background.js";
|
||||||
import { CIVILISATIONS } from "../../shared/data.js";
|
import { CIVILISATIONS } from "../../shared/data.js";
|
||||||
|
|
||||||
const network = new Network();
|
const network = new Network();
|
||||||
@@ -40,6 +41,12 @@ function status(id, message) {
|
|||||||
$(`#${id}`).text(message);
|
$(`#${id}`).text(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------- appearance ----
|
||||||
|
|
||||||
|
// Two pieces of key art ship; pick one for this launch. It backs the main menu
|
||||||
|
// and stays behind the boot log while a world loads.
|
||||||
|
chooseMenuBackground();
|
||||||
|
|
||||||
// -------------------------------------------------------------- menu ------
|
// -------------------------------------------------------------- menu ------
|
||||||
|
|
||||||
$("#menu-create").on("click", () => showScreen("screen-new"));
|
$("#menu-create").on("click", () => showScreen("screen-new"));
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// The main menu's key art. Two pieces ship and one is picked at launch; the
|
||||||
|
// chosen piece also stays behind the boot log while a world loads. The URL
|
||||||
|
// itself lives in css/style.css, keyed by the class the choice adds to <body>.
|
||||||
|
|
||||||
|
export const MENU_BACKGROUNDS = [
|
||||||
|
{ class: "menu-bg-0", source: "assets/main_menu_background.png" },
|
||||||
|
{ class: "menu-bg-1", source: "assets/main_menu_background2.png" },
|
||||||
|
];
|
||||||
|
|
||||||
|
// Picks one of the backgrounds. `random` is injectable so a test can pin it.
|
||||||
|
export function pickMenuBackground(random = Math.random) {
|
||||||
|
const index = Math.floor(random() * MENU_BACKGROUNDS.length);
|
||||||
|
return MENU_BACKGROUNDS[Math.min(index, MENU_BACKGROUNDS.length - 1)];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swaps the background class on <body>, removing whichever one was set before.
|
||||||
|
export function applyMenuBackground(choice, body = document.body) {
|
||||||
|
for (const entry of MENU_BACKGROUNDS) body.classList.remove(entry.class);
|
||||||
|
body.classList.add(choice.class);
|
||||||
|
return choice;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function chooseMenuBackground(random = Math.random, body = document.body) {
|
||||||
|
return applyMenuBackground(pickMenuBackground(random), body);
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import { TestCase } from "./framework/test_case.js";
|
||||||
|
import { setupDom, teardownDom } from "./framework/dom.js";
|
||||||
|
import {
|
||||||
|
MENU_BACKGROUNDS,
|
||||||
|
applyMenuBackground,
|
||||||
|
pickMenuBackground,
|
||||||
|
} from "../client/js/menu_background.js";
|
||||||
|
|
||||||
|
function fakeBody() {
|
||||||
|
const classes = new Set();
|
||||||
|
return {
|
||||||
|
classList: {
|
||||||
|
add: (name) => classes.add(name),
|
||||||
|
remove: (name) => classes.delete(name),
|
||||||
|
contains: (name) => classes.has(name),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MenuBackgroundTest extends TestCase {
|
||||||
|
test_ships_two_distinct_backgrounds() {
|
||||||
|
this.assertSize(MENU_BACKGROUNDS, 2);
|
||||||
|
this.assertNotEqual(MENU_BACKGROUNDS[0].source, MENU_BACKGROUNDS[1].source);
|
||||||
|
this.assertNotEqual(MENU_BACKGROUNDS[0].class, MENU_BACKGROUNDS[1].class);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_random_pick_covers_both_ends() {
|
||||||
|
this.assertEqual(pickMenuBackground(() => 0), MENU_BACKGROUNDS[0]);
|
||||||
|
this.assertEqual(pickMenuBackground(() => 0.499), MENU_BACKGROUNDS[0]);
|
||||||
|
this.assertEqual(pickMenuBackground(() => 0.5), MENU_BACKGROUNDS[1]);
|
||||||
|
this.assertEqual(pickMenuBackground(() => 1), MENU_BACKGROUNDS[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_apply_swaps_the_class_on_the_body() {
|
||||||
|
const body = fakeBody();
|
||||||
|
applyMenuBackground(MENU_BACKGROUNDS[1], body);
|
||||||
|
this.assertTrue(body.classList.contains(MENU_BACKGROUNDS[1].class));
|
||||||
|
this.assertFalse(body.classList.contains(MENU_BACKGROUNDS[0].class));
|
||||||
|
|
||||||
|
applyMenuBackground(MENU_BACKGROUNDS[0], body);
|
||||||
|
this.assertTrue(body.classList.contains(MENU_BACKGROUNDS[0].class));
|
||||||
|
this.assertFalse(body.classList.contains(MENU_BACKGROUNDS[1].class));
|
||||||
|
}
|
||||||
|
|
||||||
|
async test_app_launch_picks_a_background() {
|
||||||
|
const env = await setupDom();
|
||||||
|
try {
|
||||||
|
await import(`../client/js/app.js?background=${Date.now()}`);
|
||||||
|
const classes = env.window.document.body.classList;
|
||||||
|
this.assert(
|
||||||
|
classes.contains("menu-bg-0") || classes.contains("menu-bg-1"),
|
||||||
|
"a background class is applied at launch"
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
teardownDom(env);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user