Did work on various bits and pieces of the game this week. A rough overview:

  • Added the first piece of level geometry that deals damage on contact (spikes)
  • Overhauled my ComputeStandingY algorithm so that it takes an order of magnitude less time to run
  • Implemented a new animation for surface mantling that includes camera control
  • Moved jumping, ledge clinging and mantling from using tasks to using a combination of animation triggers and simple state machine logic

So, I guess I’ll give each bullet point a little detail.


Adding spikes was fairly straightforward. The largest challenges were getting the collision detection and rendering to work correctly. All the geometry I’ve added to levels before now has simple collision detection, in that the geometry remains relatively static and obstructs the player’s movement. Spikes, however, needed to allow the player to move through them but still detect collisions so that they could deal damage. Getting this to work meant some changes to my collision detection code, in order to correctly handle cases where a piece of geometry had no collision, and also meant that I had to add support for changing a piece of geometry’s collision on the fly – that way I could leave the spike with no collision by default, but assign it collision temporarily during each update so that I can perform a collision check to find the entities it’s touching.

            _CollisionList = _DrawList;
            this.FindObstructions(this.InflictDamage);
            _CollisionList = Game.NullCollisionList;

Rendering the spikes was a bit of a challenge as well – since they’re arbitrarily sized and can point in different directions, I had to do some work to figure out how to take an arbitrary texture and use SpriteBatch to align it with the spike’s geometry. After a lot of iteration, I ended up with something that properly scales, rotates, and aligns the sprite so that it lines up with the geometry – determining the proper inputs to a SpriteBatch.Draw call can be challenging when you’re rotating, scaling and translating all in one go, so it involved a lot of trial and error.


Some investigation of issues I was running into with standing on surfaces revealed that my current approach was getting too complicated and fragile – previously, I was scanning over all the objects under the player, and then choosing arbitrary points along their surface (left edge, middle, and right edge) and casting rays downward at those points to attempt to determine where the player should stand on the surface. This ended up not working well for complex surfaces, like the uneven edges of the stone outcroppings created by the stone potion, and being unnecessarily expensive for simple surfaces like flat rectangles (which really only need a single ray cast). Furthermore, it had a negative performance impact, since I was issuing hundreds of ray cast calls per frame in situations where I might have gotten away with only a dozen.

The solution to this ended up being simple: Where previously, I’d issue ComputeStandingY calls on each object that the player could be standing on, multiple times to cast individual rays, now I would issue a single call for each object, telling it the location of the player’s left and right edges. This way each object could have its own implementation for handling uneven surfaces – simple rectangles could just return the Y coordinate of their top edge, while complex geometry could sweep over its vertices and do the necessary math to compute the Y coordinate. In some cases, the new handlers got a bit complicated, but in most cases, they weren’t actually any harder to write than the old ones – a pleasant surprise. For example, the handler for pressure plates required a complete rewrite, since a pressure plate is represented by a rectangle (in the middle) with two triangles on the corners to give it a smooth slope:

        public override float? ComputeStandingY (float x1, float x2, float y) {
            var p = _CollisionList[0];
            if ((x2 >= p[1].X) && (x1 <= p[2].X))
                return Anchor.Y;
            else if (x2 < p[2].X)
                return RuntimeTriangle.ComputeStandingY(p[0], p[1], x1, x2, y);
            else
                return RuntimeTriangle.ComputeStandingY(p[2], p[3], x1, x2, y);
        }

While other handlers, like Triangle, required only minor changes to account for the addition of a second X coordinate:

        public static float ComputeStandingY (Vector2 slopeBegin, Vector2 slopeEnd, float x1, float x2, float y) {
            var minX = slopeBegin.X;
            var maxX = slopeEnd.X;

            if (x2 < minX)
                return slopeBegin.Y;
            else if (x1 > maxX)
                return slopeEnd.Y;

            var startY = slopeBegin.Y;
            var endY = slopeEnd.Y;
            var dX = maxX - minX;
            var dY = endY - startY;

            float x = (dY > 0) ? x1 : x2;

            var d = (x - minX) / dX;

            var result = startY + (dY * MathHelper.Clamp(d, 0.0f, 1.0f));

            return result;
        }

The end result is that ComputeStandingY went from around #10 on profiler results to well below #50 (always good to maintain a stable framerate), and a number of minor surface standing oddities went away. Future work involving complex surfaces should be much easier, as well, which will be important for some of the game content I have planned.


Earlier this week I got the art for one of the player characters’ surface mantling animations, so I decided to get it into the game. Doing this required throwing out most of the existing code for surface mantling, since I had previously animated it by actually moving the player character progressively from his old location to the new one. The new animation is simpler, in that the player switches instantly from the old location to the new one, but poses some interesting challenges: I have to realign the player such that his animation looks like it’s moving from his old location to the new one, without the jarring realignment of the camera that would normally accompany an instant relocation like that.

The end result looks pretty good. The basic approach looks like this:

        protected void BeginMantle (ICollidable mantleTarget, Vector2 targetPosition) {
            Jumping = false;
            JumpApex = false;
            LedgeClinging = false;
            Mantling = true;
            LockInput = true;

            var anim = PlayAnimation("Mantle");
            _MantleTarget = mantleTarget;
            _MantleStartPosition = Position;

            _LockCamera.Position = Position;
            _LockCamera.Weight = 1.0f;
            Game.CameraStack.Add(_LockCamera);

            Velocity = Vector2.Zero;
            Position = mantleTarget.Anchor + targetPosition;

            var rideable = mantleTarget as IRideable;
            if ((rideable != null) && (!_Riding.ContainsKey(rideable)))
                BeginRiding(rideable);
        }

        protected void EndMantle () {
            Mantling = false;
            LockInput = false;
            if (StandingOn != null)
                _RidingPosition = Position - StandingOn.Anchor;

            Game.CameraStack.Remove(_LockCamera);
            Game.CameraStack.Add(new LookAtCameraController(
                _MantleStartPosition, 0.0f, 0.0f, MantleCameraPanDuration
            ));
        }

A few things are going on here: When the player begins mantling onto a surface, I set some state flags in order to keep things sane, for example disabling the input, so that you can’t move left/right or jump while mantling is in progress. After that, I start the mantle animation and initialize some fields so that the player’s code can keep track of the surface it’s mantling onto and what the source and target positions are, for animation purposes. Next, I lock the camera on the player’s original position, so that it won’t move suddenly when I relocate the player to the new location. Finally, I move the player to his new position, reset his velocity, and if the surface being mantled onto is rideable, I set him as riding it.

The rest of the work mostly happens automatically: I tag the animation frames with markers so that the game knows what his origin is and where the top of his head is, so that his bounding box changes automatically along with the animation, and he appears to be climbing up onto the surface. When the animation finishes, it triggers a handler (EndMantle) to do the rest of the work – Cleaning up the state, and triggering a short camera pan from the old location to the new location so everything looks smooth. One final touch is that I play the ‘crouch to stand’ animation immediately after completing a mantle, so that the player appears to quickly stand back up after climbing onto a surface.

In practice, this solution actually looks smoother and more realistic than the old one, despite the fact that the animation is simpler and the collision detection approach is simpler.


And finally, this brings me to the task changes. As you might have noticed, previously I used tasks to structure ‘long-lived’ pieces of player state, like mantling onto a surface or gripping onto a ledge. This was convenient since tasks could easily take parameters and have local variables that would last for their entire duration, allowing me to track things like the source and destination positions for a mantle without needing to define fields for them. It also simplified the state machines necessary for handling player input and motion, since states like ‘is the player mantling’ could be represented entirely by the task responsible for them, and all the logic for updating during that task could be handled by the task itself, once per frame. Tasks also gave me an easy way to ensure that code ran at the beginning and end of a given animation, via the use of IDisposable, without having to manually track state and call Begin/End functions. Put together, all this was a huge timesaver initially, before the addition of my animation system and the simplification of my collision detection code – early prototypes contained some utterly terrifying state machines before I simplified things by switching to tasks.

The time had finally come to stop using tasks for this, though. The new animation system gave me a way to easily attach logic to onscreen animation, by responding to markers/triggers and to the beginning and end of an animation, and the conditional branching support in the animation format meant that the majority of my animation logic no longer needed to live in the code at all, alleviating most of the issues with huge state machines that I had before. So in the process of rigging up the new mantle animation, I converted jumping, mantling, and ledge clinging so that they used simple state machines and animations instead of tasks.

For the most part, the process was straightforward – I added boolean fields to track the player’s state where I previously used a task (so the player now has LedgeClinging and Mantling flags that he didn’t before), and created private fields for things that were previously stored in task locals (like the surface being mantled onto). Logic that needs to happen at the beginning or end now has its own handler (like the BeginMantle and EndMantle functions shown above), and in the event that I need to run some logic every frame during an animation, I write a simple function for it and insert it into the appropriate part of the state machine. Some of the code for handling player input is starting to get rather complicated, with chains of 5-6 if () else if () else if () else if () conditions, but it’s at least remaining relatively small and encapsulated.

        protected bool BeginLedgeCling (out ICollidable clingTarget) {
            if (!CanLedgeCling(out clingTarget)) {
                LedgeClinging = false;
                return false;
            }

            Velocity = Vector2.Zero;
            LedgeClinging = true;
            _ClingDirection = GetInputDirection();
            if (clingTarget != null)
                _ClingPosition = Position - clingTarget.Anchor;
            if (_ClingTarget is IRideable)
                BeginRiding(_ClingTarget as IRideable);

            return true;
        }

        protected void UpdateLedgeCling () {
            if (_ClingTarget == null)
                return;

            var delta = (_ClingTarget.Anchor + _ClingPosition) - Position;
            ApplyMotion(delta);
            AutoUpdateBounds();
        }

        protected void EndLedgeCling () {
            LedgeClinging = false;
            if (_ClingTarget is IRideable)
                StopRiding(_ClingTarget as IRideable);
            _ClingDirection = 0;
            _ClingTarget = null;
        }

During the process of moving things around, I actually found a few bugs in my implementation of ledge clinging, which made this refactoring quite worthwhile. Previously, I’d been depending on some bugs in my code in order to make the player remain stationary while clinging to a ledge, when I could have easily accomplished this with a single-line change in the right spot. I also discovered that rebounding off of a wall was actually intermittently broken before because the ledge clinging code had the ability to interfere by causing the player to begin clinging onto the ledge during the middle of a rebound. The new state machine approach made it much easier to address this problem by adding some appropriate checks, so that the player can’t even attempt to grip onto a ledge if he’s moving away from it.

All in all, a productive week!