Typescript/Three.js encounters the issue of game objects becoming undefined

Something in my code seems to have broken unexpectedly. I can't figure out why the "Game" object is defined before calling this.render() in the constructor, but becomes undefined in the render method.

Before render(), the console shows:

Game camera: Ea renderer: Dd scene: jb __proto__: Object

And after render():

Game camera: Ea renderer: Dd scene: jb __proto__: Object :3000/game.js:38 undefined

I appreciate any suggestions on how to troubleshoot this issue.

///<reference path="../typings/index.d.ts"/>
import config from './config';
import * as THREE from 'three'; 

export default class Game {

    private renderer: THREE.Renderer;
    private camera: THREE.PerspectiveCamera;
    private scene: THREE.Scene;

    constructor() {
        console.log('START');

        let container = document.querySelector(config.domSelector);
        this.renderer = new THREE.WebGLRenderer();
        this.renderer.setSize(config.rendererW, config.rendererH);
        container.appendChild(this.renderer.domElement);
        console.log('renderer added');

        this.camera = new THREE.PerspectiveCamera(config.cameraViewAngle, (config.rendererW/config.rendererH), config.cameraNear, config.cameraFar);
        this.scene = new THREE.Scene();
        this.scene.add(this.camera);
        console.log('scene initialized');

        //mesh
        let sphereMaterial:THREE.MeshLambertMaterial = new THREE.MeshLambertMaterial({color: 0xCC0000})
        let sphere:THREE.Mesh = new THREE.Mesh(
            new THREE.SphereGeometry( 50, 16, 16), sphereMaterial
        );
        sphere.position.z = -300;
        this.scene.add(sphere);

        //light
        let pointLight:THREE.PointLight = new THREE.PointLight(0xFFFFFF);
        pointLight.position.x = 10;
        pointLight.position.y = 50;
        pointLight.position.z = 130;
        this.scene.add(pointLight);

        // Schedule the first frame.
        this.render();
    }

    private render(){
        this.renderer.render(this.scene, this.camera);
        requestAnimationFrame(this.render);
    }
}

The generated javascript

define(["require", "exports", "./config", "three"], function (require, exports, config_1, THREE) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    var Game = (function () {
        function Game() {
            console.log('START');
            var container = document.querySelector(config_1.default.domSelector);
            this.renderer = new THREE.WebGLRenderer();
            this.renderer.setSize(config_1.default.rendererW, config_1.default.rendererH);
            container.appendChild(this.renderer.domElement);
            console.log('renderer added');
            this.camera = new THREE.PerspectiveCamera(config_1.default.cameraViewAngle, (config_1.default.rendererW / config_1.default.rendererH), config_1.default.cameraNear, config_1.default.cameraFar);
            this.scene = new THREE.Scene();
            this.scene.add(this.camera);
            console.log('scene initialized');
            
            //mesh
            var sphereMaterial = new THREE.MeshLambertMaterial({ color: 0xCC0000 });
            var sphere = new THREE.Mesh(new THREE.SphereGeometry(50, 16, 16), sphereMaterial);
            sphere.position.z = -300;
            this.scene.add(sphere);
            
            //light
            var pointLight = new THREE.PointLight(0xFFFFFF);
            pointLight.position.x = 10;
            pointLight.position.y = 50;
            pointLight.position.z = 130;
            this.scene.add(pointLight);
            
            // Schedule the first frame.
            this.render();
        }
        
        Game.prototype.render = function () {
            this.renderer.render(this.scene, this.camera);
            requestAnimationFrame(this.render);
        };
        
        return Game;
    }());
    
    exports.default = Game;
});
//# sourceMappingURL=/game.js.map

Answer №1

So here's the issue that I uncovered:

When executing

requestAnimationFrame(this.render);

it was scoping to window (since requestAnimationFrame is a part of window). To solve this, I had to either :

requestAnimationFrame(this.render.bind(this));

or modify the render function like this:

private render = ():void => {
       console.log("Starting the Render function")
       this.renderer.render(this.scene, this.camera);
       requestAnimationFrame(this.render);
}

Goodbye frustrating scope!

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

An error occurred: The property 'toUpperCase' cannot be read of an undefined Observable in an uncaught TypeError

Encountering an issue during the development of a mobile app using the ionic framework for a movie application. After finding an example on Github, I attempted to integrate certain functions and designs into my project. The problem arises with the 'S ...

Angular 14: A collection and schematic must be provided for execution to proceed with the process

I've recently started learning angular. After installing the latest version, I created an app called "test" using the command ng new test. Next, I opened the app in Visual Studio Code and tried to create a new component by entering the command: ng g ...

The blank screen mystery: ionic and Google maps integration not playing nice

I've been struggling to integrate Google Maps into my web application. Unfortunately, all I see is a blank screen with no errors. Here's the current code snippet that I have. It seems like there might be an issue with the mapElement variable, but ...

Navigating a parameter within an AngularJS directive

I am currently developing a directive that acts as a wrapper for the freebase search widget using jQuery. This is my first attempt at creating a directive and I have encountered some challenges. Here are the functionalities I am aiming for: 1. The ability ...

Navigate through stunning visuals using Bokeh Slider with Python callback functionality

After being inspired by this particular example from the Bokeh gallery, I decided to try implementing a slider to navigate through a vast amount of collected data, essentially creating a time-lapse of biological data. Instead of opting for a custom JavaS ...

Using Jquery to toggle the visibility of a DIV element and adding a blinking effect when it becomes visible

I have a hidden div that is displayed when a link is clicked, and I want it to blink as well. Here is my current setup: The link to display the hidden div: <a class="buttons" href="#" onclick="show(this)">join us</a> The hidden div to be di ...

"Utilizing jQuery AJAX to enable multiple file uploads with specific file extensions

I've been facing an issue with uploading multiple files using jQuery and AJAX. The problem arises when I attempt to submit a PNG or JPG file, but it fails to submit and instead alerts me to "Please Upload File" even though a file has been selected. ...

What is the process for detaching and attaching click animations using the on() method?

I am encountering an issue with a recursive loop that executes a simple animation. These animations are controlled by the page load and clicking on controls .carousel_item. Click here for live sample JSFiddles for demonstration purposes Challenge: The pr ...

How can I trigger a method after the user has finished selecting items in a v-autocomplete with multiple selection using Vuetify?

After multiple selections are made in a v-autocomplete, I need to trigger a method. However, the @input and @change events fire after each selection, not after the full batch of selections. Is there an event that triggers when the dropdown menu closes? Al ...

Sorting by date and time in a data grid using MUI X is simple with these steps

In the MaterialUI X data grid, I am facing an issue with sorting a column of dates in the format of DD/MM/YYYY HH:mm:ss. Currently, the default sorting only considers the date and does not account for the time which is causing issues with the order. I was ...

Locating the elusive comma - unraveling the mystery of Javascript Arrays nested within Objects

I've managed to put together something that functions as intended, but I'm facing an issue where I get a comma between entries when there are multiple ones. Here's the code snippet: chrome.runtime.onMessage.addListener(function (message, s ...

Get tabular information in xlsx format by utilizing the xlsx npm package for download

I have been attempting to convert my json-like data into an xlsx file format. I utilized the xlsx npm package and followed various code samples available online, however, when trying to open the file in Excel, I encountered the following error: https://i.s ...

The socket.io-client could not be located on the running Node.js server

Setting up a fresh installation of Node, Express, and Socket.io on a Linux environment using npm. When attempting to run a sample from the official socket.io source, I encountered an error stating that the 'socket.io-client' module was not found ...

Using Vue.js to loop through data objects when a button is clicked

I'm currently working on building a quiz functionality using vue.js, but I've hit a roadblock in trying to make the "Next" button cycle through my data. The goal is to have the screen display the object containing the question and answers (e.g. q ...

What is the best way to incorporate Ajax into a Rails application?

Check out the Webpage Design I am currently working on a Todo List that includes various Todo Items. Each incomplete task has a button called "Mark Item as Done" next to it, which triggers the button_to method when clicked. I am facing challenges in imple ...

Struggling to retrieve variable within the .catch function in Ionic 3

I am having trouble accessing the toast variable from the constructor in order to toast errors. It keeps showing as undefined, and I'm not sure why. This issue seems to only occur in this class, which is strange. The error message reads "ERROR TypeErr ...

Javascript does not execute properly in Google Apps Script

Encountering issues while attempting to execute the code provided in Google app script. // 1.foldername = Folder name | 3.templateId = ID of the template to use // 2.SheetId = ID of spreadsheet to use. | 4.rootFolder = ID of the root fold ...

An error occurs when attempting to use object mapping and the rest operator in a return statement due to

I've encountered a type mismatch error in my TypeScript project using Prisma while attempting to return an object with mapped properties in the getPool method. Let's take a look at the code snippet causing the issue: public async getPool({ id, v ...

Tips on showing content while filtering is taking longer with AngularJS

When working in Angular, I encountered a situation where filtering a large amount of data in a table was slowing down the process. To address this issue, I wanted to display a spinner every time a filter operation was in progress. Here is an example simil ...

Customize the appearance of the search box in Serverside Datatables

Is there a way to adjust the search and show inputs for datatables so that I can customize their width and make them fit my dynamic column sizing? The issue I ran into is that these inputs are enclosed within <label> tags in the source JavaScript, an ...