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!

 

 


Hall of Fame

By Kevin Ryan

Posted on March 18th, 2016

The other day I was rummaging through some old files on my hard drive and found some old scans from back around 2006.

At the end 1991 I left Dynamix (The Rise of a Dragon in Eugene Oregon) after being with the company from the very start as one of the four original owner-partners. Three weeks later Jeff Tunnell convinced me to come back and work at home on whatever I wanted. We talked about possible projects and then I went to the University of Oregon library and checked out some Rube Goldberg works and thought about design and how I could make Rube Goldberg  type contraptions work on computers. I spent a couple of months of thinking and writing a design document for the game.

tim1

 

Once that was done, I set up a work desk in our cold basement on West Broadway Street in Eugene, Oregon, started working on The Incredible Machine. I would walk to the office about once a week to show everyone what I was coming up with.It was real nice to open my copy of Computer Gaming World about a decade and a half later (in 2006) and see this:

hofTim


All Those Years Ago

By Kevin Ryan

Posted on March 13th, 2016

I worked on Zoo Master during my senior year the University of Oregon in 1983. It was written for the 48k Apple II Plus in 6502 machine language. The Apple II was 1 Mhz so you would want to do coding tricks like unroll your loops for speed. Most of the instructions took between 2 and 4 cycles.

I think I remember the resolution being 280×192. The Apple II also had a interesting way of specifying pixel colors. If two neighboring bits were set then the color would be white otherwise the color would be either red, green, blue, or purple depending upon if the pixel was on a even or odd screen pixel location and also whether the 8th bit was set or not. Three zero bits in a row would give you at least one black pixel.

zooMasterFront
www.topmeadow.com/plans/white720x4.jpg
At the time I did not have an assembler so I wrote it by typing in all the instructions in HEX code into the Apple. The branch instructions in 6502 were relative to the current instruction memory location. So if I wanted to branch forward to an instruction 10 bytes ahead I’d use $0A and for branching backwards I’d use a negative number like $F4. For forward branches I had to estimate how many bytes my code would need to jump over and then go back and fix the branch instruction if I got it wrong.

Since I wasn’t using an assembler everything ended up being hard coded to fixed memory locations on the Apple. The upshot of this was that I had to write bug-free code because they would be a pain to fix. I actually did have a couple bugs where I ended up I having to JMP to a free memory area do what I needed to do and then JMP back using some NOPs to clean up in the patch area. Went against my structured code college stuff, but what else could I do. I think there was an assembler available for the Apple back then, but it was beyond my college days budget.

Funny how I can still remember what hex values correspond with which 6502 instructions – for example:

$20 – JSR — jump subroutine

$4C – JMP  — jump

$60 – RTS — return subroutine

You had three 8 bit registers available to do computation with, but only the A register could be used for addition or subtraction. You could only increment (INX,INY) or decrement (DEX,DEY) the X and Y registers. There was an add with carry (ADC) instruction so you could do 16-bit computations easier.

I wrote this game for the technical fun of it. It was published by Earthware Computer Services, but never really sold. I actually played it online a few months ago somewhere online.

After Zoo Master came out I made my home town paper which made Mom and Dad proud.

zooMasterFresnoBee


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!