import * as THREE from 'three' import gsap from 'gsap' import { loadGltf } from './library/loadgltf.js' import potionIconVertex from './shaders/potionicon/vertex.glsl' import potionIconFragment from './shaders/potionicon/fragment.glsl' export default class Shopper { constructor(game, meshPath, potionInfo, scale, position, rotation, updateFunction) { this.game = game this.meshPath = meshPath this.desiredPotion = potionInfo this.scale = scale this.position = position this.rotation = rotation this.updateFunction = updateFunction this.rejectCount = 0 this.rejectionColors = [ new THREE.Color("yellow"), new THREE.Color("orange"), new THREE.Color("crimson") ] } async init() { const reaperMesh = await loadGltf(this.game, this.meshPath) reaperMesh.scale.copy(this.scale) this.object3d = new THREE.Group() this.object3d.add(reaperMesh) this.object3d.position.set(-15, 0.1, 10) this.object3d.rotateOnAxis(THREE.Object3D.DEFAULT_UP, this.rotation) this.game.scene.add(this.object3d) const defaultPlane = new THREE.PlaneGeometry(1, 1) const speechBubbleTexture = this.game.textureLoader.load('./textures/speechbubble.png') const textBubbleMaterial = new THREE.MeshBasicMaterial({ map: speechBubbleTexture, transparent: true, side: THREE.DoubleSide, }) const potionIconTexture = this.game.textureLoader.load(this.desiredPotion.image) const potionIconUniforms = { uPotionIcon: { value: potionIconTexture } } const potionIcon = new THREE.Mesh(defaultPlane.clone(), new THREE.ShaderMaterial({ uniforms: potionIconUniforms, vertexShader: potionIconVertex, fragmentShader: potionIconFragment, transparent: true, })) potionIcon.position.y = 0.085 potionIcon.position.z = 0.05 potionIcon.scale.set(0.5, 0.5, 0.5) this.requestBillboard = new THREE.Group() this.billboardSprite = new THREE.Mesh(defaultPlane.clone(), textBubbleMaterial) this.requestBillboard.add(this.billboardSprite) this.requestBillboard.add(potionIcon) this.requestBillboard.position.x = 0 this.requestBillboard.position.y = 2.5 this.requestBillboard.position.z = 0 this.requestBillboard.visible = false this.object3d.add(this.requestBillboard) gsap.to(this.object3d.position, {duration: 2, x: this.position.x, y: this.position.y, z: this.position.z}) } update(elapsedTime) { this.updateFunction(elapsedTime) } showDesire() { if (this.object3d.wantIsAnimating) { return } this.object3d.wantIsAnimating = true this.object3d.wantIsAnimating = true this.requestBillboard.lookAt(this.game.camera.position) this.requestBillboard.visible = true this.requestBillboard.position.set(0, 0.5, 0) this.requestBillboard.scale.set(0, 0, 0) gsap.to(this.requestBillboard.position, { duration: 2, y: 2.5, ease: "elastic", onUpdate: () => { this.requestBillboard.lookAt(this.game.camera.position) } }) gsap.to(this.requestBillboard.scale, { duration: 2, x: 1, y: 1, z: 1, ease: "elastic", onComplete: () => { this.object3d.wantIsAnimating = false } }) } hideDesire() { this.object3d.wantIsAnimating = true gsap.to(this.requestBillboard.position, { duration: 2, y: 0.5, ease: "back" }) gsap.to(this.requestBillboard.scale, { duration: 2, x: 0, y: 0, z: 0, ease: "back", onComplete: () => { this.requestBillboard.visible = false this.object3d.wantIsAnimating = false } }) } acceptPotion() { //give money //show happy billboard } rejectPotion(rejectAmount = 1) { this.rejectCount += rejectAmount this.billboardSprite.material.color = this.rejectionColors[Math.min(2, this.rejectCount - 1)] } showSad() { //show sad billboard console.log("not what I wanted") } isMatchingPotion(possiblePotionInfo) { return this.desiredPotion.name == possiblePotionInfo.name } }