maxime Lassort
maxime Lassort

Reputation: 71

JavaScript Game run slowly over time

i'm coding a game in JS, witch run good, but with time, the FPS slow down. After search here, i think thiks that the problem can be from the load of images, but i don't know how to use the function to run the code after images are loaded. Furthermore my code are in a DOMContentLoaded addevenlistener. the problem can really provide from the load of images ? Thanks!

Here theire a slice of my code

function animate() {    
    ctx.resetTransform();
    ctx.translate(-(player.x - canvas.width / 2), -(player.y - canvas.height / 2)); //for center the character on the map
    ctx.drawImage(Images_array[1], 0, 0, canvasSize.width / 1.1, canvasSize.height / 1.1, 0, 0, canvasSize.width, canvasSize.height); //drawing the background
    // enterInHouse();
    drawSprite(Images_array[0], player.width * player.frameX, player.height * player.frameY, player.width, player.height, player.x, player.y, player.width * scale, player.height * scale) // drawing the sprite
    movePlayer() 
    handlePlayerFrame()
    // collisionRedbox()
    // displaGameboy()
    // if (inHouse === false) {
    //     createBluebox.enterInCollision(blackBoxs, player)    
    // }  
    window.requestAnimationFrame(animate); 
    }
    animate()
    window.addEventListener('resize', displayCanvas)

i loaded the images like this.

const playerSprite = new Image();
    playerSprite.src = "img/main_chara.png ";
    const background = new Image();
    background.src = "img/background.png";
    const office = new Image();
    office.src = "img/interieur_git.png";
    const retraining = new Image();
    retraining.src = 'img/reconversion.png';
    const contact = new Image();
    contact.src = 'img/contact_me.png';
    const grangeOne= new Image();
    grangeOne.src = 'img/grange.png'
    const house= new Image();
    house.src = 'img/maison.png'
    const bigHouse= new Image();
    bigHouse.src='img/maison_principale.png'

i can show you more of code if you want. Thanks a lot for helping me

Upvotes: 1

Views: 210

Answers (2)

Tschallacka
Tschallacka

Reputation: 28722

You're binding on every drawing of your animation an eventlistner.

window.addEventListener('resize', displayCanvas)

So after 1 second at 60 fps you have 60 eventlisteners, after 2 seconds 120, after a minute 3600 event listeners, after ten minutes 36000

Bind an eventhandler once, bind it outside of your animate() function.

Also, looking at your code at https://maxlassort.github.io/MyWorld/index.js

you have the function moveplayer() that you call on every frame.

function movePlayer() {
        action_btnt.addEventListener('touchstart', function (e) {
            (actionBtn=true)
            e.stopPropagation();
        },{ passive: true })
       
        up.addEventListener('touchstart', function (e) {
            (movingUp=true)
            player.moving = true
            e.stopPropagation();
        },{ passive: true })
        up.addEventListener('touchend', function () {
            movingUp=false
            player.moving = false
        },{ passive: true })
        right.addEventListener('touchstart', function (e) {
            (movingRight=true)
            player.moving = true
            e.stopPropagation();
        },{ passive: true })
        right.addEventListener('touchend', function () {
            movingRight=false
            player.moving = false
        },{ passive: true })
        down.addEventListener('touchstart', function (e) {
            (movingDown=true)
            player.moving = true
            e.stopPropagation();
        },{ passive: true })
        down.addEventListener('touchend', function () {
            movingDown=false
            player.moving = false
        },{ passive: true })
        left.addEventListener('touchstart', function (e) {
            (movingLeft=true)
            player.moving = true
            e.stopPropagation();
        },{ passive: true })
        left.addEventListener('touchend', function () {
            movingLeft=false
            player.moving = false
        },{ passive: true })


        if(openPannels===false) {
          if(movingRight===false && movingLeft===false){
            if (movingDown===true && player.y < 2000) {
                player.y += player.speed
                player.frameY = 0;
                player.moving = true
            }
            if (movingUp===true && player.y > 360) {
                player.y -= player.speed
                player.frameY = 3;
                player.moving = true
            }
          }
            if (movingRight===true && player.x < 3000) {
                player.x += player.speed
                player.frameY = 2;
                player.moving = true
            }
            if (movingLeft===true && player.x > 360) {
                player.x -= player.speed
                player.frameY = 1;
                player.moving = true
            }
        }
    }

This function has 9 event listeners that are bound every framedraw. so 9 * 60 per second, resulting in 32400 bound events per drawn frame.

Also put those event handlers outside of the moveplayer function. That way they are bound only once, with access to your javascript context variables.

        action_btnt.addEventListener('touchstart', function (e) {
            (actionBtn=true)
            e.stopPropagation();
        },{ passive: true })

        up.addEventListener('touchstart', function (e) {
            (movingUp=true)
            player.moving = true
            e.stopPropagation();
        },{ passive: true })
        up.addEventListener('touchend', function () {
            movingUp=false
            player.moving = false
        },{ passive: true })
        right.addEventListener('touchstart', function (e) {
            (movingRight=true)
            player.moving = true
            e.stopPropagation();
        },{ passive: true })
        right.addEventListener('touchend', function () {
            movingRight=false
            player.moving = false
        },{ passive: true })
        down.addEventListener('touchstart', function (e) {
            (movingDown=true)
            player.moving = true
            e.stopPropagation();
        },{ passive: true })
        down.addEventListener('touchend', function () {
            movingDown=false
            player.moving = false
        },{ passive: true })
        left.addEventListener('touchstart', function (e) {
            (movingLeft=true)
            player.moving = true
            e.stopPropagation();
        },{ passive: true })
        left.addEventListener('touchend', function () {
            movingLeft=false
            player.moving = false
         },{ passive: true })

function movePlayer() {

        if(openPannels===false) {
          if(movingRight===false && movingLeft===false){
            if (movingDown===true && player.y < 2000) {
                player.y += player.speed
                player.frameY = 0;
                player.moving = true
            }
            if (movingUp===true && player.y > 360) {
                player.y -= player.speed
                player.frameY = 3;
                player.moving = true
            }
          }
            if (movingRight===true && player.x < 3000) {
                player.x += player.speed
                player.frameY = 2;
                player.moving = true
            }
            if (movingLeft===true && player.x > 360) {
                player.x -= player.speed
                player.frameY = 1;
                player.moving = true
            }
        }
    }

Upvotes: 2

dellink
dellink

Reputation: 564

You can use onload function to understand when image was loaded and then start your game.

const playerSprite = new Image();
playerSprite.src = "img/main_chara.png ";
playerSprite.onload = function(){}

For more information: https://www.techrepublic.com/article/preloading-and-the-javascript-image-object/

Upvotes: 0

Related Questions