Add back-mounted shield model tied to shield skill
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 19 KiB |
@@ -44,6 +44,7 @@ export class Player {
|
|||||||
mixer!: THREE.AnimationMixer;
|
mixer!: THREE.AnimationMixer;
|
||||||
private clips: Map<string, THREE.AnimationAction> = new Map();
|
private clips: Map<string, THREE.AnimationAction> = new Map();
|
||||||
private currentAnim = '';
|
private currentAnim = '';
|
||||||
|
private backShield: THREE.Group | null = null;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.body = new THREE.Group();
|
this.body = new THREE.Group();
|
||||||
@@ -88,6 +89,49 @@ export class Player {
|
|||||||
shadow.renderOrder = 999;
|
shadow.renderOrder = 999;
|
||||||
this.body.add(shadow);
|
this.body.add(shadow);
|
||||||
|
|
||||||
|
// Shield on the back while the shield skill is charged
|
||||||
|
loadGLB('shield').then((gltf) => {
|
||||||
|
const shieldModel = gltf.scene;
|
||||||
|
const shieldTexture = new THREE.TextureLoader().load('./textures/shield.png');
|
||||||
|
shieldTexture.flipY = false;
|
||||||
|
shieldTexture.colorSpace = THREE.SRGBColorSpace;
|
||||||
|
shieldModel.traverse((child) => {
|
||||||
|
if (child instanceof THREE.Mesh) {
|
||||||
|
const geo = child.geometry;
|
||||||
|
// The converted model has no UVs; project them from the
|
||||||
|
// front plane so the shield texture maps onto the face
|
||||||
|
if (!geo.attributes.uv) {
|
||||||
|
geo.computeBoundingBox();
|
||||||
|
const bb = geo.boundingBox!;
|
||||||
|
const pos = geo.attributes.position;
|
||||||
|
const uv = new Float32Array(pos.count * 2);
|
||||||
|
for (let i = 0; i < pos.count; i++) {
|
||||||
|
uv[i * 2] = (pos.getX(i) - bb.min.x) / (bb.max.x - bb.min.x);
|
||||||
|
uv[i * 2 + 1] = (pos.getY(i) - bb.min.y) / (bb.max.y - bb.min.y);
|
||||||
|
}
|
||||||
|
geo.setAttribute('uv', new THREE.BufferAttribute(uv, 2));
|
||||||
|
}
|
||||||
|
child.castShadow = true;
|
||||||
|
child.material = new THREE.MeshToonMaterial({ map: shieldTexture });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// The geometry is offset from the model origin; recenter it so
|
||||||
|
// rotation and scale act on the shield's center
|
||||||
|
const box = new THREE.Box3().setFromObject(shieldModel);
|
||||||
|
const center = box.getCenter(new THREE.Vector3());
|
||||||
|
shieldModel.position.sub(center);
|
||||||
|
const shield = new THREE.Group();
|
||||||
|
shield.add(shieldModel);
|
||||||
|
shield.scale.set(0.25, 0.25, 0.25);
|
||||||
|
shield.position.set(0, 0.85, -0.5);
|
||||||
|
shield.rotation.set(-0.15, Math.PI, 0);
|
||||||
|
shield.visible = this.stats.shield > 0 && this.shieldHp > 0;
|
||||||
|
this.backShield = shield;
|
||||||
|
this.body.add(shield);
|
||||||
|
}).catch(() => {
|
||||||
|
// No shield model available
|
||||||
|
});
|
||||||
|
|
||||||
// Weapons
|
// Weapons
|
||||||
this.leftHandWeapon = new Staff();
|
this.leftHandWeapon = new Staff();
|
||||||
this.rightHandWeapon = new Sword();
|
this.rightHandWeapon = new Sword();
|
||||||
@@ -206,6 +250,9 @@ export class Player {
|
|||||||
this.shieldTimer = 0;
|
this.shieldTimer = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.backShield) {
|
||||||
|
this.backShield.visible = this.stats.shield > 0 && this.shieldHp > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applySkillSystem(skills: SkillSystem) {
|
applySkillSystem(skills: SkillSystem) {
|
||||||
@@ -232,6 +279,9 @@ export class Player {
|
|||||||
if (this.stats.shield > 0 && this.shieldHp <= 0) {
|
if (this.stats.shield > 0 && this.shieldHp <= 0) {
|
||||||
this.shieldHp = this.stats.shield;
|
this.shieldHp = this.stats.shield;
|
||||||
}
|
}
|
||||||
|
if (this.backShield) {
|
||||||
|
this.backShield.visible = this.stats.shield > 0 && this.shieldHp > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
die() {
|
die() {
|
||||||
|
|||||||
Reference in New Issue
Block a user