### Install Dependencies and Run Development Server
Source: https://github.com/instructa/viber3d/blob/main/CONTRIBUTE.md
Install project dependencies using pnpm and start the development server. The server will be accessible at http://localhost:5173.
```bash
pnpm install
pnpm run dev
```
--------------------------------
### Initialize a new Viber3D project using the CLI
Source: https://context7.com/instructa/viber3d/llms.txt
Use the `viber3d init` command to create a new project. Interactive setup is recommended. You can also use flags for non-interactive setup, custom templates, or to skip dependency installation.
```bash
npx viber3d@latest init
```
```bash
npx viber3d@latest init my-game --defaults
```
```bash
npx viber3d@latest init my-game --template username/my-template
```
```bash
npx viber3d@latest init my-game --template next
```
```bash
npx viber3d@latest init my-game --yes --packageManager pnpm --gitInit
```
--------------------------------
### Start Development Server
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/README.md
Start the development server on http://localhost:3000 using npm, pnpm, yarn, or bun.
```bash
# npm
npm run dev
# pnpm
pnpm dev
# yarn
yarn dev
# bun
bun run dev
```
--------------------------------
### Install viber3d Project with CLI
Source: https://github.com/instructa/viber3d/blob/main/templates/starter/README.md
Use this command to create a new viber3d project. Do not install the package directly; the CLI ensures a complete setup.
```bash
npx viber3d@latest my-project
```
--------------------------------
### Install Project Dependencies
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/6.contributing/1.intro.md
Install all necessary project dependencies using pnpm.
```bash
pnpm install
```
--------------------------------
### Install Dependencies
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/README.md
Install project dependencies using npm, pnpm, yarn, or bun.
```bash
# npm
npm install
# pnpm
pnpm install
# yarn
yarn install
# bun
bun install
```
--------------------------------
### Install Viber3D
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/index.md
Install the Viber3D package using npm. This command installs the latest version of the library.
```bash
npm install @instructa/viber3d
```
--------------------------------
### Run Development Server
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/7.usage.md
Start your development server using npm or yarn to see your Viber3D application in action.
```bash
npm run dev
# or
yarn dev
```
--------------------------------
### Install Dependencies for Viber3D
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/7.usage.md
Install the necessary libraries for Viber3D, React, Three.js, and optionally a physics engine like Jolt.
```bash
yarn add react react-dom three @react-three/fiber @react-three/drei koota
```
```bash
yarn add jolt-physics
```
--------------------------------
### Example MDC File for React Component Rules
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/3.development/3.cursor-rules.md
This example shows the front matter and Markdown content for an .mdc file defining rules for React components, including guidelines for functional components, ECS data flow with Koota, and system logic placement.
```markdown
---
description: React Component Rules
globs: *.tsx
---
# React Component Guidelines
- Use functional components
- Implement ECS data flow with Koota (no direct game logic in components)
- Keep all game logic in systems, not `useFrame`
```
--------------------------------
### Install Viber3D CLI with npx
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/4.cli.md
Use npx to run the Viber3D CLI without global installation. This is useful for executing commands directly.
```bash
npx viber3d@latest [command]
```
--------------------------------
### Run viber3d Project
Source: https://github.com/instructa/viber3d/blob/main/README.md
Commands to start the development server for your viber3d project. Access the app at http://localhost:5173.
```bash
npm run dev
# or
pnpm run dev
```
--------------------------------
### Start Development Server with Hot Reload
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/3.development/1.running-dev-server.md
Run this command in your terminal to start the development server. It enables hot module replacement (HMR) and provides real-time error feedback.
```bash
npm run dev
```
--------------------------------
### Viber3D Project Structure Example
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/3.project-structure.md
This Bash snippet illustrates a typical directory and file layout for a Viber3D project, including common subdirectories for assets, components, systems, traits, and utilities, as well as core application files.
```bash
viber3d/
├── src
│ ├── assets/ # 3D models, textures, images
│ ├── components/ # React components for rendering 3D objects/UI
│ ├── systems/ # ECS Systems for game logic updates
│ ├── traits/ # ECS Traits (components) describing entity data
│ ├── utils/ # Utility functions (math, sorting, spatial hashing)
│ ├── actions.ts # Central actions to spawn or modify entities
│ ├── app.tsx # Main React component (root of your 3D scene)
│ ├── frameloop.ts # Main ECS update loop
│ ├── index.css # Global CSS or Tailwind CSS (if used)
│ ├── main.tsx # React app root, renders
│ ├── startup.tsx # Startup logic (initial spawns, intervals)
│ └── world.ts # Creates the ECS world with default traits
├── index.html # Basic HTML page with root div
├── package.json # Project dependencies and scripts
└── tsconfig.json # TypeScript configuration
```
--------------------------------
### Create Alpha Release
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/6.contributing/2.releases.md
Generate an alpha release, which is published with the 'alpha' tag on npm and not installed by default.
```bash
pnpm tsx scripts/release.ts --alpha
```
--------------------------------
### Game Loop System Execution Order
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/4.systems.md
Example of how to organize and call systems in sequence within a game loop. Ensure systems are called in a logical order for correct game state updates.
```typescript
export function GameLoop(world: World) {
// Possibly in a requestAnimationFrame or React useFrame
timeSystem(world)
inputSystem(world)
movementSystem(world)
collisionSystem(world)
cleanupSystem(world)
}
```
--------------------------------
### Define Traits, Create World, Spawn Entity, and Query
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/1.ecs-overview.md
This snippet demonstrates the basic setup of an ECS world using koota. It shows how to define traits (data structures), create a world, spawn an entity with specific traits, and then query for entities possessing multiple traits to update them.
```typescript
import { trait, createWorld } from 'koota'
// 1. Define traits (data)
export const Position = trait({ x: 0, y: 0, z: 0 })
export const Health = trait({ amount: 100 })
// 2. Create a world and spawn an entity
const world = createWorld()
world.spawn(Position({ x: 10, y: 5 }), Health({ amount: 50 }))
// 3. Query and update entities
world.query(Position, Health).updateEach(([pos, hp]) => {
// game logic that modifies position or health
})
```
--------------------------------
### Query and Render Entities with useQuery
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/7.usage.md
Use the useQuery hook to fetch entities that possess specific traits. This example demonstrates how to retrieve all entities marked as 'IsEnemy' and having a 'Position' trait for rendering.
```tsx
// EnemyRenderer.tsx
import { useQuery } from 'koota/react'
import { IsEnemy, Position } from '../ecs/traits'
export function EnemyRenderer() {
const enemies = useQuery(IsEnemy, Position)
return (
<>
{enemies.map((entity) => (
))}
>
)
}
// Basic visualization
function EnemyVisual({ entity }) {
const position = entity.get(Position)
if (!position) return null
return (
)
}
```
--------------------------------
### Implement Game Logic with Systems
Source: https://context7.com/instructa/viber3d/llms.txt
Systems are functions that execute game logic by querying entities and performing updates. They can be event-driven or run on a fixed schedule. Includes examples for movement, health regeneration, cleanup, and event emission.
```typescript
import { World } from 'koota'
import { Transform, Velocity, Health, Time, IsEnemy } from './traits'
// Movement system — runs every frame
export function movementSystem({ world, delta }: { world: World; delta: number }) {
world.query(Transform, Velocity).updateEach(([transform, vel]) => {
transform.position.x += vel.x * delta
transform.position.y += vel.y * delta
transform.position.z += vel.z * delta
})
}
// Health regen system — uses a Time singleton trait
export function healthRegenSystem(world: World) {
const time = world.get(Time)!
world.query(Health).updateEach(([health]) => {
health.amount = Math.min(health.max, health.amount + 5 * time.delta)
})
}
// Cleanup system — removes dead entities
export function cleanupSystem(world: World) {
world.query(Health).removeIf(([health]) => health.amount <= 0)
}
// Event-driven system
world.on('entityDamaged', ({ entity, amount }) => {
// spawn a hit-effect entity, play audio, etc.
})
// Apply damage and emit event
function applyDamage(entity: Entity, damage: number) {
entity.set(Health, (h) => {
const newAmount = Math.max(0, h.amount - damage)
world.emit('entityDamaged', { entity, amount: damage })
return { ...h, amount: newAmount }
})
}
// Unit test for a system
describe('movementSystem', () => {
it('updates position based on velocity', () => {
const testWorld = createWorld()
testWorld.add(Time({ delta: 1, current: 0 }))
const ent = testWorld.spawn(
Transform(),
Velocity({ x: 1, y: 0, z: 0 })
)
movementSystem({ world: testWorld, delta: 1 })
expect(ent.get(Transform)!.position.x).toBe(1)
})
})
```
--------------------------------
### ECS System with `useFrame`
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/5.components.md
Integrate ECS logic into React Three Fiber's render loop using `useFrame`. This example demonstrates a 'MovementSystem' that updates entity positions based on velocity and delta time.
```tsx
import { useFrame } from '@react-three/fiber'
import { useWorld } from 'koota/react'
import { Movement, Transform } from '../traits'
function MovementSystem() {
// This component acts as a "system" in React
const world = useWorld()
useFrame(() => {
const time = world.get(Time)
if (!time) return
const { delta } = time
world.query(Transform, Movement).updateEach(([t, m]) => {
t.position.add(m.velocity.clone().multiplyScalar(delta))
})
})
return null
}
```
--------------------------------
### Create a new project with the default template
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/4.cli.md
Initializes a new Viber3D project using the default 'starter' template in the 'my-game' directory.
```bash
npx viber3d@latest init my-game
```
--------------------------------
### Create a new project with the 'next' template
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/4.cli.md
Initializes a new Viber3D project using the experimental 'next' template in the 'my-game' directory.
```bash
npx viber3d@latest init my-game -t next
```
--------------------------------
### Create Production Build
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/3.development/2.production-build.md
Run this command to compile, bundle, and optimize your project for production. The output will be placed in the `dist/` directory.
```bash
npm run build
```
--------------------------------
### viber3d CLI Initialization with Options
Source: https://github.com/instructa/viber3d/blob/main/packages/viber3d/README.md
This command shows the general structure for initializing a viber3d project with a project name and various command-line options. Refer to the CLI Options section for a full list of available flags.
```bash
npx viber3d@latest init [project-name] [options]
```
--------------------------------
### viber3d CLI Options
Source: https://github.com/instructa/viber3d/blob/main/README.md
Available command-line options for the viber3d initialization tool. Customize project creation with these flags.
```bash
npx viber3d@latest [project-name] [options]
Options:
--cwd, -c The working directory. Defaults to the current directory
--name Project name
--force, -f Override existing directory
--install Skip installing dependencies (default: true)
--gitInit Initialize git repository
--packageManager Package manager choice (npm, pnpm, yarn)
--yes, -y Skip confirmation prompt (default: false)
--defaults, -d Use default configuration (default: false)
--silent, -s Mute output (default: false)
--help, -h Display help for command
```
--------------------------------
### Initialize a new Viber3D project
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/4.cli.md
Initialize a new Viber3D project in a specified directory. Options can be used to customize the initialization process.
```bash
npx viber3d@latest init [dir] [options]
```
--------------------------------
### Create a new project with default settings
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/4.cli.md
Initializes a new Viber3D project and skips all confirmation prompts by using the '-y' flag.
```bash
npx viber3d@latest init my-game -y
```
--------------------------------
### Initialize Callback-Based Trait Instance
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/3.traits.md
Spawn an entity with a callback-based trait, ensuring each entity gets its own instance.
```typescript
const Model = trait(() => new THREE.Mesh())
const entity = world.spawn(Model())
```
--------------------------------
### Preview Production Build
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/README.md
Locally preview the production build using npm, pnpm, yarn, or bun.
```bash
# npm
npm run preview
# pnpm
pnpm preview
# yarn
yarn preview
# bun
bun run preview
```
--------------------------------
### Build for Production
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/README.md
Build the application for production using npm, pnpm, yarn, or bun.
```bash
# npm
npm run build
# pnpm
pnpm build
# yarn
yarn build
# bun
bun run build
```
--------------------------------
### Retrieve and Modify Trait Snapshot
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/3.traits.md
Get a snapshot of a trait's data from an entity and modify it directly. Note that this does not trigger events.
```typescript
// Retrieve a trait snapshot
const health = entity.get(Health)
health.amount -= 10
```
--------------------------------
### Create a new project with a custom GitHub template
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/4.cli.md
Initializes a new Viber3D project using a template from a specified GitHub repository.
```bash
npx viber3d@latest init my-game -t username/repo
```
--------------------------------
### Adding, Removing, and Checking Traits in Koota
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/public/llms_full.txt
Provides examples for adding a trait with custom data, removing a trait from an entity, and checking for the presence of a trait.
```typescript
// Add trait
entity.add(Health({ amount: 100 }))
// Remove trait
entity.remove(Health)
// Check if a trait is present
if (entity.has(Health)) {
// ...
}
```
--------------------------------
### Initializing Trait Data in Koota
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/public/llms_full.txt
Provides examples of initializing trait data, overriding defaults when adding traits to an entity, including callback-based traits.
```typescript
entity.add(Health()) // uses defaults
entity.add(Health({ amount: 50 })) // custom amount
const Model = trait(() => new THREE.Mesh())
const entity = world.spawn(Model()) // Each entity gets its own mesh instance
```
--------------------------------
### Initialize a New viber3d Project
Source: https://github.com/instructa/viber3d/blob/main/packages/viber3d/README.md
Use this command to create a new viber3d project. You can specify a project name or let it default to the current directory.
```bash
npx viber3d@latest init
```
```bash
npx viber3d@latest init myGame
```
--------------------------------
### Compose Actions for Complex Flows
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/6.actions.md
Actions can call other actions, allowing for the creation of complex sequences of operations. This example shows `spawnEnemyWave` calling `spawnEnemy`.
```typescript
export const actions = createActions((world) => ({
spawnEnemy: (position) => {
return world.spawn(IsEnemy(), Transform({ position }), Health({ amount: 50 }))
},
spawnEnemyWave: (count) => {
for (let i = 0; i < count; i++) {
const position = getRandomPosition()
actions.spawnEnemy(position) // calling another action
}
}
}))
```
--------------------------------
### Filter Query Results
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/2.entities.md
Apply standard array filters to refine query results. This example filters enemies with health below 50. Requires 'World' from 'koota'.
```typescript
const lowHealthEnemies = world
.query(IsEnemy, Health)
.filter(([_, health]) => health.amount < 50)
```
--------------------------------
### Initialize Viber3D Project
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/2.installation.md
Run this command in your terminal to create a new project using the latest version of Viber3D.
```bash
npx viber3d@latest init
```
--------------------------------
### Commit Changes with Conventional Commits
Source: https://github.com/instructa/viber3d/blob/main/CONTRIBUTE.md
Commit your changes following the Conventional Commits specification. Use a descriptive message that starts with a type (e.g., 'feat', 'fix') and a brief description of the change.
```bash
git commit -m "feat: add your feature description"
```
--------------------------------
### Initialize Project with a Specific Template
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/6.contributing/1.intro.md
Initialize a new Viber3D project using a specific template, such as the experimental 'next' template. This command uses the latest version of the CLI.
```bash
npx viber3d@latest init my-game --template next
```
--------------------------------
### Conditional Updates within Actions
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/6.actions.md
Implement conditional logic within actions, such as checking for traits before modifying them or triggering other actions based on conditions. This example handles entity damage and destruction.
```typescript
export const actions = createActions((world) => ({
damageEntity: (entity, amount) => {
if (entity.has(Health)) {
entity.set(Health, (h) => {
const newAmount = Math.max(0, h.amount - amount)
if (newAmount <= 0) {
actions.destroyEntity(entity)
}
return { ...h, amount: newAmount }
})
}
},
destroyEntity: (entity) => entity.destroy()
}))
```
--------------------------------
### Testing a Movement System
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/4.core-concepts/4.systems.md
Unit test for the movement system, verifying that entity positions are updated correctly based on velocity and time delta. Requires a test world setup and trait mocks.
```typescript
describe('movementSystem', () => {
it('updates position based on velocity', () => {
const world = createWorld()
const ent = world.spawn(Transform(), Movement({ velocity: new Vector3(1, 0, 0) }))
world.add(Time({ delta: 1 })) // simulate 1 second
movementSystem(world)
expect(ent.get(Transform)!.position.x).toBe(1)
})
})
```
--------------------------------
### Test Production Build Locally
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/3.development/2.production-build.md
Serve your built files locally to test the production build before deployment. This command defaults to serving at http://localhost:4173.
```bash
npm run preview
```
--------------------------------
### Run Release Script with Minor Version
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/6.contributing/2.releases.md
Publish a new release by bumping the minor version using the release script.
```bash
pnpm tsx scripts/release.ts minor
```
--------------------------------
### Hypothetical Collision Handling Logic
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/5.addons/1.physics.md
This is a conceptual example of how collision events might be handled. It assumes a hypothetical `GetCollisionEvents` API on the JoltWorld and demonstrates iterating through collisions to find corresponding entities. A map of `BodyID -> Entity` is recommended for efficient lookups.
```typescript
function handleCollisions(world: World) {
const joltWorld = world.get(JoltWorld)
// some hypothetical API
const collisions = joltWorld.physicsSystem.GetCollisionEvents()
for (const c of collisions) {
const bodyA = c.bodyA
const bodyB = c.bodyB
// find which entities correspond to bodyA, bodyB, then apply logic
}
}
```
--------------------------------
### Viber3D Project Rule Files
Source: https://context7.com/instructa/viber3d/llms.txt
Lists the default rule files included in the Viber3D starter template for organizing coding standards.
```bash
# Project rule files included in the starter template:
.cursor/rules/
├── 001-base.mdc # Overarching ECS + R3F principles
├── 002-components.mdc # React component guidelines
├── 003-systems.mdc # System structure rules
├── 004-actions.mdc # Action pattern guidelines
├── 005-traits.mdc # Trait definition conventions
├── 006-utils.mdc # Utility module best practices
├── 007-tailwind.mdc # Tailwind CSS usage
└── 900-game-agent.mdc # AI game-agent persona
```
--------------------------------
### Project Rules Directory Structure
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/3.development/3.cursor-rules.md
Illustrates the typical directory structure for project-specific Cursor Rules (.mdc files) within a project's .cursor/rules directory.
```bash
.cursor/
└── rules/
├── base.mdc
├── components.mdc
├── systems.mdc
├── traits.mdc
└── utils.mdc
```
--------------------------------
### Use Centralized Actions in React with useActions
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/public/llms_full.txt
Demonstrates how to use the centralized actions defined with createActions within a React component. The useActions hook binds the action functions to the current ECS world, allowing them to be called directly. This example spawns a player on mount and cleans up by destroying all players on unmount.
```tsx
import { useEffect } from 'react'
import { useActions } from 'koota/react'
import { actions } from '../actions'
function GameController() {
const { spawnPlayer, destroyAllPlayers } = useActions(actions)
useEffect(() => {
// Spawn a player on mount
spawnPlayer({ x: 0, y: 0, z: 0 })
// Cleanup on unmount
return () => destroyAllPlayers()
}, [])
return null
}
```
--------------------------------
### Build Project Packages
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/6.contributing/1.intro.md
Build all packages within the monorepo using the pnpm build script.
```bash
pnpm build:packages
```
--------------------------------
### Run Release Script
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/6.contributing/2.releases.md
Execute the automated release script with an optional version type and options.
```bash
pnpm tsx scripts/release.ts [version-type] [options]
```
--------------------------------
### Create ECS World and Schedule
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/7.usage.md
Initialize the ECS world and define a system schedule for managing game logic updates.
```typescript
import { createWorld } from 'koota'
import { Schedule } from 'directed'
import type { World } from 'koota'
export const world = createWorld()
// Build a system schedule
export const schedule = new Schedule<{ world: World; delta: number }>()
// Add systems in order
schedule.add(movementSystem)
schedule.add(collisionSystem, { after: movementSystem })
schedule.add(aiSystem, { after: collisionSystem })
schedule.build()
```
--------------------------------
### Initialize Jolt Physics World
Source: https://context7.com/instructa/viber3d/llms.txt
Initializes the Jolt physics world. This action should be called once at application startup.
```typescript
export const useJoltActions = createActions((world) => ({
async initWorld() {
if (world.has(JoltWorld)) return
const joltInit = await import('jolt-physics')
JoltWorldImpl.JOLT_NATIVE = await joltInit.default()
world.add(JoltWorld())
},
}))
```
--------------------------------
### Initialize Jolt Physics World
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/public/llms_full.txt
Loads the Jolt WASM library and initializes the physics world. This should be called once during application startup. Stores the Jolt WASM reference globally for later use.
```typescript
// traits/jolt-world.ts
import { trait } from 'koota'
import type Jolt from 'jolt-physics'
export const JoltWorld = trait(() => new JoltWorldImpl())
export class JoltWorldImpl {
static JOLT_NATIVE: typeof Jolt
joltInterface: Jolt.JoltInterface = null!
bodyInterface: Jolt.BodyInterface = null!
physicsSystem: Jolt.PhysicsSystem = null!
initialized = false
constructor() {
if (!JoltWorldImpl.JOLT_NATIVE) {
throw new Error("Jolt not loaded yet.")
}
// Create the JoltInterface with default settings
const J = JoltWorldImpl.JOLT_NATIVE
const settings = new J.JoltSettings()
this._setupCollisionFiltering(settings)
const jolt = new J.JoltInterface(settings)
J.destroy(settings)
this.physicsSystem = jolt.GetPhysicsSystem()
this.bodyInterface = this.physicsSystem.GetBodyInterface()
this.joltInterface = jolt
this.initialized = true
}
stepPhysics(dt: number) {
// E.g., do multiple substeps if dt is large
const steps = dt > 1/55 ? 2 : 1
this.joltInterface.Step(dt, steps)
}
_setupCollisionFiltering(settings: Jolt.JoltSettings) {
// your collision layers, etc.
}
}
```
```typescript
// actions/use-jolt-actions.ts
import { createActions } from 'koota/react'
import { JoltWorld, JoltWorldImpl } from '../traits/jolt-world'
export const useJoltActions = createActions((world) => ({
async initWorld() {
if (world.has(JoltWorld)) {
// already initialized
return
}
// Load the Jolt WASM
const joltInit = await import('jolt-physics')
// Store the reference globally
JoltWorldImpl.JOLT_NATIVE = await joltInit.default()
// Add the JoltWorld trait to ECS
world.add(JoltWorld())
console.log("Jolt world created.")
}
}))
```
--------------------------------
### Spawn and Manage Entities with world.spawn and entity
Source: https://context7.com/instructa/viber3d/llms.txt
Use world.spawn() to create entities with initial traits. Entities can be updated with entity.set(), have traits added/removed with add()/remove(), and destroyed with destroy(). Relationships can also be defined and queried.
```typescript
import { World, trait, relation } from 'koota'
// Spawn an entity with initial trait values
const player = world.spawn(
IsPlayer(),
Transform(),
Health({ amount: 100 }),
)
// Read trait data
const hp = player.get(Health)
console.log(hp?.amount) // 100
// Update trait (triggers change detection)
player.set(Health, (prev) => ({ ...prev, amount: prev.amount - 25 }))
// Add / remove traits dynamically
player.add(Velocity({ x: 1, y: 0, z: 0 }))
player.remove(Velocity)
// Check trait presence
if (player.has(Health)) { /* ... */ }
// Destroy entity
player.destroy()
// --- Relationships ---
const ChildOf = relation({ autoRemoveTarget: true }) // cascade destroy
const Targeting = relation({ exclusive: true }) // only one target
const parent = world.spawn()
const child = world.spawn(ChildOf(parent))
// Query all children of parent
const children = world.query(ChildOf(parent))
// Relationship with data
const Contains = relation({ store: { amount: 0 } })
const inventory = world.spawn()
const gold = world.spawn()
inventory.add(Contains(gold))
inventory.set(Contains(gold), { amount: 10 })
```
--------------------------------
### Clone Viber3D Repository
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/6.contributing/1.intro.md
Clone the Viber3D repository locally and navigate into the project directory.
```bash
git clone https://github.com/instructa/viber3d.git
cd viber3d
```
--------------------------------
### Clone viber3d Repository
Source: https://github.com/instructa/viber3d/blob/main/CONTRIBUTE.md
Clone the viber3d repository to your local machine and navigate into the project directory.
```bash
git clone git@github.com:instructa/viber3d.git
cd viber3d
```
--------------------------------
### Step Jolt Physics Simulation
Source: https://context7.com/instructa/viber3d/llms.txt
System to advance the Jolt physics simulation by a given delta time. This should be called every frame.
```typescript
export function UpdateJolt({ world, delta }: { world: World; delta: number }) {
if (!world.has(JoltWorld)) return
world.get(JoltWorld)!.stepPhysics(delta)
}
```
--------------------------------
### Implement ECS Systems (Logic)
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/1.getting-started/7.usage.md
Create systems that process entities based on their traits, updating game state each frame. Systems receive the world and delta time as arguments.
```typescript
import { World } from 'koota'
import { Position, Rotation } from './traits'
import { Vector3 } from 'three'
export function movementSystem({ world, delta }: { world: World; delta: number }) {
// For each entity with Position, move upward
world.query(Position).updateEach(([pos]) => {
pos.y += 1 * delta
})
}
export function collisionSystem({ world }: { world: World }) {
// Example collision logic ...
}
export function aiSystem({ world }: { world: World }) {
// Example AI logic ...
}
```
--------------------------------
### Build Jolt Bodies System
Source: https://github.com/instructa/viber3d/blob/main/docs/viber3d-docs/content/5.addons/1.physics.md
This system creates Jolt physics bodies for entities that require them and have mesh data. It infers initial transforms from the mesh and creates appropriate Jolt shapes. Ensure JoltWorld is present in the world.
```typescript
import { World } from 'koota'
import { NeedsJoltBody } from '../traits/needs-jolt-body'
import { JoltBody } from '../traits/jolt-body'
import { JoltWorld, JoltWorldImpl } from '../traits/jolt-world'
import { MeshRef } from '../traits/mesh-ref'
import { inferInitTransformsFromMesh, createShapeFromGeometry } from '../misc/jolt-helper'
export function BuildJoltBodies({ world }: { world: World }) {
if (!world.has(JoltWorld)) return
const joltWorld = world.get(JoltWorld)
const J = JoltWorldImpl.JOLT_NATIVE
world.query(NeedsJoltBody, MeshRef).updateEach(([needs, meshRef], entity) => {
const { pos, rot } = inferInitTransformsFromMesh(meshRef.ref)
const shape = needs.buildConvexShape
? createShapeFromGeometry(meshRef.ref.geometry)
: /* other shape logic, e.g. BoxShape */ new J.BoxShape(1,1,1)
// create BodyCreationSettings
const layer = needs.layer === 'moving' ? 1 : 0
const motionType = {
dynamic: J.EMotionType_Dynamic,
static: J.EMotionType_Static,
kinematic: J.EMotionType_Kinematic
}[needs.motionType]
const creation = new J.BodyCreationSettings(shape, pos, rot, motionType, layer)
const body = joltWorld.bodyInterface.CreateBody(creation)
J.destroy(creation)
// add the body to jolt
joltWorld.bodyInterface.AddBody(body.GetID(), J.EActivation_Activate)
// handle continuous collision
if (needs.continuousCollisionMode) {
joltWorld.bodyInterface.SetMotionQuality(body.GetID(), J.EMotionQuality_LinearCast)
}
// remove the NeedsJoltBody trait (we built the body)
entity.remove(NeedsJoltBody)
// add the JoltBody trait referencing the new body
entity.add(JoltBody(body))
})
}
```