Three.js引擎开发:Three.js输入与交互系统_(9).Three.js输入系统基础

Three.js输入系统基础

在虚拟现实游戏中,输入系统是实现用户与游戏互动的关键部分。Three.js 提供了多种方式来处理用户输入,包括键盘、鼠标、触摸屏和游戏控制器等。本节将详细介绍如何在 Three.js 中实现基本的输入处理,帮助开发者构建更加互动和沉浸式的游戏体验。

键盘输入

键盘输入是最常见的用户输入方式之一,可以用于控制游戏中的角色移动、视角切换等操作。Three.js 本身并没有直接提供键盘输入的处理函数,但我们可以利用 JavaScript 的事件监听机制来实现。

基本原理

JavaScript 的 addEventListener 方法可以用于监听键盘事件,包括 keydownkeyupkeypress。通过这些事件,我们可以捕获用户的键盘输入,并在 Three.js 场景中做出相应的响应。

代码示例

以下是一个简单的示例,展示如何在 Three.js 中使用键盘输入来控制相机的移动:


// 引入 Three.js

import * as THREE from 'three';



// 创建场景

const scene = new THREE.Scene();



// 创建相机

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

camera.position.z = 5;



// 创建渲染器

const renderer = new THREE.WebGLRenderer();

renderer.setSize(window.innerWidth, window.innerHeight);

document.body.appendChild(renderer.domElement);



// 创建一个简单的立方体

const geometry = new THREE.BoxGeometry();

const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });

const cube = new THREE.Mesh(geometry, material);

scene.add(cube);



// 设置键盘状态

const keys = {

    ArrowUp: false,

    ArrowDown: false,

    ArrowLeft: false,

    ArrowRight: false

};



// 监听键盘按下事件

window.addEventListener('keydown', (event) => {

    if (event.code in keys) {

        keys[event.code] = true;

    }

});



// 监听键盘松开事件

window.addEventListener('keyup', (event) => {

    if (event.code in keys) {

        keys[event.code] = false;

    }

});



// 渲染循环

function animate() {

    requestAnimationFrame(animate);



    // 根据键盘状态更新相机位置

    if (keys.ArrowUp) {

        camera.position.z -= 0.1;

    }

    if (keys.ArrowDown) {

        camera.position.z += 0.1;

    }

    if (keys.ArrowLeft) {

        camera.position.x -= 0.1;

    }

    if (keys.ArrowRight) {

        camera.position.x += 0.1;

    }



    // 旋转立方体

    cube.rotation.x += 0.01;

    cube.rotation.y += 0.01;



    // 渲染场景

    renderer.render(scene, camera);

}



// 开始动画

animate();

代码解释

  1. 引入 Three.js:首先,我们引入了 Three.js 库。

  2. 创建场景、相机和渲染器:创建了一个基本的 Three.js 场景、透视相机和渲染器,并将渲染器的 DOM 元素添加到页面中。

  3. 创建立方体:创建了一个简单的立方体并添加到场景中。

  4. 设置键盘状态:定义了一个 keys 对象,用于存储各个键盘键的状态(按下或松开)。

  5. 监听键盘事件

    • keydown 事件:当用户按下键盘上的键时,将对应键的状态设置为 true

    • keyup 事件:当用户松开键盘上的键时,将对应键的状态设置为 false

  6. 渲染循环:在 animate 函数中,根据 keys 对象的状态更新相机的位置,并旋转立方体,最后渲染场景。

鼠标输入

鼠标输入是另一个常见的用户输入方式,可以用于控制相机的视角、选择物体等操作。Three.js 提供了一些工具类来帮助处理鼠标输入,如 THREE.RaycasterTHREE.Vector2

基本原理

THREE.Raycaster 类可以用于从鼠标位置发射光线,检测光线与场景中物体的交点。THREE.Vector2 类用于表示二维向量,通常用于存储鼠标在屏幕上的坐标。

代码示例

以下是一个示例,展示如何在 Three.js 中使用鼠标输入来选择并高亮显示场景中的物体:


// 引入 Three.js

import * as THREE from 'three';



// 创建场景

const scene = new THREE.Scene();



// 创建相机

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

camera.position.z = 10;



// 创建渲染器

const renderer = new THREE.WebGLRenderer();

renderer.setSize(window.innerWidth, window.innerHeight);

document.body.appendChild(renderer.domElement);



// 创建一个简单的立方体

const geometry = new THREE.BoxGeometry();

const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });

const cube = new THREE.Mesh(geometry, material);

scene.add(cube);



// 创建一个光线投射器

const raycaster = new THREE.Raycaster();

const mouse = new THREE.Vector2();



// 监听鼠标点击事件

window.addEventListener('click', (event) => {

    // 将鼠标位置归一化为设备坐标范围

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

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



    // 通过鼠标位置更新光线投射器

    raycaster.setFromCamera(mouse, camera);



    // 获取所有与光线相交的物体

    const intersects = raycaster.intersectObjects(scene.children);



    if (intersects.length > 0) {

        // 高亮显示第一个相交的物体

        intersects[0].object.material.color.set(0xff0000);

    }

});



// 渲染循环

function animate() {

    requestAnimationFrame(animate);



    // 旋转立方体

    cube.rotation.x += 0.01;

    cube.rotation.y += 0.01;



    // 渲染场景

    renderer.render(scene, camera);

}



// 开始动画

animate();

代码解释

  1. 引入 Three.js:首先,我们引入了 Three.js 库。

  2. 创建场景、相机和渲染器:创建了一个基本的 Three.js 场景、透视相机和渲染器,并将渲染器的 DOM 元素添加到页面中。

  3. 创建立方体:创建了一个简单的立方体并添加到场景中。

  4. 创建光线投射器和鼠标向量:创建了一个 THREE.Raycaster 对象和一个 THREE.Vector2 对象,用于存储鼠标在屏幕上的坐标。

  5. 监听鼠标点击事件

    • 将鼠标位置归一化为设备坐标范围。

    • 使用 raycaster.setFromCamera 方法将鼠标位置转换为射线。

    • 使用 raycaster.intersectObjects 方法检测射线与场景中物体的交点。

    • 如果有相交的物体,高亮显示第一个相交的物体。

  6. 渲染循环:在 animate 函数中,旋转立方体并渲染场景。

触摸屏输入

触摸屏输入在移动设备上非常常见,可以用于控制相机视角、滑动选择物体等操作。Three.js 也可以通过 JavaScript 的触摸事件来处理触摸屏输入。

基本原理

触摸屏输入可以通过 touchstarttouchmovetouchend 事件来处理。这些事件提供了触摸点的坐标信息,可以用于计算触摸屏上的操作。

代码示例

以下是一个示例,展示如何在 Three.js 中使用触摸屏输入来控制相机的视角旋转:


// 引入 Three.js

import * as THREE from 'three';



// 创建场景

const scene = new THREE.Scene();



// 创建相机

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

camera.position.z = 10;



// 创建渲染器

const renderer = new THREE.WebGLRenderer();

renderer.setSize(window.innerWidth, window.innerHeight);

document.body.appendChild(renderer.domElement);



// 创建一个简单的立方体

const geometry = new THREE.BoxGeometry();

const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });

const cube = new THREE.Mesh(geometry, material);

scene.add(cube);



// 触摸状态

let isDragging = false;

let lastTouchX = 0;

let lastTouchY = 0;



// 监听触摸开始事件

renderer.domElement.addEventListener('touchstart', (event) => {

    if (event.touches.length === 1) {

        isDragging = true;

        lastTouchX = event.touches[0].clientX;

        lastTouchY = event.touches[0].clientY;

    }

});



// 监听触摸移动事件

renderer.domElement.addEventListener('touchmove', (event) => {

    if (isDragging && event.touches.length === 1) {

        const touchX = event.touches[0].clientX;

        const touchY = event.touches[0].clientY;



        // 计算触摸移动的距离

        const deltaX = touchX - lastTouchX;

        const deltaY = touchY - lastTouchY;



        // 更新相机的旋转角度

        camera.rotation.y -= deltaX * 0.01;

        camera.rotation.x -= deltaY * 0.01;



        // 更新上次触摸位置

        lastTouchX = touchX;

        lastTouchY = touchY;

    }

});



// 监听触摸结束事件

renderer.domElement.addEventListener('touchend', (event) => {

    isDragging = false;

});



// 渲染循环

function animate() {

    requestAnimationFrame(animate);



    // 旋转立方体

    cube.rotation.x += 0.01;

    cube.rotation.y += 0.01;



    // 渲染场景

    renderer.render(scene, camera);

}



// 开始动画

animate();

代码解释

  1. 引入 Three.js:首先,我们引入了 Three.js 库。

  2. 创建场景、相机和渲染器:创建了一个基本的 Three.js 场景、透视相机和渲染器,并将渲染器的 DOM 元素添加到页面中。

  3. 创建立方体:创建了一个简单的立方体并添加到场景中。

  4. 触摸状态:定义了 isDragging 变量来表示是否正在拖动,lastTouchXlastTouchY 变量用于存储上一次触摸的位置。

  5. 监听触摸事件

    • touchstart 事件:当用户触摸屏幕时,设置 isDraggingtrue,并记录初始触摸位置。

    • touchmove 事件:当用户在屏幕上移动手指时,计算触摸移动的距离,并更新相机的旋转角度。

    • touchend 事件:当用户松开手指时,设置 isDraggingfalse

  6. 渲染循环:在 animate 函数中,旋转立方体并渲染场景。

游戏控制器输入

游戏控制器输入对于虚拟现实游戏尤为重要,可以提供更加丰富的交互体验。Three.js 通过 THREE.Gamepad 类来处理游戏控制器输入。

基本原理

THREE.Gamepad 类可以用于检测连接的游戏控制器,并获取按钮和摇杆的状态。通过这些状态,我们可以实现更加复杂的控制逻辑。

代码示例

以下是一个示例,展示如何在 Three.js 中使用游戏控制器输入来控制相机的移动和旋转:


// 引入 Three.js

import * as THREE from 'three';



// 创建场景

const scene = new THREE.Scene();



// 创建相机

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

camera.position.z = 10;



// 创建渲染器

const renderer = new THREE.WebGLRenderer();

renderer.setSize(window.innerWidth, window.innerHeight);

document.body.appendChild(renderer.domElement);



// 创建一个简单的立方体

const geometry = new THREE.BoxGeometry();

const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });

const cube = new THREE.Mesh(geometry, material);

scene.add(cube);



// 获取游戏控制器

const gamepads = navigator.getGamepads ? navigator.getGamepads() : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads : [] );



// 控制器状态

let isControllerConnected = false;

let controllerIndex = -1;



// 检测控制器连接状态

function checkControllerConnection() {

    const pads = gamepads();

    for (let i = 0; i < pads.length; i++) {

        if (pads[i]) {

            isControllerConnected = true;

            controllerIndex = i;

            break;

        }

    }

}



// 监听控制器连接事件

window.addEventListener('gamepadconnected', (event) => {

    isControllerConnected = true;

    controllerIndex = event.gamepad.index;

    console.log('Controller connected at index ' + controllerIndex);

});



// 监听控制器断开事件

window.addEventListener('gamepaddisconnected', (event) => {

    isControllerConnected = false;

    controllerIndex = -1;

    console.log('Controller disconnected at index ' + event.gamepad.index);

});



// 渲染循环

function animate() {

    requestAnimationFrame(animate);



    // 旋转立方体

    cube.rotation.x += 0.01;

    cube.rotation.y += 0.01;



    // 检测控制器状态

    if (isControllerConnected) {

        const pad = gamepads()[controllerIndex];



        // 使用左摇杆控制相机移动

        const leftStickX = pad.axes[0];

        const leftStickY = pad.axes[1];

        camera.position.x += leftStickX * 0.1;

        camera.position.z -= leftStickY * 0.1;



        // 使用右摇杆控制相机旋转

        const rightStickX = pad.axes[2];

        const rightStickY = pad.axes[3];

        camera.rotation.y -= rightStickX * 0.01;

        camera.rotation.x -= rightStickY * 0.01;

    }



    // 渲染场景

    renderer.render(scene, camera);

}



// 开始动画

animate();

代码解释

  1. 引入 Three.js:首先,我们引入了 Three.js 库。

  2. 创建场景、相机和渲染器:创建了一个基本的 Three.js 场景、透视相机和渲染器,并将渲染器的 DOM 元素添加到页面中。

  3. 创建立方体:创建了一个简单的立方体并添加到场景中。

  4. 获取游戏控制器:定义了一个 gamepads 函数,用于获取连接的游戏控制器。

  5. 控制器状态:定义了 isControllerConnectedcontrollerIndex 变量,用于存储控制器的连接状态和索引。

  6. 检测控制器连接状态:定义了一个 checkControllerConnection 函数,用于检测是否有控制器连接。

  7. 监听控制器连接和断开事件

    • gamepadconnected 事件:当控制器连接时,更新 isControllerConnectedcontrollerIndex,并输出连接信息。

    • gamepaddisconnected 事件:当控制器断开时,更新 isControllerConnectedcontrollerIndex,并输出断开信息。

  8. 渲染循环:在 animate 函数中,根据控制器的状态更新相机的位置和旋转角度,并渲染场景。

总结

通过本节的学习,您应该掌握了如何在 Three.js 中处理键盘、鼠标、触摸屏和游戏控制器输入的基本方法。这些输入方式可以用于实现各种复杂的交互逻辑,帮助您构建更加丰富和沉浸式的虚拟现实游戏。在接下来的章节中,我们将进一步探讨如何利用这些输入方式来实现更高级的交互功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值