tonky Posted April 28, 2016 Share Posted April 28, 2016 I am trying to reset the position of a body when it hits an object/ground. I had already achieved this successfully in p2 but for some reason, body.x and body.y wont alter in box2d. Heres the relevant code. this.physics.startSystem(Phaser.Physics.BOX2D); this.physics.box2d.gravity.y = 500; // large gravity to make scene feel smaller this.physics.box2d.friction = 0.8; this.physics.box2d.setBoundsToWorld(); var rockResetTriggerVertices = [ 13000,188, 13500,288, ]; // Make the ground body var rockResetTrigger = new Phaser.Physics.Box2D.Body(this.game, null, 0, 0, 0); rockResetTrigger.setChain(rockResetTriggerVertices); // ROCKS this.rocks1 = this.game.add.group(); this.rocks1.enableBody = true; this.rocks1.physicsBodyType = Phaser.Physics.BOX2D; this.rockg1 = this.rocks1.create(this.game.width*16.5, 100, 'rock3'); for(var i = 0; i < this.rocks1.children.length; i++){ this.rocks1.children[i].body.setRectangle(50, 50); // this.rocks1.children[i].body.kinematic = true; this.rocks1.children[i].body.dynamic = true; this.rocks1.children[i].body.setBodyContactCallback(rockResetTrigger, this.rockReset, this); } rockReset: function(body1, body2, fixture1, fixture2, begin){ // a.reset(this.game.width*16.5, 10); body1.x = this.game.width*16.5; body1.y = 10; console.log(body1); } You can see it in action at phaser.site44.com Link to comment Share on other sites More sharing options...
Tom Atom Posted April 28, 2016 Share Posted April 28, 2016 Hi, it is not good idea to change physics objects (move, destroy, ...) in callbacks, because it is in the middle of physics world calculations. I think, that in past objects were locked during physics step and it looks it is still valid (not sure, but your results looks like it). Add two variables into your class: resetRock: false, rockBody: null, then in callback just READ colision: rockReset: function(body1, body2, fixture1, fixture2, begin){ this.resetRock = true; this.rockBody = body1; console.log(body1); }, ...and in update process what you read: update: function () { if (this.resetRock) { this.resetRock = false; this.rockBody.x = this.game.width * 16.5; this.rockBody.y = 10; } Link to comment Share on other sites More sharing options...
tonky Posted April 28, 2016 Author Share Posted April 28, 2016 Hi Tomas. Thanks again for helping me, but the thing is, I want a rain of rocks/obstacles - not just one rock. And I can only reset a rocks position once that rock touches the ground. I dont want to reset all the rocks when one touches the ground. Link to comment Share on other sites More sharing options...
Tom Atom Posted April 28, 2016 Share Posted April 28, 2016 Should be easy - in your contact callback just push all rocks that collided into array and in update check if array is empty or not. If not, then reset rock by rock, until you process whole array and then clear it. drhayes 1 Link to comment Share on other sites More sharing options...
tonky Posted April 28, 2016 Author Share Posted April 28, 2016 ah! yes. Thanks a lot. You are a brilliant person. You have helped me so much throughout the years. Thanks so much. Link to comment Share on other sites More sharing options...
tonky Posted April 28, 2016 Author Share Posted April 28, 2016 Also Tomas, is there a cleaner way whereby I can destroy or kill a physics body and its sprite in the callback? For example, this.ballBody.body.setBodyContactCallback(this.truck, this.collectableFunc, this); collectableFunc: function(a, b){ // var item = a.sprite; // item.kill(); // a.destroy(); // a.sprite.kill(); }, lol, either the body stays or the sprite. I want to remove both as cleanly as possible. Link to comment Share on other sites More sharing options...
Tom Atom Posted April 28, 2016 Share Posted April 28, 2016 No, do not do any changes in box2D callbacks. What I do is, that I add some property to sprite - like "toBeDestroyed" and in update I check if sprite is marked for destruction. If you want to avoid iteration, then create something like the stack as in my previous answer. You can just kill/destroy everything, what is on stack. This is from Box2D manual: Quote It is tempting to implement game logic that alters the physics world inside a contact callback. For example, you may have a collision that applies damage and try to destroy the associated actor and its rigid body. However, Box2D does not allow you to alter the physics world inside a callback because you might destroy objects that Box2D is currently processing, leading to orphaned pointers. ... and yes, almost forgot - from plugin manual. To destroy sprite and body: Quote However, if you created the body from a sprite, in most cases you will want to destroy the sprite and the body together, which you can do like: mySprite.destroy(); Phaser plugin is doing a lot of stuff for you. If you were not using it you would have to take care for sprite and body destruction in two steps by yourself... tonky 1 Link to comment Share on other sites More sharing options...
tonky Posted April 29, 2016 Author Share Posted April 29, 2016 Morning Tom. I did what you advised and I did think you were right but have a look at this. Stacking body.sprite and then destroying it in update, gives me an error "Uncaught TypeError: Cannot read property 'destroy' of null". I am making sure that I am stacking the sprite and not just the body. If I stack just the body, then it gets removed without errors as expected but the body-less sprite gets left behind obv. Have a look yourself. http://phaser.site44.com/ Link to comment Share on other sites More sharing options...
Tom Atom Posted April 29, 2016 Share Posted April 29, 2016 Hi, your contact callback is called alwasy twice: when contact begins and when it ends. So, if you destroy body after first call (when contact begin), then when contact end, body is already destroyed and you get error. It only looks like body is not destoryed, because game stops before debug draw is redrawn So, to make things work: 1] make sure, you are clearing your array (setting to 0, assigning [], splicing, ... http://stackoverflow.com/questions/1232040/how-do-i-empty-an-array-in-javascript): update: function () { if (this.collectedArray.length !== 0) { this.collectedArray.forEach(function (item) { console.log("destory"); item.destroy(); }); // clearing... this.collectedArray.length = 0; } 2] adjust your callback to listen only when contact begins: collectableFunc: function (a, b, f1, f2, begin) { if (!begin) { return; } this.collectedArray.push(a.sprite); }, btw - examples comming with Box2D plugin are really great. I went through them and it covers everything you need in box2D. For this, I was stuck at first, but then I looked into "Contact Callbacks" example and it reminded me about calling twice (begin / end) tonky 1 Link to comment Share on other sites More sharing options...
tonky Posted April 29, 2016 Author Share Posted April 29, 2016 Makes sense now. Finally, am getting comfortable with box2d now and getting to know it better thanks to you and you alone. I downloaded your game btw and will send u a pm over the weekend on your monetary numbers as I have been doing a lot of research on monitizing games and ads. ThinkGaming is a very helpful site but your blog is amazing. Thank you for being such a helpful person. Link to comment Share on other sites More sharing options...
Recommended Posts