Search code examples
javascriptgame-physicsp5.js

Player Jumping Glitch


this is my first post! With that in mind, if I need to add anything more than what is below, please let me know. Thank you!

I am currently working to make a platformer game in Javascript where a player can move using arrow keys. Currently, my left and right movements, as well as my player gravity, works. However, when I jump, I am unable to provide smooth jumping movements. originally, I tried simply moving my player's y value higher.

if (up) { 
        this.y -= 100;
    }

However, this makes the player "teleport" upwards, rather than look like an actual jump. To fix this, I reused my gravity code to overcome the gravitational force until a certain limit, making the player look like they are smoothly jumping until they reach a certain height. Below is my code.

if (up) { // This if statement is apart of another function, did not include
            this.can_jump = false;
            this.jumping = true; this.jump();
        }

jump() { // Overcome the gravitational force, but jump force slowly lowers

        this.y -= (this.gravity * this.velocity) * 3;
        this.gravity -= 0.1;
        this.velocity -= 0.1;

        this.check();
        this.check_jump(this.jumping);

    }

check_jump(jumping) {

        if (jumping) {

            if (this.x < 500) { // While player is less than 500, keep jumping

                this.jumping = false;
                this.gravity = 2;
                this.velocity = 2;
                this.can_jump = true;

            }

        }
}

Additionally, here is the code regarding player collisions and gravity.

gravityEffect() {

        this.y += (this.gravity * this.velocity);
        this.check();

    }

    check() {

        // Too far up
        if (this.y <= 70) { this.y = 70; }
        // Too far down
        if (this.y >= 600) { this.y = 600; }
        // Too far left, teleports to other side
        if (this.x < 0) { this.x = 1200; }
        // Too far right, teleports to other side
        if (this.x > 1200) { this.x = 0; }

    }

However, when testing this, my player not only keeps jumping upwards, but also does not do so smoothly (it looks like it is glitching). Here is a link to an mp4 file download (screen recording) showcasing the glitch: https://www.mediafire.com/file/jtqh3lca72vj8nz/%25F0%259D%2590%258C%25F0%259D%2590%25B2_%25F0%259D%2590%2586%25F0%259D%2590%25AB%25F0%259D%2590%259A%25F0%259D%2590%25AF%25F0%259D%2590%25A2%25F0%259D%2590%25AD%25F0%259D%2590%25B2_-_Google_Chrome_2021-04-28_19-59-08.mp4/file

Also, here is a copy of my current code (zipped), if running the program helps: https://www.mediafire.com/file/r5ewoxtb4n57htz/game.zip/file

Please let me know what is wrong. Also, if there is a different or more efficient method of simulating player jumping, please make me aware of it. Thank you for your time.


Solution

  • While trying to keep the code mostly the same I made some changes.

    First and formost I changed how you had the controller written. Unless your intention was for the up/down/left/right arguments to stay true then you need a method for them to kick back to false. This controller class will do that.

     // Apply classes to empty variables
      console.log("Creating player...");
      player =    new Player();
      console.log("Creating world...");
      world  =    new World();
      console.log("Creating Controller...")
      controller = new Controller();
    
      // Draw canvas with set size
      console.log("Creating game screen...");
      createCanvas(1000, 750);
      
    }
    class Controller {
      constructor() {
        this.up = false;
        this.down = false;
        this.right = false;
        this.left = false;
    
        let keyEvent = (e) => {
            if (e.code === 'ArrowUp')    { this.up = e.type ===  'keydown' }
            if (e.code === 'ArrowRight') { this.right = e.type ===  'keydown' }
            if (e.code === 'ArrowDown')  { this.down = e.type ===  'keydown' }
            if (e.code === 'ArrowLeft')  { this.left = e.type ===  'keydown' }
        }
        window.addEventListener('keydown', keyEvent)
        window.addEventListener('keyup', keyEvent)
      }
    }
    

    Since we changed that we'll have to change the Player Class very slightly. I've set the X and Y velocity to 0 and we'll increment those once a button is pressed. The additional update function will update your X and Y based on that.

    Player Class

    class Player {
        // Setup player attributes
        constructor() {
            this.x = 100;
            this.y = 395;
            this.width = 50;
            this.height = 50;
            this.jumping = false;
            this.color = "#ffdb15";
            this.gravity = 2;
            this.velocityY = 0;
            this.velocityX = 0; //changed this from speed
            this.points = 0;
        }
        move() {
            // Reverse gravity to upwards, change player's color
            if (controller.up && !this.jumping) { this.jumping = true; this.jump(); this.color = this.getRandomColor(true); }
            // Reverse gravity to downwards, change player's color
            if (controller.down) { this.color = this.getRandomColor(false); }
            // Go left
            if (controller.left) { this.velocityX -= 1 }
            // Go right
            if (controller.right) { this.velocityX += 1 }
        }
        jump() {
            this.velocityY -= 35;
        }
        check() {
            // Too far up
            if (this.y <= 70) { this.y = 70; }
            // Too far down
            if (this.y >= 600) { this.y = 600; this.jumping = false } //once collision player can jump again
            // Too far left, teleports to other side
            if (this.x < 0) { this.x = 1200; }
            // Too far right, teleports to other side
            if (this.x > 1200) { this.x = 0; }
        }
        // Get a random player color
        getRandomColor(isMoving) {
            if ((this.y === 70 || this.y === 600) && isMoving) {
                // Explanation: Each color has RGB values from 0 to 255, or 256 total options
                // Since colors start from "000000" and go until "FFFFFF", there are ((256^3) - 1) possibilities
                // (256^3) - 1 = 16777215
                // Use this number, and a random number from Math.Random(), to get a random color
                // Idea from: https://css-tricks.com/snippets/javascript/random-hex-color/
                this.color = Math.floor(Math.random() * 16777215).toString(16);
                return "#" + this.color;
            } else { return this.color; }
        }
        show() {
            // Show player
            fill(this.color);
            strokeWeight(0);
            rect(this.x, this.y, this.width, this.height);
        }
        update() {
            this.velocityY += this.gravity;
            this.x += this.velocityX;
            this.y += this.velocityY;
            this.velocityY *= 0.9;
            this.velocityX *= 0.9; //provides a sliding slow down once button is released.
            this.move();
            this.check();
        }
    }
    

    The draw function is the same but replace gravity with update

    function draw() {
    
      world.generate();
    
      player.update();
      player.show();
    }
    

    This should get you where you want to go with it.