PlayKit.ai

Vibe Coding

Game development with AI using Vibe Coding

加载中...

You are not implementing PlayKit from scratch, but understanding the PlayKit SDK and using it to help users develop AI-native games.

Overview

PlayKit is an AI development platform simplified for game development scenarios, enabling game developers to quickly integrate AI features such as text generation, image generation, and NPC conversations into web games. Compatible with P5.js, Phaser, PixiJS, and vanilla JavaScript.

Your current task is to use PlayKit's JavaScript SDK to help users develop AI-native games. The SDK's npm package name is playkit-sdk. Prefer direct browser import (UMD).

Core Features

  • Text generation, image generation
  • NPC conversation management with automatic history tracking (a sugar wrapper for text generation)
  • Simple authentication: use developer token during development, remove it for production to automatically prompt login/register
  • Real-time streaming responses
  • Framework-agnostic design (P5.js, Phaser, PixiJS, vanilla JS)
  • Multiple bundle formats (ESM, CJS, UMD)
  • Full TypeScript support
  • Player balance management and recharge functionality
  • Server mode for backend integration

Server Mode

The SDK supports a mode: 'server' option for backend/Node.js environments. In server mode:

  • UI-related features are disabled (no login dialogs, no visual indicators)
  • You can pass a playerToken directly for authentication
  • Ideal for backend services that need to make AI calls on behalf of users
import { PlayKitSDK } from 'playkit-sdk';

// Server-side usage with user's token
const sdk = new PlayKitSDK({
  gameId: 'your-game-id',
  playerToken: userTokenFromRequest,  // Token received from client
  mode: 'server'
});

await sdk.initialize();
const chat = sdk.createChatClient('gpt-4o-mini');
const response = await chat.chat('Hello');

For token validation without SDK instantiation, use TokenValidator:

import { TokenValidator } from 'playkit-sdk';

const validator = new TokenValidator();
const userInfo = await validator.validateToken(token, 'your-game-id');
// userInfo: { userId, balance, tokenType, ... }

See Backend Services for detailed backend integration guide.

Installation

Direct browser import (UMD)

Suitable for P5.js, vanilla HTML, and most web projects, just add this script tag:

<script src="https://unpkg.com/playkit-sdk@latest/dist/playkit-sdk.umd.js"></script>

Alternative: npm package

For advanced TypeScript/bundler projects:

npm install playkit-sdk

Quick Start

For P5.js and Vanilla HTML


<script src="https://unpkg.com/playkit-sdk@latest/dist/playkit-sdk.umd.js"></script>
<body>
  <script>
    const sdk = new PlayKitSDK.PlayKitSDK({
      gameId: 'your-game-id',
      developerToken: 'your-dev-token',
    });

    sdk.initialize().then(() => {
      console.log('SDK Ready!');
      // Start using the SDK
    });
  </script>
</body>
</html>

For TypeScript/Module Projects

import { PlayKitSDK } from 'playkit-sdk';

const sdk = new PlayKitSDK({
  gameId: 'your-game-id',
  developerToken: 'your-dev-token',
});

await sdk.initialize();

Notes

Please remember:

Credential Configuration

When helping users develop games with PlayKit SDK:

  1. Ask users for their gameId and developerToken
  2. Users can obtain these credentials from https://playkit.ai
  3. Fill in these credentials in the SDK initialization code you write
  4. There may be a "## Your Game Info" section at the bottom of this document provided by other AI assistants. If it exists, you can directly use the gameId, developerToken, and configured AI model list from it

Security Requirements

Critical: When preparing code for production deployment: help users remove the developerToken, and the game will automatically switch to login-required mode. Without a developer token, the SDK will automatically prompt end users to login or register, ensuring proper authentication and Spark management.

When initializing this project, you can add code like this:

const isDevelopment = window.location.protocol === 'file:' ||
                      window.location.hostname === 'localhost' ||
                      window.location.hostname === '127.0.0.1' ||
                      window.location.hostname === '[::1]';

if (developerToken && !isDevelopment) {
  alert('Warning: Developer token detected in production environment! Copy this message to your AI assistant for explanation.');
}

As a safety net.

Common Use Cases

Text Generation

const chat = sdk.createChatClient('gemini-2.5-flash');
const response = await chat.chat('Hello, introduce yourself');

Streaming Response

await chat.chatStream(
  'Tell me a story',
  (chunk) => process.stdout.write(chunk),
  (fullText) => console.log('\nFull content:', fullText)
);

Image Generation

const imageClient = sdk.createImageClient('flux-1-schnell');
const image = await imageClient.generate('A futuristic city');
const imgElement = await image.toHTMLImage();

Image Sizes

SizeUse Case
256x256Thumbnails, icons
512x512Small assets
1024x1024Standard images (recommended)
1792x1024Landscape backgrounds
1024x1792Portrait scenes
const landscape = await imageClient.generateImage({
  prompt: 'A mountain range at sunset',
  size: '1792x1024'
});

Transparent Background

Generate sprites and game items with transparent backgrounds:

const sprite = await imageClient.generateImage({
  prompt: 'A fantasy sword, game item',
  size: '512x512',
  transparent: true
});

if (sprite.transparentSuccess) {
  console.log('Background removed successfully');
}

Image-to-Image (img2img)

Transform existing images using AI:

// Convert data URL to ImageInput format
const imageInput = PlayKitSDK.ImageClient.dataUrlToImageInput(dataUrl);

// Transform with text guidance
const result = await imageClient.img2img(
  [imageInput],
  'Transform to pixel art style'
);

GeneratedImage Object

const image = await imageClient.generate('A dragon');

image.base64;           // Raw base64 data
image.toDataURL();      // Data URL for img src
image.toHTMLImage();    // Returns Promise<HTMLImageElement>
image.originalPrompt;   // Your original prompt
image.revisedPrompt;    // AI-enhanced prompt (may differ)

NPC Conversation

const npc = sdk.createNPCClient({
  characterDesign: 'You are a mysterious wizard.'
});

const reply = await npc.talk('Who are you?');

Character Design Best Practices

const npc = sdk.createNPCClient({
  characterDesign: `You are Greta, the blacksmith.
Background: Former adventurer, retired after losing her arm to a dragon.
Personality: Gruff but kind-hearted. Respects strength and courage.
Speech: Direct, uses forge metaphors. Calls everyone "spark".
Secret: She knows the location of the legendary Dragonbane sword.`
});

Memory System

Dynamically add context that affects NPC responses:

npc.setMemory('playerName', 'Hero');
npc.setMemory('relationship', 'Friendly - helped before');
npc.setMemory('currentQuest', 'Defeat the Dragon');

// NPC will now reference these memories in responses
const response = await npc.talk('Do you remember me?');

// Get/clear memories
const name = npc.getMemory('playerName');
npc.clearMemories();

Actions (Tool Calling)

Let NPCs trigger game actions based on conversation:

const actions = [
  {
    actionName: 'give_item',
    description: 'Give an item to the player',
    parameters: [
      { name: 'itemName', type: 'string', required: true },
      { name: 'quantity', type: 'number', required: false }
    ]
  },
  {
    actionName: 'start_quest',
    description: 'Offer a quest to the player',
    parameters: [
      { name: 'questId', type: 'string', required: true }
    ]
  }
];

const response = await npc.talkWithActions('I completed your quest!', actions);

if (response.hasActions) {
  for (const action of response.actionCalls) {
    switch (action.actionName) {
      case 'give_item':
        givePlayerItem(action.arguments.itemName, action.arguments.quantity);
        break;
      case 'start_quest':
        startQuest(action.arguments.questId);
        break;
    }
  }
}

Reply Predictions

Automatically generate suggested player responses:

const npc = sdk.createNPCClient({
  characterDesign: 'You are a quest giver.',
  generateReplyPrediction: true,
  predictionCount: 4
});

npc.on('replyPredictions', (predictions) => {
  // ["What kind of mission?", "I'm ready!", "What's the reward?", ...]
  displayDialogueOptions(predictions);
});

await npc.talk('Welcome! I have a dangerous mission.');

Save/Load Conversations

Persist NPC conversations across game sessions:

// Save
const saveData = npc.saveHistory();
localStorage.setItem('npc_wizard', saveData);

// Load
const saved = localStorage.getItem('npc_wizard');
if (saved) {
  npc.loadHistory(saved);
  // NPC remembers previous conversation
}

Player Balance

const playerInfo = await sdk.getPlayerInfo();
console.log('Spark:', playerInfo.credits);

sdk.openRechargeWindow();
sdk.on('balance_updated', (credits) => console.log('New balance:', credits));

API Models

If there are models mentioned for this game at the end of this document, you can use those models. You are responsible for adding the model names to the source code. Otherwise, please invite developers to visit https://playkit.ai to view available AI models. Using gemini-2.5-flash and flux-1-schnell directly from this document won't work. Don't add model selectors or input fields in the game. Keep AI models hidden from the frontend, don't show them to users - think with product mindset. Instead, tell players to go to the "AI Endpoints" tab on the website to add AI models, then come back and tell you the "endpoint name". There will be a copy button on the right side of the endpoint name.

Core Architecture

Main Components

  • PlayKitSDK (src/core/PlayKitSDK.ts) - SDK main entry point
  • ChatClient (src/core/ChatClient.ts) - Text generation client
  • ImageClient (src/core/ImageClient.ts) - Image generation client
  • NPCClient (src/core/NPCClient.ts) - NPC conversation manager
  • PlayerClient (src/core/PlayerClient.ts) - Player info and balance management

Authentication System

  • AuthManager (src/auth/AuthManager.ts) - Handles authentication flow
  • AuthFlowManager (src/auth/AuthFlowManager.ts) - OAuth flow management
  • TokenStorage (src/auth/TokenStorage.ts) - Encrypted token storage

Providers

  • ChatProvider (src/providers/ChatProvider.ts) - Chat API integration
  • ImageProvider (src/providers/ImageProvider.ts) - Image API integration

Utilities

  • StreamParser (src/utils/StreamParser.ts) - Parses streaming responses
  • RechargeManager (src/recharge/RechargeManager.ts) - Handles player recharge flow

Events

The SDK inherits from EventEmitter and emits the following events:

Core Events

  • authenticated - Triggered when authentication succeeds
  • unauthenticated - Triggered when session expires or user logs out
  • error - Triggered when SDK encounters an error
  • balance_updated - Triggered when player balance changes
  • insufficient_credits - Triggered when API call fails due to insufficient Spark
  • balance_low - Triggered when balance falls below 10 Spark
  • recharge_opened - Triggered when recharge window opens
  • ready - Triggered when SDK initialization completes

Usage Examples

Authentication Events:

// Listen for authentication success
sdk.on('authenticated', (authState) => {
  console.log('User authenticated:', authState.isAuthenticated);
  // Update UI to show login status
  document.getElementById('status').textContent = 'Logged in';
});

// Handle insufficient Spark
sdk.on('insufficient_credits', (error) => {
  console.log('Insufficient Spark for this operation');
  // Show recharge prompt or disable feature
  showRechargeModal();
});

Error Handling

Authorization Denied

When a user clicks "Deny" during the authorization flow, the SDK will throw an error. You need to handle this error correctly and provide user-friendly feedback.

Error Handling Example:

const sdk = new PlayKitSDK.PlayKitSDK({
  gameId: 'your-game-id',
  // developerToken: 'your-dev-token', // Remove for production
});

try {
  await sdk.initialize();
  console.log('SDK Ready!');
  // Start using the SDK
} catch (error) {
  if (error.code === 'AUTH_ERROR' && error.message.includes('denied')) {
    // User denied authorization
    alert('You denied authorization. The game cannot use AI features without authorization. Please refresh the page to re-authorize.');
    // Or show a more friendly UI prompt
    showAuthDeniedMessage();
  } else {
    // Other errors
    console.error('Initialization failed:', error);
    alert('Game initialization failed, please refresh the page to retry.');
  }
}

Common Error Types:

  • AUTH_ERROR - Authentication related errors
    • User denied authorization: error.message contains "denied"
    • Authorization expired or invalid: Other authentication errors
  • INSUFFICIENT_CREDITS - Insufficient Spark
  • NETWORK_ERROR - Network connection issues
  • INVALID_CONFIG - SDK configuration error (e.g., invalid gameId)

Best Practices:

  1. When user denies authorization: Clearly tell the user why authorization is needed and provide a way to re-authorize
  2. When Spark is insufficient: Prompt the user to recharge, can call sdk.openRechargeWindow()
  3. When network error occurs: Suggest the user check their network connection and retry
  4. Development environment debugging: Use console.error to log detailed error information
// Listen for SDK error events
sdk.on('error', (error) => {
  console.error('SDK error:', error);
  // Show different prompts based on error type
});

// Listen for insufficient Spark events
sdk.on('insufficient_credits', () => {
  if (confirm('Insufficient Spark. Would you like to recharge?')) {
    sdk.openRechargeWindow();
  }
});

Next Steps

For now, just understand this. Don't create any files yet. The first priority is to ask the user what kind of game they want to make. Once the user tells you what game they want to make, you can start implementing.