How to adapt KeyCombo.js to 2DPlatformer Controller.js?

I would like to adapt http://www.unifycommunity.com/wiki/index.php?title=KeyCombo to 2DPlatformerController.js?

Here is the code:

KeyCombo.js

class KeyCombo
{
    var buttons : String[];
    private var currentIndex : int=0; //moves along the array as buttons are pressed
    var allowedTimeBetweenButtons : float = 0.3; //tweak as needed
    private var timeLastButtonPressed : float;

    function KeyCombo(b : String[])
    {
        buttons = b;
    }

    //usage: call this once a frame. when the combo has been completed, it will return true
    function Check() : boolean
    {
        if (Time.time > timeLastButtonPressed + allowedTimeBetweenButtons) currentIndex=0;
        if (currentIndex < buttons.length)
        {
            if ((buttons[currentIndex] == "down"  Input.GetAxisRaw("Vertical") == -1) ||
            (buttons[currentIndex] == "up"  Input.GetAxisRaw("Vertical") == 1) ||
            (buttons[currentIndex] == "left"  Input.GetAxisRaw("Vertical") == -1) ||
            (buttons[currentIndex] == "right"  Input.GetAxisRaw("Horizontal") == 1) ||
            (buttons[currentIndex] != "down"   buttons[currentIndex] != "up"   buttons[currentIndex] != "left"   buttons[currentIndex] != "right"  Input.GetButtonDown(buttons[currentIndex])) )
            {
                timeLastButtonPressed = Time.time;
                currentIndex++;
            }

            if (currentIndex >= buttons.length)
            {
                currentIndex = 0;
                return true;
            }
            else return false;
        }
    }
}

PlatformerController.js (I got it from 2D Platformer example)

function Update () {
	var movementJS = cameraTransform.TransformDirection( Vector3( 0, moveJoystick.position.y, 0 )); 
	movementJS.x = 0;
	movementJS.Normalize(); // Adjust magnitude after ignoring vertical movement
	
	var absJoyPos = Vector2( Mathf.Abs( moveJoystick.position.x ), Mathf.Abs( moveJoystick.position.y ) );
	movementJS *= movement.walkSpeed * ( ( absJoyPos.x > absJoyPos.y ) ? absJoyPos.x : absJoyPos.y );
	
	var h = movementJS.y;  	
	if (!canControl)
		h = 0.0;
	
	movement.isMoving = h > 0.1;  
		
	if (movement.isMoving  canControl)
		jump.lastButtonTime = Time.time;
		
	UpdateSmoothedMovementDirection();
	
	if (activePlatform != null) {
		var newGlobalPlatformPoint = activePlatform.TransformPoint(activeLocalPlatformPoint);
		var moveDistance = (newGlobalPlatformPoint - activeGlobalPlatformPoint);
		transform.position = transform.position + moveDistance;
		lastPlatformVelocity = (newGlobalPlatformPoint - activeGlobalPlatformPoint) / Time.deltaTime;
	} else {
		lastPlatformVelocity = Vector3.zero;	
	}
	
	activePlatform = null;
	
	lastPosition = transform.position;
	
	var currentMovementOffset = movement.direction * movement.speed + Vector3 (0, movement.verticalSpeed, 0) + movement.inAirVelocity;
	
	currentMovementOffset *= Time.deltaTime;
	
	movement.collisionFlags = controller.Move (currentMovementOffset);
	
	movement.velocity = (transform.position - lastPosition) / Time.deltaTime;
	
	if (activePlatform != null) {
		activeGlobalPlatformPoint = transform.position;
		activeLocalPlatformPoint = activePlatform.InverseTransformPoint (transform.position);
	}
	
	if (movement.direction.sqrMagnitude > 0.01)
		transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation (movement.direction), Time.deltaTime * movement.rotationSmoothing);

	if (controller.isGrounded) {
		movement.inAirVelocity = Vector3.zero;
		if (jump.jumping) {
			jump.jumping = false;

			var jumpMoveDirection = movement.direction * movement.speed + movement.inAirVelocity;
			if (jumpMoveDirection.sqrMagnitude > 0.01)
				movement.direction = jumpMoveDirection.normalized;
		}
	}		
	comboPunch();
}

function comboPunch()
{
	var falconPunch : KeyCombo = KeyCombo(["left", "right", "Fire1"]);
	if (falconPunch.Check())
        {
             // do the falcon punch
             Debug.Log("Special PUNCH"); 
        }
}

The code deployed in PlatformerController.js is:

private var falconPunch : KeyCombo = KeyCombo([“left”, “right”, “Fire1”]);

if (falconPunch.Check())
{
// do the falcon punch
Debug.Log(“Special PUNCH”);
}

Q.1 It seems the Check() did not use the iphone touch function to detect the joystick

Q.2 For an iphone joystick, how did it detect “up”, “down”, “left”, “right” and “Fire1” ?

“up”, “down”, “left”, “right” - leftpad (GUITexture)
“Fire1” - rightpad (GUITexture)

As I did not think KeyCombo([“left”, “right”, “Fire1”]); can detect it properly.

To start with, you need this slightly modified version of the Check function:-

function Check(joy: Vector2) : boolean 
    { 
        if (Time.time > timeLastButtonPressed + allowedTimeBetweenButtons) currentIndex=0; 
        if (currentIndex < buttons.length) 
        { 
            if ((buttons[currentIndex] == "down"  joy.y < 0) || 
            (buttons[currentIndex] == "up"  joy.y > 0) || 
            (buttons[currentIndex] == "left"  joy.x < 0) || 
            (buttons[currentIndex] == "right"  joy.x > 0)
            ) 
            { 
                timeLastButtonPressed = Time.time; 
                currentIndex++; 
            } 

            if (currentIndex >= buttons.length) 
            { 
                currentIndex = 0; 
                return true; 
            } 
            else return false; 
        } 
    }

This bases the movements on the value of a Vector2 passed in rather than reading the keystrokes directly. Then, you need to call Check differently in the comboPunch function:-

function comboPunch(joy: Vector2) 
{ 
   var falconPunch : KeyCombo = KeyCombo(["left", "right", "Fire1"]); 
   if (falconPunch.Check(joy)) 
        { 
             // do the falcon punch 
             Debug.Log("Special PUNCH"); 
        } 
}

Finally, when you call comboPunch, pass in the joystick vector:-

...
comboPunch(moveJoystick.position);
...

I haven’t been able to test this, unfortunately, but it should at least give you something to work from.

Dear Sir

Thank you very much for your modified code.

However, it still not returns true for the Check method.

function Check(joy: Vector2) : boolean 
    {     	
        if (Time.time > timeLastButtonPressed + allowedTimeBetweenButtons) currentIndex=0; 
        if (currentIndex < buttons.length) 
        { 
        	
            if ( (buttons[currentIndex] == "left"  joy.x < 0) || 
                (buttons[currentIndex] == "right"  joy.x > 0) ) 
            {             	
                timeLastButtonPressed = Time.time; 
                currentIndex++; 
                Debug.Log("currentIndex: " + currentIndex);
            } 

            //Debug.Log("buttons length: " + buttons.length);

            if (currentIndex >= buttons.length) 
            { 
                currentIndex = 0;
                return true; 
            } 
            else return false; 
        } 
    }

Q.1 - I want the user move joystick “left” + “right” + “Fire1” or “right” + “left” + “Fire1”

Then it calls the code insides falconPunch().

For simplicity, I removed the “up” and “down” and joy.y in if condition above and call by var falconPunch : KeyCombo = KeyCombo([“left”, “right”]) without “Fire1”.

Debug.Log("currentIndex: " + currentIndex);
It shows ‘1’.

I keep on moving joystick left and right, it stills shows
currentIndex: 1

But the buttons.length is 2, so it never returns true.

Q.2 - Since I copied the joystick code from penelope, there is a Fire1 (Jump in penelope) button on right-hand side.

How should I edit the following code to support 2nd button?

if ( (buttons[currentIndex] == “left” joy.x < 0) ||
(buttons[currentIndex] == “right” joy.x > 0) )

function Check(joy: Vector2) : boolean

if (falconPunch.Check(joy))

Thanks for advice

I changed the debug log and found the reason, but I do not know how to fix it.

Debug.Log("buttons[currentIndex]: " + buttons[currentIndex] + "; joy.x: " + joy.x);

  1. It shows

buttons[currentIndex]: right ; joy.x: -0.05

when I move character to right

  1. It shows

buttons[currentIndex]: right ; joy.x: -1

when I move character (joystick) to left

So, both conditions
(buttons[currentIndex] == “left” joy.x < 0) || (buttons[currentIndex] == “right” joy.x > 0)

did not hit.

How should I fix it?

in Check function, I added more debug log

if (currentIndex <= buttons.length) 
        {         	
        	Debug.Log("joy Vector2 A: " + joy.x);

            if ( (buttons[currentIndex] == "left"  joy.x < 0) || (buttons[currentIndex] == "right"  joy.x > 0) ) 
            {             	
            	Debug.Log("joy Vector2 B: " + joy.x);
                timeLastButtonPressed = Time.time; 
                currentIndex++;                        
            }  
            
                if (currentIndex >= buttons.length) 
                { 
                   currentIndex = 0;
                   return true; 
                } 
                else 
                {
            	   return false; 
                } 
                          
        }

joy Vector2 A: -1 to 1 (Left to Right)
Log before the code
if ( (buttons[currentIndex] == “left” joy.x < 0) || (buttons[currentIndex] == “right” joy.x > 0) )

joy Vector2 B: -1 to -0.03 (Left to Right)
Log after the code
if ( (buttons[currentIndex] == “left” joy.x < 0) || (buttons[currentIndex] == “right” joy.x > 0) )

Why the joy.x value has changed after entering the if condition?

I have worked and debugged for a week and still cannot fix it

Anyone could help?

I still haven’t fixed it.

How should I debug it?

Can you post the code you’ve got after the week’s debugging and explain how far you’ve got with it?

var moveJoystick : Joystick;
var punchJoystick : Joystick;

function Update () {
comboPunch(moveJoystick.position, punchJoystick.IsFingerDown());
}

function comboPunch(joy: Vector2, punch: boolean) 
{ 
   var falconPunch : KeyCombo = KeyCombo(["left", "right"]); 
   
   if (punch  falconPunch.Check(joy)) 
   { 
       Debug.Log("Special PUNCH"); 
   } 
}

class KeyCombo
{
    var buttons : String[];
    var currentIndex : int = 0; //moves along the array as buttons are pressed
    var allowedTimeBetweenButtons : float = 1.0; //tweak as needed
    var timeLastButtonPressed : float;

    function KeyCombo(b : String[])
    {
        buttons = b;
    }

    function Check(joy: Vector2) : boolean 
    {      	
        if (Time.time > timeLastButtonPressed + allowedTimeBetweenButtons) 
        {
        	currentIndex = 0; 
        }

        if (currentIndex < buttons.length) 
        {         	            
            var lefthand : boolean = (buttons[currentIndex] == "left"  joy.x < 0);
            var righthand : boolean = (buttons[currentIndex] == "right"  joy.x > 0);
            
            Debug.Log("(1) currentIndex: " + currentIndex + "; buttons[currentIndex]: " + buttons[currentIndex] + "; joy Vector2: " + joy.x + "; lefthand: " + lefthand + "; righthand: " + righthand);         
            
            if(lefthand || righthand) 
            {             	
                timeLastButtonPressed = Time.time; 
                currentIndex++; 
                
            Debug.Log("(2) currentIndex: " + currentIndex + "; buttons[currentIndex]: " + buttons[currentIndex] + "; joy Vector2: " + joy.x + "; lefthand: " + lefthand + "; righthand: " + righthand);                        
            }                          
        } 
        
        if (currentIndex >= buttons.length) 
        { 
           currentIndex = 0;
           return true;
        } 
        else 
        {
      	   return false; 
        } 
    }
}

I put 2 debug logs and here are the outcome when I play with unity remote:

Debug Case 1:
Move Left + Punch Button
(1) currentIndex: 0; buttons[currentIndex]: left; joy Vector2: -1; lefthand: True; righthand: False

Move Right + Punch Button
(1) currentIndex: 0; buttons[currentIndex]: left; joy Vector2: 0.3200001; lefthand: False; righthand: False

Debug Case 2:
Move Left + Punch Button
(2) currentIndex: 1; buttons[currentIndex]: right; joy Vector2: -1; lefthand: True; righthand: False

Move Right + Punch Button
(2) currentIndex: 1; buttons[currentIndex]: right; joy Vector2: -0.4400001; lefthand: True; righthand: False
[WRONG]

You can see if I put the debug log (2) insides the if condition, the
joy Vector2: -0.4400001 is negative but not positive. And, in both Move Right cases, the righthand: False and lefthand: True;

So, it works only move left. After move left and move right, move right does not work.

If I move right first then move left, it did not show debug log.

So, I guess the problem occurred in move right.

Here is the code for moving:

function UpdateSmoothedMovementDirection () {
	
	var movementJS = cameraTransform.TransformDirection( Vector3( moveJoystick.position.x, 0, 0 )); //moveJoystick.position.y ) );
	// We only want the camera-space horizontal direction
	movementJS.y = 0;
	movementJS.Normalize(); // Adjust magnitude after ignoring vertical movement
	
	// Let's use the largest component of the joystick position for the speed.
	var absJoyPos = Vector2( Mathf.Abs( moveJoystick.position.x ), Mathf.Abs( moveJoystick.position.y ) );
	movementJS *= movement.walkSpeed * ( ( absJoyPos.x > absJoyPos.y ) ? absJoyPos.x : absJoyPos.y );
	
	var h = movementJS.x; //Input.GetAxisRaw ("Horizontal"); 	
	if (!canControl)
		h = 0.0;
	
	movement.isMoving = Mathf.Abs(h) > 0.1; 
		
	if (movement.isMoving)
		movement.direction = Vector3 (h, 0, 0);
	
	// Grounded controls
	if (controller.isGrounded) {
		// Smooth the speed based on the current target direction
		var curSmooth = movement.speedSmoothing * Time.deltaTime;
		
		// Choose target speed
		var targetSpeed = Mathf.Min (Mathf.Abs(h), 1.0);
		
		movement.speed = Mathf.Lerp (movement.speed, targetSpeed, curSmooth);		
		movement.hangTime = 0.0;
	}
	else {
		// In air controls
		movement.hangTime += Time.deltaTime;
		if (movement.isMoving)
			movement.inAirVelocity += Vector3 (Mathf.Sign(h), 0, 0) * Time.deltaTime * movement.inAirControlAcceleration;
	}
}

Please advise.

Any idea?

Why the move right joystick did not work?

do the code KeyCombo([“left”, “right”]); I mean the sequence would affect it?

I also intentionally to set higher
var allowedTimeBetweenButtons : float = 1.0;

but still failed.

Any advice?

Any experts could help?