Change ball angle when hit another body (Paddle)

135 Views Asked by At

I'm studying Flame + Forge2D, developing the famous breakout game. I'm struggling with changing the ball's direction when it hits the paddle. Imagine a paddle with size 6, when the ball hits paddle's "position":

  • (0,1) -> Go Left
  • (2,3) -> Go straight up
  • (4,5) -> Go Right

It should "ignore" from which position the ball is coming from, and change the ball's angle according to the steps above, while keeping the velocity the same!

My code so far:

@override
  void beginContact(Object other, Contact contact) {
    super.beginContact(other, contact);

    if (other is Paddle) {
      final ballManifold = WorldManifold();
      contact.getWorldManifold(ballManifold);

      final intersection = ballManifold.points[0] / 20;
      var localIntersection = body.localPoint(intersection);

      final double fraction = localIntersection.x / other.size.width / 2;

      final Vector2 direction = body.linearVelocity;
      if (fraction < 0.33) {
        body.linearVelocity += Vector2(-direction.x, direction.y);
        print('left');
      } else if (fraction < 0.67) {
        body.linearVelocity = Vector2(0.0, -10.0);
        print('cenbter');
      } else {
        body.linearVelocity += Vector2(direction.x, direction.y);
        print('right');
      }
    } else if (other is PowerUp) {
      // body.applyLinearImpulse(Vector2(15, 15));
      other.hasCollidedWithBall(body);
      gameRef.paddle.increaseSize();
    }
  }

Ball:

@override
  Body createBody() {
    final bodyDef = BodyDef()
      ..type = BodyType.dynamic
      ..userData = this
      ..position = position;

    final ball = world.createBody(bodyDef);
    final fixtureDef = FixtureDef(CircleShape()..radius = radius)
      ..restitution = 1
      ..friction = 0
      ..density = 1;
    ball.createFixture(fixtureDef);

    return ball;
  }

Paddle:

@override
  Body createBody() {
    final bodyDef = BodyDef()
      ..type = BodyType.dynamic
      ..position = position
      ..fixedRotation = true
      ..angularDamping = 1
      ..linearDamping = 10;

    final paddleBody = world.createBody(bodyDef);

    final shape = PolygonShape()
      ..setAsBox(size.width / 2, size.height / 2, Vector2.zero(), 0);

    paddleBody.createFixture(
      FixtureDef(shape)
        ..density = 100
        ..userData = this
        ..friction = 0
        ..restitution = 1,
    );

    return paddleBody;
  }

Very important info:

  • Ball and Paddle are BodyComponent;
  • This snippet is inside Ball's component;
  • My game has gravity = Vector2.zero() and zoom = 20;
  • The paddle may increase or decrease width during the game;

It's super ok to answer in another language (not dart), Forge2D is a Box2D implementation in dart, I'm just trying to figure out the algorithm here!

Thanks again!

1

There are 1 best solutions below

5
spydon On

To change the velocity in Forge2D you shouldn't directly edit it, you have to change it by applying forces or impulses to the ball.

The easiest is to use body.applyLinearImpulse(Vector2). You can also use body.applyForce(Vector2), but that usually requires you to do more manual calculations.