Files

114 lines
3.5 KiB
JavaScript

/**
* Coin class - manages collectible coins with enhanced visuals
*/
class Coin {
constructor(scene, lane) {
this.scene = scene;
this.mesh = null;
this.glowMesh = null;
this.createMesh(lane);
}
createMesh(lane) {
// Create procedural texture for coin
const canvas = document.createElement('canvas');
canvas.width = 128;
canvas.height = 64;
const ctx = canvas.getContext('2d');
// Gold gradient background
const gradient = ctx.createLinearGradient(0, 0, 128, 64);
gradient.addColorStop(0, '#ffd700');
gradient.addColorStop(0.3, '#ffec8b');
gradient.addColorStop(0.5, '#ffd700');
gradient.addColorStop(0.7, '#ffec8b');
gradient.addColorStop(1, '#daa520');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 128, 64);
// Inner ring
ctx.strokeStyle = '#b8860b';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.ellipse(64, 32, 45, 20, 0, 0, Math.PI * 2);
ctx.stroke();
// Star symbol in center
ctx.fillStyle = '#b8860b';
ctx.beginPath();
const cx = 64, cy = 32;
for (let i = 0; i < 5; i++) {
const angle = (i * 4 * Math.PI / 5) - Math.PI / 2;
const x = cx + Math.cos(angle) * 15;
const y = cy + Math.sin(angle) * 15;
if (i === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
}
ctx.closePath();
ctx.fill();
const texture = new THREE.CanvasTexture(canvas);
const geometry = new THREE.CylinderGeometry(0.5, 0.5, 0.15, 24);
const material = new THREE.MeshStandardMaterial({
map: texture,
color: 0xffd700,
emissive: 0xffd700,
emissiveIntensity: 0.6,
metalness: 0.9,
roughness: 0.1
});
const LANE_WIDTH = 3.5;
this.mesh = new THREE.Mesh(geometry, material);
this.mesh.position.set(lane * LANE_WIDTH, 1, -60);
this.mesh.rotation.x = Math.PI / 2;
// Outer glow ring
const glowGeometry = new THREE.TorusGeometry(0.6, 0.12, 8, 32);
const glowMaterial = new THREE.MeshBasicMaterial({
color: 0xffd700,
transparent: true,
opacity: 0.4
});
this.glowMesh = new THREE.Mesh(glowGeometry, glowMaterial);
this.glowMesh.rotation.x = Math.PI / 2;
this.mesh.add(this.glowMesh);
// Add point light for glow
const coinLight = new THREE.PointLight(0xffd700, 0.4, 3);
this.mesh.add(coinLight);
this.scene.add(this.mesh);
}
update(gameSpeed) {
this.mesh.position.z += gameSpeed;
// Rotate coin
this.mesh.rotation.z += 0.05;
this.glowMesh.rotation.z -= 0.03;
// Bobbing motion
this.mesh.position.y = 1 + Math.sin(Date.now() * 0.005) * 0.15;
}
isPastCamera() {
return this.mesh.position.z > 15;
}
checkCollection(playerPosition) {
const dx = Math.abs(this.mesh.position.x - playerPosition.x);
const dz = Math.abs(this.mesh.position.z - playerPosition.z);
return dx < 1 && dz < 1;
}
dispose() {
this.scene.remove(this.mesh);
}
}