I'm controlling a 2D side-viewed (facing right) stickman with a joystick. The movements are fairly intuitive:
- Joystick down -> Stickman crouches down
- Joystick up -> Stickman stretches out
- Joystick right -> Stickman leans forward
- Joystick left -> Stickman leans back
The stickman consists of various rectangles representing the limbs (legs, thighs, torso, head, upper arm, lower arm), which are connected with Hingejoints.
The joint movements based on joystick input is defined like this:
// xMin xMid xMax yMin yMid yMax
this.knee = new Expo2( -90, -60, 0, -120, -60, 0);
this.hip = new Expo2( 0, 60, 90, 120, 60, 0);
this.shoulder = new Expo2( -90, 45, -90, -90, -45, 90);
this.elbow = new Expo2( 0, -60, 0, -120, -60, 0);
this.neck = new Expo2( 0, 0, -30, 30, 0, 0);
Min/Mid/Max correspond to joystick axis min/center/max respectively. The first three represent the X axis, and the next three are for the Y axis. The number is how many degrees (relative to the starting position) that joint should try to hold for that particular joystick input. For when the stick is not at axis min/max/center, the corresponding angle is interpolated from the values above.
The actual problem:
This approach works fine when only processing the axis. Say, if i ignore Y-input, the stickman stretches out and crouches as expected. However, since the X axis also needs to be taken into account, there's a conflict of interest between the two.
For example, when moving the stick up, the arms should go to -90 (straight up). Now, since the stick is still center on the X axis, it wants to hold 0 degrees just as much.
Another example: When crouching the stickman tucks in his arms (sholders down, elbows up), but if leaning back, the arms should stretch out. This creates a conflict if you move the stick down and left.
The actual question:
Up until now, for testing purposes, I've simply averaged the two, but this is far from ideal, as a limb will rarely bend or stretch to its max, unless both axises wants it to do so. Is there a different approach that might be better for what I am trying to do?
Potentially viable alternative, please advice
Instead of setting joint angles individually for each axis, I could define various stances (such as crouching, stretching, idling, leanback, leanforward) and place them in a coordinate system representing the joystick. When the stick is moved, the final stance is determined by the stances closest to the stick position, with others that are relatively close also having an effect. These coordinates can be defined as Vector2
seeing as this is done in AndEngine, but basically, just a float
pair.
For the sake of this example, let's presume that the stick is moved 75% to the upper left corner. How would i pick the three closest stances (which would be stretch, leanback, and idle), and weight their joint states based on how close that stance is to the stick position? In this case, it should be equally as stretching as leaning back, but with a little influence of the idle position as well, seeing as the stick isn't all the way out.