PhysicsActor¶
An actor with basic 2D physics properties.
Description¶
PhysicsActor extends the base Actor class by adding velocity, acceleration, friction, restitution (bounciness), and world boundary collision resolution. It is designed for objects that need to move and bounce within a defined area, such as balls, projectiles, or platformer characters.
PhysicsActor automatically handles: - Velocity-based movement - Friction application - World boundary collision and bouncing - Collision callbacks
Namespace¶
Inheritance¶
- Inherits from:
Actor - Inherited by: Your custom physics-enabled actor classes
Constructors¶
PhysicsActor(float x, float y, float w, float h)¶
Creates a physics-enabled actor with specified position and size.
Parameters: - x (float): Initial X position in world space - y (float): Initial Y position in world space - w (float): Actor width in pixels - h (float): Actor height in pixels
Notes: - Velocity starts at (0, 0) - Restitution defaults to 1.0 (perfect bounce) - Friction defaults to 0.0 (no friction) - No world limits by default
Example:
class BallActor : public pixelroot32::core::PhysicsActor {
public:
BallActor(float x, float y)
: PhysicsActor(x, y, 8.0f, 8.0f) {
// Set physics properties
setRestitution(0.8f); // 80% bounce
setFriction(0.1f); // Small friction
setWorldSize(128, 128); // World bounds
}
void draw(pixelroot32::graphics::Renderer& renderer) override {
renderer.drawFilledCircle(static_cast<int>(x + width/2),
static_cast<int>(y + height/2),
width/2,
Color::White);
}
Rect getHitBox() override {
return {x, y, width, height};
}
void onCollision(Actor* other) override {
// Bounce off other actors
}
void onWorldCollision() override {
// Play bounce sound
}
};
Protected Properties¶
float vx, vy¶
Horizontal and vertical velocity components.
Type: float
Access: Protected (use setVelocity() to modify)
Default: 0.0f
Notes: - Velocity is in pixels per second - Automatically applied during update() - Modified by friction and world collisions
Public Methods¶
void setVelocity(float x, float y)¶
Sets the linear velocity of the actor.
Parameters: - x (float): Horizontal velocity in pixels per second - y (float): Vertical velocity in pixels per second
Returns: - void
Notes: - Velocity is applied every frame during update() - Use for initial velocity or impulse-based movement - Can be called every frame for continuous control
Example:
// Set initial velocity
physicsActor->setVelocity(100.0f, -200.0f); // Move right and up
// Continuous control (e.g., player movement)
void update(unsigned long deltaTime) override {
PhysicsActor::update(deltaTime);
float speed = 150.0f;
float vx = 0.0f, vy = 0.0f;
if (input.isButtonDown(Buttons::LEFT)) vx = -speed;
if (input.isButtonDown(Buttons::RIGHT)) vx = speed;
if (input.isButtonDown(Buttons::UP)) vy = -speed;
if (input.isButtonDown(Buttons::DOWN)) vy = speed;
setVelocity(vx, vy);
}
void setRestitution(float r)¶
Sets the restitution (bounciness) of the actor.
Parameters: - r (float): Restitution value (0.0 to 1.0+) - 0.0: No bounce (stops on impact) - 1.0: Perfect bounce (no energy loss) - > 1.0: Energy gain (unrealistic but possible)
Returns: - void
Notes: - Applied when actor collides with world boundaries - Higher values = more bouncy - Typical values: 0.5-0.9 for realistic bouncing
Example:
void setFriction(float f)¶
Sets the friction coefficient.
Parameters: - f (float): Friction value - 0.0: No friction (object continues moving) - > 0.0: Friction applied to velocity each frame
Returns: - void
Notes: - Applied every frame to reduce velocity - Higher values = more friction (slower movement) - Typical values: 0.05-0.2 for smooth deceleration
Example:
void setLimits(LimitRect limits)¶
Sets custom movement limits for the actor.
Parameters: - limits (LimitRect): A rectangle defining the allowed area
Returns: - void
Notes: - Overrides world size limits - Use -1 for any boundary to disable that limit - Actor will bounce off these boundaries
Example:
pixelroot32::core::LimitRect limits;
limits.left = 0;
limits.top = 0;
limits.right = 128;
limits.bottom = 128;
physicsActor->setLimits(limits);
void setWorldSize(int width, int height)¶
Defines the world size for boundary checking.
Parameters: - width (int): Width of the world in pixels - height (int): Height of the world in pixels
Returns: - void
Notes: - Used as default limits if no custom LimitRect is provided - Actor will bounce off world boundaries - Set to display size for screen boundaries
Example:
WorldCollisionInfo getWorldCollisionInfo() const¶
Gets information about collisions with the world boundaries.
Returns: - WorldCollisionInfo: A struct containing collision flags (left, right, top, bottom)
Notes: - Updated every frame during update() - Use to detect which boundary was hit - Useful for sound effects or special behaviors
Example:
void update(unsigned long deltaTime) override {
PhysicsActor::update(deltaTime);
auto collision = getWorldCollisionInfo();
if (collision.left || collision.right) {
// Hit side wall
playSound(wallHitSound);
}
if (collision.top || collision.bottom) {
// Hit top or bottom
playSound(ceilingHitSound);
}
}
virtual void onCollision(Actor* other) override¶
Callback triggered when this actor collides with another actor.
Parameters: - other (Actor*): Pointer to the actor involved in the collision
Returns: - void
Notes: - Called automatically by the collision system - Override to implement custom collision responses - Default implementation does nothing
Example:
void onCollision(Actor* other) override {
if (other->isInLayer(DefaultLayers::kEnemy)) {
// Bounce off enemy
vx = -vx * 0.5f;
vy = -vy * 0.5f;
}
}
virtual void onWorldCollision()¶
Callback triggered when this actor collides with world boundaries.
Returns: - void
Notes: - Called automatically when a world boundary collision occurs - Override to implement custom behavior (sound effects, particles, etc.) - Default implementation does nothing
Example:
void onWorldCollision() override {
// Play bounce sound
auto& audio = engine.getAudioEngine();
pixelroot32::audio::AudioEvent sound{};
sound.type = pixelroot32::audio::WaveType::NOISE;
sound.frequency = 500.0f;
sound.duration = 0.05f;
audio.playEvent(sound);
// Spawn particles
spawnBounceParticles();
}
void update(unsigned long deltaTime) override¶
Updates the actor state. Applies physics integration and checks for world boundary collisions.
Parameters: - deltaTime (unsigned long): Time elapsed since the last frame in milliseconds
Returns: - void
Notes: - Called automatically by Scene if isEnabled is true - Applies velocity to position - Applies friction to velocity - Resolves world boundary collisions - Override to add custom update logic, but call PhysicsActor::update(deltaTime) first
Example:
void update(unsigned long deltaTime) override {
// Apply physics
PhysicsActor::update(deltaTime);
// Custom logic
if (shouldApplyGravity) {
vy += gravity * (deltaTime / 1000.0f);
}
}
LimitRect Structure¶
Bounding rectangle for world-collision resolution.
Members: - int left: Left boundary (-1 means no limit) - int top: Top boundary (-1 means no limit) - int right: Right boundary (-1 means no limit) - int bottom: Bottom boundary (-1 means no limit)
Methods: - int width() const: Calculates width (right - left) - int height() const: Calculates height (bottom - top)
Example:
pixelroot32::core::LimitRect limits(10, 10, 118, 118); // 10px margin
physicsActor->setLimits(limits);
WorldCollisionInfo Structure¶
Information about world collisions in the current frame.
Members: - bool left: True if collided with the left boundary - bool right: True if collided with the right boundary - bool top: True if collided with the top boundary - bool bottom: True if collided with the bottom boundary
Example:
auto collision = physicsActor->getWorldCollisionInfo();
if (collision.bottom) {
// On ground
canJump = true;
}
Usage Example¶
#include "core/PhysicsActor.h"
class BouncingBall : public pixelroot32::core::PhysicsActor {
public:
BouncingBall(float x, float y)
: PhysicsActor(x, y, 8.0f, 8.0f) {
// Set physics properties
setRestitution(0.9f); // Very bouncy
setFriction(0.05f); // Light friction
setWorldSize(128, 128);
// Set initial velocity
setVelocity(100.0f, -150.0f);
// Set collision layer
layer = pixelroot32::physics::DefaultLayers::kProjectile;
mask = pixelroot32::physics::DefaultLayers::kObstacle;
}
void update(unsigned long deltaTime) override {
PhysicsActor::update(deltaTime);
// Apply gravity
vy += 200.0f * (deltaTime / 1000.0f);
}
void draw(pixelroot32::graphics::Renderer& renderer) override {
renderer.drawFilledCircle(static_cast<int>(x + width/2),
static_cast<int>(y + height/2),
width/2,
Color::White);
}
Rect getHitBox() override {
return {x, y, width, height};
}
void onCollision(Actor* other) override {
// Bounce off obstacles
vx = -vx * 0.8f;
vy = -vy * 0.8f;
}
void onWorldCollision() override {
// Play bounce sound
playBounceSound();
}
};
Performance Considerations¶
- Physics integration: Very efficient (simple velocity integration)
- World bounds: Boundary checks are fast (AABB)
- Friction: Applied every frame; keep friction values reasonable
- Collision callbacks: Keep
onCollision()andonWorldCollision()fast
ESP32 Considerations¶
- Floating point: Uses float math; acceptable for ESP32 but integer math would be faster
- Frame rate: Physics is frame-rate independent (uses deltaTime)
- Memory: Each PhysicsActor consumes more memory than Actor (velocity, limits, etc.)
See Also¶
- Actor - Base actor class
- CollisionSystem - Collision detection
- Manual - Physics and Collisions
- API Overview