implement card waves for splash screen and tweak visuals
authorGeoffrey Allott <geoffrey@allott.email>
Sat, 17 Jun 2023 12:49:50 +0000 (13:49 +0100)
committerGeoffrey Allott <geoffrey@allott.email>
Sat, 17 Jun 2023 12:49:50 +0000 (13:49 +0100)
site/index.html
site/main.js
site/modules/random.js
site/modules/socket.js
site/modules/splash.js
site/style/splash.css

index f608a7cca70593970b650f018b01ee49c39cb005..5be42dcabfb515857873b40ada3a0df9e344ed8e 100644 (file)
@@ -6,7 +6,7 @@
         <script type="module" src="main.js"></script>
     </head>
     <body>
-        <div id="login-background">
+        <div id="login-background" class="hidden">
             <div id="login">
                 <label id="username-label" for="username-input">username</label>
                 <input id="username-input" />
index 5f065bbe0f3f47ec2fd6320b3e5c5dc9b6994f0c..0098b1056bc30bc8a7cd179c95c0d3ab123a977c 100644 (file)
@@ -19,6 +19,6 @@ window.onload = function() {
     const container = document.getElementById("game-tile-background");
     const splash_container = document.getElementById("splash-background");
     const splash = new SplashScreen(splash_container);
-    sockets.push(new Socket(container, login));
+    sockets.push(new Socket(container, login, splash));
     sockets[0].show_login();
 };
index 9e9b4ac785b6a7f78a9d518b975f8c43ec094e0b..e276f510fb190406f5d57a0eee779adc14035160 100644 (file)
@@ -1,3 +1,15 @@
 export function random_int(max) {
     return Math.floor(Math.random() * max);
 }
+
+export function random_float(min, max) {
+    return Math.random() * (max - min) + min;
+}
+
+export function random_sign() {
+    return Math.random() < 0.5 ? -1 : 1;
+}
+
+export function random_bool(p) {
+    return Math.random() < p;
+}
index 8102e3785ea2127e1c850b53d0f58c978ed40d37..0e11f0fffd8373d2f449cd078ed338b542db4b70 100644 (file)
@@ -15,9 +15,10 @@ function create_search_params(key_value_pairs) {
 }
 
 export class Socket {
-    constructor(container, login_all_sockets) {
+    constructor(container, login_all_sockets, splash) {
         this.container = container;
         this.login_all_sockets = login_all_sockets;
+        this.splash = splash;
         let proto = window.location.protocol === "https:" ? "wss:" : "ws:";
         let uri = proto + "//" + window.location.host + "/api";
         this.socket = new WebSocket(uri);
@@ -226,6 +227,7 @@ export class Socket {
     }
 
     hide_login() {
+        setTimeout(() => this.splash.hide(), 1200);
         document.getElementById("login-background").classList.add("hidden");
     }
 
index e4157dc2877323da0bd877b2dd0ede958a675bc5..94d6662a52a96956475afcfa48abb5e55a9fbe17 100644 (file)
@@ -1,6 +1,52 @@
 import { create_svg_element } from "./svg.js";
 import { card_href, FIFTY_TWO_CARD_DECK } from "./card.js";
-import { random_int } from "./random.js";
+import { random_float, random_bool, random_sign } from "./random.js";
+
+class CardWave {
+    constructor(svg, speed, height, slope, card_backs, initial_time) {
+        this.svg = svg;
+        this.timestep = 10;
+        this.speed = speed;
+        this.height = height;
+        this.slope = slope;
+        this.completed = false;
+
+        if (card_backs) {
+            this.cards = [...FIFTY_TWO_CARD_DECK].map(card => this.card_image(null));
+        } else {
+            this.cards = [...FIFTY_TWO_CARD_DECK].map(card => this.card_image(card));
+        }
+
+        this.schedule_frame(initial_time);
+    }
+
+    card_image(card) {
+        return create_svg_element(this.svg, card === null ? "image" : "use", [], [["width", "45"], ["height", "70"], ["x", "-100"], ["y", "215"], ["href", card_href(card)]]);
+    }
+
+    schedule_frame(time) {
+        this.render(time);
+        if (!this.completed) {
+            setTimeout(() => this.schedule_frame(time + this.timestep), this.timestep);
+        }
+    }
+
+    render(time) {
+        let x = time;
+        const initial_offset = this.speed > 0 ? -100 : 2100;
+        for (const card of this.cards) {
+            card.setAttribute("x", x * this.speed + initial_offset);
+            card.setAttribute("y", Math.sin(x * this.speed / this.slope) * this.height + 215);
+            x -= 40;
+        }
+        if (x > 2200 / Math.abs(this.speed)) {
+            this.completed = true;
+            for (const card of this.cards) {
+                this.svg.removeChild(card);
+            }
+        }
+    }
+}
 
 export class SplashScreen {
     constructor(container) {
@@ -8,15 +54,32 @@ export class SplashScreen {
         this.svg = create_svg_element(container, "svg", ["splash-screen"], [["viewBox", "0 0 2000 500"]]);
         this.hidden = false;
 
-        this.upper_bar = create_svg_element(this.svg, "rect", ["splash-upper-bar"], [["x", "0"], ["y", "0"], ["width", "2000"], ["height", "100"], ["fill", "blue"]]);
-        this.banner = create_svg_element(this.svg, "rect", [], [["x", "0"], ["y", "100"], ["width", "2000"], ["height", "300"], ["fill", "skyblue"]]);
-        this.lower_bar = create_svg_element(this.svg, "rect", ["splash-lower-bar"], [["x", "0"], ["y", "400"], ["width", "2000"], ["height", "100"], ["fill", "blue"]]);
+        this.upper_bar = create_svg_element(this.svg, "rect", ["splash-upper-bar"], [["x", "0"], ["y", "-10"], ["width", "2000"], ["height", "105"], ["fill", "#000064"], ["stroke", "skyblue"], ["stroke-width", "4px"]]);
+        this.banner = create_svg_element(this.svg, "rect", [], [["x", "0"], ["y", "90"], ["width", "2000"], ["height", "320"], ["fill", "skyblue"]]);
+        this.lower_bar = create_svg_element(this.svg, "rect", ["splash-lower-bar"], [["x", "0"], ["y", "405"], ["width", "2000"], ["height", "105"], ["fill", "#000064"], ["stroke", "skyblue"], ["stroke-width", "4px"]]);
+
+        this.wave_group = create_svg_element(this.svg, "g", [], []);
 
         this.logo = create_svg_element(this.svg, "text", ["splash-logo"], [["x", "1000"], ["y", "250"]]);
         this.logo_text = document.createTextNode("POKERWAVE");
         this.logo.append(this.logo_text);
 
         this.svg.onclick = () => this.hide();
+        this.waves = [];
+        this.card_wave(2000);
+        this.schedule_card_wave(2000);
+    }
+
+    card_wave(time) {
+        this.waves = this.waves.filter(wave => !wave.completed);
+        this.waves.push(new CardWave(this.wave_group, random_float(0.4, 0.7) * random_sign(), random_float(50, 200), random_float(50, 200), random_bool(0.3), time));
+    }
+
+    schedule_card_wave(time) {
+        if (!this.hidden) {
+            this.card_wave(time);
+            setTimeout(() => this.schedule_card_wave(0), 1500);
+        }
     }
 
     hide() {
index ce5f683172bb7133fab7e99454c1bffb5512a7fd..e5883286be7a0c75dca02ca8c50a4228452706bf 100644 (file)
@@ -19,7 +19,7 @@
 
 .splash-upper-bar {
     transform: none;
-    transition: transform 1s;
+    transition: transform ease-in 0.5s;
 }
 
 .splash-upper-bar.retract {
@@ -28,7 +28,7 @@
 
 .splash-lower-bar {
     transform: none;
-    transition: transform 1s;
+    transition: transform ease-in 0.5s;
 }
 
 .splash-lower-bar.retract {