mirror of
https://github.com/101island/lolisland.us.git
synced 2026-03-01 19:50:02 +08:00
feat: add velocity vector display
This commit is contained in:
@@ -12,6 +12,7 @@ import Particles from "./Particles.astro";
|
||||
<div class="halo"></div>
|
||||
<div class="grain"></div>
|
||||
<div id="marble-field"></div>
|
||||
<canvas id="debug-velocity-canvas"></canvas>
|
||||
<Footer />
|
||||
|
||||
<div class="content">
|
||||
@@ -315,6 +316,16 @@ import Particles from "./Particles.astro";
|
||||
transition: opacity 0.5s ease;
|
||||
}
|
||||
|
||||
#debug-velocity-canvas {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
:global(.marble-wrapper) {
|
||||
position: absolute;
|
||||
will-change: transform, width, height;
|
||||
|
||||
@@ -48,6 +48,12 @@ export const MARBLE_CONFIG = {
|
||||
sensitivity: 600, // Sensitivity
|
||||
maxForce: 6000, // Maximum force limit
|
||||
},
|
||||
// Debug configuration
|
||||
debug: {
|
||||
enabled: true, // Enable debug mode by default
|
||||
vectorScale: 0.5, // Velocity vector scale factor
|
||||
canvasId: "debug-velocity-canvas", // Debug canvas element ID
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const AVATAR_BASE_URL = "https://avatar.awfufu.com/qq/";
|
||||
|
||||
@@ -11,6 +11,8 @@ export interface PhysicsConfig {
|
||||
minSpeed?: number; // Minimum speed
|
||||
maxSpeed?: number; // Maximum speed
|
||||
enableCollisions?: boolean; // Enable/Disable collisions
|
||||
debugCanvas?: HTMLCanvasElement | null; // Optional canvas for debug rendering
|
||||
debugVectorScale?: number; // Scale factor for velocity vectors (default: 0.5)
|
||||
}
|
||||
|
||||
export class MarblePhysics {
|
||||
@@ -26,6 +28,8 @@ export class MarblePhysics {
|
||||
minSpeed: config.minSpeed ?? 30,
|
||||
maxSpeed: config.maxSpeed ?? 800,
|
||||
enableCollisions: config.enableCollisions ?? true,
|
||||
debugCanvas: config.debugCanvas ?? null,
|
||||
debugVectorScale: config.debugVectorScale ?? 0.5,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -226,4 +230,60 @@ export class MarblePhysics {
|
||||
public getConfig(): PhysicsConfig {
|
||||
return { ...this.config };
|
||||
}
|
||||
|
||||
// Render debug velocity vectors on canvas
|
||||
public renderDebugVectors(marbles: Marble[]): void {
|
||||
const canvas = this.config.debugCanvas;
|
||||
if (!canvas) return;
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
if (!ctx) return;
|
||||
|
||||
const scale = this.config.debugVectorScale ?? 0.5;
|
||||
|
||||
// Clear canvas
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
for (const m of marbles) {
|
||||
const speed = Math.hypot(m.vx, m.vy);
|
||||
if (speed < 1) continue; // Skip very slow marbles
|
||||
|
||||
// Calculate arrow end point
|
||||
const endX = m.x + m.vx * scale;
|
||||
const endY = m.y + m.vy * scale;
|
||||
|
||||
// Color based on speed (green -> yellow -> red)
|
||||
const normalizedSpeed = Math.min(speed / 500, 1);
|
||||
const hue = (1 - normalizedSpeed) * 120; // 120=green, 0=red
|
||||
ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`;
|
||||
ctx.fillStyle = `hsl(${hue}, 100%, 50%)`;
|
||||
ctx.lineWidth = 2;
|
||||
|
||||
// Draw line
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(m.x, m.y);
|
||||
ctx.lineTo(endX, endY);
|
||||
ctx.stroke();
|
||||
|
||||
// Draw arrowhead
|
||||
const arrowSize = 8;
|
||||
const angle = Math.atan2(m.vy, m.vx);
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(endX, endY);
|
||||
ctx.lineTo(
|
||||
endX - arrowSize * Math.cos(angle - Math.PI / 6),
|
||||
endY - arrowSize * Math.sin(angle - Math.PI / 6),
|
||||
);
|
||||
ctx.lineTo(
|
||||
endX - arrowSize * Math.cos(angle + Math.PI / 6),
|
||||
endY - arrowSize * Math.sin(angle + Math.PI / 6),
|
||||
);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
|
||||
// Draw speed text
|
||||
ctx.font = "10px monospace";
|
||||
ctx.fillText(`${speed.toFixed(0)}`, m.x + 5, m.y - 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,11 +40,26 @@ export class MarbleSystem {
|
||||
private fieldWidth: number;
|
||||
private fieldHeight: number;
|
||||
|
||||
// Debug mode
|
||||
private debugMode: boolean = MARBLE_CONFIG.debug.enabled;
|
||||
private debugCanvas: HTMLCanvasElement | null = null;
|
||||
|
||||
constructor(config: MarbleSystemConfig) {
|
||||
this.container = config.container;
|
||||
this.fieldWidth = config.fieldWidth;
|
||||
this.fieldHeight = config.fieldHeight;
|
||||
|
||||
// Debug Canvas Init
|
||||
if (MARBLE_CONFIG.debug.enabled) {
|
||||
this.debugCanvas = document.getElementById(
|
||||
MARBLE_CONFIG.debug.canvasId,
|
||||
) as HTMLCanvasElement | null;
|
||||
if (this.debugCanvas) {
|
||||
this.debugCanvas.width = this.fieldWidth;
|
||||
this.debugCanvas.height = this.fieldHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// MouseInteraction Init
|
||||
const mouseConfig: MouseInteractionConfig = {
|
||||
attractRadius:
|
||||
@@ -83,6 +98,8 @@ export class MarbleSystem {
|
||||
wallBounce: MARBLE_CONFIG.physics.wallBounce,
|
||||
minSpeed: MARBLE_CONFIG.physics.minSpeed,
|
||||
maxSpeed: MARBLE_CONFIG.physics.maxSpeed,
|
||||
debugCanvas: this.debugCanvas,
|
||||
debugVectorScale: MARBLE_CONFIG.debug.vectorScale,
|
||||
});
|
||||
|
||||
// MarbleFactory Init
|
||||
@@ -122,6 +139,11 @@ export class MarbleSystem {
|
||||
this.physics.handleCollisions(this.marbles);
|
||||
this.physics.handleBoundaries(this.marbles);
|
||||
this.physics.render(this.marbles);
|
||||
|
||||
// Render debug vectors if enabled
|
||||
if (this.debugMode) {
|
||||
this.physics.renderDebugVectors(this.marbles);
|
||||
}
|
||||
}
|
||||
|
||||
// Set up window resize listener
|
||||
@@ -249,4 +271,38 @@ export class MarbleSystem {
|
||||
public setCollisions(enabled: boolean): void {
|
||||
this.physics.updateConfig({ enableCollisions: enabled });
|
||||
}
|
||||
|
||||
// Toggle debug mode (show velocity vectors)
|
||||
public setDebugMode(enabled: boolean): void {
|
||||
this.debugMode = enabled;
|
||||
|
||||
// Get canvas from DOM if not already cached
|
||||
if (!this.debugCanvas) {
|
||||
this.debugCanvas = document.getElementById(
|
||||
MARBLE_CONFIG.debug.canvasId,
|
||||
) as HTMLCanvasElement | null;
|
||||
}
|
||||
|
||||
if (this.debugCanvas) {
|
||||
if (enabled) {
|
||||
// Show canvas and configure physics
|
||||
this.debugCanvas.style.display = "block";
|
||||
this.debugCanvas.width = this.fieldWidth;
|
||||
this.debugCanvas.height = this.fieldHeight;
|
||||
this.physics.updateConfig({ debugCanvas: this.debugCanvas });
|
||||
} else {
|
||||
// Hide canvas and clear
|
||||
this.debugCanvas.style.display = "none";
|
||||
const ctx = this.debugCanvas.getContext("2d");
|
||||
if (ctx)
|
||||
ctx.clearRect(0, 0, this.debugCanvas.width, this.debugCanvas.height);
|
||||
this.physics.updateConfig({ debugCanvas: null });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get debug mode status
|
||||
public isDebugMode(): boolean {
|
||||
return this.debugMode;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user