The Incredible Machine and a Billiard Ball Computer

By Kevin Ryan

Posted on August 9th, 2016

The Incredible Machine (TIM) is a computer game released in 1992 that is driven by custom physics and is very similar to Rube Goldberg and Heath Robinson machines. There were a few games in the series and it got a surprisingly large and loyal following. We won an “Honored Developer” award at the 1993 Game Developers Conference for it which I think was the first year that they gave out any sort of awards. I think I still have it somewhere – it was a pin or something like that. Later on TIM was inducted into Computer Gaming World’s Hall of Fame which was a very pleasant surprise.

TimTitle

Oh this looks neat!

In the summer of 1992 when I was partway through implementing the original group of parts in The Incredible Machine, I read about Edward Fredkin and Tommaso Toffoli’s Billiard Ball Computer. Roger Penrose also discussed it in his book The Emperor’s New Mind which I was reading at the time. Along with a technical description it had a nifty graphic showing a billiard ball model for an AND gate similar to the one pictured below.

bbc

Modeling an AND gate with Billiard Balls

Wow, that would be cool to implement! I realized that I already had the basic physics and collision frameworks in place and I could implement the needed parts in TIM without too much effort. Walls, incline, and balls were already working. Finding enough free time before shipping would be the constraint on whether I could get it done in time by the ship date or not. TIM had a very tight development schedule.

Coding The Incredible Machine

Coding on TIM started on March 26, 1992. I know that exact date from the title page of my design. On the day that I finished the design, I wrote the date on the title page, printed it out, went “whew, finally” and then immediately started coding in the unheated and unfinished basement of my home in Eugene. Note: this was not my parents’ basement – I was married and had three young kids at the time. Once I week I’d walk over to Jeff Tunnell’s office with the latest build on a floppy disk and show the build to everyone.

The Incredible Machine Design

Title page of the original design.

Collision System

The first order of business when I started coding was getting a collision system in place. No Google, no big Internet search space, so I ended up writing the collision code from scratch. I decided to go with polygon borders for all the parts. Everything had to be integers because at the time the speed of floating point operations on CPUs was slow.

The conversion factor for the 16-bit integers was: 1,024 in the physics space was equal to 1 in the screen space. A shift of 10 bits left or right would convert between the two coordinate systems. The 360 degrees of a circle were covered by 16-bits and went from 0 (0 degrees) to 65536 (360 degrees). In hex it came out as: 0x0000 flat facing up, 0x4000 vertical on left, 0x08000 flat facing down, and 0xc0000 vertical facing left.

All the parts collision shapes were defined by polygons which could be either concave or convex. The collision checks were line segment to line segment – projecting each point of the polygon to where the new position would be based upon the velocity, creating a line segment, and checking for collisions with other polygons. If a collision was found, then the projected line would be adjusted to the point of first collision.

As an aside, there are now terms for most all of this stuff which in many cases didn’t exist at the time. Lots of ad-hoc development here – making it up as I went along. So the segment-to-segment check would be what is now called swept collisions. There was also a broad-phase collision check. The way collisions were implemented allowed me to do a bit check on the high bit and reject roughly half the checks – less calculations – important because frame rate was a big concern. The fastest code is the code that isn’t executed.

The collision polygons for the Balloon and Birdcage became my debug test cases. I created graph paper version that exactly matched how they were represented in the game data. I would move the paper cutouts around by hand in various collision scenarios to verify that the code was working correctly. The hex values in the balloon and birdcage photos are the slopes of the line.

balloonAndBirdcage

Balloon and Birdcage. Testing models and how they appeared in game.

Physics Code

Written in parallel with the collision code was the physics code to apply forces to resolve collisions. Every part was a point mass with some parts being static and some dynamic. Each part had a density, mass, elasticity, friction, terminal velocity, and various other parameters. Sir Isaac Newton wrote the physics code for me roughly 300 years before TIM. I just had to put it in modern C code and make it fast and use only integers.

The structure for how the basic properties of the parts were defined is listed below. (Ugh, I don’t like the code style I used back then). Those last elements in the struct are function pointers. They pointed to general routines for the parts and I would override them with pointers to specific functions for parts that needed them. TIM was written in C and this is similar to overridable methods in C++ although I wasn’t familiar with C++ at the time.

struct part_elements
{
   short          density;
   short          mass;
   short          elasticity;
   short          friction;
   short          acel;
   short          terminal_velocity;
   TIM_VEC        max_size;
   TIM_VEC        min_size;
   struct shape   **part_shapes;
   SSHAPE         **super_shapes;
   TIM_SCVEC      *shp_offset;
   TIM_VEC        *shape_size;
   unsigned char  plane_num[2];
   short          num_borders;
   short          part_bin_order;
   VOID_BPARTFPTR bounce_func;
   VOID_PARTFPTR  internal_func;
   VOID_PARTFPTR  reinit_func;
   VOID_FPARTFPTR flip_func;
   VOID_PARTFPTR  resize_func;
   VOID_RPARTFPTR rope_func;
};

 

So Where is the Billiard Ball Gate in TIM

Short answer: It’s not there. I ran out of time.

Slightly longer answer: I really wanted to make an adder just like the picture below instead of just making an AND gate. Defining the elasticity and borders needed for the billiard balls would have been very quick and easy, but getting all the parts lined up correctly even for just the simpler AND gate would have been more time consuming than defining the needed parts.

adderCircuit

Diagram of an adder circuit.

Game Dev Weight Loss Program

As best as I can remember, we shipped the first version of The Incredible Machine in mid-November of 1992. I remember that at the time getting to gold by mid-September was important for the Christmas season. Big orders by the distributors and stores were being made in September and then they’d duplicate a whole bunch of floppies and print up all the boxes. There was a lead time for all this so we would usually be shooting for mid-September to have a gold disk ready for shipment. It was a very bad thing to have bugs in the shipping floppy disk version because there was no simple way to get out an update.

So the summer of 1992 was a mix of implementing all the parts, tweaking the collision and physics code, and creating all the puzzles that would ship with the game. Creating new puzzles started becoming harder and harder. I was very busy and over that summer my weight dropped from 155 to a little below 140. It was fun! Really! I wouldn’t still be doing games for all these years if it wasn’t fun. But it was tiring too. Near the end of TIM development I started referring to it as a 6 month sprint.

TimPuzzles

Some of the puzzles from TIM. I would go through them all and reorder how they showed up in game to gradually increase difficulty for the end users.

I just played the first version of TIM for the first time in a long time – a very long time. I had to buy it from the Good Old Games website because I don’t have a running copy here. I see that Billiard Balls aren’t even in the first version, but they did make it into the “Even More’” version where more parts and puzzles were added. And they aren’t affected by gravity and are perfectly elastic so they had the correct physics attributes to implement the AND gate. But they would have still needed work to give each of them the exact same initial velocity when entering the gate and then there would have been lots of tweaking of position to get them working correctly.

Over the last year few of years I’ve been working on Contraption Maker with Spotkin. It is published on Steam and we continue to make updates for it. There is a different publishing paradigm in place. Now it is easy to do updates seamlessly to the end user. A Billiard Ball Computer is on my to-do list for Contraption Maker although the physics system being used would make it just a little harder because it doesn’t use swept collisions. Maybe someday in an update I’ll get it in there.

More Reading:

Conservative Logic a paper by Edward Fredkin and Tommaso Toffoli.


Aidan’s Cooler in Contraption Maker – Implementation Details

By Kevin Ryan

Posted on April 22nd, 2016

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.


Aidan’s Cooler in Contraption Maker – The Backstory

By Kevin Ryan

Posted on March 28th, 2016

Part two is now posted here: Aidan’s Cooler in Contraption Maker – Implementation Details

This is Aidan’s story and an explanation of how and why the cooler is one of the parts in Contraption Maker. It is the story of a brave cheerful boy and my friends from work that did something nice for him.

Sometime soon I am going to write another post that describes in some technical detail how I went about implementing Aidan’s Cooler in Contraption Make. When I do I’ll add a link to it right here at the top of this post.

aidansCooler

 

Aidan

Aidan is my son and he was born in the first half of June 1999. He was underweight and obviously sick so he stayed in our local hospital for a few weeks while they tried to figure out what was wrong. When he was four weeks old his heart stopped for a few minutes before the doctors got it going again. He was then transferred by ambulance to UCSF (University of California, San Francisco – a research hospital) and soon after was diagnosed with Neonatal Hemochromatosis which is a liver disease that is almost always fatal (“The prognosis is extremely poor. Some infants recover with supportive care, but this rarely occurs.”). In addition to that he also had acute respiratory distress syndrome.

The doctors did not expect him to survive, but they worked heroically over many months to save him and get him to the point where he could receive a liver transplant. He had the liver transplant when he was four months old and spent most of his first year in the PICU (Pediatric Intensive Care Unit) and the NICU (Neonatal Intensive Care Unit) at UCSF with various complications – very bad and scary complications. There were a handful of times where I thought he was dying in front of my wife and me.

aidanHome3weeksOld

Aidan at 3 weeks old with his Mom.

 

a8

Aidan a few days post transplant.

 

Post Transplant

Post transplant he had numerous problems including collapsed lungs, heart problems, kidney problems, possible fungal infection in the brain, a bleed in the brain that affected his left side, acquired hydrocephalus, deaf in left ear, and more. There were occasional crises.  He wasn’t able to eat by mouth and so he had surgery to have a permanent g-tube placed. He was also on supplemental oxygen because his lungs had been damaged. He spent much of the next five years in and out of the hospital. His last major surgery was in January of 2004 where he had brain surgery (Endoscopic third ventriculostomy) which cured his hydrocephalus and allowed them to remove his shunt which was draining fluid from his brain.

We were very happy that that surgery succeeded because the fluid that was being drained by the shunt was not being absorbed in his abdomen because he had so much scar tissue there from his many surgeries. In a hospital stay previous to the brain surgery they had drained 5 lbs of fluid from his abdomen. His weight dropped from 32 to 27 lbs. This was when he was four years old.

I want to break from Aidan’s story here for a couple of paragraphs to write a short bit about his nurses. I stayed with Aidan for many weeks in the PICU, sleeping in a chair next to his bed and over the course of all those times I saw many very sick kids there. Sometimes they don’t make it. You can tell because they draw all the curtains on the room – all the walls in the PICU rooms are glass – you can see into every room. It is a tough place to be.

There are certain jobs where you are exposed to human misery and there are people that do those jobs – like the PICU nurses that became our friends. Big kudos and love to them for being a balm in such a hard place.

As he stabilized Aidan had less and less extended hospital stays and got to spend more and more time at home. When he was home he needed some supplemental oxygen. We a had big machine that would concentrate oxygen out of the air and Aidan was hooked up to it all the time with a very long tube so he could wander around the house. If we wanted to find Aidan all we had to do was follow the follow the clear plastic tube.

aidanOxygenTube

Aidan in my home office with his long oxygen tube.

 

The Highway Patrolman

We lived up in the Sierra Nevada Mountains at 5,500 feet (and still do) so when we were down at sea level he didn’t need the extra oxygen. One day when he was three we were driving back from San Francisco from a visit with his liver doctors at UCSF when we were pulled over by the highway patrol near Gilroy. We hadn’t yet put on the license plate sticker for the next year – it was in the glove compartment – showed it to patrolman – all fine. Aidan was sitting in his car seat with an oxygen tank next to him – not hooked up because he didn’t need it until we got back up to altitude at Shaver Lake. The conversation with the highway patrolman went like this:

Patrolman:  Is that hooked up?
Me:  No he doesn’t need it.
Patrolman:  It really should be hooked up.
Me:  He doesn’t need it at sea level.
Patrolman:  Uh, you really should hook it up now.
Me:  We just came from the doctors and he doesn’t need it here – only up in the mountains.
Patrolman:  (with a sudden big grin) I’m talking about the car seat.
Me:  Oh! Yeah, that’s hooked up!

I’m sure we made that patrolman’s day.

 

Wilderness Hikes

Aidan is a true innocent. He will be 17 years old this June, but mentally he is probably around 6 or so. He has been through many painful procedures throughout his life. He has to have blood draws every 6 weeks to make sure that he is not rejecting his liver. Sometimes during hospital stays it has taken one and half hours to start an iv with numerous “pokes”. That is because he has been stuck with needles so many times that his veins aren’t in great shape. His body is a battlefield covered everywhere with surgical scars. And yet throughout it all he has remained brave and cheerful. He has an indomitable spirit and courage. He finds joy in simple things. He loves and is loved. He is my hero.

At home I’d carry him on my back so he could go on mountain hikes and do everything that the rest of the family does. Hikes through the wilderness are wondrous. There is magic around every bend if you just look for it. As the years went past he just got too big for me to keep carrying. The older Aidan could walk for a while, but eventually he gets very tired so then I carry him. On the hike in the two bottom photos below, I carried him for a few miles and it was really tiring. He was getting bigger and I was getting older. By the end of the hike, my arms were tired, my legs were tired, my brain was tired, and Aidan was very happy. I wanted a Black Butte Porter.

aidanHike

Aidan on a hike with me in the Sierra Nevada mountains at Balsam Meadows Forebay.

 

carryingAidan2

Carrying Aidan on hike.

 

carryingAidan1

Carrying Aidan walking past big Southern California Edison water pipe. Just past this area it does a 2,131 foot drop to the Big Creek Power Plant.

 

Walking

He wasn’t able to walk at all in his first couple of years because his left side doesn’t work too well because of the stroke. He could stand, but to move around he’d scoot on his rear. Then one day when he was two he started using a toy as a walker to get around the house. He could really zip around with that thing – I mean run fast! One time he took a corner too fast and went down with the walker on top of himself. Didn’t faze him – he was up and off again right away. It was good he figured out how to get around his “can’t walk” problem because once he became more mobile then he could more easily play with his brothers and sister.

aidanWalkerToy

Aidan zipping around the house.

 

aidanPlaying

Playing a “flashlight-in-the-dark” game with brothers and sister.

 

Pikachu

When he was an infant he became very attracted to Pikachu. I spent many, many, many, many hours and days and weeks and months and eternities watching Pokemon with him at the hospital. One day when he was two or three he was with me at a Goodwill store and there was a big stuffed Pika in the discount bin. He shouted, “Pika!!” My wife heard him from across the store. That Pika goes everywhere with him. It has gone into many surgeries with him. Even today he uses it as a pillow and it travels with us whenever we go anywhere.

pika3

Aidan with Pikachu at hospital.

 

pika2

Aidan resting with big Pika and little Pika at home. You can see his oxygen tube going of the lower left of the photo.

 

Steve McQueen

We will occasionally stay at the Glen Tavern Inn which is in Santa Paula. It has quite of history of old Hollywood stars staying there – Houdini, John Wayne, Rin Tin Tin, etc. In 1979 Steve McQueen lived in a hanger at the Santa Paula airport just a couple of blocks from the Glen Tavern Inn. So of course, since Steve was a patron, one of the drinks that they have at the bar there now is “The Steve McQueen”. It consists of:

-Coke
-Jack Daniels
-Bacardi 151 Rum
-Jagermeister

Aidan has gotten into the habit of finding ways to help around the house. A few years ago he started taking the trash out to the street for the garbage truck. He does lots of small tasks like this. So a couple of years ago out of the blue he decided to help mix drinks for me. “Want me to make you a Steve McQueen?” So I said sure. Now Aidan likes coke and so I had been letting him have any of the left over coke. So apparently he figured out that if he puts in more alcohol there is more left over coke for himself.

One day I filmed him making me a drink. That drink started to look very dangerous, I wanted to say hold it, but I kept my mouth shut as I watched with an impending sense of doom. I think it is the Bacardi 151 Rum that is the killer. Anyway I tried to finish that drink, sipping slowly, while watching a movie with the kids, but couldn’t. It crept up on me and eventually hit me pretty hard and I had to go lie down on the bathroom floor. The last time I felt like that was my freshman year at the University of Oregon in the Bean East dorm.

Here is the video of Aidan the bartender:

 

My Name is Aidan

Back in 2007 we visited Ireland for a couple of weeks. One night we went to Knappogue Castle for a medieval feast which was lots of fun with food and singing. Aidan really enjoyed it. When we got back to the Old Ground Hotel in Ennis where we were staying my brother gave me a poem he had written.

aidanPoem

“My Name is Aidan” – Mike Ryan, Knappogue Castle 2007, Ireland

 

Coolers

Aidan will get interested in many different strange things and for some reason he started to like coolers. I’m not sure exactly why or what triggered it in his head, but he slowly acquired a small group of different size coolers. One day after watching Toy Story 3, I found that he had set up the coolers around a “See ‘n Say” toy, mimicking that scene from the movie. To this day he will still set up the coolers different places around the house having them do different tasks.

coolersBeerCapChips

Aidan’s Coolers gambling.

 

coolersToyStory

The Coolers gambling Toy Story 3 style.

 

Dynamix to Spotkin

In 1984, a year after graduating from the University of Oregon, I was living in an apartment just off campus when I got a phone call from Damon Slye. He and Jeff Tunnell had just started up Dynamix and they wanted me to do some work for them. Not long after that they asked me to come on board as one of the original four owners of the company. Our first product was with Electronic Arts (Arctic Fox) and over the years our company grew to around 200 people. We went through a lot of ups and downs over the next 16 years. Bought out by Sierra which was good. Merged with CUC International which was very bad. Here is a New York Times article about CUC and the biggest accounting fraud ever: Asleep at the Books: A Fraud That Went On and On and On

During the years when I was spending a large part of my time in the hospital with Aidan, Jeff started up Garage Games with some former Dynamix employees. I published a few games with them before it was bought out by Barry Diller’s company (IAC) in 2007. Then he started up Pushbutton Labs which was bought out by Disney in 2012. I actually worked with Disney for a year or so before I moved on to work with Jeff again on his new venture, Spotkin. That was when I started work on Contraption Maker which is in many ways an updated version of The Incredible Machine.

So over the course of development of Contraption Maker, I implemented a whole boatload of different parts. At one point in the development I was implementing some container type parts in the game like boxes, baskets, and such. Around this time I was on one of my Eugene visits and I tell the Spotkin guys (Jeff, Jon, Keith, Tim) about how Aidan likes coolers. A few days later I get the artwork from them so that I can add cooler part to the game. They even put Aidan’s name on the cooler. It is a good thing to have work colleagues who are also your friends. In Jeff’s case a friend for over 30 years now.

aidansCooler

Source Artwork for Cooler.

Cool! I implemented it in the game and then brought Aidan into my office to see. You should have seen his face light up with a huge smile the first time he saw it.


A longer version of Aidan’s early years is here: Aidan Ryan – Liver Transplant Story

It may take me a while because I’ll need to find some free time, but as I wrote above, I’m going to write another blog post that gives a technical description of how I took the artwork above and turned it into a cooler that acts with correct physics.

For now I am going to end this post with a more recent photo of Aidan and a video from his Make-a-Wish trip where he figured out he could make his shoe squeak.

happyAidan

Happy Aidan. Go Ducks!

 

 


Ropes in Contraption Maker

By Kevin Ryan

Posted on March 11th, 2016

Contraption Maker (CM) is a sandbox physics game that I developed along with Spotkin. It was built using a modified version of the Loom Engine, along with a few different libraries/components including cocos2dx and Chipmunk. After going through Steam’s early access program, the full game was released on Steam in the summer of 2014.

Getting realistic ropes working required tackling several different problems. It was mostly traveling development paths that others have already blazed and then making whatever adjustments were needed for my specific needs. This is just a quick overview of how I went about implementing them in CM and some of the potholes I hit along the way.

The Basics

The first decision made was exactly how much of a rope’s behavior I was going to model. Deciding exactly what elements or rope behavior to implement involved trade-offs affecting both performance and also design. For example, in their final incarnation, the ropes don’t collide with anything. So their only game play function is to transfer forces between the parts attached to either end. This was both a game design and a performance (speed of execution) decision. The performance was better because the code didn’t have to calculate all the collision and physics needed for the whole length of the rope cutting down drastically on the calculations needed.

This is fairly typical in the craft of game design and development in that you are always making various trade-offs. The relative sizes of the little guy, the dog, the mouse, and the soccer ball are game design decisions that bent reality for better game play possibilities.

Contraption Maker Characters

Contraption Maker Characters and Soccer Ball

I didn’t use the built-in ropes in the Chipmunk physics engine. The Chipmunk engine doesn’t have built-in ropes – easy decision. It does have a whole bunch of different types of constraints though, so my first thought was to use those to implement ropes. So browsing through the available constraints, using a slide joint for the two ends of the rope seems obvious. Maybe use the spring joint for all the points between the rope endpoints?

Speed of execution was a big concern. People playing CM are going to be able to create huge contraptions which could include ones with very many long ropes. Okay, first thoughts, rather than use Chipmunk’s general spring constraint, I’ll write a tighter custom spring-like routine specifically for our ropes with a focus on minimizing calculations needed and still simulate a rope in a way that looks and behaves realistically. I sketched out this fairly simple idea before writing any code.

Rope Design First Pass

Rope Design Ideas – First Pass

Constraining the Rope Ends

The slide joint constraint keeps two point-mass Chipmunk bodies within a specified range of each other. It is given the two bodies to constrain along with a minimum and maximum distance that the bodies should be from each other. Therefore each end of a rope is attached to a body – either to a body of a CM part or, in the case of an unattached rope end, to a physics body at end of the rope.

The slide joint is perfect for handling the behavior of the two endpoints of a rope. For ropes in CM the minimum distance is always set to zero and the maximum distance is the length of the rope. In the simple setup pictured below, a slide joint constraint is attached to the center of the static body of the hook and also attached to an offset of the center of dynamic body of the block.

Okay, great, first bit done, easiest code to write is code that someone else has already written. Now it’s time to take care of simulating the rope between the two endpoints – how it moves when it is slack. Note below that you can see how the rope passes right through the brick wall. As mentioned above, the ropes don’t collide with any other parts or with itself. My only concern with the internal rope movement was that it appear rope-like; it didn’t affect physics outside of itself. To do that I needed to break the rope into individual segments and then make move in a rope-like way. You can see each of the individual segments as purple dots in the picture below.

Purple dots for each segment

Purple dots for each segment

 

To make the display look like an actual rope it is then just a matter of replacing the purple dot artwork with rope segment artwork. The art is rotated to seamlessly join the individual segments. Here is the same setup with the purple dots replaced with rope segment art:

Artwork for rope segments

Artwork for rope segments

 

Details of Internal Rope Physics

Once I sat down and thought for a a while, I decided to go with verlet integration to take care of all the internal segments of the rope. It solves the problem very nicely and the code is very fast to execute. The process is:

  1. Use each segment’s current and previous location to determine velocity
  2. Add this velocity to current segment location to get new location
  3. Add in gravity (steps 1-3 are in first code excerpt below)
  4. Run multiple passes per time-step working towards getting neighboring rope segments a fixed distance apart. This is an iterative process where the more iterations the better the solution. A trade off between execution speed and robustness of solution. CM used seven iterations per time-step. (this is done in the second code segment below)

These four steps are explained and illustrated very well here: (http://blog.2and2.com.au/?p=883).

This is the code that applies velocity and gravity to each rope segment once per time-step.

IMPORTANT CODE NOTE: For reasons I mentioned in The Butterfly Effect, all the physics calculations are done using integers instead of floats so the code listed above is using int(s) instead of floats. There is some bit-shifting going on to keep the numbers within my fixed point number system where 65536 is equal to 1. The code is very simple:

 for (int i=0;i<=lastIndex;i++)
 {
    // Gravity (assuming only in y axis)
    CMRopeSegment *seg = static_cast<CMRopeSegment*>(mSegments->objectAtIndex(i));
    seg->mY -= gravityY;

    // Verlet
    int temp = seg->mX;
    seg->mX += (seg->mX - seg->mOldX);
    seg->mOldX = temp;
    temp = seg->mY;
    seg->mY += (seg->mY - seg->mOldY);
    seg->mOldY = temp;
 }

 

And here is the code that makes multiple passes per time-step through all of the rope segments:

// Run a few iterations to process all the links (defaults to 7 steps)
 for (int step=0;step<mIntegrationSteps;step++)
 {
    CMRopeSegment *prevSeg = static_cast<CMRopeSegment*>(mSegments->objectAtIndex(0));
    for (int i=1;i<mNumSegments;i++)
    {
       CMRopeSegment *seg = static_cast<CMRopeSegment*>(mSegments->objectAtIndex(i));
       int dx = seg->mX - prevSeg->mX;
       int dy = seg->mY - prevSeg->mY;
       int dist = tmSqrtShiftedInt32(dx * (tmInt64)dx + dy * (tmInt64)dy);

      // Keep in a sane range to prevent divide by zero from happening
      if (dist < 128)
         dist = 128;

      seg->mLength = dist;
      int delta = seg-mAdjustedLength - dist;
      tmInt64 percent = (delta * FLOAT_TO_INT64(0.7f)) / dist;
      int offsetX = (int)INT64_SHIFT_DOWN(dx * percent);
      int offsetY = (int)INT64_SHIFT_DOWN(dy * percent);
      if (i == 1 && firstIndex != 0)
      {
         seg->mX += offsetX;
         seg->mY += offsetY;
      }
      else if (i != 1 || firstIndex == 0)
      {
         prevSeg->mX -= offsetX;
         prevSeg->mY -= offsetY;
      }
      else if (i != (mNumSegments-1) || lastIndex == (mNumSegments-1))
      {
         seg->mX += offsetX;
         seg->mY += offsetY;
      }
      prevSeg = seg;
   }
}

Before the verlet integration is run, the slide joint constraint first adjusts the locations of the bodies on either end of the rope. The first and last rope segments are then set to the locations taken from where the slide joint has computed the bodies’ locations. These first and last segments are not changed by the verlet integration, only all the segments between these two are changed. The verlet code above is run adjusting all the positions of the interior rope segments and giving us nice rope-like movement, but they transfer no force to the bodies on each end of the rope.

Verlets give “springy” results which can be minimized by increasing the number of iterations run per time-step. Contraption Maker uses 7 iterations per time-step. You can see the difference below using two different iterations. Not really obvious here, but enough of a problem to be noticeable in the game is integration steps are too small.

 

intergationDif

Two integration steps takes longer to come to rest than the 21 step version. This is an example of “springy” verlet method.

Pulleys

The physics of direct rope attachments between two parts is now done. Next up was adding pulleys. There is no pulley support in Chipmunk, but I did find some code written for Chipmunk by Robert Blackwood that was based upon Box2d’s pulleys. I took that, modified it to work well with our system and eventually had pulleys working, albeit with some problems I’ll mention below. All the physics happens on the two rope segments hanging off of the first and last pulleys. All the parts of a rope that is between two pulleys is treated as a straight line with no physics processed for them. Any slack in the rope will only occur on the parts of the rope off either end of the pulleys.

The pulleys almost completely worked, but there was a problem that became very obvious when the bodies on each end of the rope have very disparate masses. This is a typical problem in physics engines where if you have two bodies where the ratio between the two masses is very great the physics can break down. And I mean break down in a very spectacular ways like this:

 

The Disparate Mass Problem

Problem with Disparate Mass

That is a fairly obvious problem, but there were also problems when the differences in masses were not as great – not as visible as above but still there. The system could get in a state where the forces acting on the bodies were oscillating back and forth causing jitters or slow rope stretching on one end of the pulley system. Problems like this are very hard to track down and fix because there is so much math calculations going on with different forces being applied at different places. Here is an example of the the log output that I would use to track down physics problems:

debugging

 

Using the balloon/wrecking ball as a good test case and tracking through what was happening with impulses and cached impulses, it looked like energy was not being lost when the balloon hit the pulley – ah, guess what – it was because the balloon wasn’t hitting the pulley – no collision shapes on the pulley. Problem identified – next step problem solution.

In Contraption Maker the pulleys did not collide with anything because this allowed them to be placed so they could overlap with walls and other parts. But this did not correctly resolve the situation like that pictured above where the length of the rope on one end of the pulleys goes to zero. To solve this I added a special collision shape at the point where the rope attaches to the pulley. This ad hoc collision shape on the pulley would then only collide with another ad hoc collision shape at the location where the rope was attached to a part.

Now the part collides with the pulley and the physics system can apply the correct forces on the bodies. Here’s the same pulleys system as above but now the balloon correctly collides with pulley. You can see how the balloon bounces off the pulley. Success. All is well in the CM world.

Disparate Mass Problem Solved!

Disparate Mass Problem Fixed!