anchor.diff:      }
     }
   }
  +
  +class SweptBoxCollision extends Collision {
  +  Body body1;
  +  Body body2;
  +
  +  Aabb2 _box1 = new Aabb2();
  +  Aabb2 _box2 = new Aabb2();
  +  Vector2 _entryDistance = new Vector2.zero();
  +  Vector2 _exitDistance = new Vector2.zero();
  +  Vector2 _entryTime = new Vector2.zero();
  +  Vector2 _exitTime = new Vector2.zero();
  +
  +  SweptBoxCollision(this.body1, this.body2);
  +
  +  void check() {
  +    _box1.copyFrom(body1.hitbox);
  +    _box2.copyFrom(body2.hitbox);
  +
  +    _box1.min.sub(body1.speed);
  +    _box1.max.sub(body1.speed);
  +
  +    if (body1.speed.x > 0) {
  +      _entryDistance.x = _box2.min.x - _box1.max.x;
  +      _exitDistance.x = _box2.max.x - _box1.min.x;
  +    } else {
  +      _entryDistance.x = _box1.min.x - _box2.max.x;
  +      _exitDistance.x = _box1.max.x - _box2.min.x;
  +    }
  +
  +    if (body1.speed.y > 0) {
  +      _entryDistance.y = _box2.min.y - _box1.max.y;
  +      _exitDistance.y = _box2.max.y - _box1.min.y;
  +    } else {
  +      _entryDistance.y = _box1.min.y - _box2.max.y;
  +      _exitDistance.y = _box1.max.y - _box2.min.y;
  +    }
  +
  +    if (body1.speed.x == 0.0) {
  +      _entryTime.x = double.INFINITY;
  +      _exitTime.x = double.INFINITY;
  +    } else {
  +      _entryTime.x = _entryDistance.x / body1.speed.x;
  +      _exitTime.x = _exitDistance.x / body1.speed.x;
  +    }
  +
  +    if (body1.speed.y == 0.0) {
  +      _entryTime.y = double.INFINITY;
  +      _exitTime.y = double.INFINITY;
  +    } else {
  +      _entryTime.y = _entryDistance.y / body1.speed.y;
  +      _exitTime.y = _exitDistance.y / body1.speed.y;
  +    }
  +
  +    double entryTime = max(_entryTime.x, _entryTime.y);
  +    double exitTime = min(_entryTime.x, _entryTime.y);
  +
  +    if (entryTime > exitTime ||
  +        _entryTime.x < 0.0 && _entryTime.y < 0.0 ||
  +        _entryTime.x > 1.0 ||
  +        _entryTime.y > 1.0) {
  +
  +      return null;
  +    } else {
  +      int side;
  +      if (_entryTime.x > _entryTime.y) {
  +        if (_entryDistance.x < 0.0) {
  +          side = Side.RIGHT;
  +        } else {
  +          side = Side.LEFT;
  +        }
  +      } else {
  +        if (_entryDistance.y < 0.0) {
  +          side = Side.BOTTOM;
  +        } else {
  +          side = Side.TOP;
  +        }
  +      }
  +      onCollisionController.add(
  +          new CollisionEvent(body1, side, body2, Side.BOTTOM));
  +    }
  +  }
  +}
  
positive.code:   Aabb2 get hitbox;
  }
  
  class Side {
    static const int TOP = 1;
    static const int BOTTOM = 2;
  
negative.code: }
  
  abstract class Collision {
    // TODO: Check if this is synchronous.
    StreamController<CollisionEvent> onCollisionController =
        new StreamController<CollisionEvent>();
    Stream<CollisionEvent> get onCollision =>
  