three.js 按键W前进、S退后、A左转、D右转运动

效果:W 键 前进;S 键后退;A 键左转;D 键右转;使用了 tween.js 动画库; 

代码:

<template><div><el-container><el-main><div class="box-card-left"><div id="threejs"></div></div></el-main></el-container></div>
</template>s
<script>
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import TWEEN from '@tweenjs/tween.js';
export default {data() {return {scene: null,camera: null,renderer: null,res1: null,res2: null,clock: null,keyState: {W: false,S: false,A: false,D: false,},left_rotation: true, // 向左旋转的标志right_rotation: true, // 向右旋转的标志VW: new this.$three.Vector3(0, 0, 0),VS: new this.$three.Vector3(0, 0, 0),curr_v: new this.$three.Vector3(0, 0, 0),person: null,deltaTime: 0,a: 30, // 加速度damping: -0.04,};},created() {},mounted() {this.name = this.$route.query.name;this.init();},methods: {goBack() {this.$router.go(-1);},init() {this.clock = new this.$three.Clock();// 创建场景this.scene = new this.$three.Scene();// 创建辅助坐标轴对象const axesHelper = new this.$three.AxesHelper(100);this.scene.add(axesHelper);// 创建环境光const ambientLight = new this.$three.AmbientLight(0xffffff, 10);this.scene.add(ambientLight);// 创建相机对象this.camera = new this.$three.PerspectiveCamera(60,1,0.01,2000);this.camera.position.set(10,10,10);this.camera.lookAt(0,0,0);// 创建渲染器对象this.renderer = new this.$three.WebGLRenderer();this.renderer.setSize(1500,1200);// 创建GLTFLoader对象;加载人物模型const gltfLoader = new GLTFLoader();gltfLoader.load("models/gltf/person2/scene.gltf", gltf => {gltf.scene.position.set(0,0,-10);gltf.scene.scale.set(2,2,2);this.person = gltf.scene;this.scene.add(gltf.scene);this.renderer.render(this.scene, this.camera);window.document.getElementById("threejs").appendChild(this.renderer.domElement);})const controls = new OrbitControls(this.camera, this.renderer.domElement);controls.addEventListener("change", () => {this.renderer.render(this.scene, this.camera);})this.addEventListenerFn();this.renderLoop();},renderLoop() {const deltaTime = this.clock.getDelta();if(this.keyState.W) {if(this.VW.length() < 5) {this.VW.add(new this.$three.Vector3(0,0,1).multiplyScalar(this.a * deltaTime));this.curr_v = this.VW.clone();}let pos = this.VW.clone().multiplyScalar(deltaTime);this.person.position.add(pos);}if(this.keyState.S) {if(this.VS.length() < 5) {this.VS.add(new this.$three.Vector3(0,0,-1).multiplyScalar(this.a * deltaTime));this.curr_v = this.VS.clone();}let pos = this.VS.clone().multiplyScalar(deltaTime);this.person.position.add(pos);}if(this.keyState.A) {}if(this.person) {// .addScaledVector ( v : Vector3, s : Float ) : 将所传入的v与s相乘所得的乘积和这个向量相加。this.curr_v.addScaledVector(this.curr_v, this.damping);let pos = this.curr_v.clone().multiplyScalar(deltaTime);this.person.position.add(pos);}this.renderer.render(this.scene, this.camera);TWEEN.update();requestAnimationFrame(this.renderLoop);},addEventListenerFn() {// 监听按下的 W 键document.addEventListener("keydown", e => {if(e.code == "KeyW") {this.keyState.W = true;}if(e.code == "KeyS") {this.keyState.S = true;}if(e.code == "KeyA") {this.keyState.A = true;if(!this.left_rotation)return false;const tween0 = new TWEEN.Tween(this.person.rotation);let deg = this.$three.MathUtils.radToDeg(this.person.rotation.y);let rad = this.$three.MathUtils.degToRad(deg + 90);if(rad != null) {tween0.to({x:0, y: rad, z:0}, 1000);tween0.start();tween0.onStart(() => {this.left_rotation = false;});tween0.onComplete(() => {this.left_rotation = true;});}}if(e.code == "KeyD") {this.keyState.D = true;if(!this.right_rotation)return false;const tween0 = new TWEEN.Tween(this.person.rotation);let deg = this.$three.MathUtils.radToDeg(this.person.rotation.y);let rad = this.$three.MathUtils.degToRad(deg - 90);if(rad != null) {tween0.to({x:0, y: rad, z:0}, 1000);tween0.start();tween0.onStart(() => {this.right_rotation = false;});tween0.onComplete(() => {this.right_rotation = true;});}}})document.addEventListener("keyup", e => {if(e.code == "KeyW") {this.keyState.W = false;this.VW = new this.$three.Vector3(0, 0, 0);}if(e.code == "KeyS") {this.keyState.S = false;this.VS = new this.$three.Vector3(0, 0, 0);}if(e.code == "KeyA") {this.keyState.A = false;}if(e.code == "KeyD") {this.keyState.D = false;}})}},
};
</script>
<style lang="less" scoped>
.box-card-left {display: flex;align-items: flex-start;flex-direction: row;width: 100%;.box-right {img {width: 500px;user-select: none;}}
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/736931.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何利用AWS CloudFront 自定义设置SSL

Amazon CloudFront 提供三种选项&#xff0c;可以加速整个网站并从 CloudFront 的边缘站点通过安全的 HTTPS 方式交付内容。除能够安全地从边缘站点交付内容外&#xff0c;您还可以配置 CDN 来使用针对源提取的 HTTPS 连接&#xff0c;这样您的数据就会实现从源到最终用户的端到…

仿牛客网项目---项目总结

本篇文章是对整个项目的一个总结。下面这张图要好好理解。 整个项目都是构建在SpringBoot之上的&#xff0c;所以把它画到最底下&#xff0c;其它技术依托在springboot之上。但是springboot并不是技术的核心&#xff0c;而只是起到了一个辅助的作用&#xff0c;它的作用仅仅是降…

浅拷贝,简单深拷贝

文章目录 浅拷贝简单深拷贝 浅拷贝 const _shallowClone target > {let copy Array.isArray(target) ? [] : {};for (let key in target) {if (target.hasOwnProperty(key)) {let value target[key];copy[key] value;}}return copy; };在这段代码中&#xff0c;我们定…

docker基本命令(持续更新)

docker基本命令&#xff08;持续更新&#xff09;&#xff1a; 文章目录 docker基本命令&#xff08;持续更新&#xff09;&#xff1a;一、镜像相关二、容器相关&#xff1a;三、dockerfile相关&#xff1a; 注&#xff1a;docker命令需要以root权限使用&#xff08;大概&…

使用Homebrew搭建java环境

Homebrew Homebrew是一款包管理工具,目前支持macOS和linux系统。 默认安装路径为 /usr/local/ 。下载包的安装路径在/usr/local/Cellar/。 #安装 /bin/sh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" #卸载 /bin/sh -c "…

vue之性能优化

1.路由懒加载 所谓路由懒加载&#xff0c;其实就是路由通过import动态引入&#xff0c;而不是在文件最上面一个个全部引入&#xff0c;因为JS执行的时候会优先执行引入的文件&#xff0c;如果一次性引入过多&#xff0c;则会增加处理时长。 2.图片懒加载 图片在网页加载过程…

Matplotlib接口和常用图形--画图接口

文章目录 任务描述编程要求 任务描述 本关任务&#xff1a;掌握matplotlib的基本使用技巧&#xff0c;并能简单使用matplotlib进行可视化。 相关知识 在深入使用matplotlib之前你需要知道几个matplotlib技巧&#xff0c;这些技巧能帮助你更快速掌握matplotlib。 导入matplot…

svg简单教程

推荐查看这个视频 一小时讲完SVG 简介 scalable 英 /ˈskeɪləbl/ 美 /ˈskeɪləbl/ adj. &#xff08;计算机&#xff09; 可扩展的&#xff1b;可改变大小的&#xff0c;可缩放的&#xff1b;可攀登的&#xff1b;可称量的&#xff1b;可去鳞的 vector 英 /ˈvektə/ 美…

lmbench学习

Ubuntu 手册页&#xff1a; lat_proc - 进程创建测试 编译时参考博客&#xff1a;lmbench基本的部署与使用 结果分析&#xff1a;性能测试工具 Lmbench 的使用方法以及解析运行结果

MIT 6.858 计算机系统安全讲义 2014 秋季(一)

译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 MIT 6.858 计算机系统安全笔记 2014 秋季 2014 年由Nickolai Zeldovich 教授和James Mickens 教授教授授课的 6.858 讲座笔记。这些讲座笔记略有修改&#xff0c;与 6.858 课程网站上发布的内容略有不同。 第1讲&#x…

搭建prometheus、grafana监控平台

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…

php调用guzzlehttp库时出现Segmentation fault的解决方案

先说结论&#xff0c;这个问题的原因是因为php7.4与openssl3不兼容产生的&#xff0c;解决方案如下&#xff1a; 输入openssl version -a查看openssl版本&#xff0c;如果是3以上的版本与php7.4不兼容&#xff0c;7.4以下的没测试过&#xff0c;估计也有问题。我最终是安装上了…

FFmepg--内存IO模式

功能&#xff1a; 内存IO模式&#xff1a;avio_alloc_context(): 自定义读写文件方式&#xff0c;打开文件 api // 自定义IO AVIOContext * avio_alloc_context (unsigend char * buffer;int buffer_size;void *opaque;int (*read_packet)(void * opaque, uint8_t * buf,in…

安装配置Spark集群

安装Spark集群主要包括以下步骤&#xff1a; 1、下载Spark安装包&#xff0c;在各节点中安装部署spark集群 2、配置整合 3、启动并测试 下载Spark 可以从官方网站下载合适的版本。当前环境已经提供了安装包&#xff0c;存放在 /opt/software目录下。 在node1节点上安装Sp…

SpringCloudAlibaba 网关gateway整合sentinel日志默认路径修改

SpringCloudAlibaba 网关gateway整合sentinel 实现网关限流熔断 问题提出 今天运维突然告诉我 在服务器上内存满了 原因是nacos日志高达3G,然后将日志文件发给我看了一下之后才发现是gateway整合sentinel使用了默认日志地址导致日志生成地址直接存在与根路径下而且一下存在多…

第16章——西瓜书强化学习

在强化学习中&#xff0c;智能体通过与环境的交互来学习如何做出决策。在每个时间步&#xff0c;智能体观察当前的环境状态&#xff0c;并根据其策略选择一个动作。环境会对智能体的动作做出响应&#xff0c;并给出一个奖励信号&#xff08;reward&#xff09;&#xff0c;该信…

安装zabbix

部署Zabbix监控平台 部署一台Zabbix监控服务器&#xff0c;一台被监控主机&#xff0c;为进一步执行具体的监控任务做准备&#xff1a; 安装LNMP环境源码安装Zabbix安装监控端主机&#xff0c;修改基本配置初始化Zabbix监控Web页面修改PHP配置文件&#xff0c;满足Zabbix需求…

zeta新增三个任务教程,即将刷新,速撸

这期是延续上期的教程&#xff0c;前面的任务不变&#xff0c;所以直接复制的前面的教程&#xff0c;多了三个任务更新在后面。 简单说一下&#xff0c;zeta是已经发币的公链项目&#xff0c;但是它社区还有6%的用户激励token份额没发完&#xff0c;做主网的几个简单任务可以获…

cudnn下载国内满速下载地址长期有效更新

【cudnn9.0.0】 cudnn-9.0.0-windows.exe下载地址&#xff1a;点我下载此版本 cudnn-linux-x86-64-9.0.0.312-cuda12-archive.tar.xz下载地址&#xff1a;点我下载此版本 cudnn-linux-x86-64-9.0.0.312-cuda11-archive.tar.xz下载地址&#xff1a;点我下载此版本 cudnn-windows…

「CISP题库精讲」CISP题库习题解析精讲5道

前言 本节只要对CISP考试中的5道习题进行详细的讲解,时间比较少,敲多少道,就算多少道,反正全部也就1400多道。 习题部分 第一题 某企业内网中感染了一种依靠移动存储进行传播的特洛伊木马病毒,由于企业部署的杀毒软件,为了解决该病毒在企业内部传播,作为信息化负责人…