piqnt / planck.js

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

Use of Stage.js #44

Open blizniak83 opened 6 years ago

blizniak83 commented 6 years ago

Hi,

I had a chance to play with Planck.js and Stage.js, but separately. I'm not js guru. In the last few days I decided to use the library without the testbed. My first choice was to replace it with Stage.js.

I follow box2d manual hello world example, nothing super ambitious. I have a bouncing ball on a flat surface/edge. Now I want to use Stage.js to render that on the screen.

It seems like all examples are testbed examples. Even though it supposed to be only a case of calling the world.step(timestep) function, I'm still struggling as I assume there will be something similar needed on the Stage.js side.

Would it be possible to post an example that uses Stage.js? Something really simple.

Thank you. Chris

Cdvalencia commented 6 years ago

Hi, the "testbet" have a basic example to create grapichs and can use Stage.js and Plank.js. i dont have a idea clear to create a firts prototype, but i know to be possible use the default render.

image for example, i have inserted this graphics using the next function:

image this lines are on the "planck-js/dist/planck-with-testbed.js", as i said, still i havn´t a clear idea, but planck and stage are joined on "planck-with-testbed.js"

blizniak83 commented 6 years ago

Hi Cristian,

Thanks for your suggestion. I'll definitely try that. It would be a lot better for me as I could use the debug/testbed functionality.

I came up with something different, but I don't know if it is correct and the most efficient way of achieving what I wanted. The example below is very primitive, is just a rolling ball down the sloped edge.

There are still few unknowns for me, like for example the step function - not sure what value should I use for that, I know 1/60 doesn't work well when you have a bouncing ball for example, as I had the impression that the ball never came to rest.

Finally, I've got a problem with scaling of my box2d/planck.js bodies vs graphics rendered by the stage.js, this is why I kind of like your approach as I still could have the debug/testbed functionality, currently I didn't manage to figure out how to enable debug/testbed in my simple stage.js example below.

Stage(function(stage) {

  // Set view box
  stage.viewbox(1000, 1000);
var Mouse = Stage.Mouse;
  // Create an image and append it to stage
  var ball = Stage.image('circle').appendTo(stage);

  var world;
  var ballBody;

  ball.pin('align', 0.5);

  var pl = planck; Vec2 = pl.Vec2;

  world = this.world = new pl.World(Vec2(0, -10));

  var floorShape = pl.Edge(Vec2(-40.0, 10.0), Vec2(40.0, 0.0));
  var ballShape = pl.Circle(.5);

  var ballFix = {
      density: 1.0,
      friction: 0.5,
      restitution: 1.0
  };

  world.createBody().createFixture(floorShape);

  ballBody = world.createBody({
      type: 'dynamic',
      position: Vec2(-39.50, 10.0)
  });

  ballBody.createFixture(ballShape,ballFix);
  var outPos = ballBody.getPosition();

    ball.pin({
            handle: .5,
            offsetX: outPos.x *(25),
            offsetY: outPos.y *(-25)
  });   

    stage.tick(function()
    {
        world.step(1/60);
        outPos = ballBody.getPosition();

        ball.pin({
            handle: .5,
            rotation: -ballBody.getAngle(),
            offsetX: outPos.x *(25),
            offsetY: outPos.y *(-25)

        });
    });
});

Stage({
    image : { src : "./example.png", ratio : 2 },
    trim : 0.2,
    textures : {
        //box :      { x : 0,    y : 32, width : 16, height : 16, top : 4, bottom : 4, left : 4, right : 4},
        circle :   { x : 32,   y : 64, width : 32, height : 32}
    }
});

Thanks for your comment once again.

shakiba commented 6 years ago

Here is my recommended approach:

See renderWorld in tesbed.

shakiba commented 6 years ago

I added a stage.js example with planck.js physics. It does not support adding graphics yet, but I will add it soon.

blizniak83 commented 6 years ago

Thanks Ali,

For your both replies. Especially the first one. I indeed took a closer look at the testbed in planck.js, especially the viewer class and then started to look at the breakout code which uses stage-p2.js, where the viewer class is almost identical and that gave me some good idea how to move on.

Thanks for the new examples, I'm sure I'll make use of them.

Chris

shakiba commented 6 years ago

@blizniak83 Right, breakout/stage-p2.js is a good example.

blizniak83 commented 6 years ago

Is there any reason why the world in the asteroid example is upside down? I remember when initially using the viewer class from the testbed I had the same problem and I had to use the scale method on the stage object (scale(1,-1)) to get the right orientation. Is this caused because of the way you attache the viewer/Stage.planck? I noticed that after adding some bodies but also after setting the gravity to -10.

shakiba commented 6 years ago

The reason is that physics y-axis is upward, but rendering is downward. Physics engines orientation/scale is usually based on real world physics, but graphic libraries is based on the screen with top-left as the origin.

blizniak83 commented 6 years ago

undetstood but if I want to render the physics bodies like they behave in the physics world then I have to flip the stage upside down, correct? I think this is what was done in the breakout example. What would be the best method to achieve that in the asteroid example? I managed to achieve that by using world.scale(80, -80), but I know it isn't the best way as it is affecting stage.on() making it no longer responsive to the changes applied to the browser window size.

blizniak83 commented 6 years ago

I think I just solved my own problem, partially of course, I applied the scale to the stage, this time scale(1,-1), it renders what I want, when looking at the physics bodies, but of course the 'status' element etc. has to be rendered differently.

shakiba commented 6 years ago

Probably you could add the world element (with -y scale) to a new element, for example called gameView, and then add gameView to stage and scale it with window resize.

blizniak83 commented 6 years ago

Thank you for your suggestion. I tried few things and at one point I thought everything was working as expected but after adding the first texture I noticed that it was upside down. Of course I could use -y scale but there must be a better way.

Below is the code extracted from the asteroid example. I know I can flip everything just by -y scaling the stage node. How would you attach the world element to a new element? Do you mean to new node (node = Stage.create())? I'm sure I'm doing something wrong, I tried to -y scale the meta element just to see if this would turn the status text upside down but that didn't work.

Stage(function(stage) {
  var activeKeys = {};
  var KEY_NAMES = {
    32 : 'fire',
    37 : 'left',
    38 : 'up',
    39 : 'right',
    40 : 'down'
  };

  var physics = new Physics({
    updateStatus: updateStatus,
    activeKeys: activeKeys
  });

  var world, meta, status, box, gameView;

  stage.background('#222222');
  //stage.scale(1,-1); // this one is fine for turning the entire scene upside down
    stage.on('viewport', function(size) {
console.log("test");        
    meta.pin({
      scaleMode : 'in-pad',
      scaleWidth : size.width,
      scaleHeight : size.height,
    });
   world.pin({    
      scaleMode : 'in-pad',
       scaleWidth : size.width,
       scaleHeight : size.height,      
    });
   });

    world = new Stage
        .planck(physics.world, { ratio: 80 });

    world.pin({
      handle : -0.5,            
      width : physics.spaceWidth,
      height : physics.spaceHeight,   
    });
    world.appendTo(stage);          

    stage.tick(physics.tick);

    meta = Stage
    .create()
    .pin({ width : 1000, height : 1000 })
    //.scale({x : 1, y: -1})    // doesn't work
    .appendTo(stage);

    var ball = Stage.image('ball').appendTo(meta);

    ball.pin('align', 0.5); 

   status = Stage
   .string('text')
   .pin({ align : 0, offsetX: 0, offsetY : 10 })
   .appendTo(meta);

   function updateStatus() {
    status.value('TEXT: ' + 3 + ' TEXT: ' + 7);
   }

  document.onkeydown = function(evt) {
    activeKeys[KEY_NAMES[evt.keyCode]] = true;
  };

  document.onkeyup = function(evt) {
    activeKeys[KEY_NAMES[evt.keyCode]] = false;
  };

   physics.start();
});
shakiba commented 6 years ago

My last suggestion was not good, now I recall for P2.js viewer I actually multiplied all y values from physics simulation by -1, for example see here.

shakiba commented 6 years ago

I updated the viewer, please feel free to try it and let me know.

shakiba commented 6 years ago

Another solution is to just setup the game world with y pointing down.

prolightHub commented 5 years ago

If shakiba would just listen to what I have to say on my issue.

lifeinchords commented 5 years ago

@prolightHub what are your thoughts?