Skip to content

Commit

Permalink
[feat] Loading menus now appear on startup and on game load.
Browse files Browse the repository at this point in the history
  • Loading branch information
Half-Shot committed Feb 19, 2025
1 parent 0b84982 commit 5605b31
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 23 deletions.
11 changes: 9 additions & 2 deletions src/frontend/components/atoms/loading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export function Loading({
className,
loadingDone,
}: {
progress: number;
progress?: number;
className?: string;
loadingDone: () => void;
}) {
Expand All @@ -27,6 +27,11 @@ export function Loading({
if (!videoRef.current) {
return;
}
if (progress === undefined) {
videoRef.current.playbackRate = 2;
videoRef.current.play();
return;
}
const expectedProgress = VIDEO_TIME_S * progress;
const currentTime = videoRef.current.currentTime;
if (expectedProgress > currentTime) {
Expand All @@ -38,14 +43,16 @@ export function Loading({
}
}, [videoRef, progress]);

// Always play muted, because it prevents browsers blocking the animation.
return (
<video
muted
style={{ maxWidth: "500px", width: "15vw" }}
className={className}
ref={videoRef}
src={video}
controls={false}
preload="auto"
></video>
/>
);
}
37 changes: 26 additions & 11 deletions src/frontend/components/ingame-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import styles from "./ingame-view.module.css";
import { Game } from "../../game";
import { AmmoCount, GameReactChannel } from "../../interop/gamechannel";
import { WeaponSelector } from "./gameui/weapon-select";
import { IRunningGameInstance } from "../../logic/gameinstance";
import { IRunningGameInstance, LocalGameInstance } from "../../logic/gameinstance";
import { LoadingPage } from "./loading-page";

export function IngameView({
scenario,
Expand All @@ -16,21 +17,35 @@ export function IngameView({
gameReactChannel: GameReactChannel;
gameInstance: IRunningGameInstance;
}) {
const [hasLoaded, setLoaded] = useState<boolean>(false);
const [fatalError, setFatalError] = useState<Error>();
const [game, setGame] = useState<Game>();
const ref = useRef<HTMLDivElement>(null);
const [weaponMenu, setWeaponMenu] = useState<AmmoCount | null>(null);
useEffect(() => {
Game.create(window, scenario, gameReactChannel, gameInstance, level)
.then((game) => {
(window as unknown as { wormgine: Game }).wormgine = game;
game.loadResources().then(() => {
setGame(game);
});
})
.catch((ex) => {
setFatalError(ex);

async function init() {
if (gameInstance instanceof LocalGameInstance) {
// XXX: Only so the game feels more responsive by capturing this inside the loading phase.
await gameInstance.startGame();
console.log("Game started");
}
const game = await Game.create(window, scenario, gameReactChannel, gameInstance, level);
setGame(game);
game.ready$.subscribe(r => {
if (r) {
console.log("Game loaded");
setLoaded(true);
}
});
// Bind the game to the window such that we can debug it.
(globalThis as unknown as { wormgine: Game }).wormgine = game;
await game.loadResources();
}

void init().catch((ex) => {
setFatalError(ex);
});
}, []);

useEffect(() => {
Expand All @@ -42,7 +57,6 @@ export function IngameView({
return;
}

// Bind the game to the window such that we can debug it.
ref.current.appendChild(game.canvas);
game.run().catch((ex) => {
setFatalError(ex);
Expand Down Expand Up @@ -85,6 +99,7 @@ export function IngameView({

return (
<>
<LoadingPage visible={!hasLoaded} force />
<div id="overlay" className={styles.overlay}>
<WeaponSelector
weapons={weaponMenu}
Expand Down
17 changes: 13 additions & 4 deletions src/frontend/components/loading-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ import { useAnimate } from "framer-motion";
export function LoadingPage({
progress,
visible,
force,
}: {
visible: boolean;
progress: number;
progress?: number;
/**
* Force hiding the loading bar when visible is false */
force?: boolean;
}) {
const [scope, animate] = useAnimate();
const [isLoadingDone, setLoadingDone] = useState(false);
const [shouldOverlay, setShouldOverlay] = useState(true);

useEffect(() => {
if (!scope.current) {
Expand All @@ -24,17 +29,21 @@ export function LoadingPage({
{ opacity: 1 },
{ delay: 0, duration: 0.25, ease: "easeIn" },
);
} else if (isLoadingDone) {
} else if (isLoadingDone || force) {
await animate(
scope.current,
{ opacity: 0 },
{ delay: 0.5, duration: 0.5, ease: "easeIn" },
);
console.log("safetoremove");
setShouldOverlay(false);
}
}
void runAnim();
}, [visible, isLoadingDone, scope.current]);
}, [visible, force, isLoadingDone, scope.current]);

if (!shouldOverlay) {
return null;
}

return (
<>
Expand Down
8 changes: 4 additions & 4 deletions src/frontend/components/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ function mainMenu(
<span onMouseOver={videoHover} onMouseOut={videoHoverOut}>
Skirmish
</span>
<video src={settingsAnim} loop />
<video muted src={settingsAnim} loop />
</button>
</li>
<li>
Expand All @@ -107,7 +107,7 @@ function mainMenu(
<span onMouseOver={videoHover} onMouseOut={videoHoverOut}>
Team Editor
</span>
<video src={settingsAnim} loop />
<video muted src={settingsAnim} loop />
</button>
</li>
<li>
Expand All @@ -120,7 +120,7 @@ function mainMenu(
<span onMouseOver={videoHover} onMouseOut={videoHoverOut}>
Online Play
</span>
<video src={settingsAnim} loop />
<video muted src={settingsAnim} loop />
</button>
</li>
<li>
Expand All @@ -133,7 +133,7 @@ function mainMenu(
<span onMouseOver={videoHover} onMouseOut={videoHoverOut}>
Settings
</span>
<video src={settingsAnim} loop />
<video muted src={settingsAnim} loop />
</button>
</li>
</ul>
Expand Down
1 change: 0 additions & 1 deletion src/frontend/components/menus/lobby.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,6 @@ function LocalLobby({ onOpenIngame, exitToMenu }: Omit<Props, "client">) {
<ActiveLobby
gameInstance={gameInstance}
onOpenIngame={() => {
gameInstance.startGame();
onOpenIngame(gameInstance);
}}
exitToMenu={exitToMenu}
Expand Down
5 changes: 4 additions & 1 deletion src/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import Logger from "./log";
import { CriticalGameError } from "./errors";
import { getGameSettings } from "./settings";
import { NetGameWorld } from "./net/netGameWorld";
import { debounceTime, fromEvent, map, merge, Observable, of } from "rxjs";
import { BehaviorSubject, debounceTime, fromEvent, map, merge, Observable, of } from "rxjs";
import { IRunningGameInstance } from "./logic/gameinstance";
import { RunningNetGameInstance } from "./net/netgameinstance";

Expand All @@ -29,6 +29,8 @@ export class Game {
public readonly world: GameWorld;
public readonly rapierGfx: Graphics;
public readonly screenSize$: Observable<{ width: number; height: number }>;
private readonly ready = new BehaviorSubject(false);
public readonly ready$ = this.ready.asObservable() ;

public get pixiRoot() {
return this.viewport;
Expand Down Expand Up @@ -124,6 +126,7 @@ export class Game {
undefined,
);
this.pixiApp.stage.addChildAt(this.rapierGfx, 0);
this.ready.next(true);

// Run physics engine at 90fps.
const tickEveryMs = 1000 / 90;
Expand Down

0 comments on commit 5605b31

Please sign in to comment.