deedeekaka

Possible Bug! Physics body is offset from child sprite

Recommended Posts

Hola hola,

So I am working on a 2D basketball game. I am using 2 small sprites (with circular physics bodies) on each side of the basket rim for collision detection with the ball. I parented the 2 sprites to the backboard so I could move them all together (as shown in the child sprite example). I turned on the debug draw for the physics bodies and found the 2 bodies were not in the same position as the sprites.

 

//Load net sprite
this.net = this.game.add.sprite(this.game.world.centerX, 200, 'net');
this.net.anchor.setTo(0.5);

//Add hoop children markers
this.leftMarker = this.net.addChild(this.game.make.sprite(-66, 60, 'marker'));
this.leftMarker.anchor.setTo(0.5);
this.rightMarker = this.net.addChild(this.game.make.sprite(66, 60, 'marker'));
this.rightMarker.anchor.setTo(0.5);

 

I parent them like so.. but my physics bodies don't act as if they are parented. They should be at the same position as the sprite, but instead they are (-66, 60) and (66, 60) from the top left corner (0, 0) instead of (-66, 60) and (66, 60) from the parents position (world center x, 200). You can see the attached image as an example.

Is there something I am missing? Is this the way it's supposed to be? Can I somehow update the physics bodies to line up with the sprites easily?

offsetBody.jpg

Share this post


Link to post
Share on other sites

If it's a bug, it should go in the github issue for the Phaser project.

Quote

Is there something I am missing? Is this the way it's supposed to be?

yes, yes I think so

What physics engine are you using? The sprites should follow the bodies.

Share this post


Link to post
Share on other sites
16 hours ago, eddieone said:

What physics engine are you using? The sprites should follow the bodies.


I'm using the P2 physics engine. I've even tried to alter the "offset" property of the bodies themselves, but no luck. When the markers aren't parented to the net, it works fine. But as soon as I parent them (because I want to move them around together easily by just moving the parent), it creates an offset.

Share this post


Link to post
Share on other sites

You are not showing the code that you should be showing, which is the actual p2 physics code not the code on how you load the sprites.

Another point that I need to mention is that setting the sprite anchor to 0.5 is redundant because applying the p2 physics on it will set it to 0.5 because of how p2 is set up.

My guess is that you are not applying the physics properly, and in lack of the actual p2 code you will have problems finding anyone willing to do the guess work.

And as a final point: I would start with arcade physics.

http://phaser.io/examples/v2/category/arcade-physics

 

 

EDIT: Definitely not a bug.

Share this post


Link to post
Share on other sites

Didn't use Arcade for lack of circle colliders (just found out they do indeed exist) and I didn't want to calculate angular rotation and whatnot (but I'm going to try with Arcade anyways, thanks :))

I had no idea that I didn't need to anchor my sprites to 0.5. But I removed them and the positions were all out of place. I didn't see that they were anchored 0.5 automatically by the physics, but maybe I'm doing something in the wrong order.

Below is my full Game.js code.

Basketball.Game = function (game) {

    this.score = null;
    this.scoreText = null;

    this.ball = null;
    this.net = null;
	this.rim = null;
    this.leftMarker = null;
    this.rightMarker = null;
	this.checker = null;

    this.ballCollisionGroup = null;
    this.rimCollisionGroup = null;

    this.ballInitRadius = null;
    this.ballResized = false;
    this.collisionsOn = false;
    this.launched = false;
	this.respawned = false;
    this.lastPointerPos = null;
    
    //HTML element that will produce screenshot
    this.clickToSave = null;
    
    //Constants
    this.GRAVITY = 1600;
    this.SHOOT_FORCE = 1400;
    this.EDGE_CUSHION = 10;
    this.SCALE_PERCENT = 0.55;

};

Basketball.Game.prototype = {

	create: function () {

        //Load net sprite
        this.net = this.game.add.sprite(this.game.world.centerX, this.game.world.centerY - 200, 'net');
        this.net.anchor.setTo(0.5);

        //Load hoop markers
        this.leftMarker = this.game.add.sprite(this.game.world.centerX - 57, 232, 'marker');
        this.rightMarker = this.game.add.sprite(this.game.world.centerX + 57, 232, 'marker');
        this.leftMarker.anchor.setTo(0.5);
        this.rightMarker.anchor.setTo(0.5);
        
        //Load ball sprite
        this.ball = this.game.add.sprite(this.game.world.centerX, this.game.world.height - 100, 'ball');
        this.ballInitRadius = this.ball.width / 2;
        this.ball.anchor.setTo(0.5);
		
		this.rim = this.game.add.sprite(this.game.world.centerX, this.game.world.centerY - 200, 'rim');
        this.rim.anchor.setTo(0.5);
		
		this.checker = this.game.add.sprite(this.game.world.centerX, this.game.world.centerY - 100, 'checker');
        this.checker.anchor.setTo(0.5);
        
        //Setting up the physics environment
        this.game.world.setBounds(-this.ball.width, -this.ball.height, this.game.width + this.ball.width * 2, this.game.height + this.ball.height * 2);
        this.game.physics.startSystem(Phaser.Physics.P2JS);
        this.game.physics.p2.gravity.y = this.GRAVITY;
		this.game.physics.setBoundsToWorld();
        
        //Setting up the marker physics
        this.game.physics.p2.enable(this.leftMarker);
        this.leftMarker.body.setCircle(this.leftMarker.width / 2);
        this.leftMarker.body.static = true;
        this.leftMarker.alpha = 0;
        this.game.physics.p2.enable(this.rightMarker);
        this.rightMarker.body.setCircle(this.rightMarker.width / 2);
        this.rightMarker.body.static = true;
        this.rightMarker.alpha = 0;
        
        //Parent markers to the net
        this.net.addChild(this.leftMarker);
        this.net.addChild(this.rightMarker);
        
		//Setting up checker physics
        this.game.physics.p2.enable(this.checker, true);
		this.checker.body.data.shapes[0].sensor = true;
        this.checker.body.static = true;
		
        //Setting up the ball physics
        this.game.physics.p2.enable(this.ball);
        this.ball.body.setCircle(this.ball.width / 2);
        this.ball.body.setZeroVelocity();
        this.ball.body.static = true;

        //Set up collision groups
        this.ballCollisionGroup = this.game.physics.p2.createCollisionGroup();
        this.rimCollisionGroup = this.game.physics.p2.createCollisionGroup();

        this.game.physics.p2.setImpactEvents(true);
        this.game.physics.p2.updateBoundsCollisionGroup();
        this.game.physics.p2.restitution = 0.8;

        //Enable input
        this.game.input.onDown.add(this.track, this);
        this.game.input.onUp.add(this.launch, this);
		this.checker.body.onBeginContact.add(this.checkIfScored, this);

        //Initialize
        this.score = 0;
        this.scoreText = this.game.add.bitmapText(this.game.world.centerX, this.game.world.centerY, 'pixel', 'Score: ' + this.score, 36);
        this.scoreText.anchor.setTo(0.5);
        this.lastPointerPos = new Phaser.Point(0, 0);

        //For mobile
        Phaser.Canvas.setTouchAction(this.game.canvas, 'auto');
        this.game.input.touch.preventDefault = true;

	},

	update : function () {
		
		//Check if the ball is out of bounds
		if (this.ball.x < this.camera.x - this.ball.width / 2 || this.ball.x > this.camera.width + this.ball.width / 2||
			this.ball.y < this.camera.y - this.ball.height / 2 || this.ball.y > this.camera.height + this.ball.height / 2) {
				
			if (!this.respawned) {
				
				this.respawn();
				
			}
			
		}
		
		if (this.ball.y < this.net.children[0].y - this.ball.height / 2) {
			
			//Turn on ball collisions
			if (!this.collisionsOn) {
				
				console.log("collision groups on!");
				this.ball.body.setCollisionGroup(this.ballCollisionGroup);
				this.leftMarker.body.setCollisionGroup(this.rimCollisionGroup);
				this.rightMarker.body.setCollisionGroup(this.rimCollisionGroup);
				this.ball.body.collides(this.rimCollisionGroup);
				this.leftMarker.body.collides(this.ballCollisionGroup);
				this.rightMarker.body.collides(this.ballCollisionGroup);
				this.collisionsOn = true;
				
			}
			
			if (!this.ballResized) {
				
				this.ball.body.setCircle(this.ballInitRadius * this.SCALE_PERCENT);
				this.ball.body.setCollisionGroup(this.ballCollisionGroup);
				this.ballResized = true;
				
			}
			
		}
		else {
			
			this.collisionsOn = false;
			
		}
		
	},
	
	track : function () {
		
		//Do a hit test to make sure finger is on the ball
		
		
		//Update the last finger position
		this.lastPointerPos.x = this.input.x;
		this.lastPointerPos.y = this.input.y;
		
		//Set the ball physics to be still
		this.launched = true;
		this.ball.body.static = true;
		this.ball.body.setZeroVelocity();
		
	},
	
	launch : function () {
		
		if (this.launched) {
			
			this.game.add.tween(this.ball.scale).to({ x: this.SCALE_PERCENT, y: this.SCALE_PERCENT }, 800, Phaser.Easing.Linear.In, true);
			this.launched = false;
			this.ball.body.static = false;
			
			//Get the direction of finger swipe, normalize it, and apply a scalar to the velocity of the ball
			var direction = new Phaser.Point(this.input.x - this.lastPointerPos.x, this.input.y - this.lastPointerPos.y);
			//direction.x = this.game.math.snapTo(direction.x, 5);
			//direction.y = this.game.math.snapTo(direction.y, 5);
			Phaser.Point.normalize(direction, direction);
			
			if (direction.y < 0) {
				
				this.ball.body.velocity.x = direction.x * this.SHOOT_FORCE;
				this.ball.body.velocity.y = direction.y * this.SHOOT_FORCE;
				
			}
			
		}
	},
	
	checkIfScored : function () {
		
		console.log(this.ball.body.velocity.y);
		if (this.ball.body.velocity.y > 0)
		{
			
			console.log("SCORED!");
			this.score++;
			this.scoreText.setText('Score: ' + this.score);
			
		}
		
	},
	
	respawn : function () {
		
		this.respawned = true;
		
		//Remove collision groups
		this.ball.body.removeCollisionGroup(this.rimCollisionGroup);
		this.leftMarker.body.removeCollisionGroup(this.ballCollisionGroup);
		this.rightMarker.body.removeCollisionGroup(this.ballCollisionGroup);
		
		//Set the ball physics to be still again
		this.ball.body.static = true;
		this.ball.body.setZeroVelocity();
		
		this.game.time.events.add(Phaser.Timer.SECOND * 0.25, function () {
			
			this.respawned = false;
			
			//Rescale the ball and its body
			this.ball.scale.setTo(1);
			this.ball.body.setCircle(this.ball.width / 2);
			this.ballResized = false;
				
			//Spawn the ball in a new, random location
			var ballSpawnX = this.game.rnd.integerInRange(this.camera.x + this.ball.width / 2 + this.EDGE_CUSHION, (this.camera.width - this.ball.width / 2) - this.EDGE_CUSHION);
			ballSpawnX = this.game.math.snapTo(ballSpawnX, 10);
			
			//Make sure the ball is in the boundary we set
			if (ballSpawnX < this.ball.width + this.EDGE_CUSHION) {
				
				ballSpawnX = this.ball.width + this.EDGE_CUSHION;
				
			}
			else if (ballSpawnX > this.world.width - this.EDGE_CUSHION) {
				
				ballSpawnX = this.world.width - this.EDGE_CUSHION;
				
			}
		
			this.ball.body.x = ballSpawnX;
			this.ball.body.y = this.game.height - 100;
			
		}, this);
		
	},
	
	saveCanvas : function () {
		
		var link = this.game.canvas.toDataURL('image/png');
		window.open(link, '_blank');
		
	},

	quitGame: function (pointer) {

		this.state.start('StartMenu');

	}

};

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.