why does the error: 'Uncaught TypeError: Cannot read property 'elt' of undefined' show up?

Hello, I was working on a little scenery thingy with clouds moving across the screen and I added this code:

var randomCld = floor(random(0,6));
for (var ncl = 0; ncl < randomCld; ncl++) {
    allClouds[ncl] = new spawnCloud(round(random(-100, innerWidth)));
}

Which starts the function:

function spawnCloud(startX) {
    this.x = startX;
    this.y = round(random(-400,150));
    this.img;
    this.randomCloud = function() {
        var sel = floor(random(1,4));
        if (sel == 1) {
            this.img = loadImage("images/cloud_1.png");
        } else if (sel == 2) {
            this.img = loadImage("images/cloud_2.png");
        } else if (sel == 3) {
            this.img = loadImage("images/cloud_3.png");
        } 
    }
}

And i get the error: 'Uncaught TypeError: Cannot read property 'elt' of undefined'

But when I do it like this:

setInterval(function(){
    var injectCloud = new spawnCloud(round(random(-400,-600)));
    allClouds.splice(0, 0, injectCloud);
    allClouds[0].randomCloud();
},8000);

No error shows up??

Answers

  • Looks and sounds like a JS scope issue; but without knowing which line throws the error, or better still having full code to test ourselves, it's very hard to say why it's happening...

  • The line that the error is on is: p5.js:20418

    code:

    var allBigtrees = [];
    var allMediumtrees = [];
    var allSmalltrees = [];
    var allLandscape = [];
    var allClouds = [];
    
    function spawnBigTree(startH, startX) {
        this.x = startX;
        this.y = startH;
        this.img;
        this.randomTree = function() {
            var sel = round(random(1,2));
            if (sel == 1) {
                this.img = loadImage("images/pine_1_big.png");
            } else if (sel == 2) {
                this.img = loadImage("images/pine_2_big.png");
            }
        }
    }
    function spawnMediumTree(startH, startX) {
        this.x = startX;
        this.y = startH;
        this.img;
        this.randomTree = function() {
            var sel = round(random(1,2));
            if (sel == 1) {
                this.img = loadImage("images/pine_3_medium.png");
            } else if (sel == 2) {
                this.img = loadImage("images/pine_4_medium.png");
            }
        }
    }
    function spawnSmallTree(startH, startX) {
        this.x = startX;
        this.y = startH;
        this.img;
        this.randomTree = function() {
            var sel = round(random(1,2));
            if (sel == 1) {
                this.img = loadImage("images/pine_5_small.png");
            } else if (sel == 2) {
                this.img = loadImage("images/pine_6_small.png");
            }
        }
    }
    function spawnLandscape(startX) {
        this.x = startX;
        this.y = innerHeight - 315;
        this.img = loadImage("images/landscape.png");
    }
    function spawnCloud(startX) {
        this.x = startX;
        this.y = round(random(-400,150));
        this.img;
        this.randomCloud = function() {
            var sel = floor(random(1,4));
            if (sel == 1) {
                this.img = loadImage("images/cloud_1.png");
            } else if (sel == 2) {
                this.img = loadImage("images/cloud_2.png");
            } else if (sel == 3) {
                this.img = loadImage("images/cloud_3.png");
            } 
        }
    }
    var bgimg;
    var bgimgX = 0;
    var bgimgY = 0;
    var spawnTreeIV;
    var spawnCloudsIV;
    
    function spawnTreeFu() {
        setTimeout(function(){})
        var randomSel = floor(random(1,4));
        if (randomSel == 1) {
            var injectBig = new spawnBigTree(innerHeight - round(random(480,500)), round(random(-400,-600)));
            allBigtrees.splice(0, 0, injectBig);
            allBigtrees[0].randomTree();
        } else if (randomSel == 2) {
            var injectMedium = new spawnMediumTree(innerHeight - round(random(490,510)), round(random(-400,-600)));
            allMediumtrees.splice(0, 0, injectMedium);
            allMediumtrees[0].randomTree();
        } else if (randomSel == 3) {
            var injectSmall = new spawnSmallTree(innerHeight - round(random(500,520)), round(random(-400,-600)));
            allSmalltrees.splice(0, 0, injectSmall);
            allSmalltrees[0].randomTree();
        }
    }
    
    
    function preload() {
        bgimg = loadImage("images/landscape.png");
    }
    
    function setup() {
        createCanvas(innerWidth, innerHeight);
        var randomCld = floor(random(0,6));
        for (var ncl = 0; ncl < randomCld; ncl++) {
            allClouds[ncl] = new spawnCloud(round(random(-100, innerWidth)));
        }
        allClouds.sort(function(a, b) {
            return parseFloat(a.x) - parseFloat(b.x);
        });
        allLandscape[0] = new spawnLandscape(-(innerWidth+140));
        allLandscape[1] = new spawnLandscape(0);
        spawnCloudsIV = setInterval(function(){
            var injectCloud = new spawnCloud(round(random(-400,-600)));
            allClouds.splice(0, 0, injectCloud);
            allClouds[0].randomCloud();
        },8000);
        spawnTreeIV = setInterval(function(){
            var randomSel = floor(random(1,4));
            if (randomSel == 1) {
                var injectBig = new spawnBigTree(innerHeight - round(random(480,500)), round(random(-400,-600)));
                allBigtrees.splice(0, 0, injectBig);
                allBigtrees[0].randomTree();
            } else if (randomSel == 2) {
                var injectMedium = new spawnMediumTree(innerHeight - round(random(490,510)), round(random(-400,-600)));
                allMediumtrees.splice(0, 0, injectMedium);
                allMediumtrees[0].randomTree();
            } else if (randomSel == 3) {
                var injectSmall = new spawnSmallTree(innerHeight - round(random(500,520)), round(random(-400,-600)));
                allSmalltrees.splice(0, 0, injectSmall);
                allSmalltrees[0].randomTree();
            }
        },1500);
    }
    
    function draw() {
        background(135,206,235);
        //LANDSCAPE
        for (var bg = 0; bg < allLandscape.length; bg++) {
            image(allLandscape[bg].img, allLandscape[bg].x, allLandscape[bg].y)
            allLandscape[bg].x += 1 * (mouseX/100);
            if (allLandscape[bg].x > innerWidth) {
                allLandscape.splice(bg, 1);
                var injectLand = new spawnLandscape(-(innerWidth+210));
                allLandscape.splice(0, 0, injectLand);
            }
        }
        //CLOUDS
        for (var cl = 0; cl < allClouds.length; cl++) {
            image(allClouds[cl].img, allClouds[cl].x, allClouds[cl].y);
            allClouds[cl].x += 0.8 * (mouseX/100);
            if (allClouds[cl].x > innerWidth + 800) {
                allClouds.splice(cl, 1);
            }
        }
        //SMALL TREES
        for (var i = 0; i < allSmalltrees.length; i++) {
            image(allSmalltrees[i].img, allSmalltrees[i].x, allSmalltrees[i].y);
            allSmalltrees[i].x += 1.40 * (mouseX/100);
            if (allSmalltrees[i].x > innerWidth + 300) {
                allSmalltrees.splice(i, 1);
            }
        }
        //MEDIUM TREES
        for (var i = 0; i < allMediumtrees.length; i++) {
            image(allMediumtrees[i].img, allMediumtrees[i].x, allMediumtrees[i].y);
            allMediumtrees[i].x += 1.80 * (mouseX/100);
            if (allMediumtrees[i].x > innerWidth + 300) {
                allMediumtrees.splice(i, 1);
            }
        }
        //BIG TREES
        for (var i = 0; i < allBigtrees.length; i++) {
            allBigtrees[i].x += 2.20 * (mouseX/100);
            if (allBigtrees[i].x > innerWidth + 300) {
                allBigtrees.splice(i, 1);
            }
        }
    }
    
  • Answer ✓

    The error is an obscure JS scope issue; but I think it's likely that it's caused by your code structure rather than by a bug in p5js. The code is relatively long so it's hard to isolate the cause; but, for example, the use of loadImage in your randomTree() methods looks like a really bad idea and the repeated use of this structure is the most likely cause...

    loadImage() is a blocking file operation so should definitely not be called from inside the draw loop as you do. Instead you should load images up front (e.g. in preload/setup) and store in global variables that can then be referenced from draw...

  • Answer ✓

    It's also not a good idea to spawn new objects the draw loop - line #137:

    var injectLand = new spawnLandscape(-(innerWidth+210));
    

    That could cause some serious memory leakage... You need to keep better control over object instantiation: and where possible re-use the same objects - e.g. once something is out of bounds; don't create a new object to replace it. Instead re-position it for re-use...

  • Okey thank you alot! i'll keep a better eye out to how I write my code! :)

Sign In or Register to comment.