> For the complete documentation index, see [llms.txt](https://docs.reneverse.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.reneverse.io/publisher-flow/sdk-integration/phaser-3/full-implementation-code.md).

# Full Implementation (Code)

```typescript
import { useRef } from "react";
import { IRefPhaserGame, PhaserGame } from "./game/PhaserGame";
import { useState } from "react";
import { PhaserHooks } from "@reneverse/rene-sdk-phaser";

function App() {
  //  References to the PhaserGame component (game and scene are exposed)
  const phaserRef = useRef<IRefPhaserGame | null>(null);

  // Initialize PhaserHooks with API Key and Private Key for ReneVerse
  const phaserHooks = new PhaserHooks({
    apiKey: process.env.NEXT_PUBLIC_API_KEY as string,
    privateKey: process.env.NEXT_PUBLIC_PRIVATE_KEY as string,
  });

  // Array to store adsf
  const [ads, setAds] = useState<any[]>([]);

  // Map to store ad impressions
  const [adImpressions, setAdImpressions] = useState<
    Map<
      string,
      {
        adCoverage: number;
        impressions: number;
      }
    >
  >(new Map());

  const serveAd = async () => {
    if (phaserRef.current) {
      const scene = phaserRef.current.scene;

      if (scene) {
        // Fetch Ad surfaces
        const adSurfaces = await phaserHooks.useReneVerse().getAdSurfaces();

        if (!adSurfaces.items.length) {
          console.log("No ad surfaces found");
          return;
        }

        // Fetch Ad from ReneVerse
        const ad = await phaserHooks
          .useReneVerse()
          .getAd(adSurfaces.items[0].adSurfaceId);

        console.log("Ad served", ad);

        // Load Ad image
        if (ad.adId) {
          // Add ad to the list
          setAds((prevAds) => [...prevAds, ad]);

          // Add ad to the impressions map
          setAdImpressions((prevImpressions) => {
            const newImpressions = new Map(prevImpressions);
            newImpressions.set(ad.adId!, {
              adCoverage: 0, // Initial coverage
              impressions: 0, // Initial impressions
            });
            return newImpressions;
          });

          scene.load.image("dynamicAd", ad.url as string);

          scene.load.once("complete", () => {
            // Add more stars
            const x = Phaser.Math.Between(100, 900);
            const y = Phaser.Math.Between(100, 600);

            //  `add.sprite` is a Phaser GameObjectFactory method and it returns a Sprite Game Object instance
            const adSurface = scene.add.sprite(x, y, "dynamicAd");

            // Set display size
            adSurface.setDisplaySize(300, 200);

            // Check visibility of the ad
            const trackAdVisibility = async () => {
              // Check if Ad is fully visible
              const visibilityCheck = phaserHooks
                .useTracking()
                .checkAdFullVisibility(adSurface, scene);

              if (visibilityCheck.isFullyVisible) {
                console.log(`Ad ${ad.adId} is fully visible`);

                // if Fully visible, calculate ad coverage
                const adCoverage = phaserHooks
                  .useTracking()
                  .calculateAdCoverage(adSurface, scene.cameras.main);

                console.log(adCoverage);

                // Track Ad
                const trackAds = await phaserHooks
                  .useReneVerse()
                  .trackAdSingle(
                    ad,
                    adCoverage.screenCoveragePercentage,
                    1000,
                    0
                  );

                if (trackAds) {
                  // If tracking is successful, update ad impressions
                  setAdImpressions((prevImpressions) => {
                    const newImpressions = new Map(prevImpressions);
                    const currentImpressionData = newImpressions.get(
                      ad.adId!
                    ) || {
                      adCoverage: 0,
                      impressions: 0,
                    };

                    newImpressions.set(ad.adId!, {
                      adCoverage: adCoverage.screenCoveragePercentage,
                      impressions: currentImpressionData.impressions + 1,
                    });

                    return newImpressions;
                  });
                } else {
                  console.log(`Failed to track ad ${ad.adId}`);
                }
              } else {
                // Ad is partially or fully blocked
                console.log(
                  `Ad ${ad.adId} is blocked by ${visibilityCheck.blockingSprites.length} sprites`,
                  {
                    blockingSprites: visibilityCheck.blockingSprites.map(
                      (sprite: any) => sprite.name || "Unnamed Sprite"
                    ),
                  }
                );
              }
            };

            // Track visibility every second
            const visibilityInterval = scene.time.addEvent({
              delay: 1000, // Check every second
              callback: trackAdVisibility,
              loop: true,
            });

            // Stop tracking after 5 minutes
            scene.time.delayedCall(5 * 60 * 1000, () => {
              visibilityInterval.remove();
              console.log(`Stopped tracking ad ${ad.adId}`);
            });
          });
        }
        scene.load.start();
      }
    }
  };

  return (
    <div className="parent">
      <PhaserGame ref={phaserRef} />

      <div className="stats">
        <button className="button" onClick={serveAd}>
          Serve Ad
        </button>

        <div>
          Total Ads: {ads.length} <br />
          Total Coverage:{" "}
          {Array.from(adImpressions.values())
            .reduce((acc, curr) => acc + curr.adCoverage, 0)
            .toFixed(2)}{" "}
          <br />
          Total Impressions:{" "}
          {Array.from(adImpressions.values()).reduce(
            (acc, curr) => acc + curr.impressions,
            0
          )}
        </div>
      </div>
    </div>
  );
}

export default App;

```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.reneverse.io/publisher-flow/sdk-integration/phaser-3/full-implementation-code.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
