Skip to content
Back to skills

Dev Phaser Physics Arcade

ASecurity

Arcade physics velocity, acceleration, collision, and bounds

  • 666 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added February 8, 2026
developmenttypescriptgitapi

Works with

  • cursor
  • api

Security analysis

A100/100

Scanned February 10, 2026

npx -y skills add majiayu000/claude-skill-registry --skill dev-phaser-physics-arcade --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dev Phaser Physics Arcade?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Dev Phaser Physics Arcade
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/majiayu000-dev-phaser-physics-arcade/badge)](https://www.skillsdirectory.com/skills/majiayu000-dev-phaser-physics-arcade)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: dev-phaser-physics-arcade
description: Arcade physics velocity, acceleration, collision, and bounds
---

# Phaser Arcade Physics

> "Fast, simple 2D physics for platformers and arcade games."

## Before/After: Manual Collision vs Phaser Arcade Physics

### ❌ Before: Manual AABB Collision

```typescript
// Manual physics without Phaser
interface Box {
  x: number;
  y: number;
  width: number;
  height: number;
  vx: number;
  vy: number;
}

const player: Box = { x: 100, y: 300, width: 32, height: 48, vx: 0, vy: 0 };
const platforms: Box[] = [
  { x: 0, y: 500, width: 800, height: 68 }
];

function checkCollision(a: Box, b: Box): boolean {
  return a.x < b.x + b.width &&
         a.x + a.width > b.x &&
         a.y < b.y + b.height &&
         a.y + a.height > b.y;
}

function updatePhysics(dt: number) {
  // Apply gravity
  player.vy += 1000 * dt;

  // Update position
  player.x += player.vx * dt;
  player.y += player.vy * dt;

  // Check collision with each platform
  for (const platform of platforms) {
    if (checkCollision(player, platform)) {
      // Resolve collision
      if (player.vy > 0 && player.y + player.height - player.vy * dt <= platform.y) {
        player.y = platform.y - player.height;
        player.vy = 0;
      }
    }
  }

  // World bounds
  if (player.x < 0) player.x = 0;
  if (player.x > 800 - player.width) player.x = 800 - player.width;
}

// Problems:
// - Manual collision detection is error-prone
// - No proper physics simulation
// - Tunneling at high speeds
// - No built-in platformer features
// - Manual state tracking
```

### ✅ After: Phaser Arcade Physics

```typescript
// Phaser handles physics automatically
export class GameScene extends Phaser.Scene {
  private player!: Phaser.Physics.Arcade.Sprite;

  create() {
    // Physics-enabled sprite with built-in collision
    this.player = this.physics.add.sprite(100, 450, 'player');
    this.player.setBounce(0); // No bounce
    this.player.setCollideWorldBounds(true);

    // Static platforms group
    const platforms = this.physics.add.staticGroup();
    platforms.create(400, 568, 'ground').setScale(2, 1).refreshBody();

    // One line to add collision
    this.physics.add.collider(this.player, platforms);
  }

  update() {
    // Simple velocity-based movement
    if (this.cursors.left.isDown) {
      this.player.setVelocityX(-160);
    } else if (this.cursors.right.isDown) {
      this.player.setVelocityX(160);
    } else {
      this.player.setVelocityX(0);
    }

    // Grounded check built-in
    if (this.cursors.up.isDown && this.player.body!.touching.down) {
      this.player.setVelocityY(-330);
    }
  }
}

// Benefits:
// - Built-in collision detection (no tunneling)
// - Touching detection (grounded, walls)
// - World bounds handling
// - Proper physics simulation
// - Easy platformer features
```

## When to Use This Skill

Use when:

- Implementing platformer games
- Creating collision detection
- Working with velocity and gravity
- Building arcade-style gameplay
- Need simple, performant physics

## Quick Start

```typescript
// Enable arcade physics in game config
physics: {
  default: 'arcade',
  arcade: {
    gravity: { y: 1000 },
    debug: false
  }
}

// Create physics sprite
const player = this.physics.add.sprite(400, 300, 'player');
player.setBounce(0.2);
player.setCollideWorldBounds(true);
```

## Decision Framework

| Need                | Use                              |
| ------------------- | -------------------------------- |
| Platformer          | Arcade with gravity              |
| Top-down            | Arcade without gravity           |
| Bouncing objects    | `setBounce(0.5)`                 |
| Static platforms    | `this.physics.add.staticGroup()` |
| Collision detection | `this.physics.add.collider()`    |

## Progressive Guide

### Level 1: Basic Physics Body

```typescript
export class GameScene extends Phaser.Scene {
  private player!: Phaser.Physics.Arcade.Sprite;

  create() {
    // Create physics sprite
    this.player = this.physics.add.sprite(400, 300, "player");

    // Physics properties
    this.player.setBounce(0.2); // Bounciness (0-1)
    this.player.setCollideWorldBounds(true); // Don't leave screen
    this.player.setDrag(0.1, 0); // Air resistance
    this.player.setFriction(0.1); // Ground friction
    this.player.setMaxVelocity(400); // Speed cap

    // Velocity control
    this.player.setVelocityX(200);
    this.player.setVelocityY(-300);
    this.player.setVelocity(100, 100);

    // Acceleration
    this.player.setAccelerationX(50);
  }
}
```

### Level 2: Collision Detection

```typescript
create() {
  const player = this.physics.add.sprite(400, 300, 'player');
  const platforms = this.physics.add.staticGroup();

  // Create platforms
  platforms.create(400, 568, 'ground').setScale(2, 1).refreshBody();
  platforms.create(600, 400, 'platform');

  // Player collides with platforms
  this.physics.add.collider(player, platforms);

  // Overlap detection (trigger, no collision response)
  const coins = this.physics.add.group({
    defaultKey: 'coin',
    bounceX: 0.5,
    bounceY: 0.5
  });

  this.physics.add.overlap(player, coins, this.collectCoin, undefined, this);
}

collectCoin(player: Phaser.Types.Physics.Arcade.GameObjectWithBody, coin: any) {
  coin.disableBody(true, true); // Disable and hide
}
```

### Level 3: Platformer Controls

```typescript
export class GameScene extends Phaser.Scene {
  private player!: Phaser.Physics.Arcade.Sprite;
  private cursors!: Phaser.Types.Input.Keyboard.CursorKeys;
  private jumpKey!: Phaser.Input.Keyboard.Key;

  create() {
    this.player = this.physics.add.sprite(100, 450, "player");
    this.player.setBounce(0);
    this.player.setCollideWorldBounds(true);

    // Setup inputs
    this.cursors = this.input.keyboard!.createCursorKeys();
    this.jumpKey = this.input.keyboard!.addKey("SPACE");

    // Platforms
    const platforms = this.physics.add.staticGroup();
    platforms.create(400, 568, "ground").setScale(2).refreshBody();

    this.physics.add.collider(this.player, platforms);
  }

  update() {
    // Left/Right movement
    if (this.cursors.left.isDown) {
      this.player.setVelocityX(-160);
    } else if (this.cursors.right.isDown) {
      this.player.setVelocityX(160);
    } else {
      this.player.setVelocityX(0);
    }

    // Jump only if touching ground
    if (this.jumpKey.isDown && this.player.body!.touching.down) {
      this.player.setVelocityY(-330);
    }
  }
}
```

### Level 4: Advanced Collision Callbacks

```typescript
create() {
  // Collision with process callback (custom collision logic)
  this.physics.add.collider(
    this.player,
    this.enemies,
    this.playerHitEnemy,
    this.checkEnemyVulnerable,
    this
  );
}

// Called to check if collision should happen
checkEnemyVulnerable(
  player: Phaser.Types.Physics.Arcade.GameObjectWithBody,
  enemy: any
): boolean {
  const enemySprite = enemy as Phaser.Physics.Arcade.Sprite;
  // Only collide if enemy is vulnerable
  return !enemySprite.getData('invincible');
}

// Called when collision occurs
playerHitEnemy(
  player: Phaser.Types.Physics.Arcade.GameObjectWithBody,
  enemy: any
) {
  const enemySprite = enemy as Phaser.Physics.Arcade.Sprite;

  // If player is above enemy, kill enemy
  if (player.body!.velocity.y > 0 && player.y < enemySprite.y - 10) {
    enemySprite.destroy();
    player.setVelocityY(-200); // Bounce
  } else {
    // Player dies
    this.handlePlayerDeath();
  }
}
```

### Level 5: Custom Physics Components

```typescript
// Physics component class
class PlatformerController {
  private speed = 160;
  private jumpForce = -330;
  private isGrounded = false;

  constructor(
    private sprite: Phaser.Physics.Arcade.Sprite,
    private cursors: Phaser.Types.Input.Keyboard.CursorKeys,
    private jumpKey: Phaser.Input.Keyboard.Key
  ) {
    this.enableDoubleJump();
  }

  update() {
    // Horizontal movement
    if (this.cursors.left.isDown) {
      this.sprite.setVelocityX(-this.speed);
      this.sprite.setFlipX(true);
    } else if (this.cursors.right.isDown) {
      this.sprite.setVelocityX(this.speed);
      this.sprite.setFlipX(false);
    } else {
      this.sprite.setVelocityX(0);
    }

    // Jump
    if (this.jumpKey.isDown && this.isGrounded) {
      this.sprite.setVelocityY(this.jumpForce);
      this.isGrounded = false;
    }
  }

  onGrounded() {
    this.isGrounded = true;
  }

  private enableDoubleJump() {
    this.jumpKey.on('down', () => {
      if (!this.isGrounded && this.sprite.body!.velocity.y > -200) {
        this.sprite.setVelocityY(this.jumpForce * 0.8);
      }
    });
  }
}

// In scene
create() {
  const controller = new PlatformerController(
    this.player,
    this.cursors,
    this.jumpKey
  );

  this.physics.add.collider(this.player, platforms, () => {
    controller.onGrounded();
  });
}

update() {
  controller.update();
}
```

## Anti-Patterns

❌ **DON'T:**

- Use Matter physics for simple platformers - Arcade is faster
- Set position directly on physics bodies - use velocity
- Forget to call `refreshBody()` after scaling static objects
- Use overlap when collider is needed
- Disable physics bodies instead of removing from scene
- Mix pixel and meter units arbitrarily

✅ **DO:**

- Use Arcade for platformers, top-down games
- Apply forces/velocity for movement
- Refresh body after scale/position changes
- Use proper collision types (collider vs overlap)
- Remove bodies from physics world when destroyed
- Keep units consistent (pixels)

## Code Patterns

### One-Way Platforms

```typescript
create() {
  const platforms = this.physics.add.staticGroup();

  // Create one-way platform
  const platform = platforms.create(400, 400, 'platform');
  platform.checkCollision.down = false; // Can jump through from below
  platform.checkCollision.up = true;    // Lands on top
}
```

### Body Size Adjustment

```typescript
const player = this.physics.add.sprite(400, 300, "player");

// Adjust body size (smaller than sprite)
player.body!.setSize(20, 40);
player.body!.setOffset(6, 8); // Center the body

// Disable body on one side
player.body!.checkCollision.up = false;
```

### Moving Platform

```typescript
export class MovingPlatform extends Phaser.Physics.Arcade.Image {
  constructor(
    scene: Phaser.Scene,
    x: number,
    y: number,
    texture: string,
    private startX: number,
    private endX: number,
  ) {
    super(scene, x, y, texture);
    scene.add.existing(this);
    scene.physics.add.existing(this, false); // false = static

    this.setVelocityX(50);
    this.scene.events.on("update", this.updatePlatform, this);
  }

  updatePlatform() {
    if (this.x >= this.endX) {
      this.setVelocityX(-50);
    } else if (this.x <= this.startX) {
      this.setVelocityX(50);
    }
  }
}
```

## Checklist

- [ ] Physics enabled in game config
- [ ] Bodies properly sized (offset from sprite)
- [ ] Static bodies use `staticGroup()`
- [ ] Dynamic bodies use `physics.add.sprite()`
- [ ] Colliders/overlaps configured
- [ ] World bounds enabled if needed
- [ ] Refresh body called after scale

## Physics Body Properties

| Property       | Type    | Description                  |
| -------------- | ------- | ---------------------------- |
| `velocity`     | Vector2 | Current velocity             |
| `acceleration` | Vector2 | Applied acceleration         |
| `drag`         | Vector2 | Deceleration over time       |
| `gravity`      | Vector2 | Applied gravity force        |
| `bounce`       | number  | Bounciness (0-1)             |
| `friction`     | number  | Surface friction             |
| `maxVelocity`  | Vector2 | Maximum speed cap            |
| `allowGravity` | boolean | Whether gravity affects body |
| `immovable`    | boolean | Body cannot be pushed        |

## Reference

- [Arcade Physics Docs](https://photonstorm.github.io/phaser3-docs/Phaser.Physics.Arcade.ArcadePhysics.html) — Official docs
- [Physics Body API](https://photonstorm.github.io/phaser3-docs/Phaser.Physics.Arcade.Body.html) — Body properties

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.