最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - First person shooter controls with three.js - Stack Overflow

programmeradmin1浏览0评论

I'm pletely new to three.js and 3D. I'm trying to make a really simple first person shooter. I found heaps of examples but they all look really plicated. I want to understand the code before I use it. What I am having trouble with is the camera rotation. Everything else is fine. My approach doesn't quite work. It seems to be rotating on the z axis even though I'm setting that to 0. Here's all my code (125 lines)

var width    = window.innerWidth, height = window.innerHeight,
    scene    = new THREE.Scene(),
    camera   = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000),
    renderer = new THREE.WebGLRenderer(),
    mouse = {
      x: 0,
      y: 0,
      movedThisFrame: false
    };
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);

var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial({
  color: 0x00ff00
});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
var floorgeometry = new THREE.BoxGeometry(100,0.1,100);
var floormaterial = new THREE.MeshBasicMaterial({
  color: 0xff0000
});
var floor = new THREE.Mesh(floorgeometry, floormaterial);
floor.position.y = -1;
scene.add(floor);

var keys = {
  w: false,
  a: false,
  s: false,
  d: false
};

camera.position.z = 5;

function radDeg(radians) {
  return radians * 180 / Math.PI;
}

function degRad(degrees) {
  return degrees * Math.PI / 180;
}

function rotateCam() {
  if (!mouse.movedThisFrame) {
    mouse.x = 0;
    mouse.y = 0;
  }
  /*

  What am I doing wrong here?

  */
  camera.rotation.x -= mouse.y * 0.001;
  camera.rotation.y -= mouse.x * 0.001;
  camera.rotation.z = 0;

  mouse.movedThisFrame = false;
}

function moveCam() {
  var rotation = camera.rotation.y % (Math.PI * 2), motion = [0,0];
  if (keys.w) {
    motion[0] += 0.1 * Math.cos(rotation);
    motion[1] += 0.1 * Math.sin(rotation);
  }
  if (keys.a) {
    motion[0] += 0.1 * Math.cos(rotation + degRad(90));
    motion[1] += 0.1 * Math.sin(rotation + degRad(90));
  }
  if (keys.s) {
    motion[0] += 0.1 * Math.cos(rotation - degRad(180));
    motion[1] += 0.1 * Math.sin(rotation - degRad(180));
  }
  if (keys.d) {
    motion[0] += 0.1 * Math.cos(rotation - degRad(90));
    motion[1] += 0.1 * Math.sin(rotation - degRad(90));
  }

  camera.position.z -= motion[0];
  camera.position.x -= motion[1];
}

window.onload = function() {
  renderer.domElement.onclick = function() {
    console.log('requested pointer lock');
    renderer.domElement.requestPointerLock();
  };

  renderer.domElement.onmousemove = function(e) {
    if (!mouse.movedThisFrame) {
      mouse.x = e.movementX;
      mouse.y = e.movementY;
      mouse.movedThisFrame = true;
    }
  };

  document.onkeydown = function(e) {
    var char = String.fromCharCode(e.keyCode);
    if (char == 'W')
      keys.w = true;
    else if (char == 'A')
      keys.a = true;
    else if (char == 'S')
      keys.s = true;
    else if (char == 'D')
      keys.d = true;
  };

  document.onkeyup = function(e) {
    var char = String.fromCharCode(e.keyCode);
    if (char == 'W')
      keys.w = false;
    else if (char == 'A')
      keys.a = false;
    else if (char == 'S')
      keys.s = false;
    else if (char == 'D')
      keys.d = false;
  };

  function animate() {
    requestAnimationFrame(animate);
    rotateCam();
    moveCam();
    renderer.render(scene, camera);
  }
  animate();
};

The problem is in the rotateCam function. It doesn't quite work and I don't really know why.

I also tried using the code on this question but it didn't work.

I'm pletely new to three.js and 3D. I'm trying to make a really simple first person shooter. I found heaps of examples but they all look really plicated. I want to understand the code before I use it. What I am having trouble with is the camera rotation. Everything else is fine. My approach doesn't quite work. It seems to be rotating on the z axis even though I'm setting that to 0. Here's all my code (125 lines)

var width    = window.innerWidth, height = window.innerHeight,
    scene    = new THREE.Scene(),
    camera   = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000),
    renderer = new THREE.WebGLRenderer(),
    mouse = {
      x: 0,
      y: 0,
      movedThisFrame: false
    };
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);

var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial({
  color: 0x00ff00
});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
var floorgeometry = new THREE.BoxGeometry(100,0.1,100);
var floormaterial = new THREE.MeshBasicMaterial({
  color: 0xff0000
});
var floor = new THREE.Mesh(floorgeometry, floormaterial);
floor.position.y = -1;
scene.add(floor);

var keys = {
  w: false,
  a: false,
  s: false,
  d: false
};

camera.position.z = 5;

function radDeg(radians) {
  return radians * 180 / Math.PI;
}

function degRad(degrees) {
  return degrees * Math.PI / 180;
}

function rotateCam() {
  if (!mouse.movedThisFrame) {
    mouse.x = 0;
    mouse.y = 0;
  }
  /*

  What am I doing wrong here?

  */
  camera.rotation.x -= mouse.y * 0.001;
  camera.rotation.y -= mouse.x * 0.001;
  camera.rotation.z = 0;

  mouse.movedThisFrame = false;
}

function moveCam() {
  var rotation = camera.rotation.y % (Math.PI * 2), motion = [0,0];
  if (keys.w) {
    motion[0] += 0.1 * Math.cos(rotation);
    motion[1] += 0.1 * Math.sin(rotation);
  }
  if (keys.a) {
    motion[0] += 0.1 * Math.cos(rotation + degRad(90));
    motion[1] += 0.1 * Math.sin(rotation + degRad(90));
  }
  if (keys.s) {
    motion[0] += 0.1 * Math.cos(rotation - degRad(180));
    motion[1] += 0.1 * Math.sin(rotation - degRad(180));
  }
  if (keys.d) {
    motion[0] += 0.1 * Math.cos(rotation - degRad(90));
    motion[1] += 0.1 * Math.sin(rotation - degRad(90));
  }

  camera.position.z -= motion[0];
  camera.position.x -= motion[1];
}

window.onload = function() {
  renderer.domElement.onclick = function() {
    console.log('requested pointer lock');
    renderer.domElement.requestPointerLock();
  };

  renderer.domElement.onmousemove = function(e) {
    if (!mouse.movedThisFrame) {
      mouse.x = e.movementX;
      mouse.y = e.movementY;
      mouse.movedThisFrame = true;
    }
  };

  document.onkeydown = function(e) {
    var char = String.fromCharCode(e.keyCode);
    if (char == 'W')
      keys.w = true;
    else if (char == 'A')
      keys.a = true;
    else if (char == 'S')
      keys.s = true;
    else if (char == 'D')
      keys.d = true;
  };

  document.onkeyup = function(e) {
    var char = String.fromCharCode(e.keyCode);
    if (char == 'W')
      keys.w = false;
    else if (char == 'A')
      keys.a = false;
    else if (char == 'S')
      keys.s = false;
    else if (char == 'D')
      keys.d = false;
  };

  function animate() {
    requestAnimationFrame(animate);
    rotateCam();
    moveCam();
    renderer.render(scene, camera);
  }
  animate();
};

The problem is in the rotateCam function. It doesn't quite work and I don't really know why.

I also tried using the code on this question but it didn't work.

Share Improve this question edited May 23, 2017 at 11:59 CommunityBot 11 silver badge asked Apr 10, 2016 at 1:27 Sneaky TurtleSneaky Turtle 3012 silver badges11 bronze badges 1
  • After some thinking a doodling I now understand the problem. Basically, we need to calculate the X and z angles based of the y angle. But I have no idea how to do that. Someone please help! – Sneaky Turtle Commented Apr 10, 2016 at 1:39
Add a ment  | 

3 Answers 3

Reset to default 5

First person controls are more plicated than you may think. Even if you figure out your angle math, when the pointer is not locked, the mouse hits the window edge and turning stops.

I suggest you start with the pointer lock example (http://threejs/examples/#misc_controls_pointerlock) which is an example of first person controls for 3js.

Here's my Three.js first person shooter demo solution. It's using the PointerLockControls class.

<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Three.js Examples - First Person Shooter Game Starter</title>
    <style>
        @font-face {
            font-family: 'Robus-BWqOd';
            src: url('https://www.shanebrumback./fonts/Robus-BWqOd.otf') format('opentype');
        }

        body {
            margin: 0;
        }

        canvas {
            display: block;
        }

        #blocker {
            position: fixed;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.5);
        }

        #instructions {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            color: white;
        }

        #crosshair {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 100px;
            height: 100px;
            display: none; /* Hide the crosshair by default */
        }

        #playButton {
            font-family: 'Robus-BWqOd';
            font-size: 5vw;
            color: white;
            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.75);
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            white-space: nowrap;
        }

        p {
            font-family: Arial;
            font-size: medium;
            text-align: center;
        }

        @media (max-width: 900px) {
            /* Styles for mobile devices with a maximum width of 767px */
            #playButton {
                font-family: 'Robus-BWqOd';
                font-size: 15vw; /* Adjust the font size as per your preference */
            }
            p {
                font-size: 4vw;
            }
        }

    </style>
</head>
<body>
    <div id="blocker">
        <div id="instructions">
            <div id="playButton">
                Play Now
                <p>
                    ESC - Menu
                    <br />
                    WASF ARROWS - Move
                    <br />
                    LEFT MOUSE  - Fire
                    <br />
                    SPACEBAR  - Fire
                    <br />
                    M - Play / Pause Music
                </p>
            </div>
        </div>
    </div>
    <img id="crosshair" src="https://www.shanebrumback./images/reticle.png" alt="Crosshair">

    <script src="https://cdn.jsdelivr/npm/three@latest/build/three.min.js"></script>
    <script src="https://cdn.jsdelivr/npm/three@latest/examples/js/controls/OrbitControls.js"></script>
    <script src="https://cdn.jsdelivr/npm/three@latest/examples/js/controls/PointerLockControls.js"></script>
    
    <script type="module">


        // Set up the scene
        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.position.set(9, 0.3, 3); // Set camera position 0.1 units above the grid

        // Create the renderer
        var renderer = new THREE.WebGLRenderer({ alpha: true, depth: true });
        // Configure renderer settings
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.toneMapping = THREE.ReinhardToneMapping;
        renderer.setClearColor(0x000000, 1); // Set background color to black
        renderer.domElement.style.position = 'fixed';
        renderer.domElement.id = 'renderer';
        renderer.domElement.style.zIndex = '-1';
        renderer.domElement.style.left = '0';
        renderer.domElement.style.top = '0';
        document.body.appendChild(renderer.domElement);

        var raycaster = new THREE.Raycaster();
        var mouse = new THREE.Vector2();
        var particles = [];
        var triangles = [];
        let cubes = []

        var hasCubeMoved = false; // Flag to track if the cube has already been moved

        // Gravity effect variables
        var gravity = new THREE.Vector3(0, -0.01, 0); // Adjust the gravity strength as needed
        var maxGravityDistance = 2; // Adjust the maximum distance affected by gravity as needed

        // Add PointerLockControls
        var controls = new THREE.PointerLockControls(camera, document.body);

        // Create a grid
        var gridHelper = new THREE.GridHelper(20, 20);

        // Set the color of the grid lines to white
        gridHelper.material.color.set(0xffffff);

        scene.add(gridHelper);

        // Create a plane geometry with the same size as the grid
        var planeGeometry = new THREE.PlaneGeometry(20, 20);

        // Create a blue material
        var blueMaterial = new THREE.MeshBasicMaterial({
            color: 0x0000ff,
            side: THREE.DoubleSide
        });

        // Create a plane mesh with the geometry and material
        var planeMesh = new THREE.Mesh(planeGeometry, blueMaterial);
        // Rotate the grid by 90 degrees
        planeMesh.rotation.x = Math.PI / 2;
        // Set the position of the plane to align with the grid
        planeMesh.position.copy(gridHelper.position);
        //scene.add(planeMesh);


        // Create a cube
        var geometry = new THREE.BoxGeometry(1, 1, 1);
        var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });

        for (var i = 0; i < 5; i++) {
            var cube = new THREE.Mesh(geometry, material);
            cube.position.set(0, 0.5, 0); // Set cube position 0.5 units above the grid
            scene.add(cube);
            cubes.push(cube);
        }

        // Set camera to face cube position
        camera.lookAt(cube.position)

        // Set up pointer lock controls
        var blocker = document.getElementById('blocker');
        var instructions = document.getElementById('instructions');
        var playButton = document.getElementById('playButton');

        playButton.addEventListener('click', function () {
            controls.lock();
        });

        controls.addEventListener('lock', function () {
            instructions.style.display = 'none';
            blocker.style.display = 'none';
            document.getElementById('crosshair').style.display = 'block'; // Show the crosshair when screen is locked
        });

        controls.addEventListener('unlock', function () {
            blocker.style.display = 'block';
            instructions.style.display = '';
            document.getElementById('crosshair').style.display = 'none'; // Hide the crosshair when screen is unlocked
        });

        scene.add(controls.getObject());

        // Keyboard controls
        var moveForward = false;
        var moveBackward = false;
        var moveLeft = false;
        var moveRight = false;

        var onKeyDown = function (event) {
            switch (event.keyCode) {
                case 38: // up arrow
                case 87: // W key
                    moveForward = true;
                    break;
                case 37: // left arrow
                case 65: // A key
                    moveLeft = true;
                    break;
                case 40: // down arrow
                case 83: // S key
                    moveBackward = true;
                    break;
                case 39: // right arrow
                case 68: // D key
                    moveRight = true;
                    break;
            }
        };

        var onKeyUp = function (event) {
            switch (event.keyCode) {
                case 38: // up arrow
                case 87: // W key
                    moveForward = false;
                    break;
                case 37: // left arrow
                case 65: // A key
                    moveLeft = false;
                    break;
                case 40: // down arrow
                case 83: // S key
                    moveBackward = false;
                    break;
                case 39: // right arrow
                case 68: // D key
                    moveRight = false;
                    break;
            }
        };

        document.addEventListener('keydown', onKeyDown);
        document.addEventListener('keyup', onKeyUp);

        // Check collision with the grid
        function checkCollision(position) {
            var gridSize = 20;
            var halfGridSize = gridSize / 2;
            var margin = 0.1;

            if (
                position.x < -halfGridSize + margin ||
                position.x > halfGridSize - margin ||
                position.z < -halfGridSize + margin ||
                position.z > halfGridSize - margin
            ) {
                return true; // Collision detected
            }

            return false; // No collision
        }

        // Render loop
        function animate() {
            requestAnimationFrame(animate);

            updateParticles();

            checkParticleCollision();

            if (controls.isLocked) {
                var delta = 0.03;

                if (moveForward) {
                    controls.moveForward(delta);
                    if (checkCollision(controls.getObject().position)) {
                        controls.moveForward(-delta); // Move back to the previous position
                    }
                }

                if (moveBackward) {
                    controls.moveForward(-delta);
                    if (checkCollision(controls.getObject().position)) {
                        controls.moveForward(delta); // Move back to the previous position
                    }
                }

                if (moveLeft) {
                    controls.moveRight(-delta);
                    if (checkCollision(controls.getObject().position)) {
                        controls.moveRight(delta); // Move back to the previous position
                    }
                }

                if (moveRight) {
                    controls.moveRight(delta);
                    if (checkCollision(controls.getObject().position)) {
                        controls.moveRight(-delta); // Move back to the previous position
                    }
                }
            }

            updateTriangles()

            renderer.render(scene, camera);
        }

        animate();

        function removeParticle(particle) {
            scene.remove(particle);
            particles.splice(particles.indexOf(particle), 1);
        }

        function createParticle() {
            playLaserSound();
            var geometry = new THREE.SphereGeometry(0.05, 16, 16);
            var material = new THREE.MeshBasicMaterial({ color: 0xADD8E6 });
            var particle = new THREE.Mesh(geometry, material);
            particle.position.copy(camera.position);
            particle.initialDirection = camera.getWorldDirection(new THREE.Vector3());
            particle.velocity = particle.initialDirection.clone().multiplyScalar(0.25);
            scene.add(particle);
            particles.push(particle);
        }

        function updateParticles() {
            var distanceThreshold = 20;

            for (var i = particles.length - 1; i >= 0; i--) {
                var particle = particles[i];
                particle.position.add(particle.velocity);

                var distance = particle.position.distanceTo(camera.position);
                if (distance > distanceThreshold) {
                    removeParticle(particle);
                }
            }
        }

        function onMouseDown(event) {
            event.preventDefault();

            if (controls.isLocked) {
                // Particle creation is allowed only when controls are locked
                if (event.button === 0) {
                    createParticle();
                }
            }
        }

        function onMouseMove(event) {
            event.preventDefault();

            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
            mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

            raycaster.setFromCamera(mouse, camera);
        }

        // Mouse click event listener
        document.addEventListener('mousedown', onMouseDown);
        document.addEventListener('mousemove', onMouseMove, false);

        // Declare a variable to count collided particles
        var collidedParticles = 0;

        var hasCubeMoved = false; // Flag to track if the cube has already been moved

        // Check collision between particles and cubes
        function checkParticleCollision() {
            for (var j = 0; j < cubes.length; j++) {
                var cube = cubes[j];
                var isColliding = false;

                if (cube.visible) {
                    for (var i = 0; i < particles.length; i++) {
                        var particle = particles[i];
                        var particlePosition = particle.position;
                        var particleEdge = particlePosition
                            .clone()
                            .add(particle.velocity.clone().normalize().multiplyScalar(0.1));

                        raycaster.set(particlePosition, particleEdge.sub(particlePosition).normalize());
                        var intersects = raycaster.intersectObject(cube);

                        if (intersects.length === 1) {
                            // Particle collided with the cube
                            isColliding = true;
                            break;
                        }
                    }
                }

                // Set cube color and visibility based on collision status
                if (isColliding) {
                    // Cube is red during collision
                    cube.material.color.set(0xff0000);
                    explosion(cube);
                    moveCubeRandomly(cube);
                    hasCubeMoved = false; // Reset the flag when the cube is hidden
                } else {
                    // Cube is green when there is no collision
                    cube.material.color.set(0x00ff00);

                    // Check if all particles have been removed and the cube has not moved
                    if (collidedParticles === particles.length && !hasCubeMoved) {
                        collidedParticles = 0; // Reset the collided particles counter
                        hasCubeMoved = true; // Set the flag to indicate that the cube has been moved
                    }
                }
            }
        }

        // Move the cube to a random location on the grid
        function moveCubeRandomly(cube) {
            var gridSize = 20; // Adjust the grid size as desired
            var randomX = Math.floor(Math.random() * gridSize) - gridSize / 2;
            var randomZ = Math.floor(Math.random() * gridSize) - gridSize / 2;

            cube.position.x = randomX;
            cube.position.z = randomZ;
        }


        // Create an explosion of small triangles
        function explosion(cube) {

            playExplosionSound();

            var explosionCount = 50;

            for (var i = 0; i < explosionCount; i++) {
                var triangle = createTriangle(cube);
                scene.add(triangle);
                triangles.push(triangle); // Add the triangle to the triangles array

                triangle.userData = {
                    direction: new THREE.Vector3(
                        Math.random() * 2 - 1,
                        Math.random() * 2 - 1,
                        Math.random() * 2 - 1
                    ).normalize(),
                    speed: Math.random() * 0.05 + 0.01, // Random speed
                    rotationAxis: new THREE.Vector3(
                        Math.random(),
                        Math.random(),
                        Math.random()
                    ).normalize(),
                    rotationSpeed: Math.random() * 0.1 + 0.005, // Random rotation speed
                    distance: 0, // Distance traveled by the triangle
                    remove: false, // Flag to mark if the triangle should be removed
                    parentCube: cube, // Reference to the collided cube
                };
            }
        }


        // Create a small triangle
        function createTriangle(cube) {
            var geometry = new THREE.BufferGeometry();
            var vertices = new Float32Array([
                -0.1, 0, 0,
                0.1, 0, 0,
                0, 0.1, 0
            ]);
            var indices = new Uint16Array([0, 1, 2]);

            geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
            geometry.setIndex(new THREE.BufferAttribute(indices, 1));

            var material = new THREE.MeshBasicMaterial({ color: 0xffff00, side: THREE.DoubleSide });

            var triangle = new THREE.Mesh(geometry, material);

            // Set initial position at the center of the collided cube
            triangle.position.copy(cube.position);

            // Set the rotation to face the camera
            triangle.lookAt(camera.position);

            // Set random scale
            var scale = Math.random() * 1 + 0.5; // Adjust the scale range as desired
            triangle.scale.set(scale, scale, scale);

            return triangle;
        }


        // Update the triangles' positions, rotations, and remove them if necessary
        function updateTriangles() {
            for (var i = 0; i < triangles.length; i++) {
                var triangle = triangles[i];
                var userData = triangle.userData;

                // Move the triangle in its direction at a random speed
                var speed = userData.speed;
                triangle.position.add(userData.direction.clone().multiplyScalar(speed));

                // Rotate the triangle around its rotation axis at a random speed
                var rotationSpeed = userData.rotationSpeed;
                triangle.rotateOnWorldAxis(userData.rotationAxis, rotationSpeed);

                // Update the distance traveled by the triangle
                userData.distance += speed;

                // If the triangle has traveled a certain distance, mark it for removal
                if (userData.distance >= 2) {
                    userData.remove = true;
                }
            }

            // Remove triangles that are marked for removal
            for (var i = triangles.length - 1; i >= 0; i--) {
                if (triangles[i].userData.remove) {
                    scene.remove(triangles[i]);
                    triangles.splice(i, 1);
                }
            }


            // Resize renderer when window size changes
            window.addEventListener('resize', function () {
                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();
                renderer.setSize(window.innerWidth, window.innerHeight);
            });


        }


        // Create an AudioContext
        var audioContext = null;
        var musicBuffer = null;
        var laserSoundBuffer = null;
        var explosionSoundBuffer = null;
        var isMusicPlaying = false;
        var musicSource = null;

        // Function to load audio files
        function loadAudioFile(url, callback) {
            var request = new XMLHttpRequest();
            request.open('GET', url, true);
            request.responseType = 'arraybuffer';

            request.onload = function () {
                audioContext.decodeAudioData(request.response, function (buffer) {
                    callback(buffer);
                });
            };

            request.send();
        }

        // Function to play the music
        function playMusic() {
            if (!audioContext) {
                audioContext = new (window.AudioContext || window.webkitAudioContext)();
            }

            if (!musicBuffer) {
                loadAudioFile('https://www.shanebrumback./sounds/first-person-shooter-music.wav', function (buffer) {
                    musicBuffer = buffer;
                    playLoopedSound(buffer, .35);
                    isMusicPlaying = true;
                });
            } else {
                if (isMusicPlaying) {
                    pauseSound();
                    isMusicPlaying = false;
                } else {
                    resumeSound();
                    isMusicPlaying = true;
                }
            }
        }

        // Function to play a sound in a loop with a specific volume
        function playLoopedSound(buffer, volume) {
            musicSource = audioContext.createBufferSource();
            musicSource.buffer = buffer;
            musicSource.loop = true; // Enable looping
            var gainNode = audioContext.createGain();
            gainNode.gain.setValueAtTime(0, audioContext.currentTime); // Set initial volume to 0
            gainNode.gain.linearRampToValueAtTime(volume, audioContext.currentTime + 2); // Gradually increase volume to desired level (adjust time as needed)
            musicSource.connect(gainNode);
            gainNode.connect(audioContext.destination);

            // Delay the start of the audio source
            musicSource.start(audioContext.currentTime + 0.1); // Adjust the delay as needed

            // Note: You can adjust the delay time and volume ramping to find the appropriate values that work best for your audio files.
        }

        // Function to pause the music
        function pauseSound() {
            if (musicSource) {
                musicSource.stop();
                musicSource.disconnect();
                musicSource = null;
            }
        }

        // Function to resume the music
        function resumeSound() {
            if (musicBuffer) {
                playLoopedSound(musicBuffer, .35);
            }
        }

        // Function to play the laser sound
        function playLaserSound() {
            if (!audioContext) {
                audioContext = new (window.AudioContext || window.webkitAudioContext)();
            }

            if (!laserSoundBuffer) {
                loadAudioFile('https://www.shanebrumback./sounds/laser.wav', function (buffer) {
                    laserSoundBuffer = buffer;
                    playSound(buffer, 1);
                });
            } else {
                playSound(laserSoundBuffer, 1);
            }
        }

        // Function to play the explosion sound
        function playExplosionSound() {
            if (!audioContext) {
                audioContext = new (window.AudioContext || window.webkitAudioContext)();
            }

            if (!explosionSoundBuffer) {
                loadAudioFile('https://www.shanebrumback./sounds/explosion.wav', function (buffer) {
                    explosionSoundBuffer = buffer;
                    playSound(buffer, 0.25); // Adjust the volume here (0.5 = 50% volume)
                });
            } else {
                playSound(explosionSoundBuffer, 0.25); // Adjust the volume here (0.5 = 50% volume)
            }
        }

        // Function to play a sound with a specific volume
        function playSound(buffer, volume) {
            var source = audioContext.createBufferSource();
            var gainNode = audioContext.createGain();
            gainNode.gain.value = volume;

            source.buffer = buffer;
            source.connect(gainNode);
            gainNode.connect(audioContext.destination);
            source.start(0);
        }


        // Event listener for key press
        document.addEventListener('keydown', function (event) {

            if (event.key === 'm' || event.key === 'M') {
                playMusic();
            } else if (event.key === ' ') {
                if (controls.isLocked) {
                    event.preventDefault(); // Prevent default action of spacebar
                    createParticle();
                    playLaserSound();
                }
            } else if (event.key === 'e' || event.key === 'E') {
                playExplosionSound();
            }

        });


    </script>

</body>
</html>

You have to use

euler.setFromQuaternion( camera.quaternion );
euler.y -= e.movementX/500;
euler.x -= e.movementY/500;
camera.quaternion.setFromEuler( euler );

(you can change the 500)

发布评论

评论列表(0)

  1. 暂无评论