feat(docs): 添加中英文国际化支持
This commit is contained in:
412
docs/en/guide/getting-started.md
Normal file
412
docs/en/guide/getting-started.md
Normal file
@@ -0,0 +1,412 @@
|
||||
# Quick Start
|
||||
|
||||
This guide will help you get started with ECS Framework, from installation to creating your first ECS application.
|
||||
|
||||
## Installation
|
||||
|
||||
### NPM Installation
|
||||
|
||||
```bash
|
||||
# Using npm
|
||||
npm install @esengine/ecs-framework
|
||||
```
|
||||
|
||||
## Initialize Core
|
||||
|
||||
### Basic Initialization
|
||||
|
||||
The core of ECS Framework is the `Core` class, a singleton that manages the entire framework lifecycle.
|
||||
|
||||
```typescript
|
||||
import { Core } from '@esengine/ecs-framework'
|
||||
|
||||
// Method 1: Using config object (recommended)
|
||||
const core = Core.create({
|
||||
debug: true, // Enable debug mode for detailed logs and performance monitoring
|
||||
debugConfig: { // Optional: Advanced debug configuration
|
||||
enabled: false, // Whether to enable WebSocket debug server
|
||||
websocketUrl: 'ws://localhost:8080',
|
||||
debugFrameRate: 30, // Debug data send frame rate
|
||||
channels: {
|
||||
entities: true,
|
||||
systems: true,
|
||||
performance: true,
|
||||
components: true,
|
||||
scenes: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Method 2: Simplified creation (backward compatible)
|
||||
const core = Core.create(true); // Equivalent to { debug: true }
|
||||
|
||||
// Method 3: Production environment configuration
|
||||
const core = Core.create({
|
||||
debug: false // Disable debug in production
|
||||
});
|
||||
```
|
||||
|
||||
### Core Configuration Details
|
||||
|
||||
```typescript
|
||||
interface ICoreConfig {
|
||||
/** Enable debug mode - affects log level and performance monitoring */
|
||||
debug?: boolean;
|
||||
|
||||
/** Advanced debug configuration - for dev tools integration */
|
||||
debugConfig?: {
|
||||
enabled: boolean; // Enable debug server
|
||||
websocketUrl: string; // WebSocket server URL
|
||||
autoReconnect?: boolean; // Auto reconnect
|
||||
debugFrameRate?: 60 | 30 | 15; // Debug data send frame rate
|
||||
channels: { // Data channel configuration
|
||||
entities: boolean; // Entity data
|
||||
systems: boolean; // System data
|
||||
performance: boolean; // Performance data
|
||||
components: boolean; // Component data
|
||||
scenes: boolean; // Scene data
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Core Instance Management
|
||||
|
||||
Core uses singleton pattern, accessible via static property after creation:
|
||||
|
||||
```typescript
|
||||
// Create instance
|
||||
const core = Core.create(true);
|
||||
|
||||
// Get created instance
|
||||
const instance = Core.Instance; // Returns current instance, null if not created
|
||||
```
|
||||
|
||||
### Game Loop Integration
|
||||
|
||||
**Important**: Before creating entities and systems, you need to understand how to integrate ECS Framework into your game engine.
|
||||
|
||||
`Core.update(deltaTime)` is the framework heartbeat, must be called every frame. It handles:
|
||||
- Updating the built-in Time class
|
||||
- Updating all global managers (timers, object pools, etc.)
|
||||
- Updating all entity systems in all scenes
|
||||
- Processing entity creation and destruction
|
||||
- Collecting performance data (in debug mode)
|
||||
|
||||
See engine integration examples: [Game Engine Integration](#game-engine-integration)
|
||||
|
||||
## Create Your First ECS Application
|
||||
|
||||
### 1. Define Components
|
||||
|
||||
Components are pure data containers that store entity state:
|
||||
|
||||
```typescript
|
||||
import { Component, ECSComponent } from '@esengine/ecs-framework'
|
||||
|
||||
// Position component
|
||||
@ECSComponent('Position')
|
||||
class Position extends Component {
|
||||
x: number = 0
|
||||
y: number = 0
|
||||
|
||||
constructor(x: number = 0, y: number = 0) {
|
||||
super()
|
||||
this.x = x
|
||||
this.y = y
|
||||
}
|
||||
}
|
||||
|
||||
// Velocity component
|
||||
@ECSComponent('Velocity')
|
||||
class Velocity extends Component {
|
||||
dx: number = 0
|
||||
dy: number = 0
|
||||
|
||||
constructor(dx: number = 0, dy: number = 0) {
|
||||
super()
|
||||
this.dx = dx
|
||||
this.dy = dy
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite component
|
||||
@ECSComponent('Sprite')
|
||||
class Sprite extends Component {
|
||||
texture: string = ''
|
||||
width: number = 32
|
||||
height: number = 32
|
||||
|
||||
constructor(texture: string, width: number = 32, height: number = 32) {
|
||||
super()
|
||||
this.texture = texture
|
||||
this.width = width
|
||||
this.height = height
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Create Entity Systems
|
||||
|
||||
Systems contain game logic and process entities with specific components. ECS Framework provides Matcher-based entity filtering:
|
||||
|
||||
```typescript
|
||||
import { EntitySystem, Matcher, Time, ECSSystem } from '@esengine/ecs-framework'
|
||||
|
||||
// Movement system - handles position and velocity
|
||||
@ECSSystem('MovementSystem')
|
||||
class MovementSystem extends EntitySystem {
|
||||
|
||||
constructor() {
|
||||
// Use Matcher to define target entities: must have both Position and Velocity
|
||||
super(Matcher.empty().all(Position, Velocity))
|
||||
}
|
||||
|
||||
protected process(entities: readonly Entity[]): void {
|
||||
// process method receives all matching entities
|
||||
for (const entity of entities) {
|
||||
const position = entity.getComponent(Position)!
|
||||
const velocity = entity.getComponent(Velocity)!
|
||||
|
||||
// Update position (using framework's Time class)
|
||||
position.x += velocity.dx * Time.deltaTime
|
||||
position.y += velocity.dy * Time.deltaTime
|
||||
|
||||
// Boundary check example
|
||||
if (position.x < 0) position.x = 0
|
||||
if (position.y < 0) position.y = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Render system - handles visible objects
|
||||
@ECSSystem('RenderSystem')
|
||||
class RenderSystem extends EntitySystem {
|
||||
|
||||
constructor() {
|
||||
// Must have Position and Sprite, optional Velocity (for direction)
|
||||
super(Matcher.empty().all(Position, Sprite).any(Velocity))
|
||||
}
|
||||
|
||||
protected process(entities: readonly Entity[]): void {
|
||||
for (const entity of entities) {
|
||||
const position = entity.getComponent(Position)!
|
||||
const sprite = entity.getComponent(Sprite)!
|
||||
const velocity = entity.getComponent(Velocity) // May be null
|
||||
|
||||
// Flip sprite based on velocity direction (optional logic)
|
||||
let flipX = false
|
||||
if (velocity && velocity.dx < 0) {
|
||||
flipX = true
|
||||
}
|
||||
|
||||
// Render logic (pseudocode here)
|
||||
this.drawSprite(sprite.texture, position.x, position.y, sprite.width, sprite.height, flipX)
|
||||
}
|
||||
}
|
||||
|
||||
private drawSprite(texture: string, x: number, y: number, width: number, height: number, flipX: boolean = false) {
|
||||
// Actual render implementation depends on your game engine
|
||||
const direction = flipX ? '<-' : '->'
|
||||
console.log(`Render ${texture} at (${x.toFixed(1)}, ${y.toFixed(1)}) direction: ${direction}`)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### 3. Create Scene
|
||||
|
||||
Recommended to extend Scene class for custom scenes:
|
||||
|
||||
```typescript
|
||||
import { Scene } from '@esengine/ecs-framework'
|
||||
|
||||
// Recommended: Extend Scene for custom scene
|
||||
class GameScene extends Scene {
|
||||
|
||||
initialize(): void {
|
||||
// Scene initialization logic
|
||||
this.name = "MainScene";
|
||||
|
||||
// Add systems to scene
|
||||
this.addSystem(new MovementSystem());
|
||||
this.addSystem(new RenderSystem());
|
||||
}
|
||||
|
||||
onStart(): void {
|
||||
// Logic when scene starts running
|
||||
console.log("Game scene started");
|
||||
}
|
||||
|
||||
unload(): void {
|
||||
// Cleanup logic when scene unloads
|
||||
console.log("Game scene unloaded");
|
||||
}
|
||||
}
|
||||
|
||||
// Create and set scene
|
||||
const gameScene = new GameScene();
|
||||
Core.setScene(gameScene);
|
||||
```
|
||||
|
||||
### 4. Create Entities
|
||||
|
||||
```typescript
|
||||
// Create player entity
|
||||
const player = gameScene.createEntity("Player");
|
||||
player.addComponent(new Position(100, 100));
|
||||
player.addComponent(new Velocity(50, 30)); // Move 50px/sec (x), 30px/sec (y)
|
||||
player.addComponent(new Sprite("player.png", 64, 64));
|
||||
```
|
||||
|
||||
## Scene Management
|
||||
|
||||
Core has built-in scene management, very simple to use:
|
||||
|
||||
```typescript
|
||||
import { Core, Scene } from '@esengine/ecs-framework';
|
||||
|
||||
// Initialize Core
|
||||
Core.create({ debug: true });
|
||||
|
||||
// Create and set scene
|
||||
class GameScene extends Scene {
|
||||
initialize(): void {
|
||||
this.name = "GamePlay";
|
||||
this.addSystem(new MovementSystem());
|
||||
this.addSystem(new RenderSystem());
|
||||
}
|
||||
}
|
||||
|
||||
const gameScene = new GameScene();
|
||||
Core.setScene(gameScene);
|
||||
|
||||
// Game loop (auto-updates scene)
|
||||
function gameLoop(deltaTime: number) {
|
||||
Core.update(deltaTime); // Auto-updates global services and scene
|
||||
}
|
||||
|
||||
// Switch scenes
|
||||
Core.loadScene(new MenuScene()); // Delayed switch (next frame)
|
||||
Core.setScene(new GameScene()); // Immediate switch
|
||||
|
||||
// Access current scene
|
||||
const currentScene = Core.scene;
|
||||
|
||||
// Using fluent API
|
||||
const player = Core.ecsAPI?.createEntity('Player')
|
||||
.addComponent(Position, 100, 100)
|
||||
.addComponent(Velocity, 50, 0);
|
||||
```
|
||||
|
||||
### Advanced: Using WorldManager for Multi-World
|
||||
|
||||
Only for complex server-side applications (MMO game servers, game room systems, etc.):
|
||||
|
||||
```typescript
|
||||
import { Core, WorldManager } from '@esengine/ecs-framework';
|
||||
|
||||
// Initialize Core
|
||||
Core.create({ debug: true });
|
||||
|
||||
// Get WorldManager from service container (Core auto-creates and registers it)
|
||||
const worldManager = Core.services.resolve(WorldManager);
|
||||
|
||||
// Create multiple independent game worlds
|
||||
const room1 = worldManager.createWorld('room_001');
|
||||
const room2 = worldManager.createWorld('room_002');
|
||||
|
||||
// Create scenes in each world
|
||||
const gameScene1 = room1.createScene('game', new GameScene());
|
||||
const gameScene2 = room2.createScene('game', new GameScene());
|
||||
|
||||
// Activate scenes
|
||||
room1.setSceneActive('game', true);
|
||||
room2.setSceneActive('game', true);
|
||||
|
||||
// Game loop (need to manually update worlds)
|
||||
function gameLoop(deltaTime: number) {
|
||||
Core.update(deltaTime); // Update global services
|
||||
worldManager.updateAll(); // Manually update all worlds
|
||||
}
|
||||
```
|
||||
|
||||
## Game Engine Integration
|
||||
|
||||
### Laya Engine Integration
|
||||
|
||||
```typescript
|
||||
import { Stage } from "laya/display/Stage";
|
||||
import { Laya } from "Laya";
|
||||
import { Core } from '@esengine/ecs-framework';
|
||||
|
||||
// Initialize Laya
|
||||
Laya.init(800, 600).then(() => {
|
||||
// Initialize ECS
|
||||
Core.create(true);
|
||||
Core.setScene(new GameScene());
|
||||
|
||||
// Start game loop
|
||||
Laya.timer.frameLoop(1, this, () => {
|
||||
const deltaTime = Laya.timer.delta / 1000;
|
||||
Core.update(deltaTime); // Auto-updates global services and scene
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Cocos Creator Integration
|
||||
|
||||
```typescript
|
||||
import { Component, _decorator } from 'cc';
|
||||
import { Core } from '@esengine/ecs-framework';
|
||||
|
||||
const { ccclass } = _decorator;
|
||||
|
||||
@ccclass('ECSGameManager')
|
||||
export class ECSGameManager extends Component {
|
||||
onLoad() {
|
||||
// Initialize ECS
|
||||
Core.create(true);
|
||||
Core.setScene(new GameScene());
|
||||
}
|
||||
|
||||
update(deltaTime: number) {
|
||||
// Auto-updates global services and scene
|
||||
Core.update(deltaTime);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
// Cleanup resources
|
||||
Core.destroy();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Next Steps
|
||||
|
||||
You've successfully created your first ECS application! Next you can:
|
||||
|
||||
- Check the complete [API Documentation](/en/api/README)
|
||||
- Explore more [practical examples](/en/examples/)
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why isn't my system executing?
|
||||
|
||||
Ensure:
|
||||
1. System is added to scene: `this.addSystem(system)` (in Scene's initialize method)
|
||||
2. Scene is set: `Core.setScene(scene)`
|
||||
3. Game loop is calling: `Core.update(deltaTime)`
|
||||
|
||||
### How to debug ECS applications?
|
||||
|
||||
Enable debug mode:
|
||||
|
||||
```typescript
|
||||
Core.create({ debug: true })
|
||||
|
||||
// Get debug data
|
||||
const debugData = Core.getDebugData()
|
||||
console.log(debugData)
|
||||
```
|
||||
43
docs/en/guide/index.md
Normal file
43
docs/en/guide/index.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Guide
|
||||
|
||||
Welcome to the ECS Framework Guide. This guide covers the core concepts and usage of the framework.
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### [Entity](./entity.md)
|
||||
Learn the basics of ECS architecture - how to use entities, lifecycle management, and best practices.
|
||||
|
||||
### [Component](./component.md)
|
||||
Learn how to create and use components for modular game feature design.
|
||||
|
||||
### [System](./system.md)
|
||||
Master system development to implement game logic processing.
|
||||
|
||||
### [Entity Query & Matcher](./entity-query.md)
|
||||
Learn to use Matcher for entity filtering and queries with `all`, `any`, `none`, `nothing` conditions.
|
||||
|
||||
### [Scene](./scene.md)
|
||||
Understand scene lifecycle, system management, and entity container features.
|
||||
|
||||
### [Event System](./event-system.md)
|
||||
Master the type-safe event system for component communication and system coordination.
|
||||
|
||||
### [Serialization](./serialization.md)
|
||||
Master serialization for scenes, entities, and components. Supports full and incremental serialization for game saves, network sync, and more.
|
||||
|
||||
### [Time and Timers](./time-and-timers.md)
|
||||
Learn time management and timer systems for precise game logic timing control.
|
||||
|
||||
### [Logging](./logging.md)
|
||||
Master the leveled logging system for debugging, monitoring, and error tracking.
|
||||
|
||||
### [Platform Adapter](./platform-adapter.md)
|
||||
Learn how to implement and register platform adapters for browsers, mini-games, Node.js, and more.
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### [Service Container](./service-container.md)
|
||||
Master dependency injection and service management for loosely-coupled architecture.
|
||||
|
||||
### [Plugin System](./plugin-system.md)
|
||||
Learn how to develop and use plugins to extend framework functionality.
|
||||
317
docs/en/index.md
Normal file
317
docs/en/index.md
Normal file
@@ -0,0 +1,317 @@
|
||||
---
|
||||
layout: page
|
||||
title: ESEngine - High-performance TypeScript ECS Framework
|
||||
---
|
||||
|
||||
<ParticleHeroEn />
|
||||
|
||||
<section class="news-section">
|
||||
<div class="news-container">
|
||||
<div class="news-header">
|
||||
<h2 class="news-title">Quick Links</h2>
|
||||
<a href="/en/guide/" class="news-more">View Docs</a>
|
||||
</div>
|
||||
<div class="news-grid">
|
||||
<a href="/en/guide/getting-started" class="news-card">
|
||||
<div class="news-card-image" style="background: linear-gradient(135deg, #1e3a5f 0%, #1e1e1e 100%);">
|
||||
<div class="news-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24"><path fill="#4fc1ff" d="M12 3L1 9l4 2.18v6L12 21l7-3.82v-6l2-1.09V17h2V9zm6.82 6L12 12.72L5.18 9L12 5.28zM17 16l-5 2.72L7 16v-3.73L12 15l5-2.73z"/></svg>
|
||||
</div>
|
||||
<span class="news-badge">Quick Start</span>
|
||||
</div>
|
||||
<div class="news-card-content">
|
||||
<h3>Get Started in 5 Minutes</h3>
|
||||
<p>From installation to your first ECS app, learn the core concepts quickly.</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="/en/guide/behavior-tree/" class="news-card">
|
||||
<div class="news-card-image" style="background: linear-gradient(135deg, #1e3a5f 0%, #1e1e1e 100%);">
|
||||
<div class="news-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24"><path fill="#4ec9b0" d="M12 2a2 2 0 0 1 2 2a2 2 0 0 1-2 2a2 2 0 0 1-2-2a2 2 0 0 1 2-2m3 20h-1v-7l-2-2l-2 2v7H9v-7.5l-2 2V22H6v-6l3-3l1-3.5c-.3.4-.6.7-1 1L6 9v1H4V8l5-3c.5-.3 1.1-.5 1.7-.5H11c.6 0 1.2.2 1.7.5l5 3v2h-2V9l-3 1.5c-.4-.3-.7-.6-1-1l1 3.5l3 3v6Z"/></svg>
|
||||
</div>
|
||||
<span class="news-badge">AI System</span>
|
||||
</div>
|
||||
<div class="news-card-content">
|
||||
<h3>Visual Behavior Tree Editor</h3>
|
||||
<p>Built-in AI behavior tree system with visual editing and real-time debugging.</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="features-section">
|
||||
<div class="features-container">
|
||||
<h2 class="features-title">Core Features</h2>
|
||||
<div class="features-grid">
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="#4fc1ff" d="M13 2.05v2.02c3.95.49 7 3.85 7 7.93c0 1.45-.39 2.79-1.06 3.95l1.59 1.09A9.94 9.94 0 0 0 22 12c0-5.18-3.95-9.45-9-9.95M12 19c-3.87 0-7-3.13-7-7c0-3.53 2.61-6.43 6-6.92V2.05c-5.06.5-9 4.76-9 9.95c0 5.52 4.47 10 9.99 10c3.31 0 6.24-1.61 8.06-4.09l-1.6-1.1A7.93 7.93 0 0 1 12 19"/><path fill="#4fc1ff" d="M12 6a6 6 0 0 0-6 6c0 3.31 2.69 6 6 6a6 6 0 0 0 0-12m0 10c-2.21 0-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4s-1.79 4-4 4"/></svg>
|
||||
</div>
|
||||
<h3 class="feature-title">High-performance ECS Architecture</h3>
|
||||
<p class="feature-desc">Data-driven entity component system for large-scale entity processing with cache-friendly memory layout.</p>
|
||||
<a href="/en/guide/entity" class="feature-link">Learn more</a>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="#569cd6" d="M3 3h18v18H3zm16.525 13.707c0-.795-.272-1.425-.816-1.89c-.544-.465-1.404-.804-2.58-1.016l-1.704-.296c-.616-.104-1.052-.26-1.308-.468c-.256-.21-.384-.468-.384-.776c0-.392.168-.7.504-.924c.336-.224.8-.336 1.392-.336c.56 0 1.008.124 1.344.372c.336.248.536.584.6 1.008h2.016c-.08-.96-.464-1.716-1.152-2.268c-.688-.552-1.6-.828-2.736-.828c-1.2 0-2.148.3-2.844.9c-.696.6-1.044 1.38-1.044 2.34c0 .76.252 1.368.756 1.824c.504.456 1.308.792 2.412.996l1.704.312c.624.12 1.068.28 1.332.48c.264.2.396.46.396.78c0 .424-.192.756-.576.996c-.384.24-.9.36-1.548.36c-.672 0-1.2-.14-1.584-.42c-.384-.28-.608-.668-.672-1.164H8.868c.048 1.016.46 1.808 1.236 2.376c.776.568 1.796.852 3.06.852c1.24 0 2.22-.292 2.94-.876c.72-.584 1.08-1.364 1.08-2.34z"/></svg>
|
||||
</div>
|
||||
<h3 class="feature-title">Full Type Support</h3>
|
||||
<p class="feature-desc">100% TypeScript with complete type definitions and compile-time checking for the best development experience.</p>
|
||||
<a href="/en/guide/component" class="feature-link">Learn more</a>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="#4ec9b0" d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10s10-4.5 10-10S17.5 2 12 2m0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8s8 3.59 8 8s-3.59 8-8 8m-5-8l4-4v3h4v2h-4v3z"/></svg>
|
||||
</div>
|
||||
<h3 class="feature-title">Visual Behavior Tree</h3>
|
||||
<p class="feature-desc">Built-in AI behavior tree system with visual editor, custom nodes, and real-time debugging.</p>
|
||||
<a href="/en/guide/behavior-tree/" class="feature-link">Learn more</a>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="#c586c0" d="M4 6h18V4H4c-1.1 0-2 .9-2 2v11H0v3h14v-3H4zm19 2h-6c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h6c.55 0 1-.45 1-1V9c0-.55-.45-1-1-1m-1 9h-4v-7h4z"/></svg>
|
||||
</div>
|
||||
<h3 class="feature-title">Multi-Platform Support</h3>
|
||||
<p class="feature-desc">Support for browsers, Node.js, WeChat Mini Games, and seamless integration with major game engines.</p>
|
||||
<a href="/en/guide/platform-adapter" class="feature-link">Learn more</a>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="#dcdcaa" d="M4 3h6v2H4v14h6v2H4c-1.1 0-2-.9-2-2V5c0-1.1.9-2 2-2m9 0h6c1.1 0 2 .9 2 2v14c0 1.1-.9 2-2 2h-6v-2h6V5h-6zm-1 7h4v2h-4z"/></svg>
|
||||
</div>
|
||||
<h3 class="feature-title">Modular Design</h3>
|
||||
<p class="feature-desc">Core features packaged independently, import only what you need. Support for custom plugin extensions.</p>
|
||||
<a href="/en/guide/plugin-system" class="feature-link">Learn more</a>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="#9cdcfe" d="M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9c-2-2-5-2.4-7.4-1.3L9 6L6 9L1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1.4 0l2.3-2.3c.5-.4.5-1.1.1-1.4"/></svg>
|
||||
</div>
|
||||
<h3 class="feature-title">Developer Tools</h3>
|
||||
<p class="feature-desc">Built-in performance monitoring, debugging tools, serialization system, and complete development toolchain.</p>
|
||||
<a href="/en/guide/logging" class="feature-link">Learn more</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style scoped>
|
||||
/* Home page specific styles */
|
||||
.news-section {
|
||||
background: #0d0d0d;
|
||||
padding: 64px 0;
|
||||
border-top: 1px solid #2a2a2a;
|
||||
}
|
||||
|
||||
.news-container {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
padding: 0 48px;
|
||||
}
|
||||
|
||||
.news-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.news-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.news-more {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 10px 20px;
|
||||
background: #1a1a1a;
|
||||
border: 1px solid #2a2a2a;
|
||||
border-radius: 6px;
|
||||
color: #a0a0a0;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
text-decoration: none;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.news-more:hover {
|
||||
background: #252525;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.news-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.news-card {
|
||||
display: flex;
|
||||
background: #1f1f1f;
|
||||
border: 1px solid #2a2a2a;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
text-decoration: none;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.news-card:hover {
|
||||
border-color: #3b9eff;
|
||||
}
|
||||
|
||||
.news-card-image {
|
||||
width: 200px;
|
||||
min-height: 140px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 16px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.news-icon {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.news-badge {
|
||||
display: inline-block;
|
||||
padding: 4px 12px;
|
||||
background: transparent;
|
||||
border: 1px solid #3a3a3a;
|
||||
border-radius: 16px;
|
||||
color: #a0a0a0;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.news-card-content {
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.news-card-content h3 {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
.news-card-content p {
|
||||
font-size: 0.875rem;
|
||||
color: #707070;
|
||||
margin: 0;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.features-section {
|
||||
background: #0d0d0d;
|
||||
padding: 64px 0;
|
||||
}
|
||||
|
||||
.features-container {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
padding: 0 48px;
|
||||
}
|
||||
|
||||
.features-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
margin: 0 0 32px 0;
|
||||
}
|
||||
|
||||
.features-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
background: #1f1f1f;
|
||||
border: 1px solid #2a2a2a;
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
border-color: #3b9eff;
|
||||
background: #252525;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
background: #0d0d0d;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
.feature-desc {
|
||||
font-size: 14px;
|
||||
color: #707070;
|
||||
line-height: 1.7;
|
||||
margin: 0 0 16px 0;
|
||||
}
|
||||
|
||||
.feature-link {
|
||||
font-size: 14px;
|
||||
color: #3b9eff;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.feature-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.news-container,
|
||||
.features-container {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.news-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.features-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.news-card {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.news-card-image {
|
||||
width: 100%;
|
||||
min-height: 120px;
|
||||
}
|
||||
|
||||
.features-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user