Home > front end >  Player not falling by 1 pixel per second
Player not falling by 1 pixel per second

Time:03-10

I have a code that tells the player that if not touching ground, change y by 1. This is suppose to be check every second(for debugging issues) but it doesn't change the player y by 1, but by 700. Also, even when it is touching the ground, it still moves. Could you help me? my code:

Player code:

class Player {
    constructor(image, x, y, width, height) {
        this.image = image
        this.x = x
        this.y = y
        this.width = width
        this.height = height
        this.player = player
    }
    
    draw() {
        let image = document.createElement('IMG')
        image.src = this.image
        c.drawImage(image, this.x, this.y, this.width, this.height)
    }
    
    update() {
    }
}

var player = new Player('stickman-removebg.png', 0, 0, 20, 40, 'stickPlayer')
player.draw()

function fall() {
    groundBlocks.forEach((block) => {
        if(player.y   player.height != block.y  && (player.x-player.width >= block.x||player.x <= block.x 20)) {
            player.y  = 1
            player.draw()
            console.log('lol')
        }
    })
}
setInterval(fall, 1000)

Update code:

function blockIntiation() {
    for (let i=innerHeight-20; i > (innerHeight/4)*3; i-=20) {
        for (let k=0; k < innerWidth; k =20) {
            groundBlocks.push(new block('#9b7653', 'dirt', k, i))
        }
    }
}
function update() {
 let updateId = requestAnimationFrame(update)
 c.clearRect(0, 0, canvas.width, canvas.height)
 c2.clearRect(0, 0, canvas.width, canvas.height)
 c3.clearRect(0, 0, canvas.width, canvas.height)

 groundBlocks.forEach((dirt) => {
     dirt.draw()
 })
 
 player.draw()
 }

window.onload = function() {
blockIntiation()
update()
}

ground code:

const canvas = document.querySelector('#gameCanvas')
const c = canvas.getContext('2d')
canvas.width = innerWidth
canvas.height = innerHeight

class block {
    constructor(color, type, x, y) {
        this.color = color
        this.type = type
        this.x = x
        this.y = y
    }
    
    draw() {
        c.beginPath()
        c.rect(this.x, this.y, 20, 20)
        c.fillStyle = this.color
        c.fill
}

var groundBlocks = []


html code:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Mars survival</title>
    <link rel="stylesheet" href="marsSurvival.css">
</head>
<body>
<canvas id='gameCanvas'></canvas>
<canvas id='backgroundCanvas'></canvas>
<canvas id='statCanvas'></canvas>
</body>
    <script src="marsSurvivalStats.js"></script>
    <script src="marsSurvivalBlockCreator.js"></script>
    <script src="marsSurvivalBackgroundMaker.js"></script>
    <script src="marsSurvivalPlayer.js"></script>
    <script src="marsSurvivalMain.js"></script>
</html>

CodePudding user response:

To answer your main question, the reason your player is falling so much is because you are checking every single block object and if he isn't on top of that specific block then he is going to fall 1 pixel! This is not what you want in my case it loads 78 blocks, and thus he falls 78 pixels, in yours it falls more... You should set the height and width of the canvas that way you know what size you are dealing with...

To be clear the answer to your question on why the player is not falling 1 pixel is because your logic checks every single block and says to fall if the player is not on that block. I will share some example code with you that will have the player fall if it isn't on any block. Here is some example code, please see the gravity function for how I check if any block is under the player:
This code isn't that great, but it will give you an idea of why the player is falling through the block. Also it has some code to ensure the player doesn't fall partially through a block when using a fall distance greater than that of 1 pixel.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Mars survival</title>
    <link rel="stylesheet" href="marsSurvival.css">
</head>
<body>
<canvas id='gameCanvas'></canvas>
<canvas id='backgroundCanvas'></canvas>
<canvas id='statCanvas'></canvas>
<img id="myPlayerImg" src="https://external-content.duckduckgo.com/iu/?u=http://www.mortalkombatwarehouse.com/mk2/noobsaibot/sprites/stance/a1.gif&f=1&nofb=1" style="display: none">
</body>
    <script src="marsSurvivalStats.js"></script>
    <script src="marsSurvivalBlockCreator.js"></script>
    <script src="marsSurvivalBackgroundMaker.js"></script>
    <script src="marsSurvivalPlayer.js"></script>
    <script src="marsSurvivalMain.js"></script>
    <script>
const canvas = document.querySelector('#gameCanvas')
const c = canvas.getContext('2d')
canvas.width = innerWidth
canvas.height = innerHeight

class Player {
    constructor(image, x, y, width, height, player) {
        let docImage = document.getElementById('myPlayerImg');
        docImage.src = image
        this.image = docImage
        this.x = x
        this.y = y
        this.width = width
        this.height = height
        this.player = player
    }
    
    draw() {
        c.drawImage(document.getElementById('myPlayerImg'), this.x, this.y, this.width, this.height)
    }
    
    update() {
    }
}
class block {
    constructor(color, type, x, y, width=20, height=20) {//Block width defaults to 20 pixels as well as the height
        this.color = color
        this.type = type
        this.x = x
        this.y = y
        this.width = width//Notice I added a width and height to the block
        this.height = height
    }
    
    draw() {
        c.beginPath()
        c.fillStyle = this.color
        c.fillRect(this.x, this.y, this.width, this.height)
        //c.fillStyle = this.color
        //c.fill()
    }
}

var groundBlocks = []
var playerImg = "https://external-content.duckduckgo.com/iu/?u=http://www.mortalkombatwarehouse.com/mk2/noobsaibot/sprites/stance/a1.gif&f=1&nofb=1";
var player = new Player(playerImg, 19, 0, 20, 40, 'stickPlayer')
//player.draw()

function gravity() {
    let contactY = 0;
    let fallDistance = 3;
    if(!groundBlocks.some((block) => {
        if(player.y   player.height fallDistance>=block.y && player.y   player.height fallDistance <= block.y block.height && ((player.x > block.x&&player.x < block.x block.width)||(player.x player.width > block.x && player.x player.width < block.x block.width))){
            contactY = block.y - player.height;
            return true;
        }
        return false
    })){
        player.y  = fallDistance;
    } else {
        player.y = contactY; //This will make sure the player doesn't fall into the block if we were moving more pixels at a time.
    }
}
function update() {
    c.clearRect(0, 0, canvas.width, canvas.height);
    //update position of anything that is dynamic
    gravity();
    //drawBackground()
    //draw blocks
    groundBlocks.forEach((block)=>block.draw());
    player.draw()
}
function blockInitiation() {
    for (let i=innerHeight-20; i > (innerHeight/4)*3; i-=20) {
        for (let k=0; k < innerWidth; k =20) {
            groundBlocks.push(new block('#9b7653', 'dirt', k, i))
        }
    }
}
blockInitiation();
setInterval(()=>{update();}, 50)
    </script>
</html>

BONUS TIP

I see that you are creating a game/animation. As such I would like to mention that you should modify your code to follow a more standard approach to game development.
Your code should have a game engine (aka. update function) that is called at a regular frequency giving you a frame rate of game play... The code above has a rate of just under 20 frames per second (50 milliseconds update). The game engine should call all update functions, and the finally call a render function that will show the updated game frame. Remember the more modular functions you can split your code into the better it is for debugging.
I see you are using ES5 syntax I recommend learning and using ES6 syntax as it is the current standard.

I hope the code above helps you a little, and the solution above makes sense as to why your player is falling so much and continues to fall through blocks.
  • Related