Skip to content

Commit

Permalink
Added setDirectControl to allow a body to calculate velocity from pos…
Browse files Browse the repository at this point in the history
…ition changes

Also added component method and internal autoFrame vec2.
  • Loading branch information
photonstorm committed Oct 26, 2023
1 parent fbec8ae commit 4d55595
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 28 deletions.
109 changes: 81 additions & 28 deletions src/physics/arcade/Body.js
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,28 @@ var Body = new Class({
*/
this._bounds = new Rectangle();

this.autoUpdate = false;
/**
* Is this Body under direct control, outside of the physics engine? For example,
* are you trying to move it via a Tween? Or have it follow a path? If so then
* you can enable this boolean so that the Body will calculate its velocity based
* purely on its change in position each frame. This allows you to then tween
* the position and still have it collide with other objects. However, setting
* the velocity will have no impact on this Body while this is set.
*
* @name Phaser.Physics.Arcade.Body#directControl
* @type {boolean}
* @since 3.61.0
*/
this.directControl = false;

/**
* Stores the previous position of the Game Object when directControl is enabled.
*
* @name Phaser.Physics.Arcade.Body#autoFrame
* @type {Phaser.Math.Vector2}
* @private
* @since 3.61.0
*/
this.autoFrame = this.position.clone();
},

Expand Down Expand Up @@ -1151,49 +1172,56 @@ var Body = new Class({

prev.set(pos.x, pos.y);

if (this.autoUpdate)
if (!this.moves)
{
this._dx = pos.x - prev.x;
this._dy = pos.y - prev.y;

return;
}

if (this.directControl)
{
var autoFrame = this.autoFrame;

vel.set(
(pos.x - this.autoFrame.x) / delta,
(pos.y - this.autoFrame.y) / delta
(pos.x - autoFrame.x) / delta,
(pos.y - autoFrame.y) / delta
);

this._dx = pos.x - this.autoFrame.x;
this._dy = pos.y - this.autoFrame.y;
}
this.world.updateMotion(this, delta);

if (this.moves)
this._dx = pos.x - autoFrame.x;
this._dy = pos.y - autoFrame.y;
}
else
{
this.world.updateMotion(this, delta);

var vx = vel.x;
var vy = vel.y;
this.newVelocity.set(vel.x * delta, vel.y * delta);

if (!this.autoUpdate)
{
this.newVelocity.set(vx * delta, vy * delta);
pos.add(this.newVelocity);

pos.add(this.newVelocity);
}
this._dx = pos.x - prev.x;
this._dy = pos.y - prev.y;
}

this.updateCenter();
var vx = vel.x;
var vy = vel.y;

this.angle = Math.atan2(vy, vx);
this.speed = Math.sqrt(vx * vx + vy * vy);
this.updateCenter();

// Now the update will throw collision checks at the Body
// And finally we'll integrate the new position back to the Sprite in postUpdate
this.angle = Math.atan2(vy, vx);
this.speed = Math.sqrt(vx * vx + vy * vy);

if (this.collideWorldBounds && this.checkWorldBounds() && this.onWorldBounds)
{
this.world.emit(Events.WORLD_BOUNDS, this, this.blocked.up, this.blocked.down, this.blocked.left, this.blocked.right);
}
}
// Now the update will throw collision checks at the Body
// And finally we'll integrate the new position back to the Sprite in postUpdate

if (!this.autoUpdate)
if (this.collideWorldBounds && this.checkWorldBounds() && this.onWorldBounds)
{
this._dx = pos.x - prev.x;
this._dy = pos.y - prev.y;
var blocked = this.blocked;

this.world.emit(Events.WORLD_BOUNDS, this, blocked.up, blocked.down, blocked.left, blocked.right);
}
},

Expand Down Expand Up @@ -1563,6 +1591,7 @@ var Body = new Class({

this.prev.copy(pos);
this.prevFrame.copy(pos);
this.autoFrame.copy(pos);

if (gameObject)
{
Expand Down Expand Up @@ -1889,6 +1918,30 @@ var Body = new Class({
return (this.debugShowBody || this.debugShowVelocity);
},

/**
* Sets whether this Body should calculate its velocity based on its change in
* position every frame. The default, which is to not do this, means that you
* make this Body move by setting the velocity directly. However, if you are
* trying to move this Body via a Tween, or have it follow a Path, then you
* should enable this instead. This will allow it to still collide with other
* bodies, something that isn't possible if you're just changing its position directly.
*
* @method Phaser.Physics.Arcade.Body#setDirectControl
* @since 3.61.0
*
* @param {boolean} [value=true] - `true` if the Body calculate velocity based on changes in position, otherwise `false`.
*
* @return {Phaser.Physics.Arcade.Body} This Body object.
*/
setDirectControl: function (value)
{
if (value === undefined) { value = true; }

this.directControl = value;

return this;
},

/**
* Sets whether this Body collides with the world boundary.
*
Expand Down
22 changes: 22 additions & 0 deletions src/physics/arcade/components/Enable.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,28 @@
*/
var Enable = {

/**
* Sets whether this Body should calculate its velocity based on its change in
* position every frame. The default, which is to not do this, means that you
* make this Body move by setting the velocity directly. However, if you are
* trying to move this Body via a Tween, or have it follow a Path, then you
* should enable this instead. This will allow it to still collide with other
* bodies, something that isn't possible if you're just changing its position directly.
*
* @method Phaser.Physics.Arcade.Components.Enable#setDirectControl
* @since 3.61.0
*
* @param {boolean} [value=true] - `true` if the Body calculate velocity based on changes in position, otherwise `false`.
*
* @return {this} This Game Object.
*/
setDirectControl: function (value)
{
this.body.setDirectControl(value);

return this;
},

/**
* Enables this Game Object's Body.
* If you reset the Body you must also pass `x` and `y`.
Expand Down

0 comments on commit 4d55595

Please sign in to comment.