Q: Restarting function in javascript tetris I'm trying to write a js tetris app as my first solo app. I wrote most of it on my own, and i ran into some trouble. I had a friend take a look at it who has a lot more experience than me, but we couldn't figure out the problem.
I would like the main function (drawOnCanvas()) to restart when the tetromino touches te bottom, but everything i tried it behaved pretty strange. I think it's because there is a recursion somewhere in it. My friend thinks it' because of the event listeners that the function doesn't work right.
I would appreciate any help that i can get. Thanks a lot.
This is the only error i get after running it runs the first time: Uncaught TypeError: Cannot read property 'height' of undefined
    at drawOnCanvas (script.js:89)
    at animate (script.js:167)
P.S.: if somebody would like to run the code i can send the images.
Here's the code:


const tetro = {
    i: [document.getElementById('tetro_i'), document.getElementById('tetro_i1')],
    j: [document.getElementById('tetro_j'), document.getElementById('tetro_j1'), document.getElementById('tetro_j2'), document.getElementById('tetro_j3')],
    l: [document.getElementById('tetro_l'), document.getElementById('tetro_l1'), document.getElementById('tetro_l2'), document.getElementById('tetro_l3')],
    o: [document.getElementById('tetro_o')],
    s: [document.getElementById('tetro_s'), document.getElementById('tetro_s1')],
    t: [document.getElementById('tetro_t'), document.getElementById('tetro_t1'), document.getElementById('tetro_t2'), document.getElementById('tetro_t3')],
    z: [document.getElementById('tetro_z'), document.getElementById('tetro_z1')]
}

let temp = 0;

const [space, left, up, right, down] = [32, 37, 38, 39, 40];

// -- Removes arrow keys function in browser //
window.addEventListener("keydown", function(e) {
    // space and arrow keys
    if([space, left, up, right, down].indexOf(e.keyCode) > -1) {
        e.preventDefault();
    }
}, false);

// Creates an array of tetro.keys
const createArray = function(obj) {
    var keys = [];
    for (var prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            keys.push(prop[0]);
        }
    }
    return keys;
}


// setup canvas
const canvas = document.getElementById('main_canvas');
canvas.width = 250;
canvas.height = 500;
const ctx = canvas.getContext("2d");

function setCanvas(c) {
    
    c.fillStyle = "solid black";
    c.fillRect(0, 0, canvas.width, canvas.height);

    for (let i = 25; i < canvas.height; i += 25) {
    
        c.beginPath();
        c.moveTo(i, 0);
        c.lineTo(i, canvas.height);
        c.strokeStyle = "white";
        c.lineWidth = 0.5;
        c.stroke();

    }

    for (let i = 25; i < canvas.height; i += 25) {

        c.beginPath();
        c.moveTo(0, i);
        c.lineTo(canvas.width, i);
        c.strokeStyle = "white";
        c.lineWidth = 0.5;
        c.stroke();

    }
    
    c.beginPath();
    c.moveTo(0, canvas.height);
    c.lineTo(canvas.width, canvas.height);
    c.strokeStyle = "yellow";
    c.lineWidth = 5;
    c.stroke();
    
}

drawOnCanvas();

function drawOnCanvas() {
    let randNum, randTetro, x, y, finalTet;
    
    // 1. select random tetromino
    
    randNum = Math.floor(Math.random() * 7);
    randTetro = createArray(tetro)[randNum];
    console.log(randTetro);

    // 2. draw on canvas
    y = -(tetro[`${randTetro}`][temp].height);
    x = 100;

    finalTet = tetro[`${randTetro}`][temp];
    console.log(tetro[`${randTetro}`].length)
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    setCanvas(ctx);
    ctx.drawImage(finalTet, x, y);

    
    // 3. Move left and right & rotate
    document.addEventListener('keydown', function(event) {
        if (event.keyCode === up || event.which === up) {
            
            if (tetro[`${randTetro}`].length > 0) {
                if(temp === tetro[`${randTetro}`].length - 1) {
                    temp = 0;
                } else {
                    temp += 1;
                }
                console.log('gor')
                
                finalTet = tetro[`${randTetro}`][temp];
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                setCanvas(ctx);
                ctx.drawImage(finalTet, x, y);
                console.log(temp)
                
            }
            //drawImageRot(finalTet, x, y, finalTet.width, finalTet.height);
               
        } else if (event.keyCode === left || event.which === left) {
            if (x >= 0 + 25) {
                console.log('levo');
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                setCanvas(ctx);
                ctx.drawImage(finalTet, x -= 25, y);
            }
                        
        } else if (event.keyCode === right || event.which === right) {
            if (x <= canvas.width - finalTet.width -25) {
                console.log('desno');
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                setCanvas(ctx);
                ctx.drawImage(finalTet, x += 25, y);
            }

        } else if (event.keyCode === down || event.which === down) {
            if (y <= (canvas.height - (finalTet.height + 25))) {
                console.log('doj');
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                setCanvas(ctx);
                ctx.drawImage(finalTet, x, y += 25);
            }
        }
    });
        
    

    function animate() {
//        const animationFrame = requestAnimationFrame(animate);
        requestAnimationFrame(animate);

    
        if (y % 25 === 0) {

            ctx.clearRect(0, 0, canvas.width, canvas.height);
            setCanvas(ctx);
            ctx.drawImage(finalTet, x, y);
            
        }

        // 4. stop when reaching bottom

        if (y >= (500 - (finalTet.height))) {
            
            // cancelAnimationFrame();
            ctx.save();
            return drawOnCanvas()
            
        }
        
        y += 1;
        
        // 5. draw new tetromino

    }  

    animate();

}
#main_canvas {
    border: 1px solid black
}

.tetrominoes {
    display: none;
}

.canvas{
    margin: 20px 40px;

}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
    
    <div class="canvas">
        <canvas id="main_canvas" tabindex='1'>
            
        </canvas>

    </div>
    <div class="tetrominoes">
        <img id="tetro_i" src="./img/tetro_i.png" alt="">
        <img id="tetro_i1" src="./img/tetro_i1.png" alt="">
        <img id="tetro_j" src="./img/tetro_j.png" alt="">
        <img id="tetro_j1" src="./img/tetro_j1.png" alt="">
        <img id="tetro_j2" src="./img/tetro_j2.png" alt="">
        <img id="tetro_j3" src="./img/tetro_j3.png" alt="">
        <img id="tetro_l" src="./img/tetro_l.png" alt="">
        <img id="tetro_l1" src="./img/tetro_l1.png" alt="">
        <img id="tetro_l2" src="./img/tetro_l2.png" alt="">
        <img id="tetro_l3" src="./img/tetro_l3.png" alt="">
        <img id="tetro_o" src="./img/tetro_o.png" alt="">
        <img id="tetro_s" src="./img/tetro_s.png" alt="">
        <img id="tetro_s1" src="./img/tetro_s1.png" alt="">
        <img id="tetro_t" src="./img/tetro_t.png" alt="">
        <img id="tetro_t1" src="./img/tetro_t1.png" alt="">
        <img id="tetro_t2" src="./img/tetro_t2.png" alt="">
        <img id="tetro_t3" src="./img/tetro_t3.png" alt="">
        <img id="tetro_z" src="./img/tetro_z.png" alt="">
        <img id="tetro_z1" src="./img/tetro_z1.png" alt="">
    </div>
    <script src="script.js"></script>
</body>
</html>


