piqnt / planck.js

2D JavaScript Physics Engine
http://piqnt.com/planck.js/
MIT License
4.87k stars 236 forks source link

Undefined Reading "x" error #269

Closed depstr1 closed 7 months ago

depstr1 commented 7 months ago

hii, i'm using planck.js latest version with phaser 3.7 But getting this error in console and game stops working: image

Screenshot 2024-01-23 032811

please help ...

i'm following this tutorial by EMANUELE FERONATO

zOadT commented 7 months ago

Hey, thank you for reporting the issue! I wasn't able to reproduce the bug yet. Are you running something like the following code or something entirely different?

<!DOCTYPE html>
<html>
<head>
    <script src="https://cdn.jsdelivr.net/npm/phaser@3.60.0/dist/phaser-arcade-physics.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/planck/dist/planck.js"></script>
</head>
<body>
<script>
let game;
window.onload = function() {
    let gameConfig = {
        type: Phaser.AUTO,
        scale: {
            mode: Phaser.Scale.FIT,
            autoCenter: Phaser.Scale.CENTER_BOTH,
            parent: "thegame",
            width: 600,
            height: 600
        },
        scene: playGame
    }
    game = new Phaser.Game(gameConfig);
    window.focus();
}
class playGame extends Phaser.Scene{
    constructor(){
        super("PlayGame");
    }
    create(){

        // Box2D works with meters. We need to convert meters to pixels.
        // let's say 30 pixels = 1 meter.
        this.worldScale = 30;

        // world gravity, as a Vec2 object. It's just a x, y vector
        let gravity = planck.Vec2(0, 3);

        // this is how we create a Box2D world
        this.world = planck.World(gravity);

        // createBox is a method I wrote to create a box, see how it works at line 55
        this.createBox(game.config.width / 2, game.config.height - 20, game.config.width, 40, false);

        // the rest of the script just creates a random box each 500ms, then restarts after 100 iterations
        this.tick = 0;
        this.time.addEvent({
            delay: 500,
            callbackScope: this,
            callback: function(){
                this.createBox(Phaser.Math.Between(100, game.config.width - 100), -100, Phaser.Math.Between(20, 80), Phaser.Math.Between(20, 80), true);
                this.tick ++;
                if(this.tick == 100){
                    this.scene.start("PlayGame");
                }
            },
            loop: true
        });
    }

    // here we go with some Box2D stuff
    // arguments: x, y coordinates of the center, with and height of the box, in pixels
    // we'll conver pixels to meters inside the method
    createBox(posX, posY, width, height, isDynamic){

        // this is how we create a generic Box2D body
        let box = this.world.createBody();
        if(isDynamic){

            // Box2D bodies born as static bodies, but we can make them dynamic
            box.setDynamic();
        }

        // a body can have one or more fixtures. This is how we create a box fixture inside a body
        box.createFixture(planck.Box(width / 2 / this.worldScale, height / 2 / this.worldScale));

        // now we place the body in the world
        box.setPosition(planck.Vec2(posX / this.worldScale, posY / this.worldScale));

        // time to set mass information
        box.setMassData({
            mass: 1,
            center: planck.Vec2(),

            // I have to say I do not know the meaning of this "I", but if you set it to zero, bodies won't rotate
            I: 1
        });

        // now we create a graphics object representing the body
        var color = new Phaser.Display.Color();
        color.random();
        color.brighten(50).saturate(100);
        let userData = this.add.graphics();
        userData.fillStyle(color.color, 1);
        userData.fillRect(- width / 2, - height / 2, width, height);

        // a body can have anything in its user data, normally it's used to store its sprite
        box.setUserData(userData);
    }

    update(){

        // advance the simulation by 1/20 seconds
        this.world.step(1 / 30);

        // crearForces  method should be added at the end on each step
        this.world.clearForces();

        // iterate through all bodies
        for (let b = this.world.getBodyList(); b; b = b.getNext()){

            // get body position
            let bodyPosition = b.getPosition();

            // get body angle, in radians
            let bodyAngle = b.getAngle();

            // get body user data, the graphics object
            let userData = b.getUserData();

            // adjust graphic object position and rotation
            userData.x = bodyPosition.x * this.worldScale;
            userData.y = bodyPosition.y * this.worldScale;
            userData.rotation = bodyAngle;
        }
    }
};
</script>
</body>
</html>
depstr1 commented 7 months ago

hii @zOadT .. firstly Thank You for your response
Here is what's in my project:

  1. Clone official vite + phaser templete from here
  2. i installed dependencies required by this template using npm install image
  3. then installed Planck.js using npm image
  4. After all this Only file i edited was scr/Scenes/Game.js ..Here it is.
  5. And run the development server using npm run dev ( firstly Main Menu Scene appears if you click on it then comes the the Game.js Scene)

I hope this will help you solving this issue

zOadT commented 7 months ago

Well, this took me way too long to see 😂 (The error message really isn't helping in this case)

world.setGravity takes a Vec2 as argument

-        world.setGravity(0,3);
+        world.setGravity(Vec2(0,3));

I would recommend to use Typescript (Vite actually supports it out of the box, but you have to run tsc in a separate process if you want errors reported by a script (otherwise the editor would still show errors on opened files))

depstr1 commented 7 months ago

Thanks a lot @zOadT and sorry for silly mistake 😅... Now i realised the need for typescript...

zOadT commented 7 months ago

No worries! Glad it works now 🙂