implement sounds
This commit is contained in:
@@ -62,6 +62,11 @@ window.GameWindow = class {
|
||||
|
||||
// Mouse buttons
|
||||
document.addEventListener('click', function (event) {
|
||||
// Create sound engine (It has to be created after user interaction)
|
||||
if(!minecraft.soundManager.isCreated()) {
|
||||
minecraft.soundManager.create(minecraft.worldRenderer);
|
||||
}
|
||||
|
||||
// Handle in-game mouse click
|
||||
minecraft.onMouseClicked(event.button);
|
||||
|
||||
|
||||
@@ -45,6 +45,9 @@ window.Minecraft = class {
|
||||
this.world = new World(this);
|
||||
this.worldRenderer.scene.add(this.world.group);
|
||||
|
||||
// Create sound manager
|
||||
this.soundManager = new SoundManager();
|
||||
|
||||
// Create player
|
||||
this.player = new Player(this, this.world);
|
||||
this.inventory = new Inventory();
|
||||
@@ -200,7 +203,19 @@ window.Minecraft = class {
|
||||
// Destroy block
|
||||
if (button === 0) {
|
||||
if (hitResult != null) {
|
||||
this.world.setBlockAt(hitResult.x, hitResult.y, hitResult.z, 0);
|
||||
// Get previous block
|
||||
let typeId = this.world.getBlockAt(hitResult.x, hitResult.y, hitResult.z);
|
||||
let block = Block.getById(typeId);
|
||||
|
||||
if (typeId !== 0) {
|
||||
let soundName = block.getSound().getBreakSound();
|
||||
|
||||
// Play sound
|
||||
this.soundManager.playSound(soundName, hitResult.x + 0.5, hitResult.y + 0.5, hitResult.z + 0.5, 1.0);
|
||||
|
||||
// Destroy block
|
||||
this.world.setBlockAt(hitResult.x, hitResult.y, hitResult.z, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,13 +242,17 @@ window.Minecraft = class {
|
||||
if (!placedBoundingBox.intersects(this.player.boundingBox)) {
|
||||
let typeId = this.inventory.getItemInSelectedSlot();
|
||||
if (typeId !== 0) {
|
||||
|
||||
// Place block
|
||||
this.world.setBlockAt(x, y, z, typeId);
|
||||
|
||||
// Handle block abilities
|
||||
let block = Block.getById(typeId);
|
||||
block.onBlockPlaced(this.world, x, y, z, hitResult.face);
|
||||
|
||||
// Play sound
|
||||
let sound = block.getSound();
|
||||
let soundName = sound.getStepSound();
|
||||
this.soundManager.playSound(soundName, hitResult.x + 0.5, hitResult.y + 0.5, hitResult.z + 0.5, sound.getPitch() * 0.8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,9 @@ window.Player = class {
|
||||
this.prevFovModifier = 0;
|
||||
this.fovModifier = 0;
|
||||
this.timeFovChanged = 0;
|
||||
|
||||
this.distanceWalked = 0;
|
||||
this.nextStepDistance = 0;
|
||||
}
|
||||
|
||||
respawn() {
|
||||
@@ -242,6 +245,9 @@ window.Player = class {
|
||||
travel(forward, vertical, strafe) {
|
||||
let prevSlipperiness = this.getBlockSlipperiness() * 0.91;
|
||||
|
||||
let prevX = this.x;
|
||||
let prevZ = this.z;
|
||||
|
||||
let value = 0.16277136 / (prevSlipperiness * prevSlipperiness * prevSlipperiness);
|
||||
let friction;
|
||||
|
||||
@@ -268,6 +274,28 @@ window.Player = class {
|
||||
this.motionX *= slipperiness;
|
||||
this.motionY *= 0.98;
|
||||
this.motionZ *= slipperiness;
|
||||
|
||||
let blockX = MathHelper.floor_double(this.x);
|
||||
let blockY = MathHelper.floor_double(this.y - 0.2);
|
||||
let blockZ = MathHelper.floor_double(this.z);
|
||||
let typeId = this.world.getBlockAt(blockX, blockY, blockZ);
|
||||
|
||||
let distanceX = this.x - prevX;
|
||||
let distanceZ = this.z - prevZ;
|
||||
|
||||
// Step sound
|
||||
this.distanceWalked += Math.sqrt(distanceX * distanceX + distanceZ * distanceZ) * 0.6;
|
||||
if (this.distanceWalked > this.nextStepDistance && typeId !== 0) {
|
||||
this.nextStepDistance++;
|
||||
|
||||
let block = Block.getById(typeId);
|
||||
let sound = block.getSound();
|
||||
|
||||
// Play sound
|
||||
if (!block.isLiquid()) {
|
||||
this.minecraft.soundManager.playSound(sound.getStepSound(), this.x, this.y, this.z, sound.getPitch());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getBlockSlipperiness() {
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
window.SoundManager = class {
|
||||
|
||||
constructor() {
|
||||
this.audioLoader = new THREE.AudioLoader();
|
||||
this.audioListener = null;
|
||||
|
||||
this.soundPool = [];
|
||||
}
|
||||
|
||||
create(worldRenderer) {
|
||||
this.scene = worldRenderer.scene;
|
||||
|
||||
this.audioListener = new THREE.AudioListener();
|
||||
worldRenderer.camera.add(this.audioListener);
|
||||
|
||||
// Load initial sound pool
|
||||
for (let i in Block.sounds) {
|
||||
let sound = Block.sounds[i];
|
||||
|
||||
// Load sound types
|
||||
this.loadSoundPool(sound.getStepSound());
|
||||
}
|
||||
}
|
||||
|
||||
loadSoundPool(name) {
|
||||
let pool = [];
|
||||
let amount = 4;
|
||||
|
||||
// Load all sounds into pool
|
||||
let path = name.replace(".", "/");
|
||||
for (let i = 0; i < amount; i++) {
|
||||
let sound = this.loadSound('src/resources/sound/' + path + (i + 1) + '.ogg');
|
||||
pool.push(sound);
|
||||
}
|
||||
|
||||
// Register sound pool
|
||||
this.soundPool[name] = pool;
|
||||
}
|
||||
|
||||
loadSound(path) {
|
||||
let scope = this;
|
||||
|
||||
// Create sound
|
||||
let sound = new THREE.PositionalAudio(this.audioListener);
|
||||
sound.setRefDistance(0.1);
|
||||
sound.setRolloffFactor(6);
|
||||
sound.setFilter(sound.context.createBiquadFilter());
|
||||
|
||||
// Load sound
|
||||
this.audioLoader.load(path, function (buffer) {
|
||||
sound.setBuffer(buffer);
|
||||
scope.scene.add(sound);
|
||||
});
|
||||
|
||||
return sound;
|
||||
}
|
||||
|
||||
playSound(name, x, y, z, pitch) {
|
||||
let pool = this.soundPool[name];
|
||||
|
||||
if (typeof pool === "undefined") {
|
||||
// Load sound pool
|
||||
this.loadSoundPool(name);
|
||||
} else if (pool.length > 0) {
|
||||
// Play random sound in pool
|
||||
let sound = pool[Math.floor(Math.random() * pool.length)];
|
||||
|
||||
// Stop previous sound
|
||||
if (sound.isPlaying) {
|
||||
sound.stop();
|
||||
}
|
||||
|
||||
// Update position
|
||||
sound.position.set(x, y, z);
|
||||
|
||||
// Update pitch
|
||||
sound.filters[0].frequency.setValueAtTime(12000 * pitch, sound.context.currentTime);
|
||||
|
||||
// Play sound
|
||||
sound.play();
|
||||
}
|
||||
}
|
||||
|
||||
isCreated() {
|
||||
return !(this.audioListener === null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,18 @@ window.Block = class {
|
||||
|
||||
static blocks = new Map();
|
||||
|
||||
static sounds = {};
|
||||
|
||||
static create() {
|
||||
// Sounds
|
||||
Block.sounds.stone = new Sound("stone", 1.0);
|
||||
Block.sounds.wood = new Sound("wood", 1.0);
|
||||
Block.sounds.gravel = new Sound("gravel", 1.0);
|
||||
Block.sounds.grass = new Sound("grass", 1.0);
|
||||
Block.sounds.cloth = new Sound("cloth", 1.0);
|
||||
Block.sounds.sand = new Sound("sand", 1.0);
|
||||
|
||||
// Blocks
|
||||
Block.STONE = new BlockStone(1, 0);
|
||||
Block.GRASS = new BlockGrass(2, 1);
|
||||
Block.DIRT = new BlockDirt(3, 2);
|
||||
@@ -17,8 +28,12 @@ window.Block = class {
|
||||
this.id = id;
|
||||
this.textureSlotId = textureSlotId;
|
||||
|
||||
// Bounding box
|
||||
this.boundingBox = new BoundingBox(0.0, 0.0, 0.0, 1.0, 1.0, 1.0);
|
||||
|
||||
// Default sound
|
||||
this.sound = Block.sounds.stone;
|
||||
|
||||
// Register block
|
||||
Block.blocks.set(id, this);
|
||||
}
|
||||
@@ -60,6 +75,14 @@ window.Block = class {
|
||||
return true;
|
||||
}
|
||||
|
||||
isLiquid() {
|
||||
return false;
|
||||
}
|
||||
|
||||
getSound() {
|
||||
return this.sound;
|
||||
}
|
||||
|
||||
getBoundingBox(world, x, y, z) {
|
||||
return this.boundingBox;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ window.BlockDirt = class extends Block {
|
||||
|
||||
constructor(id, textureSlotId) {
|
||||
super(id, textureSlotId);
|
||||
|
||||
// Sound
|
||||
this.sound = Block.sounds.gravel;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,9 @@ window.BlockGrass = class extends Block {
|
||||
|
||||
constructor(id, textureSlotId) {
|
||||
super(id, textureSlotId);
|
||||
|
||||
// Sound
|
||||
this.sound = Block.sounds.grass;
|
||||
}
|
||||
|
||||
getTextureForFace(face) {
|
||||
|
||||
@@ -2,6 +2,9 @@ window.BlockLeave = class extends Block {
|
||||
|
||||
constructor(id, textureSlotId) {
|
||||
super(id, textureSlotId);
|
||||
|
||||
// Sound
|
||||
this.sound = Block.sounds.grass;
|
||||
}
|
||||
|
||||
getOpacity() {
|
||||
|
||||
@@ -2,6 +2,9 @@ window.BlockLog = class extends Block {
|
||||
|
||||
constructor(id, textureSlotId) {
|
||||
super(id, textureSlotId);
|
||||
|
||||
// Sound
|
||||
this.sound = Block.sounds.wood;
|
||||
}
|
||||
|
||||
getTextureForFace(face) {
|
||||
|
||||
@@ -2,6 +2,9 @@ window.BlockSand = class extends Block {
|
||||
|
||||
constructor(id, textureSlotId) {
|
||||
super(id, textureSlotId);
|
||||
|
||||
// Sound
|
||||
this.sound = Block.sounds.sand;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,9 @@ window.BlockTorch = class extends Block {
|
||||
|
||||
this.boundingBox = new BoundingBox(0.4, 0.0, 0.4, 0.6, 0.6, 0.6);
|
||||
|
||||
// Sound
|
||||
this.sound = Block.sounds.wood;
|
||||
|
||||
// Create data faces
|
||||
this.dataFaces = [
|
||||
EnumBlockFace.WEST,
|
||||
|
||||
@@ -12,6 +12,10 @@ window.BlockWater = class extends Block {
|
||||
return false;
|
||||
}
|
||||
|
||||
isLiquid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
canInteract() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
window.Sound = class {
|
||||
|
||||
constructor(name, pitch) {
|
||||
this.name = name;
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
getBreakSound() {
|
||||
return "step." + this.name;
|
||||
}
|
||||
|
||||
getStepSound() {
|
||||
return "step." + this.name;
|
||||
}
|
||||
|
||||
getPitch() {
|
||||
return this.pitch;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user