Friday, 17 May 2013

TouchPad class for AS3 + Starling (Rev.2)

A month ago I shared a touch class that was pretty useful to play games in smart-phones but after some testing I realized that didn't work well when moving (with left thumb) + shooting (with right thumb) and pressing them alternatively.

After a bit of thinking, I have improved the class and now it will use always the left thumb to move and the right to shoot keeping the previous functionality. (But you can invert this easily, it have upgrade my class but it is still not public as I want to add more features before posting about it again!)

There is some tap functionality I need to implement, that will be in an future release: Ver.3....

Here it is, enjoy (for AIR or AS3):
(feel free to contribute to the class commenting here or in Starling Forum).



Class: TouchPad.as

package beekyr.controllers
{
    import flash.geom.Point;
    import starling.display.Quad;
    import starling.events.Touch;
    import starling.events.TouchEvent;
    import starling.events.TouchPhase;
    public class TouchPad extends Quad
    {
    /**
     * ...
     * @author Jaime Dominguez for Beekyr (2013)
     * http://www.jaimedominguez.com
     */
       
        private var _moveVector:Point = new Point();
        private var _tapVector:Point = new Point();
        private var _latestVector:TouchData = new TouchData();
        private var _sensitivity:Number;
        private var _touching:Boolean;
        private var _dualTouching:Boolean;
        private const TAP_SENSITIVITY:Number = 2;
        private var _tap:Boolean;
        private var _justTapped:Boolean;
       
       
        public function TouchPad(width:int, height:int, sensitivity:Number = 1) {
           
            super(width,height,0xff0000);
            _latestVector = new TouchData();
            _moveVector = new Point();
            _sensitivity = sensitivity;
            _touching = false;
            alpha = 0.05;
            addEventListener(TouchEvent.TOUCH , _handleTouch);
        }
       
        public function getLatestMovement():TouchData     {
            _latestVector._vX = _moveVector.x * _sensitivity;
            _latestVector._vY = _moveVector.y * _sensitivity;
            _latestVector.touching = _touching;
            _latestVector.dualTouching = _dualTouching;
            _latestVector.tap = _tap;
            resetValues();
            return _latestVector;
        }
       
        private function resetValues():void
        {
            _moveVector.x = 0 ;
            _moveVector.y = 0 ;
           
            _tap = false;
        }
       
        public function setWidth(w:Number):void {
            width = w;
        }
       
        public function setHeight(h:Number):void {
            height = h;
        }
       
        public function updateSensitivity(s:Number):void {
            _sensitivity = s;
        }
       
        private function _handleTouch(e:TouchEvent):void {
            e.stopImmediatePropagation()
            var touchArray:Vector. = e.getTouches(this);
            //var _wasDualTouch:Boolean = _dualTouching;
           
            _dualTouching = false;
            dispatchEventWith(TouchPhase.BEGAN);
            if (touchArray.length>0){
                var touch:Touch = touchArray[0];
                if (touchArray.length>1){
                    _dualTouching = true;

                   //If you want to move with the right thumb then edit the next line.
                    if (touchArray[0].getLocation(this).x > touchArray[1].getLocation(this).x) {
                        touch = touchArray[1];
                    }
                }
               
                switch (touch.phase){
                    case TouchPhase.BEGAN:
                        _justTapped = true;
                        storeThisPos(touch);
                    break;
                   
                    case TouchPhase.ENDED:
                        //checkForTap();
                        //stopMovement();
                        _tap = _justTapped;
                        _touching = false;
                    break;
                   
                    case TouchPhase.MOVED:
                        _justTapped = false;
                        getMovementVector(touch);
                    break;
                }
           
               
            }
           
        }
   
               
        private function getMovementVector(touch:Touch):void
        {
            _moveVector = touch.getMovement(this);
       
        }
       
        private function storeThisPos(touch:Touch):void
        {
            _touching = true;
            _tapVector = touch.getMovement(this);
        }
   
    }

}

Class:  TouchData.as 
package beekyr.controllers
{
    /**
     * ...
     * @author Jaime Dominguez
     */
    public class TouchData
    {
        public var _vX:Number;
        public var _vY:Number;

        public var touching:Boolean;
        public var dualTouching:Boolean;
        public var tap:Boolean;
           
        public function TouchData()
        {
           
        }
       
    }

}



Used in Beekyr for Android.

2 comments:

JazzCat said...

Hi Jaime,

Thank you for posting the this. As a newcomer to touch processing, I found it very useful. Thank you. :)

One thing I don't understand though is why you dispatchEventWith(TouchPhase.BEGAN) in the _handleTouch()? Would you kindly explain?

Regards,

G.

Jaime Dominguez Blazquez said...

Hi there,
That event can be easily removed, it is just throwing an event to tell that the touchpad is being touched to whoever listens for it. Nothing else... I think.