Using Box2D in Delphi Applications
Go Up to Box2D
This topic explains how to use Box2D in Delphi applications.
Contents
Configuring Your Application to Use Box2D
RAD Studio does not provide prebuilt .dcu
files for the Box2D Delphi units. To be able to build a Delphi project that contains Box2D units in its uses
clause, you must configure the search path of your project so that RAD Studio can find the Box2D units.
To configure the search path of your Delphi project so that RAD Studio can find the Box2D units:
- Select Project > Options > Delphi Compiler.
- Add
$(BDS)\source\FlatBox2D
to the Search Path field.
You can now add references to these units in your code so that you can use Box2D.
Using Box2D
The Delphi bindings for Box2D are based on the C++ API; however there are some notable differences.
- Note: To use the Delphi bindings for Box2D, you should be familiar with pointers and extended identifiers.
Delphi Mapping of Box2D Classes
The Delphi bindings for Box2D expose Box2D classes in either of the following ways:
- As a record with the original name of the Box2D class. See Using Box2D Records.
- As a record with the original name of the Box2D class suffixed with
Wrapper
. For example, the wrapper ofb2World
would beb2WorldWrapper
. See Using Box2D Wrapper Records.
In both cases, unlike with regular Delphi records, it is not enough to declare these Box2D records to create them. You must call their Create
procedure to ensure that their members have the right default values. If you declare a record and do not call Create
, the default values of is members may not match those that Box2D defines.
groundBodyDef := b2BodyDef.Create;
Using Box2D Records
The Delphi bindings for Box2D provide most Box2D classes as records. The only exceptions are classes exposed as wrapper records and listener classes.
Using Box2D Wrapper Records
The Delphi bindings for Box2D provide the following wrapper records:
b2BlockAllocatorWrapper
b2BodyWrapper
b2BroadPhaseWrapper
b2ChainAndCircleContactWrapper
b2ChainAndPolygonContactWrapper
b2ChainShapeWrapper
b2CircleContactWrapper
b2CircleShapeWrapper
b2ContactWrapper
b2ContactManagerWrapper
b2ContactSolverWrapper
b2DistanceJointWrapper
b2DrawWrapper
b2DynamicTreeWrapper
b2EdgeAndCircleContactWrapper
b2EdgeAndPolygonContactWrapper
b2EdgeShapeWrapper
b2FrictionJointWrapper
b2GearJointWrapper
b2IslandWrapper
b2JointWrapper
b2MotorJointWrapper
b2MouseJointWrapper
b2PolygonAndCircleContactWrapper
b2PolygonContactWrapper
b2PolygonShapeWrapper
b2PrismaticJointWrapper
b2PulleyJointWrapper
b2RevoluteJointWrapper
b2RopeWrapper
b2RopeJointWrapper
b2ShapeWrapper
b2StackAllocatorWrapper
b2WeldJointWrapper
b2WheelJointWrapper
b2WorldWrapper
Freeing Box2D Records and Record Wrappers
The only Box2D records or record wrappers that you must free are instances of b2WorldWrapper
. The destructor of b2WorldWrapper
frees any memory allocated by bodies, fixtures, or joints in the b2WorldWrapper
object.
The exceptions to this rule are:
- the ShapeWrappers.
- other Wrappers that you explicitly construct and that are destroyed in C++.
world.Destroy;
Box2D listeners are also an exception to this rule.
Defining Box2D Listeners
Box2D defines some listener classes. When you are using C++, you can create a subclass of a listener, create an instance of your subclass and register your listener object in some Box2D object, such as a world (b2World
).
To create a Box2D listener object of a certain type in Delphi, you must define a custom class that implements the interface of the target Box2D listener class. The interface of a Box2D listener class is named as the Box2D listener class but prefixed with a capital I
. For example, Ib2ContactListener
is the interface of the b2ContactListener
Box2D listener class.
TMyContactListener = class (TInterfacedObject, Ib2ContactListener)
public
procedure BeginContact(contact: NativeUInt); cdecl;
procedure EndContact(contact: NativeUInt); cdecl;
procedure PostSolve(contact: NativeUInt; impulse: Pb2ContactImpulse); cdecl;
procedure PreSolve(contact: NativeUInt; oldManifold: Pb2Manifold); cdecl;
end;
Once you have a class that implements the target listener interface, you must create an instance of that class.
myContactListener := TMyContactListener.Create;
Listener setters cannot handle your listener object directly. Instead you must obtain a delegate (of type NativeUInt
) for your listener object and pass that delegate to the listener setter. Use Create_<listener class>_delegate
to create a delegate of your listener object.
myContactListenerHandle := Create_b2ContactListener_delegate(myContactListener);
world.SetContactListener(myContactListenerHandle);
After you destroy the Box2D world, you can destroy your listener object by passing its handle to Destroy_<listener class>_delegate
.
world.Destroy;
Destroy_b2ContactListener_delegate(myContactListenerHandle);
Deploying Your Application
On desktop platforms, you must distribute the RAD Studio Box2D dynamic library along with your application.
The RAD Studio Box2D dynamic library file is available at:
- 32-bit Windows:
C:\Program Files (x86)\Embarcadero\Studio\21.0\bin\FlatBox2DDyn.dll
- 64-bit Windows:
C:\Program Files (x86)\Embarcadero\Studio\21.0\bin64\FlatBox2DDyn.dll
- 32-bit macOS:
C:\Program Files (x86)\Embarcadero\Studio\21.0\binosx32\libFlatBox2DDyn.dylib
- 64-bit macOS:
C:\Program Files (x86)\Embarcadero\Studio\21.0\binosx64\libFlatBox2DDyn.dylib
Add this library file to the Deployment Manager for each of the target platforms that your application supports, so that when you deploy your application for any desktop platform, the RAD Studio Box2D dynamic library file is included among the deployed files of your application.
See Also
Samples
- Box2D Hello World (Delphi)
- Box2D Hello sample
- Box2D TestBed sample
- FMX SimplePhysics sample