I tried to make a method that crushes other characters while sliding Koopa, but the sound effect works more than once when hitting characters. How can I prevent this?
`import { Trait } from '../Trait.js';
export default class Screamer extends Trait {
constructor() {
super('screamer');
}
async collides(us, them) {
if (!them.killable.screaming) {
return;
}
if (them.vel.x < us.vel.x) {
this.sounds.add('fireworks');
await this.events.emit('scream', us, them);
}
}
`}``
`import Entity from '../Entity.js';
import { Trait } from '../Trait.js';
import Killable from '../traits/Killable.js';
import PendulumMove from '../traits/PendulumMove.js';
import Physics from '../traits/Physics.js';
import Solid from '../traits/Solid.js';
import Screamer from '../traits/Screamer.js';
import { loadAudioBoard } from '../loaders/audio.js';
import { loadSpriteSheet } from '../loaders.js';
export function loadKoopa(audioContext) {
return Promise.all([
loadSpriteSheet('koopa'),
loadAudioBoard('koopa', audioContext),
])
.then(([sprite, audio]) => {
return createKoopaFactory(sprite, audio);
});
}
const STATE_WALKING = Symbol('walking');
const STATE_HIDING = Symbol('hiding');
const STATE_PANIC = Symbol('panic');
class Behavior extends Trait {
constructor() {
super('behavior');
this.hideTime = 0;
this.hideDuration = 5;
this.walkSpeed = null;
this.panicSpeed = 300;// default
this.state = STATE_WALKING;
}
collides(us, them) {
if (us.killable.dead) {
return;
}
if (us.screamer) {
this.handleSlip(us, them);
}
if (them.stomper) {
if (them.vel.y > us.vel.y) {
this.handleStomp(us, them);
} else {
this.handleNudge(us, them);
}
}
}
handleNudge(us, them) {
if (this.state === STATE_WALKING) {
them.killable.kill();
} else if (this.state === STATE_HIDING) {
this.panic(us, them);
} else if (this.state === STATE_PANIC) {
const travelDir = Math.sign(us.vel.x);
const impactDir = Math.sign(us.pos.x - them.pos.x);
if (travelDir !== 0 && travelDir !== impactDir) {
them.killable.kill();
}
}
}
handleStomp(us, them) {
if (this.state === STATE_WALKING) {
this.hide(us);
} else if (this.state === STATE_HIDING) {
us.killable.kill();
us.vel.set(100, -200);
us.solid.obstructs = false;
} else if (this.state === STATE_PANIC) {
this.hide(us);
}
}
//us-->Etkileşime giren them-->Etkileşime girilen
async handleSlip(us, them) {
if (this.state === STATE_PANIC) {
const travelDir = Math.sign(us.vel.x);
const impactDir = Math.sign(us.pos.x - them.pos.x);
if (travelDir !== 0 && travelDir !== impactDir) {
if (them.name !== 'Mario') {
them.killable.kill();
them.vel.set(100, -200);
them.solid.obstructs = false;
}
await them.killable.scream();
}
}
}
hide(us) {
us.vel.x = 0;
us.pendulumMove.enabled = false;
if (this.walkSpeed === null) {
this.walkSpeed = us.pendulumMove.speed;
}
this.hideTime = 0;
this.state = STATE_HIDING
}
unhide(us) {
us.pendulumMove.enabled = true;
us.pendulumMove.speed = this.walkSpeed;
this.state = STATE_WALKING;
}
panic(us, them) {
us.pendulumMove.enabled = true;
us.pendulumMove.speed = this.panicSpeed * Math.sign(them.vel.x);
this.state = STATE_PANIC;
}
update(us, { deltaTime }) {
if (this.state === STATE_HIDING) {
this.hideTime += deltaTime;
if (this.hideTime > this.hideDuration) {
this.unhide(us);
}
}
}
}
function createKoopaFactory(sprite, audio) {
const walkAnim = sprite.animations.get('walk');
const wakeAnim = sprite.animations.get('wake');
function routeAnim(koopa) {
if (koopa.behavior.state === STATE_HIDING) {
if (koopa.behavior.hideTime > 3) {
return wakeAnim(koopa.behavior.hideTime);
}
return 'hiding';
}
if (koopa.behavior.state === STATE_PANIC) {
return 'hiding';
}
if (koopa.killable.screaming) {
return 'upsidedown'
}
return walkAnim(koopa.lifetime);
}
function drawKoopa(context) {
sprite.draw(routeAnim(this), context, 0, 0, this.vel.x < 0);
}
return function createKoopa() {
const koopa = new Entity("Koopa");
koopa.size.set(16, 16);
koopa.offset.y = 8;
koopa.audio = audio;
koopa.addTrait(new Physics());
koopa.addTrait(new Solid());
koopa.addTrait(new PendulumMove());
koopa.addTrait(new Killable());
koopa.addTrait(new Behavior());
koopa.addTrait(new Screamer());
koopa.draw = drawKoopa;
return koopa;
};
}
`

I tried to make a method that crushes other characters while sliding Koopa, but the sound effect works more than once when hitting characters. How can I prevent this?
`import { Trait } from '../Trait.js';
export default class Screamer extends Trait {
constructor() {
super('screamer');
}
async collides(us, them) {
if (!them.killable.screaming) {
return;
}
if (them.vel.x < us.vel.x) {
this.sounds.add('fireworks');
await this.events.emit('scream', us, them);
}
}
`}``
`import Entity from '../Entity.js';
import { Trait } from '../Trait.js';
import Killable from '../traits/Killable.js';
import PendulumMove from '../traits/PendulumMove.js';
import Physics from '../traits/Physics.js';
import Solid from '../traits/Solid.js';
import Screamer from '../traits/Screamer.js';
import { loadAudioBoard } from '../loaders/audio.js';
import { loadSpriteSheet } from '../loaders.js';
export function loadKoopa(audioContext) {
return Promise.all([
loadSpriteSheet('koopa'),
loadAudioBoard('koopa', audioContext),
])
.then(([sprite, audio]) => {
return createKoopaFactory(sprite, audio);
});
}
const STATE_WALKING = Symbol('walking');
const STATE_HIDING = Symbol('hiding');
const STATE_PANIC = Symbol('panic');
class Behavior extends Trait {
constructor() {
super('behavior');
}
function createKoopaFactory(sprite, audio) {
const walkAnim = sprite.animations.get('walk');
const wakeAnim = sprite.animations.get('wake');
}
`