LogoPixi’VN

Minigiochi

Guida all'integrazione di minigiochi in Pixi'VN, incluse le best practice, la gestione del ciclo di vita e implementazioni di esempio utilizzando PixiJS e React.

IA

Puoi usare il pulsante qui sopra per creare il tuo minigioco, con l'IA.

Il bello di una storia interattiva rispetto al testo normale è che puoi prenderti una pausa e interagire con i minigiochi correlati alla storia.

I minigiochi nelle visual novel vengono solitamente avviati durante la narrazione. To switch between the narrative UI and the minigame UI, it is recommended to link the minigame to a route (e.g., "/minigame/snake") and navigate to it from the story. Ulteriori informazioni sono disponibili qui.

Ecco alcuni consigli:

  • Use PixiJS directly — either the pixi.js package itself or the @drincs/pixi-vn/pixi.js submodule that re-exports it — with components such as Graphics, Sprite, and Text, combined with PixiJS Layers to create a separate layer for your minigame, managed independently from the main visual novel interface.
  • Use hotkeys to handle keyboard input for your minigame controls. See Hotkeys to learn how to set them up.
  • It is always recommended not to use PixiJS to build the UI (buttons, score displays, game over messages, ...); use a framework such as React or Vue instead.
  • Saving and restoring the minigame's current state is the developer's responsibility.
  • Since a minigame is its own route, a project usually ends up with more than one of them under the same /minigame path (e.g. /minigame/snake, /minigame/quiz); use TanStack Router's file-based routing to share logic between them instead of duplicating it in every minigame (see below).
  • Starting a minigame is nothing more than navigating to its route from the story; if it needs a parameter (a difficulty, a level id, ...), pass it through that same route (see below).

Modelli

useMinigame è un hook personalizzato che ti aiuta a gestire il ciclo di vita di un minigioco, inclusi l'avvio, l'aggiornamento e la pulizia delle risorse. È presente in tutti i template.

Ad esempio:

src/routes/minigame/example.tsx
import { Layer } from "@drincs/pixi-vn";
import { Graphics, Ticker } from "@drincs/pixi-vn/pixi.js";
import { createFileRoute } from "@tanstack/react-router";
import { useCallback, useMemo, useState } from "react";
import { useHotkey } from "@tanstack/react-hotkeys";
import useMinigame from "@/lib/hooks/minigame-hooks";

export const Route = createFileRoute("/minigame/example")({
    component: MiniGame,
});

function MiniGame() {
    const [displayScore, setDisplayScore] = useState(0);
    const [gameOver, setGameOver] = useState(false);

    const ticker = useMemo(() => {
        const ticker = new Ticker();

        const endGame = () => {
            ticker.stop();
            setGameOver(true);
        };

        ticker.add(({ deltaMS }) => {
            // Update game logic here
        });

        return ticker;
    }, []);

    useHotkey(
        "ArrowUp",
        () => {
            // Handle key down events for game controls
        },
        { enabled: !gameOver },
    );

    const game = useCallback(
        (layer: Layer) => {
            ticker.start();
        },
        [ticker], // They must not be changed during the game otherwise the game will restart
    );

    const options = useMemo(
        () => ({
            onExit() {
                ticker.stop();
                ticker.destroy();
            },
        }),
        [ticker], // They must not be changed during the game otherwise the game will restart
    );

    const { loading } = useMinigame(game, options);

    return (
        <>
            <div
                style={{
                    position: "absolute",
                    top: 10,
                    left: 10,
                    color: "white",
                    fontSize: "24px",
                    background: "rgba(0,0,0,0.5)",
                    padding: "5px 10px",
                    borderRadius: "5px",
                }}
            >
                Score: {displayScore}
            </div>

            {gameOver && (
                <div
                    style={{
                        position: "absolute",
                        top: "50%",
                        left: "50%",
                        transform: "translate(-50%, -50%)",
                        color: "red",
                        fontSize: "48px",
                        background: "rgba(0,0,0,0.7)",
                        padding: "20px 40px",
                        borderRadius: "10px",
                    }}
                >
                    GAME OVER
                </div>
            )}
        </>
    );
}

Examples

Il team di Pixi’VN accoglie con favore nuove proposte e contributi per rendere questa biblioteca ancora più completa. Feel free to share or propose your minigame implementations in the chat below!

In questa pagina