【问题标题】:Camera position for endless game in ThreeJsThreeJs中无尽游戏的相机位置
【发布时间】:2019-06-05 16:43:15
【问题描述】:

我正在学习 Three.js,我正在尝试做我的第一个游戏:和无尽的游戏。

我已经阅读了this article,目的是做一些非常相似的事情。 主角(英雄)是一个向“无限”滚动的蓝色球,必须避开一些在他面前逐渐出现的障碍。用户可以通过向左或向右引导球并跳跃来避开这些障碍(想法是使用键盘,特别是左/右箭头键和空格键来跳跃)。

这是我的想法:

我想按照文章的思路而不是复制代码(我想理解它)。 这是我到目前为止所做的:

let sceneWidth = window.innerWidth;
let sceneHeight = window.innerHeight;
let canvas;
let camera;
let scene;
let renderer;
let dom;
let sun;
let hero;
let ground;
let clock;
let spotLight;
let ambientLight;

init();

function init() {
  createScene();
  showHelpers();
  update();
}

/**
 * Set up scene.
 */
function createScene() {
  clock = new THREE.Clock();
  clock.start();
  scene = new THREE.Scene();
  window.scene = scene;

  camera = new THREE.PerspectiveCamera(60, sceneWidth / sceneHeight, 0.1, 1000);
  camera.position.set(0, 0, 0);

  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setClearColor(0x333f47, 1);
  renderer.shadowMap.enabled = true;
  renderer.shadowMapSoft = true;
  renderer.setSize(sceneWidth, sceneHeight);

  canvas = renderer.domElement;
  document.body.appendChild(canvas);

  // const orbitControls = new THREE.OrbitControls(camera, canvas);

  addGround();
  addHero();
  addLight();

  camera.position.set(0, -1, 0.6);
  camera.lookAt(new THREE.Vector3(0, 0, 0));

  window.addEventListener("resize", onWindowResize, false);
}

/**
 * Show helper.
 */
function showHelpers() {
  const axesHelper = new THREE.AxesHelper(5);
  // scene.add(axesHelper);

  const spotLightHelper = new THREE.SpotLightHelper(spotLight);
  scene.add(spotLightHelper);
}

/**
 * Add ground to scene.
 */
function addGround() {
  const geometry = new THREE.PlaneGeometry(1, 4);
  const material = new THREE.MeshLambertMaterial({
    color: 0xcccccc,
    side: THREE.DoubleSide
  });
  ground = new THREE.Mesh(geometry, material);
  ground.position.set(0, 1, 0);
  ground.receiveShadow = true;
  scene.add(ground);
}

/**
 * Add hero to scene.
 */
function addHero() {
  var geometry = new THREE.SphereGeometry(0.03, 32, 32);
  var material = new THREE.MeshLambertMaterial({
    color: 0x3875d8,
    side: THREE.DoubleSide
  });
  hero = new THREE.Mesh(geometry, material);
  hero.receiveShadow = true;
  hero.castShadow = true;
  scene.add(hero);
  hero.position.set(0, -0.62, 0.03);
}

/**
 * Add light to scene.
 */
function addLight() {
  // spot light
  spotLight = new THREE.SpotLight(0xffffff);
  spotLight.position.set(2, 30, 0);
  spotLight.angle = degToRad(10);
  spotLight.castShadow = true;
  spotLight.shadow.mapSize.width = 1024;
  spotLight.shadow.mapSize.height = 1024;
  spotLight.shadow.camera.near = 1;
  spotLight.shadow.camera.far = 4000;
  spotLight.shadow.camera.fov = 45;
  scene.add(spotLight);

  // ambient light
  ambientLight = new THREE.AmbientLight(0x303030, 2);
  scene.add(ambientLight);
}

/**
 * Call game loop.
 */
function update() {
  render();
  requestAnimationFrame(update);
}

/**
 * Render the scene.
 */
function render() {
  renderer.render(scene, camera);
}

/**
 * On window resize, render again the scene.
 */
function onWindowResize() {
  sceneHeight = window.innerHeight;
  sceneWidth = window.innerWidth;
  renderer.setSize(sceneWidth, sceneHeight);
  camera.aspect = sceneWidth / sceneHeight;
  camera.updateProjectionMatrix();
}

/**
 * Degree to radiants
 */
function degToRad(degree) {
  return degree * (Math.PI / 180);
}
<script src="https://threejs.org/build/three.min.js"></script>

(JSFiddle)

我有几个问题,第一个是物体和相机的位置。

我希望能够定位平面,使次边位于屏幕的开头(因此整个平面必须可见,不得有隐藏部分)。

我希望球水平放置在中间,垂直放置几乎在地板的开始处(简而言之,如图所示),并且阴影投射到平面上。每个对象都必须将阴影投影到平面上。 我正在使用聚光灯和兰伯特材料,所以阴影应该在那里,但没有。为什么?

我什至不明白如何定位对象。 我知道点(0, 0, 0) 是屏幕的中心。 我希望地面位于y=0,并且所有其他对象都位于上方,就好像它们在休息一样。 我的代码有效,但我不知道是否有更好的方法来处理对象放置。

我还可以通过指定球体半径1 而不是0.03 来简化我的生活,然后让场景“更小”,将相机移开以缩小(我认为这是诀窍)。

所以,我需要帮助正确设置场景。

这是我在 ThreeJs 中的第一个应用程序,欢迎提出任何建议!


编辑 1

我将camera.lookAt(new THREE.Vector3(0, 0, 0)); 更改为camera.lookAt(new THREE.Vector3(0, 0, -5)); 并添加了spotLight.lookAt(new THREE.Vector3(0, 0, -5));

这是结果:

不是我想要的……

【问题讨论】:

    标签: javascript three.js


    【解决方案1】:

    您将平面和球体放置在 y 轴上的 0 处是正确的。您遇到的问题是,当您这样做时,您是在告诉相机直视 (0, 0, 0)

    camera.lookAt(0, 0, 0);

    这样你就可以让球完全居中。您应该做的是告诉相机稍微向前看球体。您必须调整该值,但这样的事情应该可以解决问题:

    camera.lookAt(0, 0, -5);

    此外,您的聚光灯正指向前方。当你把它放在 (2, 30, 0) 时,它的效果就会消失。您需要将其指向您想要的位置:

    spotLight.lookAt(0, 0, -5);

    【讨论】:

    • 感谢您的回复。我按照你的建议更改了我的代码,结果不是我希望的。我在主信息中添加了一张图片。
    • 是的,我不知道你在 JSFiddle 中在做什么......你的对象定位真的在地图上,你的相机现在正仰望 bottom i> 你的飞机。我建议您花点时间玩一下three.js 编辑器,真正熟悉 x、y、z 轴:threejs.org/editor 尝试通过添加平面、球体和障碍物来重新创建场景, 并尽量记住:+x 向右,+y 向上,+z 朝向观察者。
    • 注意:camera.lookAt( x, y, z ) 有效,不会导致实例化新的Vector3
    • @WestLangley 哎呀,你是对的!固定的。我在他的代码中看到了它,然后将其复制到我的答案中。
    猜你喜欢
    • 2013-07-31
    • 2021-09-23
    • 1970-01-01
    • 2014-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多