-- | Description: Low-level Haskell bindings to Chipmunk2D physics library -- Chiphunk is a __low-level__ Haskell bindings for the <https://chipmunk-physics.net/ Chipmunk2D physics engine>. -- It includes most (almost all) of the functions mentioned in the main documentation for Chipmunk2D, -- except for some (relatively) exotic ones, which may be added later per request. module Chiphunk.Low ( -- * Disclaymer -- | This bindings are so low-level so that they even require you to free the memory the Chipmunk2D has allocated -- for your objects. Module with more high-level api can be built around this low-level bingings at some point, -- in the meantime, however, you're advised to provide wrapper layer for your games so that you do not have to -- keep track of such things in the core of your game's logic. -- -- See below for an adoptation of the original Chipmunk documentation available -- <https://chipmunk-physics.net/release/ChipmunkLatest-Docs/ here>. I've skipped some sections not related -- to the bindings, like the reason author chose C language in the first place and limitations of the C api. -- Obviously, it's thanks to that choice that I was able to write bindings around the library in Haskell. -- -- __Howling Moon Software is not affiliated with this bindings.__ -- __In all of the following \"I\" refers to the original documentation author for Chipmunk2D.__ -- * Chipmunk2D 7.0.2 -- | Chipmunk2D is a 2D rigid body physics library distributed under the MIT license. -- It is blazingly fast, portable, numerically stable, and easy to use. -- For this reason it has been used in hundreds of games across just about every system you can name. -- This includes top quality titles such as Night Sky for the Wii and many #1 sellers on the iPhone App Store! -- I’ve put thousands of hours of work over many years to make Chipmunk2D what it is today. -- If you find Chipmunk2D has saved you a lot of time, please consider -- <https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6666552 donating>. -- You’ll make an indie game developer very happy! -- | First of all, I would like to give a Erin Catto a big thank you, as Chipmunk2D’s impulse solver -- was directly inspired by his example code way back in 2006. -- (Now a full fledged physics engine all its own: <http://www.box2d.org/ Box2D.org>). -- His contact persistence idea allows for stable stacks of objects with very few iterations of the solver. -- My previous solver produced mushy piles of objects or required a large amount of CPU to operate stably. -- ** Support -- | The best way to get support is to visit the <http://www.slembcke.net/forums/viewforum.php?f=1 Chipmunk Forums>. -- There are plenty of people around using Chipmunk on the just about every platform -- I’ve ever heard of. If you are working on a commercial project, Howling Moon Software -- (my company) is <http://howlingmoonsoftware.com/contracting.php available for contracting>. -- We can help with implementing custom Chipmunk behaviors, -- as well as priority bug fixes and performance tuning. -- ** Contact -- | If you find any bugs in Chipmunk, errors or broken links in this document, -- or have a question or comment about Chipmunk you can contact me at -- slembcke(at)gmail(dot)com. (email or GTalk) -- ** License -- | Chipmunk is licensed under the MIT license. -- -- @ -- Copyright (c) 2007-2015 Scott Lembcke and Howling Moon Software -- -- Permission is hereby granted, free of charge, to any person obtaining a copy -- of this software and associated documentation files (the "Software"), to deal -- in the Software without restriction, including without limitation the rights -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -- copies of the Software, and to permit persons to whom the Software is -- furnished to do so, subject to the following conditions: -- -- The above copyright notice and this permission notice shall be included in -- all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -- SOFTWARE. -- @ -- -- This means that you do not have to buy a license or pay to use Chipmunk in commercial projects. (Though we really appreciate donations) -- ** Links -- | -- * <http://chipmunk2d.net/forum Chipmunk Forums> – The official forum Chipmunk2D forum. -- -- * <http://howlingmoonsoftware.com/ Howling Moon Software> – The software company I co-founded. -- (We are available for contract work!) -- -- * <http://chipmunk2d.net/games.php Games> – A small list of games we know that use Chipmunk. -- * Hello Chipmunk (World) -- | Hello world Chipmunk style. Create a simple simulation where a ball falls onto a static line segment, -- then rolls off. Print out the coordinates of the ball. -- -- @ -- main :: IO () -- main = do -- let gravity = 'Vect' 0 (-100) -- -- -- Create an empty space. -- space <- 'spaceNew' -- 'spaceGravity' space $= gravity -- -- -- Add a static line segment shape for the ground. -- -- We'll make it slightly tilted so the ball will roll off. -- -- We attach it to a static body to tell Chipmunk it shouldn't be movable. -- static <- get $ 'spaceStaticBody' space -- ground <- 'segmentShapeNew' static (Vect (-20) 5) (Vect 20 (-5)) 0 -- 'shapeFriction' ground $= 1 -- 'spaceAddShape' space ground -- -- -- Now let's make a ball that falls onto the line and rolls off. -- -- First we need to make a cpBody to hold the physical properties of the object. -- -- These include the mass, position, velocity, angle, etc. of the object. -- -- Then we attach collision shapes to the 'Body' to give it a size and shape. -- -- let radius = 5 -- let mass = 1 -- -- -- The moment of inertia is like mass for rotation -- -- Use the momentFor* functions to help you approximate it. -- let moment = 'momentForCircle' mass 0 radius (Vect 0 0) -- -- -- The spaceAdd* functions return the thing that you are adding. -- ballBody <- 'bodyNew' mass moment -- 'spaceAddBody' space ballBody -- 'bodyPosition' ballBody $= Vect 0 15 -- -- -- Now we create the collision shape for the ball. -- -- You can create multiple collision shapes that point to the same body. -- -- They will all be attached to the body and move around to follow it. -- ballShape <- 'circleShapeNew' ballBody radius (Vect 0 0) -- 'spaceAddShape' space ballShape -- 'shapeFriction' ballShape $= 0.7 -- -- -- Now that it's all set up, we simulate all the objects in the space by -- -- stepping forward through time in small increments called steps. -- -- It is *highly* recommended to use a fixed size time step. -- let timeStep = 1/60 -- runFor 2 timeStep $ \time -> do -- pos <- get $ 'bodyPosition' ballBody -- vel <- get $ 'bodyVelocity' ballBody -- printf "Time is %4.2f. ballBody is at (%6.2f, %6.2f), it's velocity is (%6.2f, %6.2f).\n" -- time (vX pos) (vY pos) (vX vel) (vY vel) -- -- 'spaceStep' space timeStep -- -- 'shapeFree' ballShape -- 'bodyFree' ballBody -- 'shapeFree' ground -- 'spaceFree' space -- where -- runFor time step inner = go time -- where -- go time' -- | time' <= 0 = pure () -- | otherwise = inner (time - time') *> go (time' - step) -- @ -- * Chipmunk2D Basics -- ** Overview -- | There are 4 basic object types you will use in Chipmunk. -- | -- * __Rigid Bodies__ ('Body'): A rigid body holds the physical properties of an object. -- (mass, position, rotation, velocity, etc.) It does not have a shape until you attach one or more collision shapes -- to it. If you’ve done physics with particles before, rigid bodies differ in that they are able to rotate. -- Rigid bodies generally tend to have a 1:1 correlation to sprites in a game. -- You should structure your game so that you use the position and rotation of the rigid body -- for drawing your sprite. -- -- * __Collision Shapes__ ('Shape'): By attaching shapes to bodies, you can define the a body’s shape. -- You can attach as many shapes to a single body as you need to in order to define a complex shape. -- Shapes contain the surface properties of an object such as how much friction or elasticity it has. -- -- * __Constraints/Joints__ ('Constraint'): Constraints and joints describe how bodies are attached to each other. -- -- * __Spaces__ ('Space'): Spaces are containers for simulating objects in Chipmunk. -- You add bodies, shapes and joints to a space and then update the space as a whole. -- They control how all the rigid bodies, shapes, and constraints interact together. -- -- There is often confusion between rigid bodies and their collision shapes in Chipmunk -- and how they relate to sprites. A sprite would be a visual representation of an object, -- while a collision shape is an invisible property that defines how objects should collide. -- Both the sprite’s and the collision shape’s position and rotation are controlled by the motion of a rigid body. -- Generally you want to create a game object type that ties these things all together. -- ** Memory Management the Chipmunk way -- | For most of the structures you will use, Chipmunk uses a more or less standard and straightforward set -- of memory management functions. Take the 'Space' struct for example: -- -- * 'spaceNew' — Allocates and initializes a 'Space' struct. -- -- * 'spaceFree' — Destroys and frees the 'Space' struct. -- -- You are responsible for freeing any structs that you allocate. Chipmunk does not do reference counting or garbage collection. If you call a new function, you must call the matching free function or you will leak memory. -- ** Math the Chipmunk way -- | First of all, Chipmunk uses double precision floating point numbers throughout its calculations by default. -- This is likely to be faster on most modern desktop processors, -- and means you don’t have to worry as much about floating point accuracy. -- -- However, there are a few unique functions you will probably find very useful: fClamp , fLerp , fLerpConst -- * Chipmunk Vectors -- ** Struct Definition, Constants and Constructors , Vect (..) , vZero , cpv -- ** Operations -- | (__Note for bindings__: Most of these are Chipmunk2D-style aliases for 'Vect' typeclasses methods: -- 'Eq', 'Data.VectorSpace.AdditiveGroup', 'Data.VectorSpace.VectorSpace', 'Data.VectorSpace.InnerSpace', -- 'Data.Cross.HasCross2') , vEql , vAdd , vSub , vNeg , vMult , vDot , vCross , vPerp , vRPerp , vProject , vRotate , vUnRotate , vLength , vLengthSq , vLerp , vLerpConst , vSLerp , vSLerpConst , vNormalize , vClamp , vDist , vDistSq , vNear , vForAngle , vToAngle -- * Chipmunk Axis Aligned Bounding Boxes -- ** Struct Definition and Constructors , BB (..) , bbNew , bbNewForExtents , bbNewForCircle -- ** Operations , bbIntersects , bbContainsBB , bbContainsVect , bbMerge , bbExpand , bbCenter , bbArea , bbMergedArea , bbSegmentQuery , bbIntersectsSegment , bbClampVect , bbWrapVect -- * Chipmunk Rigid Bodies , Body -- ** Dynamic, Kinematic, and Static Bodies , BodyType (..) -- ** Movement, Teleportation, and Velocity -- | A graphics engine only needs to know the position of an object for each frame that its drawn. -- For a physics engine, this isn’t enough information to calculate a collision response. -- When you set the position of a body, you are effectively asking it to teleport itself. -- This means that it will instantly move to its new position instead of moving through space and time -- like a normal object. If you teleport an object so that it overlaps another one, -- the best the physics engine can do is to attempt to push the objects apart again -- since there is no information about their movement. This generally results in very mushy looking collisions. -- So instead of setting the position of an object, it’s better to set its velocity and allow the physics engine -- to update the position. That way it can resolve any resulting colisions natuarally since it knows -- how the objects were moving. This is why kinematic bodies work the way they do. -- You set the velocity, and the physics updates their position so the two are never out of sync. -- -- For dynamic bodies, setting the velocity explicitly every frame can cause problems. -- For example, a problem occurs when a light dynamic body (like a person) is pressed against a heavy dynamic body -- (like a car), and you set velocity of the small object so that it’s pushing it into the big body. -- To the physics engine, the change in velocity is the same as applying a large impulse -- (a very short, very large force). Even if the velocity is low, the large force can allow the small body -- to push the big body, even when it normally wouldn’t be able to. For example, a person walking into a car -- can overpower the car’s friction and cause it to creep along the ground slowly. -- Additionally, when you set the velocity of an object that is already in contact, -- it can cause the two objects to overlap by a small amount. The easiest way to avoid both of these problems -- is to make smaller changes to the body’s velocity, accelerating it over a fraction of a second -- instead of a single frame. An even better solution, which is covered more thoroughly later, -- is to use constraints to move the object. -- ** Memory Management Functions -- | Standard set of Chipmunk memory management functions. , bodyNew , bodyNewKinematic , bodyNewStatic , bodyFree -- ** Creating Dynamic Bodies -- | There are two ways to set up a dynamic body. The easiest option is to create a body -- with a mass and moment of 0, and set the mass or density of each collision shape added to the body. -- Chipmunk will automatically calculate the mass, moment of inertia, and center of gravity for you. -- This is probably preferred in most cases. -- -- The other option is to set the mass of the body when it’s created, and leave the mass of the shapes -- added to it as 0.0. This approach is more flexible, but is not as easy to use. -- __Don’t__ set the mass of both the body and the shapes. If you do so, -- it will recalculate and overwite your custom mass value when the shapes are added to the body. -- ** Properties -- | Chipmunk provides getter/setter functions for a number of properties on rigid bodies. -- Setting most properties automatically wakes the rigid bodies up if they were sleeping. , bodyType , bodyMass , bodyMoment , bodyPosition , bodyCenterOfGravity , bodyVelocity , bodyForce , bodyAngle , bodyAngularVelocity , bodyTorque , bodyRotation , bodySpace , bodyUserData -- ** Moment of Inertia and Area Helper Functions -- | Use the following functions to approximate the moment of inertia for your body, -- adding the results together if you want to use more than one. , momentForCircle , momentForSegment , momentForPoly , momentForBox -- | Use the following functions to get the area for common Chipmunk shapes if you want to approximate masses -- or density or whatnot. , areaForCircle , areaForSegment , areaForPoly -- ** Coordinate Conversion Functions -- | Many things are defined in coordinates local to a body meaning that the (0,0) is at the center of gravity -- of the body and the axis rotate along with the body. , bodyLocalToWorld , bodyWorldToLocal -- ** Velocity Conversion Functions -- | It’s often useful to know the absolute velocity of a point on the surface of a body -- since the angular velocity affects everything except the center of gravity. , bodyVelocityAtWorldPoint -- ** Applying Forces and Torques -- | People are sometimes confused by the difference between a force and an impulse. -- An impulse is a very large force applied over a very short period of time. -- Some examples are a ball hitting a wall or cannon firing. Chipmunk treats impulses as if they occur -- instantaneously by adding directly to the velocity of an object. -- Both impulses and forces are affected the mass of an object. -- Doubling the mass of the object will halve the effect. , bodyApplyForceAtWorldPoint , bodyApplyForceAtLocalPoint , bodyApplyImpulseAtWorldPoint , bodyApplyImpulseAtLocalPoint -- ** Sleeping Functions -- | Chipmunk supports a sleeping feature which improves performance by not simulating groups of objects -- that aren’t moving. Read more about it in the 'Space' section. , bodyIsSleeping , bodyActivate , bodySleep , bodyActivateStatic , bodySleepWithGroup -- ** Iterators , BodyShapeIteratorFunc , bodyEachShape , BodyConstraintIteratorFunc , bodyEachConstraint , BodyArbiterIteratorFunc , bodyEachArbiter -- * Chipmunk Collision Shapes , Shape -- ** Properties -- | Chipmunk provides getter/setter functions for a number of properties on collision shapes. -- Setting most properties will automatically wake the attached rigid body, if it’s sleeping. , shapeBody , shapeBB , shapeSensor , shapeElasticity , shapeFriction , shapeSurfaceVelocity , shapeCollisionType , ShapeFilter (..) , shapeFilter , shapeSpace , shapeUserData -- ** Fast Collision Filtering using ShapeFilter -- | Chipmunk has two primary means of ignoring collisions: groups and category masks. -- -- __Groups__ are used to ignore collisions between parts on a complex object. -- A ragdoll is a good example. When jointing an arm onto the torso, you’ll want them to allow them to overlap. -- Groups allow you to do exactly that. Shapes that have the same group don’t generate collisions. -- So by placing all of the shapes in a ragdoll in the same group, you’ll prevent it from colliding -- against other parts of itself. -- __Category__ masks allow you to mark which categories an object belongs to -- and which categories it collidies with. -- -- For example, a game has four collision categories: player (0), enemy (1), player bullet (2), -- and enemy bullet (3). Neither players nor enemies should not collide with their own bullets, -- and bullets should not collide with other bullets. -- However, players collide with enemy bullets, and enemies collide with player bullets. -- -- +-----------------+-----------------+---------------+ -- | Object | Object Category | Category Mask | -- +=================+=================+===============+ -- | \"Player\" | 1 | 4, 5 | -- +-----------------+-----------------+---------------+ -- | \"Enemy\" | 2 | 2, 3, 5 | -- +-----------------+-----------------+---------------+ -- | "Player Bullet" | 3 | 1, 5 | -- +-----------------+-----------------+---------------+ -- | "Enemy Bullet" | 4 | 2, 5 | -- +-----------------+-----------------+---------------+ -- | \"Walls\" | 5 | 1, 2, 3, 4 | -- +-----------------+-----------------+---------------+ -- -- Note that everything in this example collides with walls. Additionally, the enemies collide with eachother. -- -- By default, objects exist in every category and collide with every category. -- -- Objects can fall into multiple categories. For instance, you might have a category for a red team, -- and have a red player bullet. In the above example, each object only has one category. -- -- There is one last way of filtering collisions using collision handlers. See the section on callbacks -- for more information. Collision handlers can be more flexible, but can be slower. -- Fast collision filtering rejects collisions before running the expensive collision detection code, -- so using groups or category masks is preferred. -- ** Memory Management Functions , shapeFree -- ** Misc functions , shapeCacheBB , shapeUpdate -- ** Working With Circle Shapes , circleShapeNew -- ** Working With Segment Shapes , segmentShapeNew , segmentShapeNeighbors -- ** Working With Polygon Shapes , polyShapeNew , polyShapeNewRaw -- *** Boxes -- | Because boxes are so common in physics games, Chipmunk provides shortcuts to create box shaped polygons. -- The boxes will always be centered at the center of gravity of the body you are attaching them to. -- Adding a small radius will bevel the corners and can significantly reduce problems -- where the box gets stuck on seams in your geometry. If you want to create an off-center box, -- you will need to use 'polyShapeNew'. , boxShapeNew , boxShapeNew2 -- *** Poly Shape Helper Functions , centroidForPoly -- *** Convex Hull Helper Functions , convexHull -- ** Modifying 'Shape's -- | The short answer is that you can’t because the changes would be only picked up as a change to the position -- of the shape’s surface, but not its velocity. -- ** Notes -- | -- * You can attach multiple collision shapes to a rigid body. This should allow you to create almost any shape -- you could possibly need. -- -- * Shapes attached to the same rigid body will never generate collisions. You don’t have to worry -- about overlap when attaching multiple shapes to a rigid body. -- -- * Make sure you add both the body and its collision shapes to a space. -- * Chipmunk Spaces , Space -- ** What Are Iterations, and Why Should I Care? -- | Chipmunk uses an iterative solver to figure out the forces between objects in the space. -- What this means is that it builds a big list of all of the collisions, joints, and other constraints -- between the bodies and makes several passes over the list considering each one individually. -- The number of passes it makes is the iteration count, and each iteration makes the solution more accurate. -- If you use too many iterations, the physics should look nice and solid, but may use up too much CPU time. -- If you use too few iterations, the simulation may seem mushy or bouncy when the objects should be solid. -- Setting the number of iterations lets you balance between CPU usage and the accuracy of the physics. -- Chipmunk’s default of 10 iterations is sufficient for most simple games. -- ** Sleeping -- | Spaces can disable entire groups of objects that have stopped moving to save CPU time and battery life. -- In order to use this feature you must do two things. You must enable sleeping explicitly -- by choosing a time threshold value with 'spaceSetSleepTimeThreshold'. This threshold is the amount of time -- something must be idle before it falls asleep. 'spaceSetIdleSpeedThreshold' defines what is considered idle. -- If you do not set idle speed threshold explicitly, a value will be chosen automatically -- based on the current amount of gravity. Be mindful that objects cannot fall asleep if they are touching -- or jointed to a kinematic body. -- ** Properties , spaceIterations , spaceGravity , spaceDamping , spaceIdleSpeedThreshold , spaceSleepTimeThreshold , spaceCollisionSlop , spaceCollisionBias , spaceCollisionPersistence , spaceCurrentTimeStep , spaceIsLocked , spaceUserData , spaceStaticBody -- ** Memory Management Functions -- | More standard Chipmunk memory functions. , spaceNew , spaceFree -- ** Operations -- | These functions add and remove shapes, bodies and constraints from space. The add/remove functions -- cannot be called from within a callback other than a 'postStep' callback (which is different than a 'postSolve' -- callback!). Attempting to add or remove objects from the space while 'spaceStep' is still executing -- will throw an assertion. See the callbacks section for more information. Be careful not to free bodies -- before removing shapes and constraints attached to them or you will cause crashes.. -- The contains functions allow you to check if an object has been added to the space or not. , spaceAddShape , spaceAddBody , spaceAddConstraint , spaceRemoveShape , spaceRemoveBody , spaceRemoveConstraint , spaceContainsShape , spaceContainsBody , spaceContainsConstraint -- ** Spatial Indexing -- | Occasionally, you might want to update the collision detection data for a shape. -- If you move a static shape or a static body you must do this to let Chipmunk know -- it needs to have its collision detection data updated. You may also want to manually update the collision data -- for normal shapes if you move them and still want to perform queries against them -- before the next call to 'spaceStep'. , spaceReindexShape , spaceReindexShapesForBody , spaceReindexStatic -- ** Iterators , SpaceBodyIteratorFunc , spaceEachBody , SpaceShapeIteratorFunc , spaceEachShape , SpaceConstraintIteratorFunc , spaceEachConstraint -- ** Simulating the Space , spaceStep -- * Notes -- | -- * When removing objects from the space, make sure you remove any other objects that reference it. -- For instance, when you remove a body, remove the joints and shapes attached to it. -- -- * Using more iterations or smaller time steps will increase the physics quality, but also increase the CPU usage. -- * Chipmunk Constraints , Constraint -- ** What constraints are and what they are not -- | Constraints in Chipmunk are all velocity based constraints. -- This means that they act primarily by synchronizing the velocity of two bodies. -- A pivot joint holds two anchor points on two separate bodies together by defining equations that say -- that the velocity of the anchor points must be the same and calculating impulses to apply to the bodies -- to try and keep it that way. A constraint takes a velocity as it’s primary input and produces a velocity change -- as its output. Some constraints, (joints in particular) apply velocity changes to correct differences -- in positions. More about this in the next section. -- -- A spring connected between two bodies is not a constraint. It’s very constraint-like as it creates forces -- that affect the velocities of the two bodies, but a spring takes distances as input and produces forces -- as its output. If a spring is not a constraint, then why do I have two varieties of spring constraints you ask? -- The reason is because they are damped springs. The damping associated with the spring is a true constraint -- that creates velocity changes based on the relative velocities of the two bodies it links. -- As it is convenient to put a damper and a spring together most of the time, I figured I might as well just apply -- the spring force as part of the constraint instead of having a damper constraint and having the user -- calculate and apply their own spring forces separately. -- ** Properties , constraintBodyA , constraintBodyB , constraintMaxForce , constraintErrorBias , constraintMaxBias , constraintSpace , constraintCollideBodies , constraintUserData , constraintImpulse -- ** Error correction by Feedback -- | Joints in Chipmunk are not perfect. A pin joint can’t maintain the exact correct distance between its anchor -- points, nor can a pivot joint hold its anchor points completely together. Instead, they are designed -- to deal with this by correcting themselves over time. Since Chipmunk 5, you have a fair amount of extra control -- over how joints correct themselves and can even use this ability to create physical effects -- that allow you to use joints in unique ways: -- -- * Servo motors – Ex: open/close doors or rotate things without going over a maximum force. -- -- * Winches – Pull one object towards another at a constant speed without going over a maximum force. -- -- * Mouse manipulation – Interact with objects smoothly given coarse/shaky mouse input. -- -- There are three properties of 'Constraint' structs that control the error correction, -- maxForce, maxBias, and biasCoef. maxForce is pretty self explanatory, a joint or constraint -- will not be able to use more than this amount of force in order to function. If it needs more force -- to be able to hold itself together, it will fall apart. maxBias is the maximum speed at which error correction -- can be applied. If you change a property on a joint so that the joint will have to correct itself, -- it normally does so very quickly. By setting a maxSpeed you can make the joint work like a servo, -- correcting itself at a constant rate over a longer period of time. Lastly, biasCoef is the percentage -- of error corrected every step before clamping to a maximum speed. You can use this -- to make joints correct themselves smoothly instead of at a constant speed, but is probably the least useful -- of the three properties by far. -- ** Constraints and Collision Shapes -- | Neither constraints or collision shapes have any knowledge of the other. -- When connecting joints to a body the anchor points don’t need to be inside of any shapes attached to the body -- and it often makes sense that they shouldn’t. Also, adding a constraint between two bodies -- doesn’t prevent their collision shapes from colliding. In fact, this is the primary reason -- that the collision group property exists. -- ** Video Tour of Current Joint Types -- | http://www.youtube.com/watch?v=ZgJJZTS0aMM -- ** Shared Memory Management Functions , constraintFree -- ** Constraint Types -- *** Pin Joints , pinJointNew -- **** Properties , pinJointAnchorA , pinJointAnchorB , pinJointDist -- *** Slide Joints , slideJointNew -- **** Properties , slideJointAnchorA , slideJointAnchorB , slideJointMin , slideJointMax -- *** Pivot Joints -- | (__Note for bindings__: So each instance of pivot joint can be replaced with pin joint with dist of 0?) , pivotJointNew , pivotJointNew2 -- **** Properties , pivotJointAnchorA , pivotJointAnchorB -- *** Groove Joint , grooveJointNew -- **** Properties , grooveJointGrooveA , grooveJointGrooveB , grooveJointAnchorB -- *** Damped Spring , dampedSpringNew -- **** Properties , dampedSpringAnchorA , dampedSpringAnchorB , dampedSpringRestLength , dampedSpringStiffness , dampedSpringDamping -- *** Damped Rotary Spring -- | Like a damped spring, but works in an angular fashion. , dampedRotarySpringNew -- **** Properties , dampedRotarySpringRestAngle , dampedRotarySpringStiffness , dampedRotarySpringDamping -- *** Rotary Limit Joint -- | Constrains the relative rotations of two bodies. -- It is implemented so that it’s possible to for the range to be greater than a full revolution. , rotaryLimitJointNew -- **** Properties , rotaryLimitJointMin , rotaryLimitJointMax -- *** Ratchet Joint -- | Works like a socket wrench. , ratchetJointNew -- **** Properties , ratchetJointAngle , ratchetJointPhase , ratchetJointRatchet -- *** Gear Joint -- | Keeps the angular velocity ratio of a pair of bodies constant. , gearJointNew -- **** Properties , gearJointPhase , gearJointRatio -- *** Simple Motor -- | Keeps the relative angular velocity of a pair of bodies constant. -- You will usually want to set an force (torque) maximum for motors as otherwise -- they will be able to apply a nearly infinite torque to keep the bodies moving. , simpleMotorNew -- **** Properties , simpleMotorRate -- ** Notes -- | * You can add multiple joints between two bodies, but make sure that they don’t fight. -- Doing so can cause the bodies jitter or spin violently. -- * Overview of Collision Detection in Chipmunk -- | In order to make collision detection in Chipmunk as fast as possible, the process is broken down -- into several stages. While I’ve tried to keep it conceptually simple, the implementation can be a bit daunting. -- Fortunately as a user of the library, you don’t need to understand everything about how it works. -- Though if you are trying to squeeze every bit of performance out of Chipmunk, understanding this section -- can be helpful. -- ** Spatial Indexing -- | A for loop that checks every object against every other object in the scene would be very slow. -- So the first stage of the collision detection, commonly called the broadphase, uses a high level -- spatial algorithm to decide which pairs of objects to check for collisions. -- Currently Chipmunk supports two spatial indexes, an axis-aligned bounding box tree and a spatial hash. -- These spatial indexes are able to quickly identify which pairs of shapes are near each other -- and should be checked for a collision. -- ** Fast Collision Filtering -- | After the spatial index figures out which pairs of shapes are likely to be near each other, -- it passes each pair back to the space using a callback to perform some additional filtering on the pairs. -- Before doing anything else, Chipmunk performs a few quick tests to check if shapes should collide. -- -- * __Bounding Box Test__: The shapes are not colliding if their bounding boxes are not overlapping. -- Objects like diagonal line segments can trigger a lot of false positives here, -- but it’s unlikely to be something you should worry about. -- -- * __Category Mask Test__: The categories of each shape are bitwise ANDed against the category mask -- of the other shape. If either result is 0, the shapes do not collide. -- -- * __Group Test__: Shapes shouldn’t collide with other shapes in the same non-zero group. -- ** Constraint Based Filtering -- | After fast collision filtering, Chipmunk checks the list of joints on one of the bodies -- to see if it has a constraint that attaches it to the other body. If that constraint’s collideBodies -- property is false, the collision will be ignored. This check is often very fast -- since most scenes don’t contain a lot of constraints. -- ** Primitive Shape to Shape Collision Detection -- | The most expensive test is to actually check for overlap based on their geometry. -- Circle to circle and circle to line collisions are very fast. Segment to segment and poly to poly collisions -- are handled using the GJK/EPA algorithms, and get more expensive as the number of vertexes increases. -- Simpler shapes make for faster collisions, and often more important, fewer collision points -- for the solver to run. Chipmunk uses a small dispatch table to figure out which function to use to check -- if the shapes overlap. -- -- Without going into too much detail, the GJK algorithm checks the distance between two objects, -- and the EPA algorithm checks how much they are overlapping. If you give you segment and poly shapes -- a small radius when creating them, the EPA algorithm can usually be skipped, speeding up the collision detection -- considerably. The radius should be at least as big as the amount of allowed collision slop. -- ** Collision Handler Filtering -- | After checking if two shapes overlap Chipmunk will look to see if you have defined a collision handler -- for the collision types of the shapes. This is vital to process collisions events for the gameplay, -- but also gives you a very flexible way to filter out collisions. The return value of the begin and preSolve -- callbacks determines whether or not the colliding pair of shapes is discarded or not. -- Returning true will keep the pair, false will discard it. Rejecting a collision from a begin callback -- is permanent, rejecting it from the preSolve only applies to the step it occured in. If you don’t define -- a handler for the given collision types, Chipmunk will call the space’s default handler, which by default -- is defined to simply accept all collisions. -- -- Wildcard collisions can also return a value, but they are handled in a more complicated way. -- When you create a collision handler between two specific collision types, it’s your responsibility -- to decide when to call the wildcard handlers and what to do with their return values. -- Otherwise, the default is to call the wildcard handler for the first type, then the second type, -- and use a logical AND of their return values as filtering value. See DefaultBegin() in cpSpace.c -- for more information. -- -- While using callbacks to filter collisions is the most flexible way, keep in mind that by the time your callback -- is called all of the most expensive collision detection has already been done. For simulations -- with a lot of colliding objects each frame, the time spent finding collisions is small compared to the time -- spent solving the physics for them so it may not be a big deal. Fast collision filtering should be preferred -- if possible. -- * Collision Callbacks -- | A physics library without any events or feedback would not be very useful for games. -- How would you know when the player bumped into an enemy so that you could take some health points away? -- How would you know how hard the car hit something so you don’t play a loud crash noise when a pebble hits it? -- What if you need to decide if a collision should be ignored based on specific conditions, -- like implementing one way platforms? Chipmunk has a number of powerful callback systems -- that you can use to solve these problems. -- ** Collision Handlers -- | Collision handler function types. While all of them take an arbiter, space, and a user data pointer, -- only the begin and preSolve callbacks return a value. See above for more information. , CollisionCallback -- Collision callbacks are closely associated with 'Arbiter' structs. -- You should familiarize yourself with those as well. -- -- __Note__: Shapes tagged as sensors (cpShape.sensor == true) never generate collisions that get processed, -- so collisions between sensors shapes and other shapes will never call the postSolve callback. -- They still generate begin, and separate callbacks, and the preSolve callback is also called -- every frame even though there is no collision response. -- -- __Note #2__: preSolve callbacks are called before the sleeping algorithm runs. -- If an object falls asleep, its postSolve callback won’t be called until it’s reawoken. , CollisionType , CollisionHandler (..) , CollisionHandlerPtr , spaceAddCollisionHandler , spaceAddWildcardHandler , spaceAddDefaultCollisionHandler , modifyCollisionHandler , mkCallback , mkCallbackB -- ** Post-Step Callbacks -- | Post-step callbacks are the one place where you can break the rules about adding or removing objects -- from within a callback. In fact, their primary function is to help you safely remove objects from the space -- that you wanted to disable or destroy in a collision or query callback. -- -- Post step callbacks are registered as a function and a pointer that is used as a key. -- You can only register one postStep callback per key. This prevents you from accidentally removing -- an object more than once. For instance, say that you get a collision callback between a bullet and object A. -- You want to destroy both the bullet and object A, so you register a postStep callback -- to safely remove them from your game. Then you get a second collision callback between the bullet and object B. -- You register a postStep callback to remove object B, and a second postStep callback to remove the bullet. -- Because you can only register one callback per key, the postStep callback for the bullet -- will only be called once and you can’t accidentally try to remove it twice. , PostStepFunc , spaceAddPostStepCallback -- ** Examples -- | See -- <https://chipmunk-physics.net/release/ChipmunkLatest-Docs/examples.html#CollisionCallbacks the callback examples> -- for more information. -- * Chipmunk Collision Pairs , Arbiter -- ** Memory Management -- | You will never need to create or free an arbiter. More importantly, -- because they are entirely managed by the space you should never store a reference to an arbiter -- as you don’t know when they will be freed or reused. Use them within the callback where they are given to you -- and then forget about them or copy out the information you need. -- ** Properties , arbiterRestitution , arbiterFriction , arbiterSurfaceVelocity , arbiterUserData -- *** Collision Point(s) , arbiterCount , arbiterNormal , arbiterPointA , arbiterPointB , arbiterDepth -- *** Other , arbiterIsFirstContact , arbiterIsRemoval -- *** Bodies and shapes , arbiterShapes , arbiterBodies -- *** Running wildcard handlers -- | These functions invoke the wildcard handlers for a given collision. For custom collision handlers -- between specific types or overriding the default handler, you must decide how to invoke the wildcard handlers -- since it may be important to call the wildcards first, last, or possibly skip them entirely. -- For the begin and preSolve callbacks, you also need to decide what to do with their return values -- since they may not agree with each other or the specific handler they were called from. -- Every collision handler is defined for two types, the “A” variants of these functions call the wildcard handler -- for the first type, and the “B” variants call the handler for the second type. , arbiterCallWildcardBeginA , arbiterCallWildcardBeginB , arbiterCallWildcardPreSolveA , arbiterCallWildcardPreSolveB , arbiterCallWildcardPostSolveA , arbiterCallWildcardPostSolveB , arbiterCallWildcardSeparateA , arbiterCallWildcardSeparateB -- * Misc , DataPtr , Transform (..) -- * Re-exports , nullPtr , HasGetter (..) , HasSetter (..) ) where import Foreign import Data.StateVar import Chiphunk.Low.Types import Chiphunk.Low.Math import Chiphunk.Low.Helper import Chiphunk.Low.Vect import Chiphunk.Low.BB import Chiphunk.Low.Body import Chiphunk.Low.Shape import Chiphunk.Low.Space import Chiphunk.Low.Constraint import Chiphunk.Low.Callback import Chiphunk.Low.Arbiter