Loading...
Loading...
Use this skill when using Arcade Physics in Phaser 4. Covers enabling physics, velocity, acceleration, gravity, collisions, overlap, world bounds, physics groups, static bodies, and collision categories. Triggers on: physics, arcade, velocity, gravity, collide, overlap, bounce, physics body.
npx skill4agent add phaserjs/phaser physics-arcadeSetting up and using Arcade Physics in Phaser 4 -- enabling physics in GameConfig, creating physics-enabled sprites/images/groups, velocity, acceleration, gravity, collisions (collide/overlap), world bounds, body properties, and collision categories.
src/physics/arcade/ArcadePhysics.jssrc/physics/arcade/World.jssrc/physics/arcade/Body.jssrc/physics/arcade/StaticBody.jssrc/physics/arcade/Factory.jssrc/physics/arcade/components/src/physics/arcade/events/class GameScene extends Phaser.Scene {
create() {
// Physics sprite (dynamic body, affected by gravity)
this.player = this.physics.add.sprite(100, 300, 'player');
this.player.setCollideWorldBounds(true);
this.player.setBounce(0.2);
// Static group (immovable platforms)
this.platforms = this.physics.add.staticGroup();
this.platforms.create(400, 568, 'ground').setScale(2).refreshBody();
// Register a persistent collider (checked every frame automatically)
this.physics.add.collider(this.player, this.platforms);
this.cursors = this.input.keyboard.createCursorKeys();
}
update() {
if (this.cursors.left.isDown) {
this.player.setVelocityX(-160);
} else if (this.cursors.right.isDown) {
this.player.setVelocityX(160);
} else {
this.player.setVelocityX(0);
}
}
}
// Enable Arcade Physics in game config
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
physics: {
default: 'arcade',
arcade: {
gravity: { y: 300 },
debug: false
}
},
scene: GameScene
};
const game = new Phaser.Game(config);this.physics.worldPhaser.Physics.Arcade.Worldthis.physics.worldVector2this.physics.world.gravity.y = 300RectangleSetBodySetStaticBodyProcessQueueColliderthis.physics.add.colliderthis.physics.add.overlapworld.setFPS(120)truefalseworld.pause()world.resume()truetruedebug: trueBodythis.physics.add.sprite()this.physics.add.image()gameObject.bodyBodyVector2Vector2Vector2Vector2Vector2Vector2(1, 0)Vector2(10000, 10000)-11falsetruetruefalsetruefalsetruefalsefalsetruefalsefalsetruesetCircleVector2{ none, up, down, left, right }StaticBodythis.physics.add.staticSprite()this.physics.add.staticImage()this.physics.add.staticGroup()body.reset()gameObject.refreshBody()collisionCategorycollisionMask// Add a physics body to any existing Game Object
this.physics.add.existing(mySprite); // dynamic body
this.physics.add.existing(mySprite, true); // static body
// Or enable via the world directly
this.physics.world.enable(mySprite); // dynamic
this.physics.world.enable(mySprite, Phaser.Physics.Arcade.STATIC_BODY);// Via the physics factory (this.physics.add)
const player = this.physics.add.sprite(100, 200, 'player'); // dynamic body
const coin = this.physics.add.image(300, 100, 'coin'); // dynamic body
const wall = this.physics.add.staticImage(400, 300, 'wall'); // static body
const platform = this.physics.add.staticSprite(400, 500, 'plat'); // static body
// Standalone bodies (no Game Object)
const sensor = this.physics.add.body(200, 200, 32, 32); // dynamic Body
const zone = this.physics.add.staticBody(100, 100, 64, 64); // static Body// Direct velocity
player.setVelocity(200, -300); // x=200 px/s, y=-300 px/s (upward)
player.setVelocityX(200);
player.body.velocity.set(200, -300); // equivalent via Vector2
// Acceleration + max velocity
player.setAcceleration(100, 0);
player.setMaxVelocity(300, 600);
// Per-body gravity (added to world gravity)
player.body.gravity.y = 200;
player.body.allowGravity = false; // exempt from world gravity
// Drag (applied only when acceleration is zero)
player.setDrag(300); // linear deceleration
player.body.useDamping = true;
player.setDrag(0.05); // damping mode: keeps 5% velocity/sec
// Bounce
player.setBounce(0.5); // both axes
player.setBounceY(1); // full vertical bounceupdate()// --- Persistent Colliders (preferred) ---
// Created via this.physics.add.collider / this.physics.add.overlap
// Automatically checked every physics step
const collider = this.physics.add.collider(player, platforms);
const overlap = this.physics.add.overlap(player, coins, collectCoin, null, this);
function collectCoin (player, coin) {
coin.disableBody(true, true); // disable physics and hide
}
// Collider management
collider.active = false; // temporarily disable
collider.destroy(); // remove permanently
// With processCallback (must return boolean to allow collision)
this.physics.add.collider(player, enemies, onHit, canCollide, this);
function canCollide (player, enemy) {
return !player.getData('invincible');
}
// --- One-shot checks (in update) ---
// Called manually each frame; no Collider object created
this.physics.collide(player, platforms);
this.physics.overlap(player, coins, collectCoin, null, this);
// Self-collision within a single group
this.physics.add.collider(enemies, enemies);// Dynamic physics group -- members get dynamic bodies automatically
const bullets = this.physics.add.group({
classType: Phaser.Physics.Arcade.Sprite, // default: ArcadeSprite
maxSize: 20,
collideWorldBounds: true,
bounceX: 1,
bounceY: 1,
velocityX: 200,
velocityY: 0,
allowGravity: false,
immovable: false
});
// Static physics group -- members get static bodies
const platforms = this.physics.add.staticGroup();
platforms.create(400, 568, 'ground');
platforms.create(600, 400, 'ground');
// After modifying a static group member's transform, refresh:
platforms.create(400, 568, 'ground').setScale(2).refreshBody();
// Group velocity helpers
bullets.setVelocity(200, 0); // all members
bullets.setVelocityX(200);
bullets.setVelocityY(0, 10); // with step increment per membercollideWorldBoundsbounceX/YaccelerationX/YdragX/YgravityX/YfrictionX/YvelocityX/YangularVelocityangularAccelerationangularDragmaxVelocityX/YmaxSpeedmassimmovableallowDragallowGravityallowRotationuseDampingenable// Set bounds size and which edges collide (left, right, up, down)
this.physics.world.setBounds(0, 0, 1600, 1200, true, true, false, true);
this.physics.world.setBoundsCollision(true, true, false, true); // edges only
// Per-body world bounds
player.setCollideWorldBounds(true);
player.body.setBoundsRectangle(new Phaser.Geom.Rectangle(100, 100, 600, 400));
player.body.worldBounce = new Phaser.Math.Vector2(0.5, 0.5);
// Detect world bounds hit via event (requires opt-in)
player.body.onWorldBounds = true;
this.physics.world.on('worldbounds', (body, up, down, left, right) => {
console.log('Hit edge:', { up, down, left, right });
});// Size and shape
player.body.setSize(24, 32, true); // width, height, re-center on GO
player.body.setOffset(4, 0); // offset from GO position
player.body.setCircle(16); // circular body, radius 16
player.body.setCircle(16, 4, 4); // circular with offset
// Collision behavior
player.body.setImmovable(true); // not moved by collisions
player.body.setPushable(false); // reflects velocity to collider
player.body.slideFactor.set(0, 0); // Sokoban-style: stops after push
player.body.setMass(2); // affects momentum exchange
// Enable / disable
player.disableBody(true, true); // disable body + hide Game Object
player.enableBody(true, x, y, true, true); // re-enable at position + show
// Per-direction collision check
player.body.checkCollision.up = false; // don't collide from above
player.body.syncBounds = true; // auto-sync size to texture// Get unique category values from the physics plugin
const CAT_PLAYER = this.physics.nextCategory(); // 0x0002
const CAT_ENEMY = this.physics.nextCategory(); // 0x0004
const CAT_BULLET = this.physics.nextCategory(); // 0x0008
// Assign categories to bodies or groups
player.setCollisionCategory(CAT_PLAYER);
enemy.setCollisionCategory(CAT_ENEMY);
bullet.setCollisionCategory(CAT_BULLET);
// Set what each body collides with
player.setCollidesWith([CAT_ENEMY]); // player hits enemies only
enemy.setCollidesWith([CAT_PLAYER, CAT_BULLET]); // enemies hit player + bullets
bullet.setCollidesWith([CAT_ENEMY]); // bullets hit enemies only
// Add/remove individual categories from existing mask
player.addCollidesWith(CAT_BULLET);
player.removeCollidesWith(CAT_ENEMY);
// Check if a body will collide with a category
player.willCollideWith(CAT_ENEMY); // returns boolean
// Reset to default (collides with everything)
player.resetCollisionCategory();
// Works on Groups too
enemies.setCollisionCategory(CAT_ENEMY);
enemies.setCollidesWith([CAT_PLAYER, CAT_BULLET]);0x00011(1 & 1) !== 02147483647resetCollisionCategory()ArcadeWorldConfigphysics.arcade| Property | Default | Description |
|---|---|---|
| | Physics steps per second |
| | Use fixed timestep vs render sync |
| | Simulation speed multiplier |
| | World gravity in px/sec |
| | World bounds origin |
| game size | World bounds dimensions |
| all | |
| | Overlap threshold for separation |
| | Tile overlap threshold |
| | Separate horizontally first |
| | Start simulation paused |
| | Enable debug rendering |
| | Debug display toggles |
| | Debug colors |
| | RTree items per node |
| | Use RTree for dynamic bodies |
| | If true, call |
this.physics.world| Event | String | Condition | Callback Args |
|---|---|---|---|
| | Two bodies collide and at least one has | |
| | Two bodies overlap and at least one has | |
| | Body hits world edge and has | |
| | Body collides with a tile | |
| | Body overlaps a tile | |
| | After each physics step | |
| | World paused | none |
| | World resumed | none |
body.onCollidebody.onOverlapbody.onWorldBoundstruethis.physics| Method | Description |
|---|---|
| Create sprite with dynamic body |
| Create image with dynamic body |
| Sprite with static body |
| Image with static body |
| Dynamic physics group |
| Static physics group |
| Add body to existing Game Object |
| Standalone dynamic Body (no GO) |
| Standalone static Body (no GO) |
| Persistent collider |
| Persistent overlap |
| One-shot collision check |
| One-shot overlap check |
| Next collision category bitmask |
| Pause/resume simulation |
| Accelerate toward point |
| Move toward point at speed |
| Angle (deg) to velocity |
| Rotation (rad) to velocity |
| Find nearest body |
| Find farthest body |
| Query bodies in rectangle |
| Query bodies in circle |
accelerateToObjectmoveToObjectcollideTilesoverlapTilesenableUpdatedisableUpdatethis.physics.world| Method | Description |
|---|---|
| Set boundary + edge checks |
| Set which edges collide |
| Change physics step rate |
| Enable physics on object/group/array |
| Disable physics on object/group/array |
| Add/remove Body from simulation |
| Create Collider (same args as factory) |
| Remove Collider |
| Pause/resume simulation |
| Create debug rendering graphic |
| Method | Description |
|---|---|
| Set velocity |
| Set acceleration |
| Velocity caps |
| Bounce and drag |
| Enable damping mode |
| Friction and per-body gravity |
| Mass and collision behavior |
| Resize/offset body |
| Switch to circular body |
| World bounds collision |
| Custom bounds rectangle |
| Toggle physics features |
| Enable/disable body |
| Category filtering |
| Reset to default (all) |
| Reset position or zero velocity |
debug: truebody.reset()gameObject.refreshBody()collideoverlapcollideoverlapoverlapthis.physics.add.collider()this.physics.collide()update()'collide''overlap''worldbounds'onCollideonOverlaponWorldBoundstrue0x000112147483647this.physics.nextCategory()resetCollisionCategory()defaultsvelocityXbounceYdefaultscustomUpdatecustomUpdate: truethis.physics.world.update(time, delta)useDampinguseDampingtrue0.050.05immovable = truepushable = falseoverlapOnlyuseTree: false| File | Purpose |
|---|---|
| Scene plugin ( |
| Physics world -- bodies, gravity, bounds, colliders, step loop, setBounds, addCollider |
| Dynamic body -- velocity, acceleration, bounce, drag, gravity, mass, immovable, pushable |
| Static body -- immovable, no velocity, optimized RTree lookup |
| |
| Collider object -- persistent collision/overlap check with callbacks |
| Dynamic physics group with per-member defaults |
| Static physics group with auto-refresh |
| Body component mixins -- Acceleration, Angular, Bounce, Collision, Debug, Drag, Enable, Friction, Gravity, Immovable, Mass, Pushable, Size, Velocity |
| Collision category/mask methods -- setCollisionCategory, setCollidesWith, addCollidesWith, removeCollidesWith |
| Event constants -- COLLIDE, OVERLAP, WORLD_BOUNDS, TILE_COLLIDE, TILE_OVERLAP, WORLD_STEP, PAUSE, RESUME |
| TypeDef for arcade physics config options |