Aidan’s Cooler in Contraption Maker – Implementation Details

Preliminary Note 1: Part one  of this subject can be found here: Aidan’s Cooler in Contraption Maker – The Backstory

Preliminary Note 2: So after trying, I find that embedding the code within this post just doesn’t work well. So you can find it all in one spot here. I’ll hook up the links in all the sections below as I write about each element.


aidansCooler

In this second post about Aidan’s Cooler I am going to briefly discuss and list the specifics about how I implemented it.

First you can find the code for the Aidan’s Cooler class here:

CMPartAidansCooler.h
CMPartAidansCooler.cpp

For Contraption Maker I wanted everything to be as data-driven as possible. So I created a CMPartManager class that would be responsible for making all the different parts in the game. My idea was that all the parts would be defined by JSON files which describe all the physical attributes of the part and then I’d have a base CMPart class that took care of all shared/general part methods. And then part specific code needed would be in part specific classes. In the end it almost worked that way.

This line is still in my CMPartManager.cpp file right before all the different sets of arrays that define all of the parts in the game:

// Hard coding here for now just to get 1st pass structure/data in place to work with
// -- will move into loadable JSON files

So unfortunately because of time constraints, something that sometimes happens during development, things never got moved into JSON files. It was a lower priority task. All the part definitions are data-driven, but from hard coded arrays instead of loadable JSON files. It may eventually happen, especially if I end up creating a part editor so that end users can create their own parts, but for now Aidan’s Cooler is defined by a few arrays. It’s not a hard thing to do, just takes time.

Here is the initial artwork that I received in order to create the cooler.

aidansCooler

Aidan’s Cooler Art

The Arrays

The group of arrays that completely define the cooler are here:

Code Excerpt #1

In each short section below I’ll briefly explain the details of each.

Preliminaries

Let me list out a couple of the macros before going over each separate element. These are used because I modified the physics engine we are using to used fixed point instead of floating point math and so I made a few macros to easily convert values between regular floating point and our integer system. You can read about the reason why used fixed point in this post: The Butterfly Effect

Code Excerpt #2

Polygon Vectors

First thing listed in Code Excerpt #1 above are the cpVect arrays. Each array contains the points of a polygon collision shape for the cooler. In the Chipmunk physics engine the polygons must be convex so for many parts multiple polygons are needed because their shape is irregular. The values in these arrays look ugly with lots of numbers and subtractions which were half the width/height of the artwork because I transferred each points value by hand from the artwork in Photoshop. I should have automated the process. Here is a sample of how I went about it from the Contraption Maker bear. Not a pretty process:

cmBearPolyVerts

Dynamic Bodies

Next up are the dynamic bodies which are just point masses. There is one body for the cooler body, another body for the cooler’s handle, and a third body for the wheel. Each of these bodies can move and rotate independently of each other. They are attached to each other by joint constraints that are described further down in this post. Here is the constructor for the dynamic body class:

Code Excerpt #3

Most of the variables are self explanatory.

  • id – Unique id for the body. Used by contraints, shapes, attachments, and artwork.
  • pos – Is just (surprise) the position of the body. It is usually just (0,0).
  • Mass – Mass of body
  • Density – Density of body
  • noGravity – Whether body is affected by gravity. Billiard balls aren’t effected by gravity. This is a carry over from what I did in The Incredible Machine where I was planning on making a billiard ball computer.
  • dampsRope – Whether this body will apply damping to attached ropes
  • shouldSave – Whether this body info should be saved in level files
  • next – Pointer to next body. All the different properties the describe a part are in null terminated linked lists.

The cooler has three bodies: the main container of the cooler, the handle, and the wheel. The main thing you see here is the offsets to the positions of the handle and wheel to the main cooler body and also the relative masses of the the three bodies.

Constraints

After the dynamic bodies are the constraints. There are joints that attached one body to another. You can check out this YouTube video which shows all the different Chipmunk constraints and joints in action. Here are the constructors for the rotary limit constraint:

Code Excerpt #4 – Rotary Limit Constraint

  • id – Unique id for the constraint
  • body1Id – First body that this joint connects
  • body2Id – Second body that this joint connects
  • minAngle – Minimum angle between these two bodies
  • maxAngle – Maximum angle between these two bodies
  • shouldSave – Whether this specific constraint info should be saved in the level file
  • next – Pointer to next constraint for this part

This rotary limit constraint is used to control how far the handle can rotate relative to the cooler body. The other two constraints are pivot joint constraints and they are used to connect the handle to the body and also the wheel to the body. Here is the constructor for the pivot joint constraint.

Code Excerpt #5 – Pivot Joint Constraint

  • id – Unique id
  • body1Id – First body that this joint connects
  • body2Id – Second body that this joint connects
  • pivot – Offset to location of where the two bodies are connected
  • shouldSave – Whether this specific constraint info should be saved in the level file
  • next – Pointer to next constraint for this part (null terminated linked list)\

If you look at the pivot joint arrays you’ll see that the body ids are set to hook the main body to the wheel and the main body to the handle.

Collision Shapes

The collision shapes for the cooler are made up of one circle and quite a few polygon shapes. As mentioned above polygons must be convex so many parts will need multiple polygons to correctly represent their irregular shapes. All of the collision shapes have Chipmunk group, type, and layers associated with them. Here is the code that has the defines for them:

Code Excerpt #6 – Defines for Collision Group, Type, and Layer

There a quite a few different shape properties that are defined. This code excerpt has the struct which has the three types of values define for each type of property and also a list of all the different types that Contraption Maker is currently using:

Code Excerpt #7 – Shapes’ Physics’ Properties

And there are also defines for different shape properties. This is so shapes can automatically play the correct sound effect when they hit different surfaces.

Code Excerpt #8 – Shapes’ Sound Properties

And here the constructor for the circle shape which is used by the cooler’s wheel:

Code Excerpt #9 – Circle Collision Shape

  • id – Unique id
  • pos – Offset to the position of the center of the circle
  • bodyId – The body that this collision shape is attached to
  • shapeProperty – Description of the friction and elasticity of the shape
  • shapeSfxProperty – Sound that this shape makes when hitting something
  • radius – The radius of the circle
  • group – The Chipmunk collision group this shape is in
  • collisionType – What type of collision callbacks this shape uses
  • layer – Which Chipmunk collision layers that this shape is in
  • shouldSave – Whether this specific collision shape should be saved in the level file
  • next – Pointer to next collision shape in a linked list

And this is the constructor for polygon collision shapes:

Code Excerpt #10 – Polygon Collision Shape

  • id – Unique id
  • pos – Offset to the position of the polygon
  • bodyId – The body that this collision shape is attached to
  • shapeProperty – Description of the friction and elasticity of the shape
  • shapeSfxProperty – Sound that this shape makes when colliding with something
  • verts – Pointer to an array of the vertices of the polygon
  • numVerts – Number of verts in the polygon
  • group – The Chipmunk collision group this shape is in
  • collisionType – What type of collision callbacks this shape uses
  • layer – Which Chipmunk collision layers this shape is in
  • shouldSave – Whether this specific collision shape should be saved in the level file
  • next – Pointer to next collision shape in a linked list

There are quite a few polygons for the cooler because there need to be separate shapes for the sides and the bottom on the cooler.

Rope Attachments

The cooler is set up so that a rope can be attached to the handle. This is handled in Contraption Maker by adding a rope attachment to a part. Any part can have any number of rope attachments. They just need to be part of the linked list of attachments in the part definition array. This is the rope attachment constructor:

Code Excerpt #11

  • id – Unique id
  • pos – Offset of the position of the rope attachment to the body it is attached to
  • bodyLinkId – The id of the body that this rope attachment is connected to
  • shouldSave – Whether this attachment should be saved in the level file
  • next – Point to the next attachment in a linked list

Nothing fancy with the rope attachment. Its location is just at the end of the handle and it is on the handle body.

Artwork

The final element describing the cooler is the only element that is actually seen on screen – the artwork. Everything else goes on behind the scenes. Each sprite is connected to a body and then tracks its position and/or rotation. There are few special cases where the artwork is connected to an attachment (like a rope attachment) instead of a body. Here is the rope attachment constructor:

Code Excerpt #12

  • id – Unique id
  • layer – Which layer it is draw on. Controls which sprites are drawn in front or behind each other
  • posLinkId – The id of the body whose position this sprite will track. -1 means don’t track any body’s position.
  • rotLinkId – The id of the body whose rotation this sprite will track. -1 means don’t track any body’s rotation.
  • spriteName – The sprite’s file name
  • width – Sprite’s display width
  • height – Sprite’s display height
  • partAttachmentId – Only used for special cases where we want this sprite to track an attachments location (like a rope attachment where the sprite would be the knot)
  • pos – Offset to the sprite’s location relative to the body
  • useFrameCache – Set to true if the sprite is inside of a sprite sheet
  • usedForBb – Set to true if this sprite should adjust size of part’s bounding box – use by the gui
  • shouldSave – Whether the info about this sprite should be saved in a level file
  • shouldPostProcess – Set to true if this sprite needs to be processed after physics have run. Used for cpu efficiency purposes so we can ignore lots of sprites each frame and only spend cpu time on those that need it.
  • opacity – Ranges from 0 to 255.  Used to control sprite’s transparency.
  • next – Pointer to next sprite in a linked list.]

If you take a look at the CMPartAidansCooler.cpp code, you should be able to figure out why the artwork for the word “Aidan” is reversed on one of the sprites.

Chipmunk Calls

Each of these constructors then use the definitions from the arrays to make calls to various Chipmunk routines to build up all the elements that make up the part. In the code excerpt below I’ve just put all those various calls in one place.

Code Excerpt #13

Final Wrap up

That is pretty much it. Here is a quick diagram of the various elements that make up Aidan’s Cooler.

coolerOverview

 

This post ended up being quite a bit longer that I thought it would be. Hope it is at least halfway helpful to someone.

Leave a Reply