Jump to content

sprites occasionally moving to different locations


InsaneHero
 Share

Recommended Posts

I have a strange one here and just hoping someone else might have encountered it and solved it.

 

I'm creating a helicopter sprite and a bunch of people during my game initialisation, but I noticed that sometimes the people aren't within the ranges where they're supposed to be so I started debugging.

Turns out that after creating them and before their first update function they are moving to a different 'x' location than where I created them.

I noticed they are quite often (not always) created at the exact same location as the helicopter so I figured this was probably a messed up reference issue...  After digging deeper it turns out the helicopter (an entirely separate 'class' with it's own separate references) is also being moved horizontally.

 

The distance moved varies - they seem to end up on one of a set of recurring x locations.  The body velocities are zero when the movement is first detected (I memorise the x location at create then compare against it in update).

I need to find out what is making the 'x' change but without a 'set breakpoint on variable' debug option I'm actually struggling to work out how (unless I step everything from create to update which will take a long time).

 

Has anyone seen anything similar?

 

I'm using the very latest dev build btw.  I guess I should plug in the release and see if it still happens although that will break some parts of the game so it's not a true test after I change the source.

 

Link to comment
Share on other sites

You got me all excited!  Unfortunately it turns out that chrome only evaluates the conditional at the point where you set the breakpoint and edit it.

http://www.randomthink.net/blog/2012/11/breakpoint-actions-in-javascript/

Which is a slightly simpler way of doing what I'm already doing (bracketing sections of code and checking to see 'has it changed yet'?)

 

In devStudio it was possible to just 'watch' a variable and then you'd get a breakpoint when it changed, on the line which was changing it.  However chasing up your lead I encountered a few other suggestions and using a getter/setter and setting a breakpoint there should capture the culprit!

Link to comment
Share on other sites

BTW no, I don't know what causes this (and haven't seen it personally) - however I'm expecting it'll be a transform reference / undefined error somewhere in Pixi, or preUpdate where Phaser caches it.

 

The core game loop has stepping support built in too, so you could trigger it off when you think you're in the right place, then just step through it piece by piece dumping out what you need. I can post an example if you'd like to see it.

Link to comment
Share on other sites

Arcade postUpdate has an incorrect value for body.prev.x (-825 instead of -425).  Still tracking backwards...

 

My world is centered on 0 so I have negative x coordinates for anything to the left of center... are there any known problems with Arcade physics and negative coordinates maybe?

Link to comment
Share on other sites

My sprite bodys are being detected as outside the world bounds and are pushed back in, then the distance they moved (deltaX function) is applied to the sprite position making it jump sideways.

 

However the sprites never go anywhere near the world bounds... it looks like there's a discrepancy in sprite.position vs sprite.world in regards to Arcade physics body position calculations.  It's all tangled up with sprite.worldTransform values and the camera position, so I'm having a hell of a time tracking it back properly - there are a lot of interdependent variables in this system.

Link to comment
Share on other sites

Finding a few errors as I track this down:

 

Arcade Body

 

c'tor (move width and height up, calculate position properly instead of using sprite.x/y):

    /**
    * @property {number} width - The calculated width of the physics body.
    */
    this.width = sprite.width;
 
    /**
    * @property .numInternal ID cache
    */
    this.height = sprite.height;
 
    /**
    * @property {Phaser.Point} offset - The offset of the Physics Body from the Sprite x/y position.
    */
    this.offset = new Phaser.Point();
 
    /**
    * @property {Phaser.Point} position - The position of the physics body.
    * @readonly
    */
//    this.position = new Phaser.Point(sprite.x, sprite.y);
    this.position = new Phaser.Point((this.sprite.world.x - (this.sprite.anchor.x * this.width)) + this.offset.x,
                                 (this.sprite.world.y - (this.sprite.anchor.y * this.height)) + this.offset.y);
 

setSize (update position when the width and height change... position is top-left corner and center should remain stationary):

        // update position value using the new width and height values
        this.position.x = (this.sprite.world.x - (this.sprite.anchor.x * this.width)) + this.offset.x;
        this.position.y = (this.sprite.world.y - (this.sprite.anchor.y * this.height)) + this.offset.y;
        // refresh the previous position memory (it didn't move, it just changed size)
        this.prev.x = this.position.x;
        this.prev.y = this.position.y;
 
I'm still looking for the fundamental problem.
Link to comment
Share on other sites

In Sprite.js there's a line that calculates the world position:

 

    this.world.setTo(this.game.camera.x + this.worldTransform.tx, this.game.camera.y + this.worldTransform.ty);
 
My object is at world -220 (x coord), the worldTransform.tx is at -220, and the camera.x is at -500.
This moves the Sprite to a world.x of -720 which is outside the world bounds (the world is -500...+500 in the x direction).
 
As seen previously the Body calculation uses Sprite.world:
        this.position.x = (this.sprite.world.x - (this.sprite.anchor.x * this.width)) + this.offset.x;
 
Then Body.checkWorldBounds() detects that the body is outside of the world and pushes it back in again:
        if (this.position.x < this.game.physics.arcade.bounds.x && this.game.physics.arcade.checkCollision.left)
        {
            this.position.x = this.game.physics.arcade.bounds.x;
            this.velocity.x *= -this.bounce.x;
            this.blocked.left = true;
        }
 
The deltaX calculation sees that the body has moved because position.x != prev.x, and moves the sprite by the same amount (using sprite.x NOT sprite.world.x - which is probably wrong but I'll skip that for now, sprite.world.x may be fixed somewhere I haven't looked yet)
 
So that's why my sprites are jumping sideways.  The only remaining question is why is this.game.camera.x = -500.  The camera is tracking the chopper and the chopper is at -220 initially.  I'll track that down now.
Link to comment
Share on other sites

Right got it I think...

 

The camera is 800 px wide, when the chopper is at -220 the camera left edge will be at -620 which is outside the world bounds so it gets set back by Camera.checkBounds.

 

There should never be any sprite position calculations that use the camera position as a starting point because the camera is restricted to the world bounds - the sprite should continue to move towards the edge after the camera has been stopped.  So this is wrong:

 

Sprite.js

    this.world.setTo(this.game.camera.x + this.worldTransform.tx, this.game.camera.y + this.worldTransform.ty);

 
The reason this problem was intermittent in my game is because the chopper is created at a random x location so sometimes the camera is not being adjusted because it isn't off the edge of the world.
 
So, TLDR:
 
- When a camera is tracking a game object which is created close enough to the edge of a map that the camera cannot center the object, it will be adjusted into the game world limits.
- The adjusted camera position feeds back into the sprite world location coordinates.
- The sprite world coordinates are used by the physics body in preUpdate to set it's position (why?)
 
Additionally:
- Sometimes the adjusted physics body based on these incorrect Sprite.world coordinates will be outside of the world bounds.  If it is enabled then checkWorldBounds will push the body back into the world
- The deltaX function will see the difference between the body position now and last frame, and will move the sprite.position by the same amount.  Thus the sprite will move with no obvious cause and will not be created at the location specified.
 
Phew.  Someone else can work out how to fix this, I'm knackered.
Link to comment
Share on other sites

  • 1 year later...

I am having completely inconsistent results using world.x/y. For example, if I have a muzzle flash which is the child of a sprite, and has its own rotation, x/y coordinates relative to its parent, the world.x/y property doesn't deliver accurate results. Oddly, the position of the camera sometimes effects the world x/y.  It's a big hot mess, I've circled back to this issue many times before. 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...