Add game source, converter pipeline, and web port
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
import * as THREE from 'three';
|
||||
import { Weapon } from './Weapon';
|
||||
import { Player } from './Player';
|
||||
import { Fireball } from './Fireball';
|
||||
import { playSound } from './SoundManager';
|
||||
import { loadGLB } from './MeshLoader';
|
||||
|
||||
export class Staff extends Weapon {
|
||||
constructor() {
|
||||
super();
|
||||
this.COOLDOWN1_TIME = 5;
|
||||
this.COOLDOWN2_TIME = 50;
|
||||
|
||||
// Fallback geometry
|
||||
const shaftGeom = new THREE.CylinderGeometry(0.04, 0.05, 1.0, 8);
|
||||
const crystalGeom = new THREE.OctahedronGeometry(0.08);
|
||||
const woodMat = new THREE.MeshToonMaterial({ color: 0x8B4513 });
|
||||
const crystalMat = new THREE.MeshToonMaterial({ color: 0x4488ff });
|
||||
const shaft = new THREE.Mesh(shaftGeom, woodMat);
|
||||
shaft.position.y = 0.3;
|
||||
shaft.castShadow = true;
|
||||
const crystal = new THREE.Mesh(crystalGeom, crystalMat);
|
||||
crystal.position.y = 0.9;
|
||||
this.mesh.add(shaft);
|
||||
this.mesh.add(crystal);
|
||||
|
||||
this.mesh.position.set(0.35, 0.3, 0.35);
|
||||
this.mesh.scale.set(0.35, 0.35, 0.35);
|
||||
this.mesh.rotation.set(-0.2, 0, -0.2);
|
||||
}
|
||||
|
||||
async init() {
|
||||
try {
|
||||
const gltf = await loadGLB('staff');
|
||||
const model = gltf.scene;
|
||||
const staffTexture = new THREE.TextureLoader().load('./textures/staff1.png');
|
||||
staffTexture.flipY = false;
|
||||
staffTexture.colorSpace = THREE.SRGBColorSpace;
|
||||
model.traverse((child) => {
|
||||
if (child instanceof THREE.Mesh) {
|
||||
child.castShadow = true;
|
||||
child.material = new THREE.MeshToonMaterial({ map: staffTexture });
|
||||
}
|
||||
});
|
||||
while (this.mesh.children.length > 0) {
|
||||
this.mesh.remove(this.mesh.children[0]);
|
||||
}
|
||||
this.mesh.add(model);
|
||||
} catch {
|
||||
// Keep fallback
|
||||
}
|
||||
}
|
||||
|
||||
skill1(groundPoint: THREE.Vector3, player: Player): void {
|
||||
if (this.cooldown1 > 0) return;
|
||||
this.cooldown1 = this.COOLDOWN1_TIME;
|
||||
|
||||
// Spawn at staff height, fly toward the cursor point
|
||||
const spawnPos = player.body.position.clone();
|
||||
spawnPos.y += 0.8;
|
||||
|
||||
const dir = new THREE.Vector3()
|
||||
.subVectors(groundPoint, spawnPos)
|
||||
.normalize()
|
||||
.multiplyScalar(25);
|
||||
dir.setY(0);
|
||||
|
||||
const fb = new Fireball(spawnPos, dir);
|
||||
player.game.scene.add(fb.body);
|
||||
player.game.fireballs.push(fb);
|
||||
playSound('fireball', 0.5);
|
||||
}
|
||||
|
||||
skill2(groundPoint: THREE.Vector3, player: Player): void {
|
||||
if (this.cooldown2 > 0) return;
|
||||
this.cooldown2 = this.COOLDOWN2_TIME;
|
||||
|
||||
const newPos = groundPoint.clone();
|
||||
newPos.y = 0.5;
|
||||
newPos.x = Math.max(-47, Math.min(47, newPos.x));
|
||||
newPos.z = Math.max(-47, Math.min(47, newPos.z));
|
||||
player.body.position.copy(newPos);
|
||||
playSound('teleport', 0.5);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user