feat: 添加跨平台运行时、资产系统和UI适配功能 (#256)
* feat(platform-common): 添加WASM加载器和环境检测API * feat(rapier2d): 新增Rapier2D WASM绑定包 * feat(physics-rapier2d): 添加跨平台WASM加载器 * feat(asset-system): 添加运行时资产目录和bundle格式 * feat(asset-system-editor): 新增编辑器资产管理包 * feat(editor-core): 添加构建系统和模块管理 * feat(editor-app): 重构浏览器预览使用import maps * feat(platform-web): 添加BrowserRuntime和资产读取 * feat(engine): 添加材质系统和着色器管理 * feat(material): 新增材质系统和着色器编辑器 * feat(tilemap): 增强tilemap编辑器和动画系统 * feat(modules): 添加module.json配置 * feat(core): 添加module.json和类型定义更新 * chore: 更新依赖和构建配置 * refactor(plugins): 更新插件模板使用ModuleManifest * chore: 添加第三方依赖库 * chore: 移除BehaviourTree-ai和ecs-astar子模块 * docs: 更新README和文档主题样式 * fix: 修复Rust文档测试和添加rapier2d WASM绑定 * fix(tilemap-editor): 修复画布高DPI屏幕分辨率适配问题 * feat(ui): 添加UI屏幕适配系统(CanvasScaler/SafeArea) * fix(ecs-engine-bindgen): 添加缺失的ecs-framework-math依赖 * fix: 添加缺失的包依赖修复CI构建 * fix: 修复CodeQL检测到的代码问题 * fix: 修复构建错误和缺失依赖 * fix: 修复类型检查错误 * fix(material-system): 修复tsconfig配置支持TypeScript项目引用 * fix(editor-core): 修复Rollup构建配置添加tauri external * fix: 修复CodeQL检测到的代码问题 * fix: 修复CodeQL检测到的代码问题
This commit is contained in:
556
packages/math/src/Color.ts
Normal file
556
packages/math/src/Color.ts
Normal file
@@ -0,0 +1,556 @@
|
||||
/**
|
||||
* Color utility class for game engine
|
||||
* 游戏引擎颜色工具类
|
||||
*
|
||||
* Provides color conversion, manipulation, and packing utilities.
|
||||
* 提供颜色转换、操作和打包工具。
|
||||
*/
|
||||
|
||||
/**
|
||||
* RGBA color components
|
||||
* RGBA 颜色分量
|
||||
*/
|
||||
export interface RGBA {
|
||||
r: number;
|
||||
g: number;
|
||||
b: number;
|
||||
a: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* HSL color components
|
||||
* HSL 颜色分量
|
||||
*/
|
||||
export interface HSL {
|
||||
h: number;
|
||||
s: number;
|
||||
l: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Color class for color manipulation and conversion
|
||||
* 颜色类,用于颜色操作和转换
|
||||
*/
|
||||
export class Color {
|
||||
/** Red component (0-255) | 红色分量 (0-255) */
|
||||
public r: number;
|
||||
/** Green component (0-255) | 绿色分量 (0-255) */
|
||||
public g: number;
|
||||
/** Blue component (0-255) | 蓝色分量 (0-255) */
|
||||
public b: number;
|
||||
/** Alpha component (0-1) | 透明度分量 (0-1) */
|
||||
public a: number;
|
||||
|
||||
// ===== Predefined Colors | 预定义颜色 =====
|
||||
|
||||
/** White (0xFFFFFF) | 白色 */
|
||||
static readonly WHITE = new Color(255, 255, 255);
|
||||
/** Black (0x000000) | 黑色 */
|
||||
static readonly BLACK = new Color(0, 0, 0);
|
||||
/** Red (0xFF0000) | 红色 */
|
||||
static readonly RED = new Color(255, 0, 0);
|
||||
/** Green (0x00FF00) | 绿色 */
|
||||
static readonly GREEN = new Color(0, 255, 0);
|
||||
/** Blue (0x0000FF) | 蓝色 */
|
||||
static readonly BLUE = new Color(0, 0, 255);
|
||||
/** Yellow (0xFFFF00) | 黄色 */
|
||||
static readonly YELLOW = new Color(255, 255, 0);
|
||||
/** Cyan (0x00FFFF) | 青色 */
|
||||
static readonly CYAN = new Color(0, 255, 255);
|
||||
/** Magenta (0xFF00FF) | 品红色 */
|
||||
static readonly MAGENTA = new Color(255, 0, 255);
|
||||
/** Transparent (0x00000000) | 透明 */
|
||||
static readonly TRANSPARENT = new Color(0, 0, 0, 0);
|
||||
/** Gray (0x808080) | 灰色 */
|
||||
static readonly GRAY = new Color(128, 128, 128);
|
||||
|
||||
/**
|
||||
* Create a new Color instance
|
||||
* 创建新的 Color 实例
|
||||
*/
|
||||
constructor(r: number = 255, g: number = 255, b: number = 255, a: number = 1) {
|
||||
this.r = Math.round(Math.max(0, Math.min(255, r)));
|
||||
this.g = Math.round(Math.max(0, Math.min(255, g)));
|
||||
this.b = Math.round(Math.max(0, Math.min(255, b)));
|
||||
this.a = Math.max(0, Math.min(1, a));
|
||||
}
|
||||
|
||||
// ===== Factory Methods | 工厂方法 =====
|
||||
|
||||
/**
|
||||
* Create color from hex string
|
||||
* 从十六进制字符串创建颜色
|
||||
* @param hex Hex string (e.g., "#FF0000", "#F00", "FF0000") | 十六进制字符串
|
||||
* @param alpha Optional alpha value (0-1) | 可选的透明度值
|
||||
*/
|
||||
static fromHex(hex: string, alpha: number = 1): Color {
|
||||
const { r, g, b } = Color.hexToRgb(hex);
|
||||
return new Color(r, g, b, alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create color from packed uint32 (0xRRGGBB or 0xAARRGGBB)
|
||||
* 从打包的 uint32 创建颜色
|
||||
* @param value Packed color value | 打包的颜色值
|
||||
* @param hasAlpha Whether value includes alpha | 是否包含透明度
|
||||
*/
|
||||
static fromUint32(value: number, hasAlpha: boolean = false): Color {
|
||||
if (hasAlpha) {
|
||||
const a = ((value >> 24) & 0xFF) / 255;
|
||||
const r = (value >> 16) & 0xFF;
|
||||
const g = (value >> 8) & 0xFF;
|
||||
const b = value & 0xFF;
|
||||
return new Color(r, g, b, a);
|
||||
} else {
|
||||
const r = (value >> 16) & 0xFF;
|
||||
const g = (value >> 8) & 0xFF;
|
||||
const b = value & 0xFF;
|
||||
return new Color(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create color from HSL values
|
||||
* 从 HSL 值创建颜色
|
||||
* @param h Hue (0-360) | 色相
|
||||
* @param s Saturation (0-1) | 饱和度
|
||||
* @param l Lightness (0-1) | 亮度
|
||||
* @param a Alpha (0-1) | 透明度
|
||||
*/
|
||||
static fromHSL(h: number, s: number, l: number, a: number = 1): Color {
|
||||
const { r, g, b } = Color.hslToRgb(h, s, l);
|
||||
return new Color(r, g, b, a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create color from normalized float values (0-1)
|
||||
* 从归一化浮点值创建颜色 (0-1)
|
||||
*/
|
||||
static fromFloat(r: number, g: number, b: number, a: number = 1): Color {
|
||||
return new Color(r * 255, g * 255, b * 255, a);
|
||||
}
|
||||
|
||||
// ===== Conversion Methods | 转换方法 =====
|
||||
|
||||
/**
|
||||
* Convert hex string to RGB
|
||||
* 将十六进制字符串转换为 RGB
|
||||
*/
|
||||
static hexToRgb(hex: string): { r: number; g: number; b: number } {
|
||||
const colorHex = hex.replace('#', '');
|
||||
|
||||
let r = 255, g = 255, b = 255;
|
||||
|
||||
if (colorHex.length === 6) {
|
||||
r = parseInt(colorHex.substring(0, 2), 16);
|
||||
g = parseInt(colorHex.substring(2, 4), 16);
|
||||
b = parseInt(colorHex.substring(4, 6), 16);
|
||||
} else if (colorHex.length === 3) {
|
||||
r = parseInt(colorHex[0] + colorHex[0], 16);
|
||||
g = parseInt(colorHex[1] + colorHex[1], 16);
|
||||
b = parseInt(colorHex[2] + colorHex[2], 16);
|
||||
} else if (colorHex.length === 8) {
|
||||
// AARRGGBB format
|
||||
r = parseInt(colorHex.substring(2, 4), 16);
|
||||
g = parseInt(colorHex.substring(4, 6), 16);
|
||||
b = parseInt(colorHex.substring(6, 8), 16);
|
||||
}
|
||||
|
||||
return { r, g, b };
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert RGB to hex string
|
||||
* 将 RGB 转换为十六进制字符串
|
||||
*/
|
||||
static rgbToHex(r: number, g: number, b: number): string {
|
||||
const toHex = (n: number) => Math.round(n).toString(16).padStart(2, '0');
|
||||
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert HSL to RGB
|
||||
* 将 HSL 转换为 RGB
|
||||
*/
|
||||
static hslToRgb(h: number, s: number, l: number): { r: number; g: number; b: number } {
|
||||
h = ((h % 360) + 360) % 360 / 360;
|
||||
s = Math.max(0, Math.min(1, s));
|
||||
l = Math.max(0, Math.min(1, l));
|
||||
|
||||
let r: number, g: number, b: number;
|
||||
|
||||
if (s === 0) {
|
||||
r = g = b = l;
|
||||
} else {
|
||||
const hue2rgb = (p: number, q: number, t: number) => {
|
||||
if (t < 0) t += 1;
|
||||
if (t > 1) t -= 1;
|
||||
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
||||
if (t < 1 / 2) return q;
|
||||
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
||||
return p;
|
||||
};
|
||||
|
||||
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
||||
const p = 2 * l - q;
|
||||
|
||||
r = hue2rgb(p, q, h + 1 / 3);
|
||||
g = hue2rgb(p, q, h);
|
||||
b = hue2rgb(p, q, h - 1 / 3);
|
||||
}
|
||||
|
||||
return {
|
||||
r: Math.round(r * 255),
|
||||
g: Math.round(g * 255),
|
||||
b: Math.round(b * 255)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert RGB to HSL
|
||||
* 将 RGB 转换为 HSL
|
||||
*/
|
||||
static rgbToHsl(r: number, g: number, b: number): HSL {
|
||||
r /= 255;
|
||||
g /= 255;
|
||||
b /= 255;
|
||||
|
||||
const max = Math.max(r, g, b);
|
||||
const min = Math.min(r, g, b);
|
||||
let h = 0;
|
||||
let s = 0;
|
||||
const l = (max + min) / 2;
|
||||
|
||||
if (max !== min) {
|
||||
const d = max - min;
|
||||
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||
|
||||
switch (max) {
|
||||
case r:
|
||||
h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
|
||||
break;
|
||||
case g:
|
||||
h = ((b - r) / d + 2) / 6;
|
||||
break;
|
||||
case b:
|
||||
h = ((r - g) / d + 4) / 6;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return { h: h * 360, s, l };
|
||||
}
|
||||
|
||||
// ===== Packing Methods | 打包方法 =====
|
||||
|
||||
/**
|
||||
* Pack color to uint32 (0xRRGGBB)
|
||||
* 打包颜色为 uint32 (0xRRGGBB)
|
||||
*/
|
||||
static packRGB(r: number, g: number, b: number): number {
|
||||
return ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack color to uint32 (0xAARRGGBB)
|
||||
* 打包颜色为 uint32 (0xAARRGGBB)
|
||||
*/
|
||||
static packARGB(r: number, g: number, b: number, a: number): number {
|
||||
const alpha = Math.round(a * 255);
|
||||
return ((alpha & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack color to uint32 for WebGL (0xAABBGGRR)
|
||||
* 打包颜色为 WebGL 格式的 uint32 (0xAABBGGRR)
|
||||
*/
|
||||
static packABGR(r: number, g: number, b: number, a: number): number {
|
||||
const alpha = Math.round(a * 255);
|
||||
return ((alpha & 0xFF) << 24) | ((b & 0xFF) << 16) | ((g & 0xFF) << 8) | (r & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack hex string and alpha to WebGL uint32 (0xAABBGGRR)
|
||||
* 将十六进制字符串和透明度打包为 WebGL 格式 uint32
|
||||
*/
|
||||
static packHexAlpha(hex: string, alpha: number): number {
|
||||
const { r, g, b } = Color.hexToRgb(hex);
|
||||
return Color.packABGR(r, g, b, alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpack uint32 to RGBA (assumes 0xAARRGGBB)
|
||||
* 解包 uint32 为 RGBA (假设格式为 0xAARRGGBB)
|
||||
*/
|
||||
static unpackARGB(value: number): RGBA {
|
||||
return {
|
||||
a: ((value >> 24) & 0xFF) / 255,
|
||||
r: (value >> 16) & 0xFF,
|
||||
g: (value >> 8) & 0xFF,
|
||||
b: value & 0xFF
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpack uint32 to RGBA (assumes 0xAABBGGRR - WebGL format)
|
||||
* 解包 uint32 为 RGBA (假设格式为 0xAABBGGRR - WebGL 格式)
|
||||
*/
|
||||
static unpackABGR(value: number): RGBA {
|
||||
return {
|
||||
a: ((value >> 24) & 0xFF) / 255,
|
||||
b: (value >> 16) & 0xFF,
|
||||
g: (value >> 8) & 0xFF,
|
||||
r: value & 0xFF
|
||||
};
|
||||
}
|
||||
|
||||
// ===== Color Operations | 颜色操作 =====
|
||||
|
||||
/**
|
||||
* Interpolate between two colors
|
||||
* 在两个颜色之间插值
|
||||
*/
|
||||
static lerp(from: Color, to: Color, t: number): Color {
|
||||
t = Math.max(0, Math.min(1, t));
|
||||
return new Color(
|
||||
from.r + (to.r - from.r) * t,
|
||||
from.g + (to.g - from.g) * t,
|
||||
from.b + (to.b - from.b) * t,
|
||||
from.a + (to.a - from.a) * t
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolate between two packed uint32 colors (0xRRGGBB)
|
||||
* 在两个打包的 uint32 颜色之间插值
|
||||
*/
|
||||
static lerpUint32(from: number, to: number, t: number): number {
|
||||
t = Math.max(0, Math.min(1, t));
|
||||
const fromR = (from >> 16) & 0xFF;
|
||||
const fromG = (from >> 8) & 0xFF;
|
||||
const fromB = from & 0xFF;
|
||||
const toR = (to >> 16) & 0xFF;
|
||||
const toG = (to >> 8) & 0xFF;
|
||||
const toB = to & 0xFF;
|
||||
|
||||
const r = Math.round(fromR + (toR - fromR) * t);
|
||||
const g = Math.round(fromG + (toG - fromG) * t);
|
||||
const b = Math.round(fromB + (toB - fromB) * t);
|
||||
|
||||
return (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix two colors
|
||||
* 混合两个颜色
|
||||
*/
|
||||
static mix(color1: Color, color2: Color, ratio: number = 0.5): Color {
|
||||
return Color.lerp(color1, color2, ratio);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lighten a color
|
||||
* 使颜色变亮
|
||||
*/
|
||||
static lighten(color: Color, amount: number): Color {
|
||||
const hsl = Color.rgbToHsl(color.r, color.g, color.b);
|
||||
hsl.l = Math.min(1, hsl.l + amount);
|
||||
const rgb = Color.hslToRgb(hsl.h, hsl.s, hsl.l);
|
||||
return new Color(rgb.r, rgb.g, rgb.b, color.a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Darken a color
|
||||
* 使颜色变暗
|
||||
*/
|
||||
static darken(color: Color, amount: number): Color {
|
||||
const hsl = Color.rgbToHsl(color.r, color.g, color.b);
|
||||
hsl.l = Math.max(0, hsl.l - amount);
|
||||
const rgb = Color.hslToRgb(hsl.h, hsl.s, hsl.l);
|
||||
return new Color(rgb.r, rgb.g, rgb.b, color.a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saturate a color
|
||||
* 增加颜色饱和度
|
||||
*/
|
||||
static saturate(color: Color, amount: number): Color {
|
||||
const hsl = Color.rgbToHsl(color.r, color.g, color.b);
|
||||
hsl.s = Math.min(1, hsl.s + amount);
|
||||
const rgb = Color.hslToRgb(hsl.h, hsl.s, hsl.l);
|
||||
return new Color(rgb.r, rgb.g, rgb.b, color.a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Desaturate a color
|
||||
* 降低颜色饱和度
|
||||
*/
|
||||
static desaturate(color: Color, amount: number): Color {
|
||||
const hsl = Color.rgbToHsl(color.r, color.g, color.b);
|
||||
hsl.s = Math.max(0, hsl.s - amount);
|
||||
const rgb = Color.hslToRgb(hsl.h, hsl.s, hsl.l);
|
||||
return new Color(rgb.r, rgb.g, rgb.b, color.a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invert a color
|
||||
* 反转颜色
|
||||
*/
|
||||
static invert(color: Color): Color {
|
||||
return new Color(255 - color.r, 255 - color.g, 255 - color.b, color.a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert color to grayscale
|
||||
* 将颜色转换为灰度
|
||||
*/
|
||||
static grayscale(color: Color): Color {
|
||||
const gray = Math.round(0.299 * color.r + 0.587 * color.g + 0.114 * color.b);
|
||||
return new Color(gray, gray, gray, color.a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get color luminance (perceived brightness)
|
||||
* 获取颜色亮度(感知亮度)
|
||||
*/
|
||||
static luminance(color: Color): number {
|
||||
return (0.299 * color.r + 0.587 * color.g + 0.114 * color.b) / 255;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get contrast ratio between two colors
|
||||
* 获取两个颜色之间的对比度
|
||||
*/
|
||||
static contrastRatio(color1: Color, color2: Color): number {
|
||||
const l1 = Color.luminance(color1);
|
||||
const l2 = Color.luminance(color2);
|
||||
const lighter = Math.max(l1, l2);
|
||||
const darker = Math.min(l1, l2);
|
||||
return (lighter + 0.05) / (darker + 0.05);
|
||||
}
|
||||
|
||||
// ===== Instance Methods | 实例方法 =====
|
||||
|
||||
/**
|
||||
* Convert to hex string
|
||||
* 转换为十六进制字符串
|
||||
*/
|
||||
toHex(): string {
|
||||
return Color.rgbToHex(this.r, this.g, this.b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to hex string with alpha
|
||||
* 转换为带透明度的十六进制字符串
|
||||
*/
|
||||
toHexAlpha(): string {
|
||||
const alphaHex = Math.round(this.a * 255).toString(16).padStart(2, '0');
|
||||
return `#${alphaHex}${this.toHex().slice(1)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to CSS rgba string
|
||||
* 转换为 CSS rgba 字符串
|
||||
*/
|
||||
toRgba(): string {
|
||||
return `rgba(${this.r}, ${this.g}, ${this.b}, ${this.a})`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to CSS rgb string
|
||||
* 转换为 CSS rgb 字符串
|
||||
*/
|
||||
toRgb(): string {
|
||||
return `rgb(${this.r}, ${this.g}, ${this.b})`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to HSL
|
||||
* 转换为 HSL
|
||||
*/
|
||||
toHSL(): HSL {
|
||||
return Color.rgbToHsl(this.r, this.g, this.b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack to uint32 (0xRRGGBB)
|
||||
* 打包为 uint32 (0xRRGGBB)
|
||||
*/
|
||||
toUint32(): number {
|
||||
return Color.packRGB(this.r, this.g, this.b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack to uint32 with alpha (0xAARRGGBB)
|
||||
* 打包为带透明度的 uint32 (0xAARRGGBB)
|
||||
*/
|
||||
toUint32Alpha(): number {
|
||||
return Color.packARGB(this.r, this.g, this.b, this.a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack to WebGL uint32 (0xAABBGGRR)
|
||||
* 打包为 WebGL 格式 uint32 (0xAABBGGRR)
|
||||
*/
|
||||
toWebGL(): number {
|
||||
return Color.packABGR(this.r, this.g, this.b, this.a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get normalized float array [r, g, b, a] (0-1)
|
||||
* 获取归一化浮点数组 [r, g, b, a] (0-1)
|
||||
*/
|
||||
toFloatArray(): [number, number, number, number] {
|
||||
return [this.r / 255, this.g / 255, this.b / 255, this.a];
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this color
|
||||
* 克隆此颜色
|
||||
*/
|
||||
clone(): Color {
|
||||
return new Color(this.r, this.g, this.b, this.a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set color values
|
||||
* 设置颜色值
|
||||
*/
|
||||
set(r: number, g: number, b: number, a?: number): this {
|
||||
this.r = Math.round(Math.max(0, Math.min(255, r)));
|
||||
this.g = Math.round(Math.max(0, Math.min(255, g)));
|
||||
this.b = Math.round(Math.max(0, Math.min(255, b)));
|
||||
if (a !== undefined) {
|
||||
this.a = Math.max(0, Math.min(1, a));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy from another color
|
||||
* 从另一个颜色复制
|
||||
*/
|
||||
copy(other: Color): this {
|
||||
this.r = other.r;
|
||||
this.g = other.g;
|
||||
this.b = other.b;
|
||||
this.a = other.a;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check equality with another color
|
||||
* 检查与另一个颜色是否相等
|
||||
*/
|
||||
equals(other: Color): boolean {
|
||||
return this.r === other.r && this.g === other.g && this.b === other.b && this.a === other.a;
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation
|
||||
* 字符串表示
|
||||
*/
|
||||
toString(): string {
|
||||
return `Color(${this.r}, ${this.g}, ${this.b}, ${this.a})`;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
* - 碰撞检测算法
|
||||
* - 动画插值和缓动函数
|
||||
* - 数学工具函数
|
||||
* - 颜色工具类
|
||||
*/
|
||||
|
||||
// 核心数学类
|
||||
@@ -18,6 +19,9 @@ export { Circle } from './Circle';
|
||||
// 数学工具
|
||||
export { MathUtils } from './MathUtils';
|
||||
|
||||
// 颜色工具
|
||||
export { Color, type RGBA, type HSL } from './Color';
|
||||
|
||||
// 碰撞检测
|
||||
export * from './Collision';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user