Home > Software engineering >  Is it possible store static array of objects for separate instances in game in pure JavaScript?
Is it possible store static array of objects for separate instances in game in pure JavaScript?

Time:11-22

I have the class StdObject. My goal is to have this as a superclass and store objects for each instance of the classes that inherit from this StdObject-class instead of storing arrays for each object. It seemed to make more sense to store call getAll() as a static method.

class StdObject {
    static objs = [];

    //When creating new objects, these properties 
    //are used/set by default
    constructor(x=null,y=0,width=10,height=10,speed=0.4) {                   
        if (x == null) x = Math.floor(Math.random() * canvas_width);
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.speed = speed;
        this.friction = 0.3;    
        this.color = '#000000'; 
        this.gravity = 0;    
        this.constructor.addObj(); //Add this instance to the array
    }

    //Update is here if no update() is created in classes
    //the extends this class
    update() {};
        
    //Render the objects to the canvas as rectangle
    //If another shape should be used, just create a render() in that class
    //to overwrite this method
    render() {      
        ctx.clearRect(this.x, this.y, this.width, this.height);  
        ctx.fillStyle = this.color;
        ctx.fillRect(this.x, this.y, this.width, this.height);       
    }

    //Adds an object to objects array objs
    static addObj() {
        this.objs.push(this);
    }

    //Gets a specific object in array objs
    static getObj(index) {
        return this.objs[index];
    }

    //Get all objects (StdObject.getAll() is called instead of the actual class used)
    //because there are no inheritance when static methods are used.
    static getAll() {
        console.log(this);
        console.log('ALL OBJECTS=');
        console.log(this.objs);
        return this.objs;
    }

}

class Ball extends StdObject {
    constructor(x,y,width,height,speed) {
        super(x,y,width,height,speed);      
        this.angle = 0;
        this.shoot = 0;
        this.moving = false;
        this.speed = 0;
        this.radius = 7;
    }

    update() {
       //Move, update of positions for these balls etc
    }

    render() {
        //Update to canvas
    }
}

class Enemy extends StdObject {
    constructor(x,y,width,height,speed) {
        super(x,y,width,height,speed);      
        this.angle = 0;
        this.shoot = 0;
        this.moving = false;
        this.speed = 0;
    }

    update() {
       //Move, update of positions for these enemies etc
    }

    render() {
        //Update to canvas
    }
}

In the game-loop I would like to do something like this:

var obl = StdObject.getAll().length;

function gameLoop() {
    let i;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    for(i=0;i<obl;i  ) {
        StdObject.getObj[i].update();
    }

    for(i=0;i<obl;i  ) {
        StdObject.getObj[i].render();          
    }
    
    window.requestAnimationFrame(gameLoop);
}

The issue is that StdObject.getObj[i].update(); and StdObject.getObj[i].render(); is not refered to the actual instance of the object (They are referenced to the objects inside of the static array in StdObject class). Therefore I get errors

Uncaught TypeError: Cannot read properties of undefined (reading 'update') at gameLoop

Is this possible to solve with static methods? (It does not make sense to create an instance of an object just to retrieve all instances of that object.)

( Yes, I know I could store a global variable with all array of objects and just loop through them and call update() and render() )

CodePudding user response:

There are multiple issues with the code.

  1. You are trying to call a function as array but it should be called as function, StdObject.getObj(i).render() instead of StdObject.getObj[i].render();
  2. When creating instance in constructor it was not getting registered properly in array objs.

class StdObject {
            static objs = [];
            //When creating new objects, these properties 
            //are used/set by default
            constructor(x=null,y=0,width=10,height=10,speed=0.4) {                   
                if (x == null) x = Math.floor(Math.random() * canvas_width);
                this.x = x;
                this.y = y;
                this.width = width;
                this.height = height;
                this.speed = speed;
                this.friction = 0.3;    
                this.color = '#000000'; 
                this.gravity = 0;    
                StdObject.addObj(this); //Add this instance to the array
            }
        
            //Update is here if no update() is created in classes
            //the extends this class
            update() {};
                
            //Render the objects to the canvas as rectangle
            //If another shape should be used, just create a render() in that class
            //to overwrite this method
            render() {      
                ctx.clearRect(this.x, this.y, this.width, this.height);  
                ctx.fillStyle = this.color;
                ctx.fillRect(this.x, this.y, this.width, this.height);       
            }
        
            //Adds an object to objects array objs
            static addObj(obj) 
            {
                StdObject.objs.push(obj);
            }
        
            //Gets a specific object in array objs
            static getObj(index) {
                return this.objs[index];
            }
        
            //Get all objects (StdObject.getAll() is called instead of the actual class used)
            //because there are no inheritance when static methods are used.
            static getAll() {
                console.log(this);
                console.log('ALL OBJECTS=');
                console.log(this.objs);
        
                return this.objs;
            }
        
        }
        
        class Ball extends StdObject {
            constructor(x,y,width,height,speed) {
                super(x,y,width,height,speed);      
                this.angle = 0;
                this.shoot = 0;
                this.moving = false;
                this.speed = 0;
                this.radius = 7;
            }
        
            update() {
               //Move, update of positions for these balls etc
                console.log('Ball update');
            }
        
            render() {
                //Update to canvas
                console.log('Ball render');
            }
        }
        
        class Enemy extends StdObject {
            constructor(x,y,width,height,speed) {
                super(x,y,width,height,speed);      
                this.angle = 0;
                this.shoot = 0;
                this.moving = false;
                this.speed = 0;
            }
        
            update() {
               //Move, update of positions for these enemies etc
            console.log('update enemy');
            }
        
            render() {
                //Update to canvas
                console.log('render enemy');
            }
        }
        
        
        
        var enemy = new Enemy(100,100,10,10,0.4);
        var ball = new Ball(100,100,10,10,0.4);
        
        const ctx = document.getElementById('canvas').getContext('2d');
        
        function gameLoop() 
        {
        var obl = StdObject.getAll().length;
        
            let i;
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            for(i=0;i<obl;i  ) {
                StdObject.getObj(i).update();
            }
        
            for(i=0;i<obl;i  ) {
                StdObject.getObj(i).render();          
            }
            
            window.requestAnimationFrame(gameLoop);
        }
        
        gameLoop();
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related