Skip to content

create youtube playables template #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ const FRAMEWORKS: Framework[] = [
display: "Web",
color: yellow,
},
{
name: "creation-youtube",
display: "YouTube",
color: red,
},
// {
// name: "creation-discord",
// display: "Discord",
Expand All @@ -139,11 +144,6 @@ const FRAMEWORKS: Framework[] = [
// display: "Facebook",
// color: blueBright,
// },
// {
// name: "creation-youtube",
// display: "YouTube",
// color: red,
// },
],
},
{
Expand Down
121 changes: 121 additions & 0 deletions templates/template-creation-youtube/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# PixiJS YouTube Playables Template

This template provides a starting point for creating YouTube Playable games using PixiJS. It includes the YouTube Playables SDK integration and a convenient plugin system to handle all YouTube-specific functionality.

## Features

- Full YouTube Playables SDK integration
- Built-in plugin for handling YouTube game lifecycle
- TypeScript support
- Asset management system
- Audio support with automatic pause/resume
- Responsive design

## Getting Started

1. Create a new project using this template:
```bash
npm create pixi@latest
```
2. Name your project and choose the "Youtube" template under "Creation Templates"

3. Then simply run:
```bash
cd <PROJECT_NAME>
npm install
npm run dev
```

4. Test your game in the YouTube SDK Test Suite:
- Go to [YouTube Playables Test Suite](https://developers.google.com/youtube/gaming/playables/test_suite)
- Enter `http://localhost:8080` as the Game URL
- Test your game's integration with the YouTube SDK

## User Settings & Persistence

This template saves user settings and game state **persistently** using the official YouTube Playables API (`ytgame.game.saveData`/`loadData`) when running in the Playables environment, and falls back to `localStorage` for local development/testing.

All settings are stored as a single JSON object. The provided `StorageWrapper` class exposes an async API for getting and setting values of various types:

```typescript
// Get/set a string value
await storage.setString('username', 'Alice');
const username = await storage.getString('username');

// Get/set a number value
await storage.setNumber('highScore', 12345);
const score = await storage.getNumber('highScore');

// Get/set a boolean value
await storage.setBool('musicEnabled', true);
const musicEnabled = await storage.getBool('musicEnabled');

// Get/set an object
await storage.setObject('settings', { volume: 0.5, theme: 'dark' });
const settings = await storage.getObject<{ volume: number; theme: string }>('settings');
```

### How it works
- In YouTube Playables: Uses `ytgame.game.saveData` and `ytgame.game.loadData` for persistence.
- Locally: Falls back to `localStorage` using a single key (`user_settings`).
- All storage APIs are **async** and should be awaited.

### Example: Saving and Loading User Settings
```typescript
// Save settings
await storage.setObject('user', { masterVolume: 0.8, sfxVolume: 0.5 });

// Load settings
const userSettings = await storage.getObject<{ masterVolume: number; sfxVolume: number }>('user');
```

## YouTube Plugin Usage

The template includes a `YouTubePlugin` for Playables-specific features:

```typescript
import { engine } from "../../getEngine";

// The plugin is automatically initialized with the engine

const currentScore = await engine().youtube.getScore();

if (add) {
this.score += 1;
} else if (this.score > 0) {
this.score -= 1;
}

// Update display
this.updateScoreDisplay();

// Submit to YouTube
await engine().youtube.submitScore(currentScore);
```

## Project Structure

- `src/engine/youtube/YouTubePlugin.ts` - YouTube integration plugin
- `src/app/screens/` - Game screens (LoadScreen, MainScreen)
- `src/app/ui/` - UI components
- `src/app/popups/` - Popup components
- `raw-assets/` - Source assets
- `public/` - Static assets and styles


## YouTube Playables Requirements

Make sure your game follows YouTube's requirements:

1. SDK loaded before any game code
2. Initial bundle < 15 MiB
3. firstFrameReady called before gameReady
4. gameReady called
5. Cloud save data < 3 MiB
6. JS heap size < 512 MiB

## Documentation

- [YouTube Playables SDK Documentation](https://developers.google.com/youtube/gaming/playables/reference/sdk)
- [PixiJS Documentation](https://pixijs.com/docs)

28 changes: 28 additions & 0 deletions templates/template-creation-youtube/_gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

public/assets
.assetpack
src/manifest.json
15 changes: 15 additions & 0 deletions templates/template-creation-youtube/eslint__config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import js from "@eslint/js";
import tseslint from "typescript-eslint";

export default tseslint.config(
{ ignores: ["dist"] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ["**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: "latest",
sourceType: "module",
},
rules: {},
},
);
19 changes: 19 additions & 0 deletions templates/template-creation-youtube/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/png" href="/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/style.css">
<title>PixiJS - Template</title>
</head>

<body>
<div id="app">
<div id="pixi-container"></div>
</div>
<!-- YouTube Playables SDK must be loaded before any game code. -->
<script src="https://www.youtube.com/game_api/v1"></script>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
27 changes: 27 additions & 0 deletions templates/template-creation-youtube/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "template-creation-youtube",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"start": "npm run dev",
"build": "npm run lint && tsc && vite build",
"lint": "eslint .",
"dev": "vite"
},
"dependencies": {
"@esotericsoftware/spine-pixi-v8": "^4.2.74",
"@pixi/sound": "^6.0.1",
"@pixi/ui": "^2.2.2",
"motion": "^12.4.7",
"pixi.js": "^8.8.1"
},
"devDependencies": {
"@assetpack/core": "^1.4.0",
"@eslint/js": "^9.21.0",
"eslint": "^9.21.0",
"typescript": "~5.7.3",
"typescript-eslint": "^8.25.0",
"vite": "^6.2.0"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions templates/template-creation-youtube/public/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
body {
margin: 0;
padding: 0;
color: rgba(255, 255, 255, 0.87);
background-color: #000000;
}

#app {
width: 100%;
height: 100vh;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading