用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/feliperyba/ralph-orchestra --skill dev-phaser-physics-arcade命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Complete Developer workflow orchestration - task research sequence, implementation flow, validation gates, PRD synchronization, exit conditions.
Complete Game Designer workflow - skill invocation protocol, GDD creation, playtest flow with GDD review, design sessions. MUST load before starting assignments.
Complete PM Coordinator workflow - task assignment, project orchestration, PRD management, worker coordination. Use proactively when starting PM agent work.
正在显示 SKILL.md
基于 SOC 职业分类
| name | dev-phaser-physics-arcade |
| description | Arcade physics velocity, acceleration, collision, and bounds |
"Fast, simple 2D physics for platformers and arcade games."
// 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
// 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(., platforms);
}
() {
(...) {
..(-);
} (...) {
..();
} {
..();
}
(... && ..!..) {
..(-);
}
}
}
Use when:
// 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);
| 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() |
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..();
..(-);
..(, );
..();
}
}
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, , );
}
() {
coin.(, );
}
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!.();
platforms = ...();
platforms.(, , ).().();
...(., platforms);
}
() {
(...) {
..(-);
} (...) {
..();
} {
..();
}
(.. && ..!..) {
..(-);
}
}
}
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 ...;
(player.!.. > && player. < enemySprite. - ) {
enemySprite.();
player.(-);
} {
.();
}
}
// 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...) {
..(.);
..();
} {
..();
}
(.. && .) {
..(.);
. = ;
}
}
() {
. = ;
}
() {
..(, {
(!. && ..!.. > -) {
..(. * );
}
});
}
}
() {
controller = (
.,
.,
.
);
...(., platforms, {
controller.();
});
}
() {
controller.();
}
❌ DON'T:
refreshBody() after scaling static objects✅ DO:
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
}
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;
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(-);
} (. <= .) {
.();
}
}
}
staticGroup()physics.add.sprite()| 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 |