Rotating the camera in a 2D space using three.js

Within my app, I have implemented a camera:

camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.z = 1;
camera.position.y = -5;
camera.rotateOnAxis(new THREE.Vector3(1, 0, 0), degInRad(90));
camera.up = new THREE.Vector3(0, 0, 1);  

The code inside the render function is supposed to rotate the camera as I press certain keys:

if (leftPressed) {
    camera.rotateOnAxis((new THREE.Vector3(0, 1, 0)).normalize(), degInRad(1));
} else if (rightPressed) {
    camera.rotateOnAxis((new THREE.Vector3(0, 1, 0)).normalize(), degInRad(-1));
}
if (upPressed) {
    camera.rotateOnAxis((new THREE.Vector3(1, 0, 0)).normalize(), degInRad(1));
} else if (downPressed) {
    camera.rotateOnAxis((new THREE.Vector3(1, 0, 0)).normalize(), degInRad(-1));
}  

The camera rotates, but not in the manner I desire. I want the camera rotation to mimic that of a first-person shooter game on a plane. Refer to the image below for better understanding of what I mean...
I attempted to use sin(1) and cos(1), but I am struggling to comprehend how the rotateOnAxis method works, as the translate functions work seamlessly and move the camera in the direction it is facing.
P.S.
Check out the documentation for three.js here. Maybe it can provide some insights.
For handling keyboard events, I have utilized KeyboardJS.
Here is the degInRad function:

function degInRad(deg) {
    return deg * Math.PI / 180;
}  

Link to the JSFiddle

O - position of camera
O-O1 - current camera direction
R1 - current rotation direction
R - desired rotation direction
Apologies for the simplistic illustration.

Answer №1

By just specifying camera.rotation.order = 'YXZ';, you could possibly achieve your desired outcome.

Answer №2

If you're thinking about setting up a camera rig, here's one way to approach it. Start by creating an Object3D to serve as the "neck", and then attach the camera to that object with your desired rotation. By applying rotations to the Object3D, you can look around without any wobbling effect. To take it a step further, you could nest that "neck" object within another Object3D acting as the "body" and apply translations to move around the scene. This essentially gives you a basic camera controller rig. I made some adjustments to your fiddle, check them out:

Update: modified implementation for @ostapische's specific scenario. Here's the revised fiddle link

function degInRad(deg) {
    return deg * Math.PI / 180;
}
/////////////////////////////////
function render() {
    requestAnimationFrame(render);
    if (leftPressed) {
        neck.rotation.y += degInRad(1);
    } else if (rightPressed) {
        neck.rotation.y -= degInRad(1);
    }
    if (upPressed) {
        camera.rotation.x += degInRad(1);
    } else if (downPressed) {
        camera.rotation.x -= degInRad(1);
    }
    renderer.render(scene, camera);
}
/////////////////////////////////
var scene, camera, renderer, grass, neck;
var leftPressed = false;
var rightPressed = false;
var upPressed = false;
var downPressed = false;
/////////////////////////////////
window.onload = function() {
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
    cameraHolder = new THREE.Object3D();
    cameraHolder.add( camera );
    renderer = new THREE.WebGLRenderer();
    renderer.rendererSize = {width: window.innerWidth, height: window.innerHeight, quality: 100, maxQuality: 400, minQuality: 20};
    renderer.setSize( renderer.rendererSize.width, renderer.rendererSize.height );
    document.body.appendChild( renderer.domElement );

    var texture, material, geometry, element;

    material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
    material.side = THREE.DoubleSide;
    geometry = new THREE.PlaneGeometry(24, 24);   
    grass = new THREE.Mesh( geometry, material );
    grass.name = "grass";
    scene.add( grass );

    neck = new THREE.Object3D();
    neck.rotateOnAxis(new THREE.Vector3(1, 0, 0), degInRad(90));
    neck.up = new THREE.Vector3(0, 0, 1);
    neck.position.z = 1;
    neck.position.y = -5;


    neck.add(camera);
    scene.add(neck);    

    KeyboardJS.on('left', function() { leftPressed = true; }, function() { leftPressed = false; });
    KeyboardJS.on('right', function() { rightPressed = true; }, function() { rightPressed = false; });
    KeyboardJS.on('up', function() { upPressed = true; }, function() { upPressed = false; });
    KeyboardJS.on('down', function() { downPressed = true; }, function() { downPressed = false; });

    render();
}

I was going to suggest using PointLockControl or FirstPersonControl, but it seems WestLangley has already recommended it. Best of luck,

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Execute code after selecting the link

To simplify my question, I will provide an example: Suppose I have two sample pages that I want to demonstrate: Page 01 <script> var demo = 'X1'; alert(demo); $( document ).ready(function() { $("#cont").on("click" ...

Solving an object in ui-router state using ui-sref

Dealing with a large JSON object in an Angular controller and wanting to pass it to the controller of a template that will be displayed in a ui-view. I am aware that parameters can be passed to states using ui-sref, but I do not want this object to be visi ...

Issue encountered: The function car.reviews.find() is not recognized

Encountering an issue with the find() method in my MERN stack application. I am looking to implement a reviews route where users can add comments about cars within the app. In the frontend, fields and buttons have been added; meanwhile, a post request has ...

Double loading issue with jQuery AJAX

I'm currently working on a website and I've encountered an issue. Below is the jQuery code that I am using: $('input[type="text"][name="appLink"]').keyup(function() { var iTunesURL = $(this).val(); var iTunesAppID = $('i ...

Tips for managing this JavaScript JSON array

Here is an example of a JSON array: var data = { name: 'Mike', level: 1, children: [ { name: 'Susan', level: 2, }, { name: 'Jake', level: 2 }, { name: 'Roy', level: 2 }, ...

Having trouble activating a function through the context API using React hooks

I'm attempting to initiate a function via my CartContext API upon a click event, but it doesn't seem to be functioning correctly. I have verified that the method is operational, however, when I introduce the context function, nothing occurs. See ...

Tips on adding to Jquery html code while maintaining the current CSS styling

My JavaScript function looks like this: function appendAllQna(qnaList, num){ for (var i in qnaList){ var qnaCom = ""; qnaCom += "<div class='scomment scommentLine'>"; if(qnaList[i].sellerYn == "Y"){ ...

The JavaScript code does not call an external function to retrieve data from the database

I'm currently facing an issue with retrieving the same version data from my MySQL (MariaDB) Server. In order to streamline the process and improve maintenance, I decided to create a single connection Object to manage all database queries. However, I&a ...

Is there a way to set an image as the background of my HTML screen?

{% extends "layout.html" %} {% block app_content %} <div> {% from "_formhelpers.html" import render_field %} <form method="post" enctype="multipart/form-data"> <div class = "container"> < ...

The Angular Google Maps Module fails to initialize

After updating angular-google-maps to version 2.0.1 via bower and adding the required dependencies (bluebird, jquery, loadash), I noticed that my app works fine when I comment out google-maps. This suggests that the issue lies with angular-google-maps. He ...

Trouble with Angular: Passing output between child components is not working

Just dipping my toes into Angular, I started learning it yesterday for a take-home job interview project. Please excuse any rookie mistakes in advance. For some hands-on practice, I decided to work on a basic project where the main component (app) has two ...

A Guide to Making a Floating Widget That Can Move Beyond the Boundaries of a Website in React

Currently, I am in the process of developing a project that requires the implementation of a floating widget capable of overlaying content not just within the confines of the website, but outside as well. This widget needs to have the ability to remain on ...

Sorting JSON content to obtain particular outcomes

I am utilizing the Quotes on Design API https://quotesondesign.com/api-v4-0/ to display random quotes by various designers on my website. However, I am looking to showcase quotes by specific designers in a random manner. Unfortunately, the code snippet ...

Preventing scrolling in jQuery UI Draggable when using flexbox

In my project, I am looking to organize a container using jQuery UI draggable/droppable feature. Since the elements in my list are arranged in a straight horizontal line, I have utilized display: flex. This arrangement works well when adding new items to ...

Utilizing dependency injection within an Angular 1 TypeScript application

Seeking assistance with integrating angular-jwt with typescript in my angular1 project. The angular-jwt package was installed using the following command: typings install dt~angular-jwt --global The package is located in typings>globals>angular-jwt ...

Tips for displaying a close icon after completing a file upload

I need to implement a feature where once a user uploads a file, a cross sign should be enabled on the file. I attempted to use javascript for this functionality, but it seems to not be working as expected. There are more than 8-10 different file types that ...

How can Vue detect modifications made in the edited field?

I am facing an issue with tracking changes in a specific object. Here is the structure of the object: users: { email: '', password: '' } My goal is to detect any edits made to the keys within the users object and store the key ...

Exploring how to retrieve time using PHP and JavaScript

When displaying a date in php or javascript, what factors influence the calculation? Is it dependent on the user's computer time settings, or is it sourced externally? If the user has control over it, how can I ensure my code accurately retrieves the ...

What is the best way to calculate the sum of a field within a map?

Having trouble determining how to calculate the total of an array received from an API request. Working with Next.js {positions.map(position => { return ( <List title={position.title} slug={position.slug} quantity={position ...

What is the best way for library creators to indicate to VSCode which suggested "import" is the correct one?

As a library creator, I have noticed that VSCode often suggests incorrect imports to users. For instance, VSCode typically suggests the following import: import useTranslation from 'next-translate/lib/esm/useTranslation' However, the correct im ...