A Dart port of Box2D

Overview

flame

Forge2D - A Dart port of the Box2D physics engine

Test

The Box2D physics engine is a fairly famous open source physics engine and this is our dart port of it.

You can use it independently in Dart or in your Flame project with the help of flame_forge2d.

Some documentation of how to use it together with flame can be found here.

Timeline

Box2D was first written in C++ and released by Erin Catto in 2007, but it is still maintained.

It was then ported to Java (jbox2d) by Daniel Murphy around 2015.

Then from that Java port it was ported to Dart by Dominic Hamon and Kevin Moore.

A few years after that Lukas Klingsbo refactored the code to follow the dart standard more, since it still had a lot of reminiscence from C++. After this refactor we renamed it to Forge2D since the upstream wasn't maintained to take in our PRs.

There has also been countless other contributors which we are very thankful to!

Credits

  • The Flame engine team who is continuously working on maintaining and improving Forge2D.
  • Special thanks for Lukas Klingsbo, a Flame team member which took this project under his wing and greatly improved the project!
  • The Dart port of Box2D.
Comments
  • settings are difficult to change

    settings are difficult to change

    There are some tunable limits in src/settings.dart. I couldn't find a way for the caller to pass in new values for these. So I created a fork with my values. I realize these limits aren't meant to be changed often but I have found it useful. The presenting case was to increase maxTranslation in order to verify the cause of my body's velocity limit was this parameter and not something wrong in my logic. It would be very useful to be able to tune these settings without forking a new version.

    opened by dynamicbutter 7
  • Exception: Concurrent modification during iteration when body containing joints is destroyed

    Exception: Concurrent modification during iteration when body containing joints is destroyed

    I'm using Flame & Forge2d draw some components based on the state of my application. There's also the option to filter such state to display only a certain type of data, which in turn means the Forge2DGame rebuilds to reflect the new data source.

    In my simulation, I have the components drawn into a tree-like structure, where children are tied to their parent through a Joint. Whenever my game gets rebuilt (and, in the process, destroyed) I get the following exception: The following ConcurrentModificationError was thrown building _BodyBuilder: Concurrent modification during iteration: Instance(length:2) of '_GrowableList'.

    It seems that the culprit is forge2d/lib/src/dynamics/world.dart:144:

      // Delete the attached joints.
      for (final joint in body.joints) {
        destroyListener?.onDestroyJoint(joint);
        destroyJoint(joint);
      }
    

    Maybe something in the line of this would work to fix it?

    Here's a minimal reproducible example:

    import 'dart:math' as math;
    
    import 'package:flame/components.dart';
    import 'package:flame/game.dart';
    import 'package:flame_forge2d/body_component.dart';
    import 'package:flame_forge2d/forge2d_game.dart';
    import 'package:flutter/material.dart';
    import 'package:forge2d/forge2d.dart';
    
    void main() {
      runApp(const MaterialApp(home: SampleScreen()));
    }
    
    class SampleScreen extends StatefulWidget {
      const SampleScreen({Key? key}) : super(key: key);
    
      @override
      State<SampleScreen> createState() => _SampleScreenState();
    }
    
    class _SampleScreenState extends State<SampleScreen> {
      int childrenCount = 3;
    
      void incr() => setState(() => childrenCount += 1);
    
      void decr() => setState(() => childrenCount -= 1);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Stack(
            alignment: AlignmentDirectional.topEnd,
            children: [
              GameWidget(game: SampleGame(childrenCount)),
              Positioned(
                bottom: 20,
                right: 20,
                child: Row(
                  children: [
                    IconButton(onPressed: incr, icon: const Icon(Icons.add)),
                    IconButton(onPressed: decr, icon: const Icon(Icons.remove)),
                  ],
                ),
              ),
            ],
          ),
        );
      }
    }
    
    class SampleGame extends Forge2DGame with HasTappables {
      SampleGame(this.count) : super(gravity: Vector2(0, 0));
      final int count;
    
      @override
      Color backgroundColor() => Colors.transparent;
    
      @override
      Future<void> onLoad() async {
        await super.onLoad();
        final worldCenter = screenToWorld(size * camera.zoom / 2);
        add(SampleComponent(worldCenter, radius: 8, numberOfChildren: count));
      }
    }
    
    class SampleComponent extends BodyComponent with Tappable {
      SampleComponent(
        this._position, {
        required this.radius,
        this.numberOfChildren = 0,
        this.parentComponent,
      }) {
        paint = Paint()..color = Colors.teal;
      }
    
      final double radius;
      final Vector2 _position;
      final int numberOfChildren;
      final SampleComponent? parentComponent;
    
      @override
      Future<void> onLoad() async {
        await super.onLoad();
    
        for (var i = 0; i < numberOfChildren; i++) {
          final angle = i * (2 * math.pi / numberOfChildren);
    
          var polar = Vector2(math.cos(angle), math.sin(angle));
          final scaled = polar.clone()..scaleTo((radius + radius / 3));
    
          var component = SampleComponent(_position - scaled,
              radius: radius / 3, parentComponent: this);
    
          gameRef.add(component);
        }
      }
    
      @override
      Body createBody() {
        final bodyDef = BodyDef()
          ..userData = this
          ..angularDamping = 0.8
          ..position = _position
          ..type = BodyType.dynamic;
    
        final shape = CircleShape();
        shape.radius = radius;
    
        final fixtureDef = FixtureDef(shape)
          ..restitution = 0.8
          ..density = 1.0
          ..friction = 0.4;
    
        final body = world.createBody(bodyDef)..createFixture(fixtureDef);
    
        if (parentComponent != null) {
          final jointDef = DistanceJointDef();
          jointDef.initialize(
            body,
            parentComponent!.body,
            body.position,
            parentComponent!.body.position,
          );
          world.createJoint(jointDef);
        }
    
        return body;
      }
    }
    

    Full Stacktrace

    ======== Exception caught by widgets library =======================================================
    The following ConcurrentModificationError was thrown building _BodyBuilder:
    Concurrent modification during iteration: Instance(length:2) of '_GrowableList'.
    
    When the exception was thrown, this was the stack: 
    #0      ListIterator.moveNext (dart:_internal/iterable.dart:336:7)
    #1      World.destroyBody (package:forge2d/src/dynamics/world.dart:144:30)
    #2      BodyComponent.onRemove (package:flame_forge2d/body_component.dart:146:11)
    #3      Component.onRemove.<anonymous closure> (package:flame/src/components/component.dart:208:13)
    #4      IterableMixin.forEach (dart:collection/iterable.dart:45:35)
    #5      Component.onRemove (package:flame/src/components/component.dart:207:14)
    #6      _GameWidgetState.didUpdateWidget (package:flame/src/game/game_widget/game_widget.dart:201:22)
    #7      StatefulElement.update (package:flutter/src/widgets/framework.dart:4943:57)
    #8      Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #9      RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:5787:32)
    #10     MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6445:17)
    #11     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #12     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
    #13     Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
    #14     StatelessElement.update (package:flutter/src/widgets/framework.dart:4834:5)
    #15     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #16     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
    #17     Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
    #18     ProxyElement.update (package:flutter/src/widgets/framework.dart:5108:5)
    #19     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #20     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
    #21     Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
    #22     ProxyElement.update (package:flutter/src/widgets/framework.dart:5108:5)
    #23     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #24     RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:5787:32)
    #25     MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6445:17)
    #26     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #27     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
    #28     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4928:11)
    #29     Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
    #30     StatefulElement.update (package:flutter/src/widgets/framework.dart:4960:5)
    #31     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #32     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
    #33     Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
    #34     ProxyElement.update (package:flutter/src/widgets/framework.dart:5108:5)
    #35     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #36     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
    #37     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4928:11)
    #38     Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
    #39     StatefulElement.update (package:flutter/src/widgets/framework.dart:4960:5)
    #40     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #41     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6291:14)
    #42     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #43     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
    #44     Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
    #45     StatelessElement.update (package:flutter/src/widgets/framework.dart:4834:5)
    #46     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #47     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6291:14)
    #48     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #49     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
    #50     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4928:11)
    #51     Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
    #52     StatefulElement.update (package:flutter/src/widgets/framework.dart:4960:5)
    #53     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #54     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
    #55     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4928:11)
    #56     Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
    #57     StatefulElement.update (package:flutter/src/widgets/framework.dart:4960:5)
    #58     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #59     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
    #60     Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
    #61     ProxyElement.update (package:flutter/src/widgets/framework.dart:5108:5)
    #62     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #63     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
    #64     Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
    #65     StatelessElement.update (package:flutter/src/widgets/framework.dart:4834:5)
    #66     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #67     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
    #68     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4928:11)
    #69     Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
    #70     StatefulElement.update (package:flutter/src/widgets/framework.dart:4960:5)
    #71     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #72     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
    #73     Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
    #74     ProxyElement.update (package:flutter/src/widgets/framework.dart:5108:5)
    #75     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #76     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
    #77     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4928:11)
    #78     Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
    #79     StatefulElement.update (package:flutter/src/widgets/framework.dart:4960:5)
    #80     Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
    #81     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
    #82     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4928:11)
    #83     Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
    #84     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2659:19)
    #85     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:882:21)
    #86     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:363:5)
    #87     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1144:15)
    #88     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1081:9)
    #89     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:995:5)
    #93     _invoke (dart:ui/hooks.dart:151:10)
    #94     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:308:5)
    #95     _drawFrame (dart:ui/hooks.dart:115:31)
    (elided 3 frames from dart:async)
    ====================================================================================================
    

    Thanks for the great package! Let me know if any further info is needed.

    bug 
    opened by brenodt 6
  • Unused method arguments in `Rot`. Can it be removed?

    Unused method arguments in `Rot`. Can it be removed?

    These two methods in common/rot.dart:

    Vector2 getXAxis(Vector2 xAxis) => Vector2(cos, sin);
    
    Vector2 getYAxis(Vector2 yAxis) => Vector2(-sin, cos);
    

    Take a Vector2 but as far as I can see they aren't used. It looks like dynamics/fixture.dart calls this method and passes in a Vector2 but I think it is defunct.

    I'm trying to port this library to another language and I just hope I'm not missing anything here.

    opened by gkjpettet 5
  • chore: include PULL_REQUEST_TEMPLATE.md

    chore: include PULL_REQUEST_TEMPLATE.md

    Description

    Includes a PULL_REQUEST_TEMPLATE.md.

    Checklist

    • [X] The title of my PR starts with a [Conventional Commit] prefix (fix:, feat:, docs: etc).
    • [X] I have read the [Contributor Guide] and followed the process outlined for submitting PRs.
    • [X] I have updated/added tests for ALL new/updated/fixed functionality.
    • [X] I have updated/added relevant documentation in docs and added dartdoc comments with ///.
    • [X] I have updated/added relevant examples in examples.

    Breaking Change

    Does your PR require Flame users to manually update their apps to accommodate your change?

    • [ ] Yes, this is a breaking change. (Indicate it in the [Conventional Commit] prefix with a !, e.g. feat!:, fix!:).
    • [X] No, this is not a breaking change.

    Related Issues

    Aims to resolve #31

    opened by alestiago 5
  • Fix deleting contacts during destroyBody

    Fix deleting contacts during destroyBody

    There was a fundamental bug with deleting elements from the list during iterating it. Calling destroy() on contact manager calls

    c.bodyA.contacts.remove(c);
    c.bodyB.contacts.remove(c);
    

    which deletes the contact from body's contacts list.

    opened by Alex-A4 5
  • PolygonShape Creates Invalid Convex Hull From Vertices

    PolygonShape Creates Invalid Convex Hull From Vertices

    The code refactoring done in PR #7 to the gift wrapping algorithm for creating a convex hull is incorrect. The previous code properly implemented the gift wrapping algorithm and correctly generated a valid convex hull. The refactored code does not properly implement the gift wrapping algorithm. To demonstrate the error of the refactored code, consider this set of vertices to define a polygon:

    var vertices = [
        Vector2(-10, 20),
        Vector2(-10, 0),
        Vector2(0, -30),
        Vector2(10, 0),
        Vector2(10, 10),
      ];
    
    final shape = PolygonShape()..set(vertices);
    

    The correct convex hull output from this set of vertices from the gift wrapping algorithm is (and was from the old code):

        Vector2(10, 0),
        Vector2(10, 10),
        Vector2(-10, 20),
        Vector2(-10, 0),
        Vector2(0, -30),
    

    But the output from the new refactored code is an invalid polygon that crosses over itself:

        Vector2(10, 0),
        Vector2(-10, 0),
        Vector2(0, -30),
        Vector2(10, 10),
        Vector2(-10, 20),
    

    The incorrect refactored code is in forge2d-0.7.2 > lib > src > collision > shapes > polygon_shape.dart beginning at line 90:

        final hull = <Vector2>[rightMostPoint];
        for (final point1 in points) {
          var currentPoint = hull.last;
          for (final point2 in points) {
            if (currentPoint == hull.last) {
              currentPoint = point2;
              continue;
            }
    
            final r = currentPoint.clone()..sub(point1);
            final v = point2.clone()..sub(point1);
            final c = r.cross(v);
            if (c < 0.0) {
              currentPoint = point2;
            }
    
            // Collinearity check
            if (c == 0.0 && v.length2 > r.length2) {
              currentPoint = point2;
            }
          }
    
          if (!hull.contains(currentPoint)) {
            hull.add(currentPoint);
          }
        }
    

    Not only is this code incorrect, but it also changes the complexity of the gift wrapping algorithm from O(nh) where n is the number of vertices and h is the number of vertices on the hull, to O(nn).

    I'd like to offer this fix for consideration as a correct implementation of the gift wrapping algorithm:

        final hull = <Vector2>[rightMostPoint];
        var pointOnHull = rightMostPoint;
        do {
          // Set first point in the set as the initial candidate for the
          // next point on the convex hull.
          var endPoint = points[0];
    
          // Test the candidate point against all points in the set to find
          // the next convex hull point.
          for (final point in points) {
            // If the candidate point is current last point on the convex
            // hull update the candidate point to the current point and continue
            // checking against the remaining points.
            if (endPoint == pointOnHull) {
              endPoint = point;
              continue;
            }
    
            // Use the cross product of the vectors from the current convex hull
            // point to the candidate point and the current test point to see if
            // the test point is changes the winding to CW. Update the candidate
            // point when the winding changes.
            final r = endPoint.clone()..sub(pointOnHull);
            final v = point.clone()..sub(pointOnHull);
            final c = r.cross(v);
            if (c < 0.0) {
              endPoint = point;
            }
    
            // Collinearity check
            if (c == 0.0 && v.length2 > r.length2) {
              endPoint = point;
            }
          }
    
          // Set the end point candidate as the new current convex hull point.
          pointOnHull = endPoint;
          if (!hull.contains(pointOnHull)) {
            hull.add(pointOnHull);
          }
        } while (pointOnHull != hull.first);
    
    bug 
    opened by mjordan56 4
  • refactor!: used getter and setters for maxMotorForce

    refactor!: used getter and setters for maxMotorForce

    Description

    Changes:

    • Renamed getMaxMotorForce to maxMotorForce (now a Dart setter)
    • Renamed setMaxMotorForce to maxMotorForce (now a Dart getter)
    // Before:
    final joint = PrismaticJoint(jointDef);
    joint.setMaxMotorForce(20); // Sets max motor force
    joint.getMaxMotorForce; // Gets max motor force (20)
    
    // After:
    final joint = PrismaticJoint(jointDef);
    joint.maxMotorForce = 20; // Sets max motor force
    joint.maxMotorForce; // Gets max motor force (20)
    

    Checklist

    • [X] The title of my PR starts with a Conventional Commit prefix (fix:, feat:, docs: etc).
    • [X] I have read the Contributor Guide and followed the process outlined for submitting PRs.
    • [X] I have updated/added tests for ALL new/updated/fixed functionality.
    • [X] I have updated/added relevant documentation in docs and added dartdoc comments with ///.
    • [X] I have updated/added relevant examples in examples.

    Breaking Change

    • [X] Yes, this is a breaking change.
    • [ ] No, this is not a breaking change.

    Related Issues

    opened by alestiago 3
  • How can I create a BodyComponent that keeps moving horizontally?

    How can I create a BodyComponent that keeps moving horizontally?

    PositionComponent was driven by redefining position as follows.

    @override void update(double dt) { super.update(dt); position += Vector2( 1, 0) }

    However, since BodyComponent's position is only get, it cannot be redefined and cannot be moved horizontally. If there is a way to handle this, could you please let me know?

    opened by usedatiek 2
  • fix: Fixed wrong particle position when creating a particle group

    fix: Fixed wrong particle position when creating a particle group

    Description

    Fixes an issue where particles created in ParticleSystem.createParticleGroup() were centred around (0,0) rather than the position stipulated in the group definition. This bug is also present in the JBox2D library.

    Checklist

    • [x] The title of my PR starts with a [Conventional Commit] prefix (fix:, feat:, docs: etc).
    • [x] I have read the [Contributor Guide] and followed the process outlined for submitting PRs.
    • [ ] I have updated/added tests for ALL new/updated/fixed functionality.
    • [x] I have updated/added relevant documentation in docs and added dartdoc comments with ///.
    • [ ] I have updated/added relevant examples in examples.

    Breaking Change

    This should not be a breaking change as it implements expected behaviour.

    • [ ] Yes, this is a breaking change.
    • [x] No, this is not a breaking change.

    Related Issues

    Fixes https://github.com/flame-engine/forge2d/issues/68

    opened by gkjpettet 2
  • Bug in `particle/particle_system.dart`

    Bug in `particle/particle_system.dart`

    I think that the commented line (particle/particle_system.dart line 233) below needs deleting:

    for (var y = (aabb.lowerBound.y / stride).floor() * stride;
              y < upperBoundY;
              y += stride) {
            for (var x = (aabb.lowerBound.x / stride).floor() * stride;
                x < upperBoundX;
                x += stride) {
              final p = _tempVec..setValues(x, y);
              if (shape.testPoint(identity, p)) {
                p.setFrom(Transform.mulVec2(transform, p));
                final particle = seedParticle.clone();
                p.sub(groupDef.position); // <---- This needs removing
                particle.position.setFrom(p);
                p.scaleOrthogonalInto(
                  groupDef.angularVelocity,
                  particle.velocity,
                );
                particle.velocity.add(groupDef.linearVelocity);
                createParticle(particle);
              }
            }
          }
    

    By subtracting the group definition's position from the particle's position it causes all particles in the group being created to be centred around world position (0, 0). If you remove the commented line then any offset you apply to the group's position (via GroupDef.position is honoured.

    This bug is also present in JBox2D.

    opened by gkjpettet 2
  • refactor: removed mock instances

    refactor: removed mock instances

    Description

    Removed Mock instances in favour of more realistic tests.

    Checklist

    • [X] The title of my PR starts with a Conventional Commit prefix (fix:, feat:, docs: etc).
    • [X] I have read the Contributor Guide and followed the process outlined for submitting PRs.
    • [X] I have updated/added tests for ALL new/updated/fixed functionality.
    • [X] I have updated/added relevant documentation in docs and added dartdoc comments with ///.
    • [X] I have updated/added relevant examples in examples.

    Breaking Change

    • [ ] Yes, this is a breaking change.
    • [ ] No, this is not a breaking change.

    Related Issues

    opened by alestiago 2
  • bug: Particles are never destroyed

    bug: Particles are never destroyed

    As far as I can see, particles in a particle system are never destroyed.

    In the original LiquidFun library, particles expired after a certain time period:

    https://google.github.io/liquidfun/Programmers-Guide/html/md__chapter11__particles.html

    Looking through the particle system in Forge2D however, I can't see anyway that a particle is ever removed automatically from the particle system. The only time a particle is removed from the system's internal list is if it is a "zombie" by having it's flags property set to have the zombie flag. However, I can't see any code that ever does this.

    Am I missing something here?

    opened by gkjpettet 5
  • refactor!: gravity getter and setter

    refactor!: gravity getter and setter

    Description

    Removed setGravity and getGravity.

    Checklist

    • [X] The title of my PR starts with a Conventional Commit prefix (fix:, feat:, docs: etc).
    • [X] I have read the Contributor Guide and followed the process outlined for submitting PRs.
    • [ ] I have updated/added tests for ALL new/updated/fixed functionality.
    • [ ] I have updated/added relevant documentation in docs and added dartdoc comments with ///.
    • [ ] I have updated/added relevant examples in examples.

    Breaking Change

    • [X] Yes, this is a breaking change.
    • [ ] No, this is not a breaking change.

    Related Issues

    opened by alestiago 0
  • refactor!: bullet getter and setter

    refactor!: bullet getter and setter

    Description

    Removes setBullet and isBuller in favour of setter and getters.

    // Before:
    body.setBullet(true);
    body.isBullet(); // true
    
    // After:
    body.bullet = true;
    body.bullet; // true
    

    Checklist

    • [X] The title of my PR starts with a Conventional Commit prefix (fix:, feat:, docs: etc).
    • [X] I have read the Contributor Guide and followed the process outlined for submitting PRs.
    • [X] I have updated/added tests for ALL new/updated/fixed functionality.
    • [X] I have updated/added relevant documentation in docs and added dartdoc comments with ///.
    • [X] I have updated/added relevant examples in examples.

    Breaking Change

    • [X] Yes, this is a breaking change.
    • [ ] No, this is not a breaking change.

    Related Issues

    opened by alestiago 0
  • feat!: Use sensible fixture defaults

    feat!: Use sensible fixture defaults

    Description

    In #54 the friction was set to 0, but I realized it is much more useful to have it set to some value like 0.2 that gives a more wanted result in most of the time (since everything obviously just slides around with 0).

    Checklist

    • [x] The title of my PR starts with a Conventional Commit prefix (fix:, feat:, docs: etc).
    • [x] I have read the Contributor Guide and followed the process outlined for submitting PRs.
    • [x] I have updated/added tests for ALL new/updated/fixed functionality.
    • [x] I have updated/added relevant documentation in docs and added dartdoc comments with ///.
    • [x] I have updated/added relevant examples in examples.

    Breaking Change

    • [x] Yes, this is a breaking change.

    Related Issues

    opened by spydon 5
  • feat: update API to allow optional parameters

    feat: update API to allow optional parameters

    Description

    From flame, one can instantiate a component as follows:

     textComponent = TextComponent(
        text: counter.toString(),
        textRenderer: _textPaint,
      );
    

    See implementation here.

    For consistency, perhaps it would be nice to update forge2d API to also support this pattern. For example, with shapes. We could:

    final shape = CircleShape(radius: radius);
    

    instead of

    final shape = CircleShape()
      ..radius = radius;
    

    Additional Context Personally, both can be seen as equivalent. I think both APIs should be supported (cascading and optional parameters). Besides consistency with flame, one could also argue that using the positional parameter avoids setting/changing the value first unnecessary, since we already know its computed value and will change instantly after.

    In addition, we also benefit from the analyser when we are setting default values.

    This issue is open to discussion. If we decide to proceed I'm willing to contribute with this update.

    opened by alestiago 2
  • [Feature Request] Box2d Lights

    [Feature Request] Box2d Lights

    Hi! First of all thank you very much for all the work implied in this project. It looks promising! 😄 💙

    A while ago I made a game with libGDX and Box2d, using Box2dLights to create nice lightnings visuals. So I was wondering if you have in mind (maybe in the future) to incorporate Box2d Lights into forge2d? I think it can be a really good addition to the package and flame itself.

    enhancement help wanted 
    opened by raulmabe 2
Owner
Flame Engine
2D game engine built on top of Flutter. Mainteined by https://github.com/bluefireteam
Flame Engine
Flutter port of the famous Trex game

Trex game Flutter edition The joy of our offline hours recreated with Flutter and Flame Article https://medium.com/@renancaraujo/creating-the-t-rex-ga

Blue Fire 2 Nov 25, 2022
The simple game known as Tic Tac Toe developed with Flutter and Dart language

tic_tac_toe A new Flutter project. Game Restarted : Getting Started This project is a starting point for a Flutter application. A few resources to get

Mootaz Jaballah 1 Oct 15, 2021
An online version of the popular game four in a row, written in Flutter + Dart on the client and Rust on the server side.

Four in a Row - App An online version of the popular game four in a row, written in Flutter + Dart on the client and Rust on the server side. Download

Filippo Orrù 24 Jan 2, 2023
Tic-tac-toe - A fun Tic Tac Toe game made with dart

Tic Tac Toe game app This is a tic tac toe game app with all dart facilities. Sc

Munem Sarker 1 Jul 26, 2022
Copying of the famous WORDLE game in dart using Flutter

Wordle Copia del famoso juego WORDLE en dart usando Flutter. Reglas Las palabras solo se pueden escribir en minusculas Al finalizar la palabra tienes

Aitroll 3 Jul 16, 2022
A Dart Tiled library. Parse your TMX files into useful representations. Compatible with Flame.

Tiled Dart A Dart Tiled library. Install from Dart Pub Repository Include the following in your pubspec.yaml: dependencies: tiled: 0.8.1 Usa

Flame Engine 44 Oct 31, 2022
A Dwarf game made with Dart, Flutter and Flame

Dwart Generated by the Very Good CLI ?? Dwart game Getting Started ?? This project contains 3 flavors: development staging production To run the desir

Erick 7 Jun 11, 2022
A full-stack Dart realtime game example

dart_realtime_game An example of using Dart and Flutter to build a realtime game. Uses Dart for the full stack, shares code between client and server.

Eric Seidel 26 Aug 9, 2022
Flutter UI challenge (with Box2D physic)- Smart washing machine app

Flutter UI Challenge- SMART Washing Machine About project The application was written based on this great UI concept: https://dribbble.com/shots/11018

Tomasz Pawlikowski 754 Dec 27, 2022
Flutter UI challenge (with Box2D physic)- Smart washing machine app

Flutter UI Challenge- SMART Washing Machine About project The application was written based on this great UI concept: https://dribbble.com/shots/11018

Tomasz Pawlikowski 754 Dec 27, 2022
Box2D Flutter Slide Puzzle

It uses Box2D physics to create an interesting gameplay mechanic where you need to manage a bit more than a simple slider. The code is all pure Flutter with widgets, animations, and CustomPaint. It doesn't use any Flutter game engine.

Gordon Hayes 25 Nov 11, 2022
Dart port for artwork-extractor using FFI

A simple library to extract & save artwork of a ?? music/audio file. This library is using a artwork-extractor library by alexmercerind. It is super s

null 3 Feb 23, 2022
A Dart port of zxing that encode and decode multiple 1D/2D barcodes.

ZXing-Dart A Dart port of zxing that encode and decode multiple 1D/2D barcodes. Progress Core package translate Core test translate Core unit test(all

shirne 35 Dec 14, 2022
An r-tree for Dart; port of @mourner's rbush.

RBush RBush is a high-performance Dart library for 2D spatial indexing of points and rectangles. It's based on an optimized R-tree data structure with

Ilya Zverev 7 Nov 1, 2022
Dart port of FormCoreJS: A minimal pure functional language based on self dependent types.

FormCore.js port to Dart. So far only the parser and typechecker have been ported i.e. the FormCore.js file in the original repo. (Original readme fro

Modestas Valauskas 2 Jan 28, 2022
Radiance - Dart port of gdx-ai

⚠️ This package is currently under development. This library is a collection of AI algorithms used in games. This includes: Steering behaviors (NYI) F

Flame Engine 20 Oct 30, 2022
A pure Dart utility library that checks for an internet connection by opening a socket to a list of specified addresses, each with individual port and timeout. Defaults are provided for convenience.

data_connection_checker A pure Dart utility library that checks for an internet connection by opening a socket to a list of specified addresses, each

Kristiyan Mitev 103 Nov 29, 2022
A port of kotlin-stdlib for Dart/Flutter including immutable collections (KtList, KtMap, KtSet) and other packages

kt.dart This project is a port of Kotlin's Kotlin Standard library for Dart/Flutter projects. It's a useful addition to dart:core and includes collect

Pascal Welsch 460 Jan 9, 2023
A dart port of the excellent Guard Clauses C# package by Ardalis

Guard Clauses A dart port of the excellent C# Guard Clauses package by Ardalis. A simple extensible package with guard clause extensions. A guard clau

Chris Hibler 1 Apr 15, 2022