Introduction
Following in the footsteps of my previous article, it would have been improper not to take on the task of xamlizing a four-legged creature. In short, I decided to work on a WPF project that replicated a walking four-legged animal.
Requirements
To run the project provided from the download link above, you require either of the following:
- Visual Studio 2010
- Expression Blend
If you're using VS 2008, you can download the source files from here.
NB: Ensure that you open the solution using Visual Basic Express if you're using the Express edition of Visual Studio.
Avalona
How It Works
To make Avalona walk, just press the right arrow key. Avalona will amble on a treadmill, this time the action taking place inside the M Labs Animaloid Research Centre.
Ambling
The amble is an easy gait (way of walking), most common in horses, where at least one leg/hoof touches the ground during the phases of motion. There is no suspension phase, i.e., a phase where all the legs are entirely off the ground. This was the primary reason I decided to replicate the amble. During this gait, a maximum of two legs can/will support the weight of the animal. The following sequence of photographs show the phases followed during this gait.
A short and detailed explanation of the phases of movement shown above can be found here.
There are 11 phases in the photos above, which are a bit of a handful, so I narrowed it down to 5 phases which would offer me equally suitable results.
From the initial sequence of photos, I chose the 4th, 5th, 6th, 7th, and 9th phases.
If you want to, you can watch a video of a horse ambling here.
Design and Layout
I designed Avalona
, Treadmill
, and the Lab_Screen
in Expression Design. The rest of the elements were added in Expression Blend. The following image shows the layout of the elements of concern and their names (the same applies to the left legs),
NB: The center of the joints of each section of Avalona act as center points.
Leg Movement
The standing posture of Avalona and that of a horse are slightly different. Avalona's limbs are more slightly angled especially those of the hind legs.
This presented a bit of a challenge in my attempt at replicating the amble. Because of this difference, Avalona's gait is a slightly modified version of a horse's amble.
In order to get a better picture of how to proceed, I drew stick figures of the ambling horse and then drew stick figures of a ambling Avalona, taking into account their differences in standing posture. I then adjusted the elements of concern in Expression Blend, at positions similar to those of the stick figures, noting down the angles which I felt would offer suitable results. These were the results:
The Code
The calculations that provide us with the necessary wizardry are found in the module MovementCalculations
:
Module MovementCalculations
Public RhtHindLeg_A_Angles() As Integer = {4, 8, 14, -4, -14}
Public RhtHindLeg_B_Angles() As Integer = {4, 8, 14, 20, -10}
Public RhtHindLeg_C_Angles() As Integer = {-4, -10, -31, -42, 4}
Public RhtHindLegPawAngles() As Integer = {-4, 2, 3, 22, 20}
Public LeftHindLeg_A_Angles() As Integer = {-14, -12, -9, -5, 4}
Public LeftHindLeg_B_Angles() As Integer = {-10, -14, -20, -10, 4}
Public LeftHindLeg_C_Angles() As Integer = {4, 9, 21, 12, -4}
Public LeftHindLegPawAngles() As Integer = {20, 22, 8, 3, -4}
Public RhtForeLeg_A_Angles() As Integer = {3, 4, 5, 9, 6}
Public RhtForeLeg_B_Angles() As Integer = {2, 9, 13, 15, -41}
Public RhtForeLeg_C_Angles() As Integer = {0, 0, 0, 18, 68}
Public RhtForeLegPawAngles() As Integer = {-5, -13, -18, -25, -31}
Public LeftForeLeg_A_Angles() As Integer = {6, 9, 1, -8, 3}
Public LeftForeLeg_B_Angles() As Integer = {-41, -60, -46, -8, 2}
Public LeftForeLeg_C_Angles() As Integer = {68, 66, 55, 0, 0}
Public LeftForeLegPawAngles() As Integer = {-31, -16, -8, 29, -5}
Public LeftHindLeg_A_Shift1 As Double = _
Math.Abs(LeftHindLeg_A_Angles(0) / RhtHindLeg_A_Angles(0))
Public LeftHindLeg_B_Shift1 As Double = _
Math.Abs(LeftHindLeg_B_Angles(0) / RhtHindLeg_A_Angles(0))
Public LeftHindLeg_C_Shift1 As Double = _
(LeftHindLeg_C_Angles(0) / RhtHindLeg_A_Angles(0))
Public LeftHindLegPawShift1 As Double = _
(LeftHindLegPawAngles(0) / RhtHindLeg_A_Angles(0))
Public RhtForeLeg_A_Shift1 As Double = _
(RhtForeLeg_A_Angles(0) / RhtHindLeg_A_Angles(0))
Public RhtForeLeg_B_Shift1 As Double = _
(RhtForeLeg_B_Angles(0) / RhtHindLeg_A_Angles(0))
Public RhtForeLegPawShift1 As Double = _
Math.Abs(RhtForeLegPawAngles(0) / RhtHindLeg_A_Angles(0))
Public LeftForeLeg_A_Shift1 As Double = _
(LeftForeLeg_A_Angles(0) / RhtHindLeg_A_Angles(0))
Public LeftForeLeg_B_Shift1 As Double = _
Math.Abs(LeftForeLeg_B_Angles(0) / RhtHindLeg_A_Angles(0))
Public LeftForeLeg_C_Shift1 As Double = _
(LeftForeLeg_C_Angles(0) / RhtHindLeg_A_Angles(0))
Public LeftForeLegPawShift1 As Double = _
Math.Abs(LeftForeLegPawAngles(0) / RhtHindLeg_A_Angles(0))
Public Phase2Shift As Double = _
(RhtHindLeg_A_Angles(1) - RhtHindLeg_A_Angles(0))
Public RhtHindLeg_B_Shift2 As Double = _
(RhtHindLeg_B_Angles(1) - RhtHindLeg_B_Angles(0)) / Phase2Shift
Public RhtHindLeg_C_Shift2 As Double = _
Math.Abs(RhtHindLeg_C_Angles(1) - RhtHindLeg_C_Angles(0)) / Phase2Shift
Public RhtHindLegPawShift2 As Double = _
(RhtHindLegPawAngles(1) - RhtHindLegPawAngles(0)) / Phase2Shift
Public LeftHindLeg_A_Shift2 As Double = _
(LeftHindLeg_A_Angles(1) - LeftHindLeg_A_Angles(0)) / Phase2Shift
Public LeftHindLeg_B_Shift2 As Double = _
Math.Abs(LeftHindLeg_B_Angles(1) - LeftHindLeg_B_Angles(0)) / Phase2Shift
Public LeftHindLeg_C_Shift2 As Double = _
(LeftHindLeg_C_Angles(1) - LeftHindLeg_C_Angles(0)) / Phase2Shift
Public LeftHindLegPawShift2 As Double = _
(LeftHindLegPawAngles(1) - LeftHindLegPawAngles(0)) / Phase2Shift
Public RhtForeLeg_A_Shift2 As Double = _
(RhtForeLeg_A_Angles(1) - RhtForeLeg_A_Angles(0)) / Phase2Shift
Public RhtForeLeg_B_Shift2 As Double = _
(RhtForeLeg_B_Angles(1) - RhtForeLeg_B_Angles(0)) / Phase2Shift
Public RhtForeLegPawShift2 As Double = _
Math.Abs(RhtForeLegPawAngles(1) - RhtForeLegPawAngles(0)) / Phase2Shift
Public LeftForeLeg_A_Shift2 As Double = _
(LeftForeLeg_A_Angles(1) - LeftForeLeg_A_Angles(0)) / Phase2Shift
Public LeftForeLeg_B_Shift2 As Double = _
Math.Abs(LeftForeLeg_B_Angles(1) - LeftForeLeg_B_Angles(0)) / Phase2Shift
Public LeftForeLeg_C_Shift2 As Double = _
Math.Abs(LeftForeLeg_C_Angles(1) - LeftForeLeg_C_Angles(0)) / Phase2Shift
Public LeftForeLegPawShift2 As Double = _
(LeftForeLegPawAngles(1) - LeftForeLegPawAngles(0)) / Phase2Shift
Public Phase3Shift As Double = _
(RhtHindLeg_A_Angles(2) - RhtHindLeg_A_Angles(1))
Public RhtHindLeg_B_Shift3 As Double = _
(RhtHindLeg_B_Angles(2) - RhtHindLeg_B_Angles(1)) / Phase3Shift
Public RhtHindLeg_C_Shift3 As Double = _
Math.Abs(RhtHindLeg_C_Angles(2) - RhtHindLeg_C_Angles(1)) / Phase3Shift
Public RhtHindLegPawShift3 As Double = _
(RhtHindLegPawAngles(2) - RhtHindLegPawAngles(1)) / Phase3Shift
Public LeftHindLeg_A_Shift3 As Double = _
(LeftHindLeg_A_Angles(2) - LeftHindLeg_A_Angles(1)) / Phase3Shift
Public LeftHindLeg_B_Shift3 As Double = _
Math.Abs(LeftHindLeg_B_Angles(2) - LeftHindLeg_B_Angles(1)) / Phase3Shift
Public LeftHindLeg_C_Shift3 As Double = _
(LeftHindLeg_C_Angles(2) - LeftHindLeg_C_Angles(1)) / Phase3Shift
Public LeftHindLegPawShift3 As Double = _
Math.Abs(LeftHindLegPawAngles(2) - LeftHindLegPawAngles(1)) / Phase3Shift
Public RhtForeLeg_A_Shift3 As Double = _
(RhtForeLeg_A_Angles(2) - RhtForeLeg_A_Angles(1)) / Phase3Shift
Public RhtForeLeg_B_Shift3 As Double = _
(RhtForeLeg_B_Angles(2) - RhtForeLeg_B_Angles(1)) / Phase3Shift
Public RhtForeLegPawShift3 As Double = _
Math.Abs(RhtForeLegPawAngles(2) - RhtForeLegPawAngles(1)) / Phase3Shift
Public LeftForeLeg_A_Shift3 As Double = _
Math.Abs(LeftForeLeg_A_Angles(2) - LeftForeLeg_A_Angles(1)) / Phase3Shift
Public LeftForeLeg_B_Shift3 As Double = _
(LeftForeLeg_B_Angles(2) - LeftForeLeg_B_Angles(1)) / Phase3Shift
Public LeftForeLeg_C_Shift3 As Double = _
Math.Abs(LeftForeLeg_C_Angles(2) - LeftForeLeg_C_Angles(1)) / Phase3Shift
Public LeftForeLegPawShift3 As Double = _
(LeftForeLegPawAngles(2) - LeftForeLegPawAngles(1)) / Phase3Shift
Public Phase4Shift As Double = _
Math.Abs(RhtHindLeg_A_Angles(3) - RhtHindLeg_A_Angles(2))
Public RhtHindLeg_B_Shift4 As Double = _
(RhtHindLeg_B_Angles(3) - RhtHindLeg_B_Angles(2)) / Phase4Shift
Public RhtHindLeg_C_Shift4 As Double = _
Math.Abs(RhtHindLeg_C_Angles(3) - RhtHindLeg_C_Angles(2)) / Phase4Shift
Public RhtHindLegPawShift4 As Double = _
(RhtHindLegPawAngles(3) - RhtHindLegPawAngles(2)) / Phase4Shift
Public LeftHindLeg_A_Shift4 As Double = _
(LeftHindLeg_A_Angles(3) - LeftHindLeg_A_Angles(2)) / Phase4Shift
Public LeftHindLeg_B_Shift4 As Double = _
(LeftHindLeg_B_Angles(3) - LeftHindLeg_B_Angles(2)) / Phase4Shift
Public LeftHindLeg_C_Shift4 As Double = _
Math.Abs(LeftHindLeg_C_Angles(3) - LeftHindLeg_C_Angles(2)) / Phase4Shift
Public LeftHindLegPawShift4 As Double = _
Math.Abs(LeftHindLegPawAngles(3) - LeftHindLegPawAngles(2)) / Phase4Shift
Public RhtForeLeg_A_Shift4 As Double = _
(RhtForeLeg_A_Angles(3) - RhtForeLeg_A_Angles(2)) / Phase4Shift
Public RhtForeLeg_B_Shift4 As Double = _
(RhtForeLeg_B_Angles(3) - RhtForeLeg_B_Angles(2)) / Phase4Shift
Public RhtForeLeg_C_Shift4 As Double = _
(RhtForeLeg_C_Angles(3)) / Phase4Shift
Public RhtForeLegPawShift4 As Double = _
Math.Abs(RhtForeLegPawAngles(3) - RhtForeLegPawAngles(2)) / Phase4Shift
Public LeftForeLeg_A_Shift4 As Double = _
Math.Abs(LeftForeLeg_A_Angles(3) - LeftForeLeg_A_Angles(2)) / Phase4Shift
Public LeftForeLeg_B_Shift4 As Double = _
(LeftForeLeg_B_Angles(3) - LeftForeLeg_B_Angles(2)) / Phase4Shift
Public LeftForeLeg_C_Shift4 As Double = _
CDbl((LeftForeLeg_C_Angles(2)) / Phase4Shift)
Public LeftForeLegPawShift4 As Double = _
(LeftForeLegPawAngles(3) - LeftForeLegPawAngles(2)) / Phase4Shift
Public Phase5Shift As Double = _
Math.Abs(RhtHindLeg_A_Angles(4) - RhtHindLeg_A_Angles(3))
Public RhtHindLeg_B_Shift5 As Double = _
Math.Abs(RhtHindLeg_B_Angles(4) - RhtHindLeg_B_Angles(3)) / Phase5Shift
Public RhtHindLeg_C_Shift5 As Double = _
(RhtHindLeg_C_Angles(4) - RhtHindLeg_C_Angles(3)) / Phase5Shift
Public RhtHindLegPawShift5 As Double = _
Math.Abs(RhtHindLegPawAngles(4) - RhtHindLegPawAngles(3)) / Phase5Shift
Public LeftHindLeg_A_Shift5 As Double = _
(LeftHindLeg_A_Angles(4) - LeftHindLeg_A_Angles(3)) / Phase5Shift
Public LeftHindLeg_B_Shift5 As Double = _
(LeftHindLeg_B_Angles(4) - LeftHindLeg_B_Angles(3)) / Phase5Shift
Public LeftHindLeg_C_Shift5 As Double = _
Math.Abs(LeftHindLeg_C_Angles(4) - LeftHindLeg_C_Angles(3)) / Phase5Shift
Public LeftHindLegPawShift5 As Double = _
Math.Abs(LeftHindLegPawAngles(4) - LeftHindLegPawAngles(3)) / Phase5Shift
Public RhtForeLeg_A_Shift5 As Double = _
Math.Abs(RhtForeLeg_A_Angles(4) - RhtForeLeg_A_Angles(3)) / Phase5Shift
Public RhtForeLeg_B_Shift5 As Double = _
Math.Abs(RhtForeLeg_B_Angles(4) - RhtForeLeg_B_Angles(3)) / Phase5Shift
Public RhtForeLeg_C_Shift5 As Double = _
(RhtForeLeg_C_Angles(4) - RhtForeLeg_C_Angles(3)) / Phase5Shift
Public RhtForeLegPawShift5 As Double = _
(RhtForeLegPawAngles(4) - RhtForeLegPawAngles(3)) / Phase5Shift
Public LeftForeLeg_A_Shift5 As Double = _
(LeftForeLeg_A_Angles(4) - LeftForeLeg_A_Angles(3)) / Phase5Shift
Public LeftForeLeg_B_Shift5 As Double = _
(LeftForeLeg_B_Angles(4) - LeftForeLeg_B_Angles(3)) / Phase5Shift
Public LeftForeLegPawShift5 As Double = _
Math.Abs(LeftForeLegPawAngles(4) - LeftForeLegPawAngles(3)) / Phase5Shift
End Module
We check which key has been pressed in the MainWindow KeyDown
event handler:
Private Sub MainWindow_KeyDown(ByVal sender As Object, _
ByVal e As System.Windows.Input.KeyEventArgs) Handles Me.KeyDown
If e.Key = Key.Right Then
WalkForward()
End If
End Sub
The WalkForward
method does as its name suggests:
Private Sub WalkForward()
If FocusOnRightHind = True Then
If MoveRhtLegBackwards = True Then
RightHindBack()
Else
RightHindForward()
End If
Else
If MoveLeftLegBackwards = True Then
LeftHindBack()
Else
LeftHindForward()
End If
End If
TreadmillRedTr.Angle -= 5
RightHindLeg_A.RenderTransform = RhtHindLeg_A_Tr
RightHindLeg_B.RenderTransform = RhtHindLeg_B_Tr
RightHindLeg_C.RenderTransform = RhtHindLeg_C_Tr
RightHindLegPaw.RenderTransform = RhtHindPawTr
LeftHindLeg_A.RenderTransform = LeftHindLeg_A_Tr
LeftHindLeg_B.RenderTransform = LeftHindLeg_B_Tr
LeftHindLeg_C.RenderTransform = LeftHindLeg_C_Tr
LeftHindLegPaw.RenderTransform = LeftHindPawTr
RightForeLeg_A.RenderTransform = RhtForeLeg_A_Tr
RightForeLeg_B.RenderTransform = RhtForeLeg_B_Tr
RightForeLeg_C.RenderTransform = RhtForeLeg_C_Tr
RightForeLegPaw.RenderTransform = RhtForePawTr
LeftForeLeg_A.RenderTransform = LeftForeLeg_A_Tr
LeftForeLeg_B.RenderTransform = LeftForeLeg_B_Tr
LeftForeLeg_C.RenderTransform = LeftForeLeg_C_Tr
LeftForeLegPaw.RenderTransform = LeftForePawTr
TreadmillRedGroup.RenderTransform = TreadmillRedTr
End Sub
In the method above, method calls are made based on the values of various variables, of Boolean type. The RightHindBack
method rotates the various sections of Avalona's legs from the standing position to Phase 3. It later alternates to rotating elements from Phase 1 to Phase 3.
Private Sub RightHindBack()
If RhtHindLeg_A_Tr.Angle < 4 Then
RhtHindLeg_A_Tr.Angle += 1 * speed
RhtHindLeg_B_Tr.Angle += 1 * speed
RhtHindLeg_C_Tr.Angle -= 1 * speed
RhtHindPawTr.Angle -= 1 * speed
LeftHindLeg_A_Tr.Angle -= LeftHindLeg_A_Shift1 * speed
LeftHindLeg_B_Tr.Angle -= LeftHindLeg_B_Shift1 * speed
LeftHindLeg_C_Tr.Angle += LeftHindLeg_C_Shift1 * speed
LeftHindPawTr.Angle += LeftHindLegPawShift1 * speed
RhtForeLeg_A_Tr.Angle += RhtForeLeg_A_Shift1 * speed
RhtForeLeg_B_Tr.Angle += RhtForeLeg_B_Shift1 * speed
RhtForePawTr.Angle -= RhtForeLegPawShift1 * speed
LeftForeLeg_A_Tr.Angle += LeftForeLeg_A_Shift1 * speed
LeftForeLeg_B_Tr.Angle -= LeftForeLeg_B_Shift1 * speed
LeftForeLeg_C_Tr.Angle += LeftForeLeg_C_Shift1 * speed
LeftForePawTr.Angle -= LeftForeLegPawShift1 * speed
End If
If RhtHindLeg_A_Tr.Angle >= 4 And RhtHindLeg_A_Tr.Angle < 8 Then
RhtHindLeg_A_Tr.Angle += 1 * speed
RhtHindLeg_B_Tr.Angle += RhtHindLeg_B_Shift2 * speed
RhtHindLeg_C_Tr.Angle -= RhtHindLeg_C_Shift2 * speed
RhtHindPawTr.Angle += RhtHindLegPawShift2 * speed
LeftHindLeg_A_Tr.Angle += LeftHindLeg_A_Shift2 * speed
LeftHindLeg_B_Tr.Angle -= LeftHindLeg_B_Shift2 * speed
LeftHindLeg_C_Tr.Angle += LeftHindLeg_C_Shift2 * speed
LeftHindPawTr.Angle += LeftHindLegPawShift2 * speed
RhtForeLeg_A_Tr.Angle += RhtForeLeg_A_Shift2 * speed
RhtForeLeg_B_Tr.Angle += RhtForeLeg_B_Shift2 * speed
RhtForePawTr.Angle -= RhtForeLegPawShift2 * speed
LeftForeLeg_A_Tr.Angle += LeftForeLeg_A_Shift2 * speed
LeftForeLeg_B_Tr.Angle -= LeftForeLeg_B_Shift2 * speed
LeftForeLeg_C_Tr.Angle -= LeftForeLeg_C_Shift2 * speed
LeftForePawTr.Angle += LeftForeLegPawShift2 * speed
End If
If RhtHindLeg_A_Tr.Angle >= 8 And RhtHindLeg_A_Tr.Angle < 14 Then
RhtHindLeg_A_Tr.Angle += 1 * speed
RhtHindLeg_B_Tr.Angle += RhtHindLeg_B_Shift3 * speed
RhtHindLeg_C_Tr.Angle -= RhtHindLeg_C_Shift3 * speed
RhtHindPawTr.Angle += RhtHindLegPawShift3 * speed
LeftHindLeg_A_Tr.Angle += LeftHindLeg_A_Shift3 * speed
LeftHindLeg_B_Tr.Angle -= LeftHindLeg_B_Shift3 * speed
LeftHindLeg_C_Tr.Angle += LeftHindLeg_C_Shift3 * speed
LeftHindPawTr.Angle -= LeftHindLegPawShift3 * speed
RhtForeLeg_A_Tr.Angle += RhtForeLeg_A_Shift3 * speed
RhtForeLeg_B_Tr.Angle += RhtForeLeg_B_Shift3 * speed
RhtForePawTr.Angle -= RhtForeLegPawShift3 * speed
LeftForeLeg_A_Tr.Angle -= LeftForeLeg_A_Shift3 * speed
LeftForeLeg_B_Tr.Angle += LeftForeLeg_B_Shift3 * speed
LeftForeLeg_C_Tr.Angle -= LeftForeLeg_C_Shift3 * speed
LeftForePawTr.Angle += LeftForeLegPawShift3 * speed
End If
If RhtHindLeg_A_Tr.Angle = 14 Then
MoveRhtLegBackwards = False
End If
End Sub
The RightHindForward
method rotates the various sections of Avalona's legs from Phase 3 to Phase 5.
Private Sub RightHindForward()
If RhtHindLeg_A_Tr.Angle <= 14 And RhtHindLeg_A_Tr.Angle > -4 Then
RhtHindLeg_A_Tr.Angle -= 1 * speed
RhtHindLeg_B_Tr.Angle += RhtHindLeg_B_Shift4 * speed
RhtHindLeg_C_Tr.Angle -= RhtHindLeg_C_Shift4 * speed
RhtHindPawTr.Angle += RhtHindLegPawShift4 * speed
LeftHindLeg_A_Tr.Angle += LeftHindLeg_A_Shift4 * speed
LeftHindLeg_B_Tr.Angle += LeftHindLeg_B_Shift4 * speed
LeftHindLeg_C_Tr.Angle -= LeftHindLeg_C_Shift4 * speed
LeftHindPawTr.Angle -= LeftHindLegPawShift4 * speed
RhtForeLeg_A_Tr.Angle += RhtForeLeg_A_Shift4 * speed
RhtForeLeg_C_Tr.Angle += RhtForeLeg_C_Shift4 * speed
RhtForePawTr.Angle -= RhtForeLegPawShift4 * speed
LeftForeLeg_A_Tr.Angle -= LeftForeLeg_A_Shift4 * speed
LeftForeLeg_B_Tr.Angle += LeftForeLeg_B_Shift4 * speed
LeftForeLeg_C_Tr.Angle -= LeftForeLeg_C_Shift4 * speed
LeftForePawTr.Angle += LeftForeLegPawShift4 * speed
ShiftAvalonaUp()
End If
If RhtHindLeg_A_Tr.Angle = -4 Then
LeftForeLeg_C_Tr.Angle = 0
End If
If RhtHindLeg_A_Tr.Angle <= -4 And RhtHindLeg_A_Tr.Angle > -14 Then
RhtHindLeg_A_Tr.Angle -= 1 * speed * 0.5
RhtHindLeg_B_Tr.Angle -= RhtHindLeg_B_Shift5 * speed * 0.5
RhtHindLeg_C_Tr.Angle += RhtHindLeg_C_Shift5 * speed * 0.5
RhtHindPawTr.Angle -= RhtHindLegPawShift5 * speed * 0.5
LeftHindLeg_A_Tr.Angle += LeftHindLeg_A_Shift5 * speed * 0.5
LeftHindLeg_B_Tr.Angle += LeftHindLeg_B_Shift5 * speed * 0.5
LeftHindLeg_C_Tr.Angle -= LeftHindLeg_C_Shift5 * speed * 0.5
LeftHindPawTr.Angle -= LeftHindLegPawShift5 * speed * 0.5
RhtForeLeg_A_Tr.Angle -= RhtForeLeg_A_Shift5 * speed * 0.5
RhtForeLeg_B_Tr.Angle -= RhtForeLeg_B_Shift5 * speed * 0.5
RhtForeLeg_C_Tr.Angle += RhtForeLeg_C_Shift5 * speed * 0.5
RhtForePawTr.Angle += RhtForeLegPawShift5 * speed * 0.5
LeftForeLeg_A_Tr.Angle += LeftForeLeg_A_Shift5 * speed * 0.5
LeftForeLeg_B_Tr.Angle += LeftForeLeg_B_Shift5 * speed * 0.5
LeftForePawTr.Angle -= LeftForeLegPawShift5 * speed * 0.5
ShiftAvalonaDown()
End If
If RhtHindLeg_A_Tr.Angle = -14 Then
FocusOnRightHind = False
RhtHndFocusPhase5Stance()
End If
End Sub
The LeftHindBack
method is similar to the RightHindBack
method, with the code for shifting from the standing position missing and an interchange of variables. The logic is still the same.
Private Sub LeftHindBack()
If LeftHindLeg_A_Tr.Angle >= 4 And LeftHindLeg_A_Tr.Angle < 8 Then
LeftHindLeg_A_Tr.Angle += 1 * speed
LeftHindLeg_B_Tr.Angle += RhtHindLeg_B_Shift2 * speed
LeftHindLeg_C_Tr.Angle -= RhtHindLeg_C_Shift2 * speed
LeftHindPawTr.Angle += RhtHindLegPawShift2 * speed
RhtHindLeg_A_Tr.Angle += LeftHindLeg_A_Shift2 * speed
RhtHindLeg_B_Tr.Angle -= LeftHindLeg_B_Shift2 * speed
RhtHindLeg_C_Tr.Angle += LeftHindLeg_C_Shift2 * speed
RhtHindPawTr.Angle += LeftHindLegPawShift2 * speed
LeftForeLeg_A_Tr.Angle += RhtForeLeg_A_Shift2 * speed
LeftForeLeg_B_Tr.Angle += RhtForeLeg_B_Shift2 * speed
LeftForePawTr.Angle -= RhtForeLegPawShift2 * speed
RhtForeLeg_A_Tr.Angle += LeftForeLeg_A_Shift2 * speed
RhtForeLeg_B_Tr.Angle -= LeftForeLeg_B_Shift2 * speed
RhtForeLeg_C_Tr.Angle -= LeftForeLeg_C_Shift2 * speed
RhtForePawTr.Angle += LeftForeLegPawShift2 * speed
End If
If LeftHindLeg_A_Tr.Angle >= 8 And LeftHindLeg_A_Tr.Angle < 14 Then
LeftHindLeg_A_Tr.Angle += 1 * speed
LeftHindLeg_B_Tr.Angle += RhtHindLeg_B_Shift3 * speed
LeftHindLeg_C_Tr.Angle -= RhtHindLeg_C_Shift3 * speed
LeftHindPawTr.Angle += RhtHindLegPawShift3 * speed
RhtHindLeg_A_Tr.Angle += LeftHindLeg_A_Shift3 * speed
RhtHindLeg_B_Tr.Angle -= LeftHindLeg_B_Shift3 * speed
RhtHindLeg_C_Tr.Angle += LeftHindLeg_C_Shift3 * speed
RhtHindPawTr.Angle -= LeftHindLegPawShift3 * speed
LeftForeLeg_A_Tr.Angle += RhtForeLeg_A_Shift3 * speed
LeftForeLeg_B_Tr.Angle += RhtForeLeg_B_Shift3 * speed
LeftForePawTr.Angle -= RhtForeLegPawShift3 * speed
RhtForeLeg_A_Tr.Angle -= LeftForeLeg_A_Shift3 * speed
RhtForeLeg_B_Tr.Angle += LeftForeLeg_B_Shift3 * speed
RhtForeLeg_C_Tr.Angle -= LeftForeLeg_C_Shift3 * speed
RhtForePawTr.Angle += LeftForeLegPawShift3 * speed
End If
If LeftHindLeg_A_Tr.Angle = 14 Then
MoveLeftLegBackwards = False
End If
End Sub
The LeftHindForward
method is similar to the RightHindForward
method with an interchange of variables.
Private Sub LeftHindForward()
If LeftHindLeg_A_Tr.Angle <= 14 And LeftHindLeg_A_Tr.Angle > -4 Then
LeftHindLeg_A_Tr.Angle -= 1 * speed
LeftHindLeg_B_Tr.Angle += RhtHindLeg_B_Shift4 * speed
LeftHindLeg_C_Tr.Angle -= RhtHindLeg_C_Shift4 * speed
LeftHindPawTr.Angle += RhtHindLegPawShift4 * speed
RhtHindLeg_A_Tr.Angle += LeftHindLeg_A_Shift4 * speed
RhtHindLeg_B_Tr.Angle += LeftHindLeg_B_Shift4 * speed
RhtHindLeg_C_Tr.Angle -= LeftHindLeg_C_Shift4 * speed
RhtHindPawTr.Angle -= LeftHindLegPawShift4 * speed
LeftForeLeg_A_Tr.Angle += RhtForeLeg_A_Shift4 * speed
LeftForeLeg_B_Tr.Angle += RhtForeLeg_B_Shift4 * speed
LeftForeLeg_C_Tr.Angle += RhtForeLeg_C_Shift4 * speed
LeftForePawTr.Angle -= RhtForeLegPawShift4 * speed
RhtForeLeg_A_Tr.Angle -= LeftForeLeg_A_Shift4 * speed
RhtForeLeg_B_Tr.Angle += LeftForeLeg_B_Shift4 * speed
RhtForeLeg_C_Tr.Angle -= LeftForeLeg_C_Shift4 * speed
RhtForePawTr.Angle += LeftForeLegPawShift4 * speed
ShiftAvalonaUp()
End If
If LeftHindLeg_A_Tr.Angle = -4 Then
RhtForeLeg_C_Tr.Angle = 0
End If
If LeftHindLeg_A_Tr.Angle <= -4 And LeftHindLeg_A_Tr.Angle > -14 Then
LeftHindLeg_A_Tr.Angle -= 1 * speed * 0.5
LeftHindLeg_B_Tr.Angle -= RhtHindLeg_B_Shift5 * speed * 0.5
LeftHindLeg_C_Tr.Angle += RhtHindLeg_C_Shift5 * speed * 0.5
LeftHindPawTr.Angle -= RhtHindLegPawShift5 * speed * 0.5
RhtHindLeg_A_Tr.Angle += LeftHindLeg_A_Shift5 * speed * 0.5
RhtHindLeg_B_Tr.Angle += LeftHindLeg_B_Shift5 * speed * 0.5
RhtHindLeg_C_Tr.Angle -= LeftHindLeg_C_Shift5 * speed * 0.5
RhtHindPawTr.Angle -= LeftHindLegPawShift5 * speed * 0.5
LeftForeLeg_A_Tr.Angle -= RhtForeLeg_A_Shift5 * speed * 0.5
LeftForeLeg_B_Tr.Angle -= RhtForeLeg_B_Shift5 * speed * 0.5
LeftForeLeg_C_Tr.Angle += RhtForeLeg_C_Shift5 * speed * 0.5
LeftForePawTr.Angle += RhtForeLegPawShift5 * speed * 0.5
RhtForeLeg_A_Tr.Angle += LeftForeLeg_A_Shift5 * speed * 0.5
RhtForeLeg_B_Tr.Angle += LeftForeLeg_B_Shift5 * speed * 0.5
RhtForePawTr.Angle -= LeftForeLegPawShift5 * speed * 0.5
ShiftAvalonaDown()
End If
If LeftHindLeg_A_Tr.Angle = -14 Then
FocusOnRightHind = True
MoveRhtLegBackwards = True
MoveLeftLegBackwards = True
LeftHndFocusPhase5Stance()
End If
End Sub
Extra Resources
I'm sure that Avalona can do more than just amble. It can run, walk,... maybe even swim. If you are of the same opinion and have the time and interest, the following resources could prove to be useful:
Conclusion
I hope you enjoyed reading the article and taking Avalona for a walk, even if it was only on a treadmill. Stay tuned for the next episode when the Speedster, Xaml Man, and Avalona join forces in an epic battle against Winn Fommz... just kidding. If you want to add some enhancements to Avalona, the doors of the M Labs Animaloid Research Center are wide open once you download the source files and open the solution. Cheers!
History
- 1st February, 2011: Initial post