Skip to content

Commit

Permalink
Improve loader
Browse files Browse the repository at this point in the history
  • Loading branch information
Half-Shot committed Feb 21, 2025
1 parent 7699ad1 commit 9058440
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 12 deletions.
6 changes: 1 addition & 5 deletions src/frontend/components/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
IRunningGameInstance,
LocalGameInstance,
} from "../../logic/gameinstance";
import { LoadingPage } from "./loading-page";

interface LoadGameProps {
scenario: string;
Expand Down Expand Up @@ -88,9 +87,7 @@ export function App() {
);

let root = null;
if (!assetsLoaded) {
root = null;
} else if (gameState) {
if (gameState) {
root = (
<IngameView
scenario={gameState.scenario}
Expand All @@ -112,7 +109,6 @@ export function App() {

return (
<MotionConfig reducedMotion={settings.reduceMotion ? "always" : "user"}>
<LoadingPage visible={!assetsLoaded} progress={assetProgress} />
{root}
</MotionConfig>
);
Expand Down
21 changes: 18 additions & 3 deletions src/frontend/components/atoms/loading.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { useEffect, useRef } from "preact/hooks";
import { useEffect, useRef, useState } from "preact/hooks";
import video from "../../../assets/ui/loading.webm";

const staticVideo = fetch(video, { priority: "high" }).then((v) => v.blob()).then((v) => URL.createObjectURL(v)).finally(() => {
console.log("Video load done");
});

const VIDEO_TIME_S = 3;

export function Loading({
Expand All @@ -13,13 +17,21 @@ export function Loading({
loadingDone: () => void;
}) {
const videoRef = useRef<HTMLVideoElement | null>(null);
const [videoSrc, setVideoSrc] = useState<string>();
useEffect(() => {
staticVideo.then((src) => setVideoSrc(src));
}, []);

useEffect(() => {
if (!videoRef.current) {
return;
}
videoRef.current.addEventListener("ended", () => {
loadingDone();
console.log("Loading ended");
if (videoRef.current?.currentTime === VIDEO_TIME_S) {
console.log("Loading Done");
loadingDone();
}
});
}, [videoRef]);

Expand All @@ -28,17 +40,20 @@ export function Loading({
return;
}
if (progress === undefined) {
console.log("No progress, playing at full rate");
videoRef.current.playbackRate = 2;
videoRef.current.play();
return;
}
const expectedProgress = VIDEO_TIME_S * progress;
const currentTime = videoRef.current.currentTime;
if (expectedProgress > currentTime) {
console.log("Progress behind", currentTime, expectedProgress);
videoRef.current.playbackRate =
expectedProgress - currentTime > 2 ? 3 : 1;
videoRef.current.play();
} else if (currentTime >= expectedProgress) {
console.log("Progress ahead of current time, pausing", currentTime, expectedProgress);
videoRef.current.pause();
}
}, [videoRef, progress]);
Expand All @@ -50,7 +65,7 @@ export function Loading({
style={{ maxWidth: "500px", width: "15vw" }}
className={className}
ref={videoRef}
src={video}
src={videoSrc}
controls={false}
preload="auto"
/>
Expand Down
17 changes: 17 additions & 0 deletions src/frontend/components/preloader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { assetLoadPercentage, assetsAreReady } from "../../assets";
import { useObservableEagerState } from "observable-hooks";
import { useGameSettingsHook } from "../../settings";
import { MotionConfig } from "framer-motion";
import { LoadingPage } from "./loading-page";

export function Preloader() {
const assetProgress = useObservableEagerState(assetLoadPercentage);
const assetsLoaded = useObservableEagerState(assetsAreReady);
const [settings] = useGameSettingsHook();

return (
<MotionConfig reducedMotion={settings.reduceMotion ? "always" : "user"}>
<LoadingPage visible={!assetsLoaded} progress={assetProgress} />
</MotionConfig>
);
}
25 changes: 21 additions & 4 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
// Ensure we load the video early.
import "./frontend/components/atoms/loading";
import { render } from "preact";
import "./index.css";
import { App } from "./frontend/components/app";
import { loadAssets } from "./assets";
import "core-js/actual/typed-array/from-base64";
import { useEffect, useState } from "preact/hooks";
import { Preloader } from "./frontend/components/preloader";
import type { App as AppType } from "./frontend/components/app";

void loadAssets();

render(<App />, document.getElementById("app") as HTMLElement);

function Main() {
const [AppImport, setApp] = useState<{ App: typeof AppType }>();
useEffect(() => {
void loadAssets();
// TODO: Error state.
import("./frontend/components/app").then((_app) => setApp(_app));
}, []);

return <>
<Preloader />
{AppImport ? <AppImport.App /> : null}
</>;
}

render(<Main />, document.getElementById("app") as HTMLElement);

0 comments on commit 9058440

Please sign in to comment.