Skip to main content

physics-and-movement

Physics and Movement in FlatRedBall2. Use when working with velocity, acceleration, drag, gravity, kinematic movement, projectiles, rotation-based thrust, or coordinate system (Y+ up). Also covers GameRandom helpers for randomized spawning. Trigger on any physics or movement question.

Aller à l'installation

Informations de source

Dépôt
vchelaru/FlatRedBall2
Dernière activité de la source
29 avril 2026 à 16:48
Langue détectée de SKILL.md
anglais
Étoiles
14
Forks
8

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
physics-and-movement
description
Physics and Movement in FlatRedBall2. Use when working with velocity, acceleration, drag, gravity, kinematic movement, projectiles, rotation-based thrust, or coordinate system (Y+ up). Also covers GameRandom helpers for randomized spawning. Trigger on any physics or movement question.
# Physics and Movement in FlatRedBall2 ## Coordinate System **Y+ is UP.** This is the opposite of screen-space pixels. - A value of `Y = 100` places an entity *above* center. - Gravity is a **negative** AccelerationY. - The camera applies a Y-flip when converting world → screen, so everything renders correctly. ## Physics Properties on Entity ```csharp entity.X // world position (Y+ up) entity.Y entity.VelocityX // units per second entity.VelocityY entity.AccelerationX // units per second² entity.AccelerationY entity.Drag // fraction of velocity removed per second (0 = no drag) ``` ## Gravity Pattern Set a negative `AccelerationY` to simulate gravity. Spawn the entity with a positive `Y` so it has room to fall: ```csharp public class Ball : Entity { public override void CustomInitialize() { var circle = new Circle { Radius = 8f, IsVisible = true }; Add(circle); AccelerationY = -200f; // gravity pulls downward (Y- direction) } } // At spawn time: var ball = _ballFactory.Create(); ball.X = 0f; ball.Y = Engine.Random.Between(50f, 150f); // start above the floor ball.VelocityX = Engine.Random.Between(-150f, 150f); // random horizontal launch ``` ## Kinematic Formula (Second-Order) Each frame, `PhysicsUpdate` applies: ``` position += velocity * dt + acceleration * (dt² / 2) velocity += acceleration * dt velocity -= velocity * drag * dt ``` This is second-order (Verlet-style), so acceleration is smoothly integrated even at low frame rates. ## Drag `Drag` is a multiplier applied to velocity each frame: ```csharp entity.Drag = 1f; // removes 100% of velocity per second (stops fast) entity.Drag = 0.5f; // removes 50% per second (gentle air resistance) entity.Drag = 0f; // no drag (default) ``` Drag does *not* affect acceleration — only velocity. A falling entity with drag will reach terminal velocity when gravity equals drag deceleration. ## Update Order Each Frame See `engine-overview` for the full 8-step frame loop. The key point: **Physics → Collision → CustomActivity** — game logic sees already-corrected positions. ## Common Patterns ### Horizontal movement with deceleration ```csharp // In CustomActivity: VelocityX = input.X * 200f; // direct velocity set — no drag needed // or AccelerationX = input.X * 500f; Drag = 4f; // decelerates when input stops ``` ### Jump ```csharp // AccelerationY = -400f set in CustomInitialize if (jumpPressed && IsOnGround) VelocityY = 350f; // upward impulse; gravity brings it back down ``` ### Rotation-based thrust (top-down ship) **Angle convention:** Standard math — 0 = right (1, 0), 90° = up (0, 1), positive = counter-clockwise. `Rotation.ToVector2()` returns the unit vector the entity is facing. Use it directly for thrust. Set acceleration in the forward direction each frame and use `Drag` to decelerate naturally when thrust stops: ```csharp // CustomInitialize: Drag = 3f; // CustomActivity: const float ThrustForce = 400f; var forward = Rotation.ToVector2(); if (kb.IsKeyDown(Keys.Up)) { AccelerationX = forward.X * ThrustForce; AccelerationY = forward.Y * ThrustForce; } else { AccelerationX = 0f; AccelerationY = 0f; // Drag continues to bleed off existing velocity } ``` ### Projectile ```csharp var bullet = _bulletFactory.Create(); bullet.X = X; bullet.Y = Y; bullet.VelocityX = facingDirection * 600f; // No AccelerationY — bullet travels in a straight line ``` **Aiming at the cursor:** `cursor.WorldPosition` is already in world space (Y+ up) — no coordinate conversion needed. Guard `Vector2.Normalize` against a zero-length vector when the cursor is exactly on the entity. ## GameRandom — Randomized Spawning `FlatRedBallService.Random` (type `GameRandom`, a subclass of `System.Random`) provides game-friendly helpers: ```csharp Engine.Random.Between(-150f, 150f) // float in range Engine.Random.Between(50f, 100f) // float in range Engine.Random.NextSign() // returns +1f or -1f Engine.Random.NextBool() // true or false Engine.Random.RadialVector2(50f, 100f) // random direction, length 50–100 Engine.Random.PointInCircle(80f) // uniformly distributed point inside circle Engine.Random.NextAngle() // random Angle (0 to 2π) Engine.Random.In(list) // random element from a list ``` In unit tests, create `new GameRandom(seed: 42)` for deterministic results.
Voir sur GitHub