[BS-04] Bouncing Balls

posted

2023-05-14

updated

2023-05-19
[BS-04] Bouncing Balls - Teaser

Now with Images


Next up was adding images to the project.
Basically just replacing the letters with AI-generated balls.

Features


Pressing spacebar will spawn new balls with a random velocity.
The balls can bounce off the canvas and each other transfering their impuls.
Restart the app with "CTRL + R".

Upcoming


At this point a bit more gameplay would be nice.
Maybe like Bricks that can be destroyed with a ball while controlling a paddle.

Or we add sound on impact next.

Details


There is now an AssetManager, that can load images, and the AABBPhysicsEngine now supports a "complex" collision solver.

The AssetManager can register new assets, which should be done on game-construct.
After the required images have been registered, they should be loaded with the loadAll function of the AssetManager.
Currently loading new images at runtime is not really supported.

export function registerAssets(asset_manager: AssetManager) {
    asset_manager.addImage("ball-blue", assets.ball_blue);
    asset_manager.addImage("ball-red", assets.ball_red);
    asset_manager.addImage("ball-green", assets.ball_green);
    asset_manager.addImage("ball-cyan", assets.ball_cyan);
    asset_manager.addImage("background", assets.background);
}  

The complex solving for physics solution allows for more dynamic collisions between two colliding objects.
It will take into account the speed and angle the objects hit each other and change there velocities based on their impact force,
instead of simply inverting the speed.

 public solveCollisionComplex(collision: AABBCollision) {

        const { overlap, a, b } = collision;
        const overlap_rect = Rect.fromBoundingBox(overlap);

        // calculate the new velocity for each box
        const a_mass = a.outerBox.size.x * a.outerBox.size.y;
        const b_mass = b.outerBox.size.x * b.outerBox.size.y;
        const total_mass = a_mass + b_mass;
        const impact_vector_a = b.outerBox.center.cpy().sub(a.outerBox.center).normalize();
        const impact_vector_b = impact_vector_a.cpy().mul(-1);
        const a_force = a.velocity.dot(impact_vector_a) * (a_mass);
        const b_force = b.velocity.dot(impact_vector_b) * (b_mass);
        const impact_force = a_force + b_force;
        a.velocity.add(impact_vector_b.cpy().mul(impact_force / a_mass)).mul(0.999);
        b.velocity.add(impact_vector_a.cpy().mul(impact_force / b_mass)).mul(0.999);
        
        if (overlap_rect.w < overlap_rect.h) {
            // if the overlap is taller than it is wide, then the collision is horizontal
            const a_direction = (overlap_rect.center.x < a.outerBox.center.x) ? 1 : -1;
            a.outerBox.center.x += overlap_rect.w / 2 * a_direction;
            const b_direction = (overlap_rect.center.x < b.outerBox.center.x) ? 1 : -1;
            b.outerBox.center.x += overlap_rect.w / 2 * b_direction;
        } else {
            // if the overlap is wider than it is tall, then the collision is vertical
            const a_direction = (overlap_rect.center.y < a.outerBox.center.y) ? 1 : -1;
            a.outerBox.center.y += overlap_rect.h / 2 * a_direction;
            const b_direction = (overlap_rect.center.y < b.outerBox.center.y) ? 1 : -1;
            b.outerBox.center.y += overlap_rect.h / 2 * b_direction;
        }
    }

Github

Releases

Comments

captcha