Critically Damped Springs
Saturday 11th of May 2013 10:36:59 AM

This class is one I turn to it again and again, especially when animating OSD components or creating camera controllers.

What it does is update an object's position and velocity towards a target destination over an arbitrary amount of time. The spring velocity will be damped over time meaning it slows down as it reaches its target.

To use it as a camera spring create one for the camera position and another for the target and update these values every frame, then call Update() passing the frame delta.

using Microsoft.Xna.Framework;

namespace Utils
{
    public class CriticallyDampedSpring
    {
        public CriticallyDampedSpring()
        {
            SmoothTime = 100.0f;
        }

        public float SmoothTime { get; set; }
        public Vector3 Current { get; set; }
        public Vector3 SpringVelocity { get; set; }
        public Vector3 Target
        {
            get { return mValTo; }
            set
            {
                mValFrom = Current;
                mValTo = value;
            }
        }

        public void Update(float frameTime)
        {
            Vector3 diff, temp;
            float omega, rX, expo;

            omega = 2.0f / SmoothTime;
            rX = omega * frameTime;
            expo = 1.0f /
                (1.0f + rX +
                (kQuadraticCoef * rX * rX) +
                (kCubicCoef * rX * rX * rX));

            diff = mValFrom - mValTo;
            temp = (SpringVelocity + (diff * omega)) * frameTime;
            SpringVelocity = (SpringVelocity - (temp * omega)) * expo;

            Current = mValTo + ((diff + temp) * expo);
        }

        // Start position of spring head
        private Vector3 mValFrom = Vector3.Zero;
        
        // Target position of spring head
        private Vector3 mValTo = Vector3.Zero;     

        private const float kQuadraticCoef = 0.48f;
        private const float kCubicCoef = 0.235f;

    }
}
    
The Devil Makes Work...
Saturday 30th of June 2012 11:22:48 AM

Boredom's a terrible thing but the website Dinosaur Comics is not. So when, in the midst of holiday boredom I stumbled across this comic I decided have a go at implementing it.

I don't often get to use PHP so I decided it'd be a good excercise for me to use the language. There's a few implementations of this online but mine's the only one I've seen which handles the "[goto panel two and play recursively] / [choose any ol' noun from the dictionary]" block.

You can see it in action here.

<?php
function RandomBool()
{
    return 0.01 * rand(0, 100) >= 0.5;
}

function RandomLine($filename)
{
    $lines = file($filename);
    return $lines[array_rand($lines)];
}

function GetPrefix($noun)
{
    $vowels = array("a", "e", "i", "o", "u");

    if(in_array(strtolower($noun[0]), $vowels))
    {
        return "an";
    }
    else
    {
        return "a";
    }
}

function RandomNoun()
{
    return trim(RandomLine("../protected/data/nouns.txt"));
}

function RandomFromArray($array)
{
    $key = array_rand($array);
    return $array[$key];
}

function CharacterType($index)
{
    $adjectives = array(
        array("meat", "robot", "urban", "silver", "animal",
            "sex", "fruit", "adult", "child", "famed",
            "licensed", "problem"),
        array("meaty", "famous", "infamous", "wide-eyed",
            "sullen", "attractive", "competing", "powerful",
            "space", "hairy", "social"));

    $nouns = array(
        array("stylist", "engineer", "astronaut", "ecologist",
            "planner", "model", "smith", "dancer", "producer",
            "lawyer", "loner", "priest", "criminal", "prodigy",
            "terrorist", "dinosaur", "clone", "athelete",
            "head of state"),
        array("teen", "doctor", "ghost", "artist", "surgeon",
            "corsetièr", "superhero", "cartoonist",
            "spouse", "dog", "religion",
            "medical health professional", "senior", "telepath",
            "jerk", "family"));

    $adj = RandomFromArray($adjectives[$index]);
    $noun = RandomFromArray($nouns[$index]);
    $prefix = GetPrefix($adj);

    return $prefix . " " . $adj . " " . $noun;
}

function BuildCharacter()
{
    $verbs = array("create", "destroy", "get over", "bewitch",
        "unmask", "sex up", "steal", "hug", "give birth to",
        "team up with", "profit from");

    $result = CharacterType(0);

    $result = $result . " who wants to " . RandomFromArray($verbs) .
        " " . CharacterType(1);
    $result = $result . " but is blocked in this desire by ";

    if (RandomBool())
    {
        $result = $result . BuildCharacter();
    }
    else
    {
        $noun = RandomNoun();
        $prefix = GetPrefix($noun);
        $result = $result . $prefix . " " . $noun . ".";
    }

    return $result;
}

echo BuildCharacter();
?>