diff --git a/src/js/net/minecraft/client/GameWindow.js b/src/js/net/minecraft/client/GameWindow.js index 209c96d..3b3055a 100644 --- a/src/js/net/minecraft/client/GameWindow.js +++ b/src/js/net/minecraft/client/GameWindow.js @@ -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); diff --git a/src/js/net/minecraft/client/Minecraft.js b/src/js/net/minecraft/client/Minecraft.js index fe834cc..87070a8 100644 --- a/src/js/net/minecraft/client/Minecraft.js +++ b/src/js/net/minecraft/client/Minecraft.js @@ -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); } } } diff --git a/src/js/net/minecraft/client/entity/Player.js b/src/js/net/minecraft/client/entity/Player.js index f4f181f..2eaa0cd 100644 --- a/src/js/net/minecraft/client/entity/Player.js +++ b/src/js/net/minecraft/client/entity/Player.js @@ -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() { diff --git a/src/js/net/minecraft/client/sound/SoundManager.js b/src/js/net/minecraft/client/sound/SoundManager.js new file mode 100644 index 0000000..5b0a9b9 --- /dev/null +++ b/src/js/net/minecraft/client/sound/SoundManager.js @@ -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); + } + +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/world/block/Block.js b/src/js/net/minecraft/client/world/block/Block.js index 49e24d9..37f85fa 100644 --- a/src/js/net/minecraft/client/world/block/Block.js +++ b/src/js/net/minecraft/client/world/block/Block.js @@ -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; } diff --git a/src/js/net/minecraft/client/world/block/BlockDirt.js b/src/js/net/minecraft/client/world/block/BlockDirt.js index 3bbdf34..232e010 100644 --- a/src/js/net/minecraft/client/world/block/BlockDirt.js +++ b/src/js/net/minecraft/client/world/block/BlockDirt.js @@ -2,6 +2,9 @@ window.BlockDirt = class extends Block { constructor(id, textureSlotId) { super(id, textureSlotId); + + // Sound + this.sound = Block.sounds.gravel; } } \ No newline at end of file diff --git a/src/js/net/minecraft/client/world/block/BlockGrass.js b/src/js/net/minecraft/client/world/block/BlockGrass.js index 79ce0ce..408d63e 100644 --- a/src/js/net/minecraft/client/world/block/BlockGrass.js +++ b/src/js/net/minecraft/client/world/block/BlockGrass.js @@ -2,6 +2,9 @@ window.BlockGrass = class extends Block { constructor(id, textureSlotId) { super(id, textureSlotId); + + // Sound + this.sound = Block.sounds.grass; } getTextureForFace(face) { diff --git a/src/js/net/minecraft/client/world/block/BlockLeave.js b/src/js/net/minecraft/client/world/block/BlockLeave.js index 614b82d..b69ec12 100644 --- a/src/js/net/minecraft/client/world/block/BlockLeave.js +++ b/src/js/net/minecraft/client/world/block/BlockLeave.js @@ -2,6 +2,9 @@ window.BlockLeave = class extends Block { constructor(id, textureSlotId) { super(id, textureSlotId); + + // Sound + this.sound = Block.sounds.grass; } getOpacity() { diff --git a/src/js/net/minecraft/client/world/block/BlockLog.js b/src/js/net/minecraft/client/world/block/BlockLog.js index 5cd05b5..6e09af6 100644 --- a/src/js/net/minecraft/client/world/block/BlockLog.js +++ b/src/js/net/minecraft/client/world/block/BlockLog.js @@ -2,6 +2,9 @@ window.BlockLog = class extends Block { constructor(id, textureSlotId) { super(id, textureSlotId); + + // Sound + this.sound = Block.sounds.wood; } getTextureForFace(face) { diff --git a/src/js/net/minecraft/client/world/block/BlockSand.js b/src/js/net/minecraft/client/world/block/BlockSand.js index 32f895a..fd3bc49 100644 --- a/src/js/net/minecraft/client/world/block/BlockSand.js +++ b/src/js/net/minecraft/client/world/block/BlockSand.js @@ -2,6 +2,9 @@ window.BlockSand = class extends Block { constructor(id, textureSlotId) { super(id, textureSlotId); + + // Sound + this.sound = Block.sounds.sand; } } \ No newline at end of file diff --git a/src/js/net/minecraft/client/world/block/BlockTorch.js b/src/js/net/minecraft/client/world/block/BlockTorch.js index 3664a5e..9051a87 100644 --- a/src/js/net/minecraft/client/world/block/BlockTorch.js +++ b/src/js/net/minecraft/client/world/block/BlockTorch.js @@ -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, diff --git a/src/js/net/minecraft/client/world/block/BlockWater.js b/src/js/net/minecraft/client/world/block/BlockWater.js index 6755cb7..24ece1b 100644 --- a/src/js/net/minecraft/client/world/block/BlockWater.js +++ b/src/js/net/minecraft/client/world/block/BlockWater.js @@ -12,6 +12,10 @@ window.BlockWater = class extends Block { return false; } + isLiquid() { + return true; + } + canInteract() { return false; } diff --git a/src/js/net/minecraft/client/world/block/sound/Sound.js b/src/js/net/minecraft/client/world/block/sound/Sound.js new file mode 100644 index 0000000..d4f8753 --- /dev/null +++ b/src/js/net/minecraft/client/world/block/sound/Sound.js @@ -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; + } + +} \ No newline at end of file diff --git a/src/resources/sound/step/cloth1.ogg b/src/resources/sound/step/cloth1.ogg new file mode 100644 index 0000000..0ea73f8 Binary files /dev/null and b/src/resources/sound/step/cloth1.ogg differ diff --git a/src/resources/sound/step/cloth2.ogg b/src/resources/sound/step/cloth2.ogg new file mode 100644 index 0000000..a607a9e Binary files /dev/null and b/src/resources/sound/step/cloth2.ogg differ diff --git a/src/resources/sound/step/cloth3.ogg b/src/resources/sound/step/cloth3.ogg new file mode 100644 index 0000000..64b5ef9 Binary files /dev/null and b/src/resources/sound/step/cloth3.ogg differ diff --git a/src/resources/sound/step/cloth4.ogg b/src/resources/sound/step/cloth4.ogg new file mode 100644 index 0000000..b65ed79 Binary files /dev/null and b/src/resources/sound/step/cloth4.ogg differ diff --git a/src/resources/sound/step/grass1.ogg b/src/resources/sound/step/grass1.ogg new file mode 100644 index 0000000..12f5751 Binary files /dev/null and b/src/resources/sound/step/grass1.ogg differ diff --git a/src/resources/sound/step/grass2.ogg b/src/resources/sound/step/grass2.ogg new file mode 100644 index 0000000..05dff55 Binary files /dev/null and b/src/resources/sound/step/grass2.ogg differ diff --git a/src/resources/sound/step/grass3.ogg b/src/resources/sound/step/grass3.ogg new file mode 100644 index 0000000..e792b34 Binary files /dev/null and b/src/resources/sound/step/grass3.ogg differ diff --git a/src/resources/sound/step/grass4.ogg b/src/resources/sound/step/grass4.ogg new file mode 100644 index 0000000..8421e6a Binary files /dev/null and b/src/resources/sound/step/grass4.ogg differ diff --git a/src/resources/sound/step/gravel1.ogg b/src/resources/sound/step/gravel1.ogg new file mode 100644 index 0000000..97ae71e Binary files /dev/null and b/src/resources/sound/step/gravel1.ogg differ diff --git a/src/resources/sound/step/gravel2.ogg b/src/resources/sound/step/gravel2.ogg new file mode 100644 index 0000000..5133141 Binary files /dev/null and b/src/resources/sound/step/gravel2.ogg differ diff --git a/src/resources/sound/step/gravel3.ogg b/src/resources/sound/step/gravel3.ogg new file mode 100644 index 0000000..1b8debd Binary files /dev/null and b/src/resources/sound/step/gravel3.ogg differ diff --git a/src/resources/sound/step/gravel4.ogg b/src/resources/sound/step/gravel4.ogg new file mode 100644 index 0000000..94a0c1c Binary files /dev/null and b/src/resources/sound/step/gravel4.ogg differ diff --git a/src/resources/sound/step/sand1.ogg b/src/resources/sound/step/sand1.ogg new file mode 100644 index 0000000..e9cb62d Binary files /dev/null and b/src/resources/sound/step/sand1.ogg differ diff --git a/src/resources/sound/step/sand2.ogg b/src/resources/sound/step/sand2.ogg new file mode 100644 index 0000000..ce2eeb0 Binary files /dev/null and b/src/resources/sound/step/sand2.ogg differ diff --git a/src/resources/sound/step/sand3.ogg b/src/resources/sound/step/sand3.ogg new file mode 100644 index 0000000..c94fc1b Binary files /dev/null and b/src/resources/sound/step/sand3.ogg differ diff --git a/src/resources/sound/step/sand4.ogg b/src/resources/sound/step/sand4.ogg new file mode 100644 index 0000000..ae2d818 Binary files /dev/null and b/src/resources/sound/step/sand4.ogg differ diff --git a/src/resources/sound/step/snow1.ogg b/src/resources/sound/step/snow1.ogg new file mode 100644 index 0000000..f8d92e9 Binary files /dev/null and b/src/resources/sound/step/snow1.ogg differ diff --git a/src/resources/sound/step/snow2.ogg b/src/resources/sound/step/snow2.ogg new file mode 100644 index 0000000..b75843d Binary files /dev/null and b/src/resources/sound/step/snow2.ogg differ diff --git a/src/resources/sound/step/snow3.ogg b/src/resources/sound/step/snow3.ogg new file mode 100644 index 0000000..b739c4d Binary files /dev/null and b/src/resources/sound/step/snow3.ogg differ diff --git a/src/resources/sound/step/snow4.ogg b/src/resources/sound/step/snow4.ogg new file mode 100644 index 0000000..6290af2 Binary files /dev/null and b/src/resources/sound/step/snow4.ogg differ diff --git a/src/resources/sound/step/stone1.ogg b/src/resources/sound/step/stone1.ogg new file mode 100644 index 0000000..746d282 Binary files /dev/null and b/src/resources/sound/step/stone1.ogg differ diff --git a/src/resources/sound/step/stone2.ogg b/src/resources/sound/step/stone2.ogg new file mode 100644 index 0000000..333c970 Binary files /dev/null and b/src/resources/sound/step/stone2.ogg differ diff --git a/src/resources/sound/step/stone3.ogg b/src/resources/sound/step/stone3.ogg new file mode 100644 index 0000000..f8b629f Binary files /dev/null and b/src/resources/sound/step/stone3.ogg differ diff --git a/src/resources/sound/step/stone4.ogg b/src/resources/sound/step/stone4.ogg new file mode 100644 index 0000000..d705cf3 Binary files /dev/null and b/src/resources/sound/step/stone4.ogg differ diff --git a/src/resources/sound/step/wood1.ogg b/src/resources/sound/step/wood1.ogg new file mode 100644 index 0000000..f9a474a Binary files /dev/null and b/src/resources/sound/step/wood1.ogg differ diff --git a/src/resources/sound/step/wood2.ogg b/src/resources/sound/step/wood2.ogg new file mode 100644 index 0000000..b55d49b Binary files /dev/null and b/src/resources/sound/step/wood2.ogg differ diff --git a/src/resources/sound/step/wood3.ogg b/src/resources/sound/step/wood3.ogg new file mode 100644 index 0000000..61922ae Binary files /dev/null and b/src/resources/sound/step/wood3.ogg differ diff --git a/src/resources/sound/step/wood4.ogg b/src/resources/sound/step/wood4.ogg new file mode 100644 index 0000000..f5a02c5 Binary files /dev/null and b/src/resources/sound/step/wood4.ogg differ diff --git a/src/start.js b/src/start.js index 38af26a..c0ad66b 100644 --- a/src/start.js +++ b/src/start.js @@ -106,6 +106,8 @@ loadTexture([ "src/js/net/minecraft/client/gui/screens/GuiControls.js", "src/js/net/minecraft/client/gui/screens/GuiIngameMenu.js", "src/js/net/minecraft/client/GameWindow.js", + "src/js/net/minecraft/client/sound/SoundManager.js", + "src/js/net/minecraft/client/world/block/sound/Sound.js", "src/js/net/minecraft/client/world/block/Block.js", "src/js/net/minecraft/client/world/block/BlockStone.js", "src/js/net/minecraft/client/world/block/BlockGrass.js",