javascript - 使用键盘输入在平面上移动 Three.js 主体
问题描述
我一直在尝试创建一个 Color Bump 3D 模型,但它似乎超出了我的想象,但我仍然会尝试。我有一个飞机和一个球,问题是我不能用键盘事件移动球。每当我按下按键时,控制台都会向我发出错误提示
未捕获的类型错误:无法在 Game.onDocumentKeyDown 读取未定义的属性(读取“位置”)
这是代码:
import * as CANNON from '../../libs/cannon-es.js';
import { CannonHelper } from '../../libs/CannonHelper.js';
import { OrbitControls } from '../../libs/three128/OrbitControls.js';
import { Table } from './Table.js';
import { Ball } from './ball.js';
const xSpeed = 0.1;
const ySpeed = 0.1;
class Game{
constructor(){
this.initThree();
this.initWorld();
this.initScene();
// document.addEventListener('keydown', this.onDocumentKeyDown.bind(this), false);
// document.addEventListener('keyup', this.keyUp.bind(this));
// document.addEventListener('touchstart', this.mouseDown.bind(this));
// document.addEventListener('touchend', this.mouseUp.bind(this));
// document.addEventListener('mousedown', this.mouseDown.bind(this));
// document.addEventListener('mouseup', this.mouseUp.bind(this));
}
initThree(){
const container = document.createElement( 'div' );
document.body.appendChild( container );
this.camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 20 );
this.camera.position.set( -6, 2, 0 );
this.camera.lookAt(0, 0, 6);
this.cameraContoller = new THREE.Object3D();
this.cameraContoller.add(this.camera);
this.cameraTarget = new THREE.Vector3(0, 0, 6);
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color( 0xaaaaaa );
this.scene.add(this.cameraContoller);
const ambient = new THREE.HemisphereLight(0xffffff, 0xbbbbff, 0.3);
this.scene.add(ambient);
const light = new THREE.DirectionalLight();
light.position.set( 0.2, 1, 0);
light.castShadow = true;
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
const size = 10;
light.shadow.camera.top = size;
light.shadow.camera.right = size;
light.shadow.camera.bottom = -size;
light.shadow.camera.left = -size;
light.shadow.camera.near = 0.2;
light.shadow.camera.far = 10;
this.scene.add(light);
this.renderer = new THREE.WebGLRenderer({ antialias: true } );
this.renderer.shadowMap.enabled = true;
this.renderer.setPixelRatio( window.devicePixelRatio );
this.renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( this.renderer.domElement );
const controls = new OrbitControls( this.camera, this.renderer.domElement );
this.renderer.setAnimationLoop(this.render.bind(this));
window.addEventListener('resize', this.resize.bind(this) );
}
initWorld() {
const world = new CANNON.World();
world.gravity.set(0, -10, 0);
this.helper = new CannonHelper( this.scene, world);
this.world = world;
}
random(min, max){
const range = max - min;
return Math.random() * range + min;
}
// Spheres
initScene(){
this.Table = new Table(this);
const sphereShape = new CANNON.Sphere(0.1)
const sphereBody = new CANNON.Body({
mass: 1,
})
sphereBody.position.x = -3.5;
sphereBody.position.y = 1;
sphereBody.position.z = 0;
sphereBody.addShape(sphereShape)
this.world.addBody(sphereBody)
this.helper.addVisual(sphereBody, 0xFF0000);
document.addEventListener('keydown', this.onDocumentKeyDown.bind(this), false);
// this.createBalls();
}
onDocumentKeyDown(event) {
const keyCode = event.which;
if (keyCode == 87) {
console.log(this.sphereBody.position);
// playerBall.position.y += ySpeed;
} else if (keyCode == 83) {
playerBall.position.y -= ySpeed;
} else if (keyCode == 65) {
playerBall.position.x -= xSpeed;
} else if (keyCode == 68) {
playerBall.position.x += xSpeed;
} else if (keyCode == 32) {
playerBall.position.set(0, 0, 0);
}
};
updateCamera = () => {
this.cameraContoller.position.copy(this.playerBall.position);
this.cameraContoller.position.y = 0;
this.cameraTarget.copy(this.plane.position);
this.cameraTarget.z += 6;
this.camera.lookAt(this.cameraTarget);
}
createBalls () {
// this.playerBall = new Ball(this, -Table.LENGTH/2.5 ,0)
}
resize(){
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize( window.innerWidth, window.innerHeight );
}
render( ) {
this.world.step(0.0167);
this.helper.update();
this.renderer.render( this.scene, this.camera );
}
}
export { Game };
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!--favicon -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel="apple-touch-icon" sizes="180x180" href="../../css/favicon/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="../../css/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="../../css/favicon/favicon-16x16.png">
<link rel="manifest" href="../../css/favicon/site.webmanifest">
<link rel="mask-icon" href="../../css/favicon/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<title>ColorBump</title>
<style>
body{
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<script type="module">
import { Game } from './game.js';
document.addEventListener("DOMContentLoaded", function(){
const game = new Game();
window.game = game;
});
</script>
</body>
</html>
解决方案
推荐阅读
- postgresql - 如何用postgres中另一个表中的行完成表中缺失的行?
- python - 如何立即生成我的迷宫,所以我不必观看它生成?
- google-play-console - 为什么付款后没有创建我的 Google Play 控制台帐户?. 我找不到来自 Google Play 管理中心的任何回复
- java - 如何解决此问题:LoginController 中构造函数的参数 0 需要找不到类型为“OktaOAuth2Properties”的 bean
- openstreetmap - 使用 osmosis 快照模式创建 osm-pbf 的 Postgres 数据失败
- magento-1.9 - 如何使用自定义扩展 magento 1.9 在产品页面的描述选项卡下添加自定义数据?
- python - 匹配自定义数据集的 PyTorch 张量维度
- node.js - 无法写入文件和读取 NodeJS/NestJS 微服务应用程序基本文件夹中的文件
- python - 将分层 CSV 数据转换为 JSON
- c# - 正确设置 .NET 库项目,这样我就不需要将 DLL 和其他文件复制到调用程序中