Create a D-pad with Cocos2d


Cocos2d is a popular native game framework which is out there for many years. There are several version of Cocos2d like Cocos2d-x or Cocos2d-html5. Cocos2d also supports different coding languages, such as lua, C++ and Javascript. This features makes Cocos2d a really powerful tool when it comes to real cross device solutions, code once and deploy it everywhere immediately.
I assume you already have set up your Cocos2d environment, and you know how to create an empty project. We will start of with the basic project template provided by CocosStudio and use javascript as coding language. After some basic coding we will end up with a customizable D-pad which will work on every platform supported by Cocos2d.

 

New to cocos2d? Here some helpful links:

http://www.cocos2d-x.org
 Getting Started
 docs

D-pad script

Starting off with extending a cc.Laye class, which will handle our touch inputs and draw the sprites. We can easily add all the touch events we need to this layer. Since we have multi touch response, we need to check each touch coordinate with the position of our input elements. Once the positions overlaps the input element will be activated. While a button element has just a pressed state, the analog stick will return an x and y value between -1 and 1.
The analog stick gets updated each time the touch-move event occurs. Once the touch-end event is fired, the input element state will fall back to deactivated.
Once the script is included into your cocos2d project you can add a analog-stick or a button by a simple command. You should definitely customize your input script to perfectly fit into your theme.

 ctor:function () {
        
        this._super();
        
        
        //ARRAY WHICH HOLDS ALL CONTROLL ELEMENTS
        this.controls = [];
        
        //HANDLE INPUT EVENTS
         cc.eventManager.addListener(cc.EventListener.create({
            		event: cc.EventListener.TOUCH_ALL_AT_ONCE,
                    swallowTouches: true,
             
                    onTouchesBegan: function (touches, event) {
                        var controls = event.getCurrentTarget().controls;
                        //FOR EACH TOUCH
                        for (var i = 0; i < touches.length; i++)
                        { 
                            var touch = touches[i]; //CURRENT TOUCH EVENT
                            var pos = touch.getLocation(); //TOUCH POSITION
                            
                            //CHECK TOUCH POSITION AGAINST EACH CONTROLL ELEMENT
                            for (var j = 0; j < controls.length; j++)
                            {
                                var dist = Math.sqrt((pos.x-controls[j].pos.x)*(pos.x-controls[j].pos.x) + (pos.y-controls[j].pos.y)*(pos.y-controls[j].pos.y));
                                //ON A INPUT ELEMENT
                                if(dist < controls[j].size)
                                {
                                    controls[j].touchStart(touch);
                                };
                            };
                        };
                    },
            		
                    onTouchesMoved:function (touches, event) {
                        
                        var controls = event.getCurrentTarget().controls; 
                        
                        //FOR EACH TOUCH
                        for (var i = 0; i < touches.length; i++)
                        { 
                            var touch = touches[i]; //CURRENT TOUCH EVENT
                            
                            //FOR EACH CONTROLL ELEMENT
                            for (var j = 0; j < controls.length; j++)
                            {
                                //IF TOUCH ID == CONTROLL ELEMENT TOUCH ID
                                if(touch.getID() == controls[j].touchID)
                                {
                                    //MOVE EMLEMENT
                                    controls[j].touchMove(touch);
                                };
                            };
                        };
            		},
                    
                    onTouchesEnded:function (touches, event) {
                         
                        var controls = event.getCurrentTarget().controls;
                        
                        //FOR EACH TOUCH
                        for (var i = 0; i < touches.length; i++)
                        { 
                            var touch = touches[i]; //CURRENT TOUCH EVENT
                            
                            //FOR EACH CONTROLL ELEMENT
                            for (var j = 0; j < controls.length; j++)
                            {
                                //IF TOUCH ID == CONTROLL ELEMENT TOUCH ID
                                if(touch.getID() == controls[j].touchID)
                                {
                                    controls[j].touchEnd();
                                };
                            };
                        };
            		}
            	}), this);
    },
    
    //ADD A NEW ANALOG STICK
    addStick:function(posX,posY)
    {
        //ADD ANALOG STICK BASE SPRITE
        var base = cc.Sprite.create("res/input/StickBase.png");
            base.setPosition(cc.p(posX,posY));
            this.addChild(base);
        
        //ADD ANALOG STICK SPRITE
        var stick = cc.Sprite.create("res/input/Stick.png"); // SET SPRITE
            stick.setPosition(cc.p(posX,posY)); // SET POSITION
            stick.pos = {x:posX,y:posY}; // SAVE START POSITION
            stick.size = 40; // TOUCH SIZE / MOVABLE RADIUS SIZE
            stick.startPos = {x:0,y:0}; // TOUCH START POSITION
            stick.input = {x:0,y:0}; // CURRENT INPUT VALUE
            stick.touchID = -1; // TOUCH ID
            stick.opacity = 150; // LOW OPACITY 0-255
            
        this.addChild(stick); //ADD STICK TO SCENE
        
            // ON TOUCH START
            stick.touchStart = function(touch)
            {
            	this.startPos = {x:touch.getLocation().x,y:touch.getLocation().y}; //GET TOUCH START POSITION           
                this.opacity = 255; //SET FULL OPACITY
                this.touchID = touch.getID(); //GET TOUCH ID
            };
        
            // ON TOUCH MOVE
            stick.touchMove = function(touch)
            {
                
                var pos = touch.getLocation(); //CURRENT LOCATION
                
                var dx = touch.getLocation().x - this.startPos.x; //MOVED IN X DIRECTION
                var dy = touch.getLocation().y - this.startPos.y; //MOVED IN Y DIRECTION
                
                var r = Math.sqrt(dx * dx + dy * dy); //GET MOVE DISTANCE
                        
                var _r = Math.min(r, this.size); //KEEP DISTANCE BETWEEN 0 - SIZE
                        
                dx = dx * _r / r; 
                
                //RECALCULATE dx based on _r
                if (isNaN(dx) === true) {
                	dx = 0.0;
                }
                
                //RECALCULATE dy based on _r
                dy = dy * _r / r;
                if (isNaN(dy) === true) {
                	dy = 0.0;
                }                
          
                //UPDATE STICK POSITION
                this.setPosition(cc.p(this.pos.x+dx,this.pos.y+dy));
                
                //UPDATE INPUT VALUE TO STAY BETWEEN 0-1;
                this.input = {x:dx/this.size,y:dy/this.size};
                
            };
            
            // ON TOUCH END
            stick.touchEnd = function()
            {
                this.setPosition(cc.p(this.pos.x,this.pos.y)); // SET POSITION TO 0,0
                this.opacity = 150; // SET OPACITY
                this.touchID = -1; // REMOVE TOUCH ID
                this.input = {x:0,y:0}; //RESET INPUT VALUE
            };
        
            //GET ANGLE FROM STICK
            stick.getAngle = function()
            {
                return  Math.atan2(this.input.x, this.input.y)* 180/Math.PI;
            }
        
        this.controls.push(stick); //ADD STICK TO CONTROLL ARRAY
        
        return stick; //RETURN STICK FOR EASY ACCESS
    },
    
    //ADD A NEW BUTTON
    addButton:function(posX,posY)
    {
        var button = cc.Sprite.create("res/input/button.png"); // SET SPRITE
            button.setPosition(cc.p(posX,posY)); //SET POSITION
            button.pos = {x:posX,y:posY}; // SAVE START POSITION
            button.opacity = 150; //SET OPACITY
            button.size = 40; // TOUCH SIZE
            button.input = false; // CURRENT INPUT VALUE
            button.touchID = -1; // TOUCH ID
            
        this.addChild(button); //ADD BUTTON TO SCENE
            
        // ON TOUCH START
            button.touchStart = function(touch)
            {
                this.input = true; //SET INPUT TO TRUE
                this.opacity = 255; //SET FULL OPACITY
                this.touchID = touch.getID(); //GET TOUCH ID
            };
        
            button.touchMove = function(touch,target)
            {
            };
        
            button.touchEnd = function()
            {
                this.input = false; //SET INPUT TO FALSE
                this.opacity = 150; //SET LOW OPACITY
                this.touchID = -1; //REMOVE TOUCH ID
            };
        
        this.controls.push(button); //ADD STICK TO CONTROLL ARRAY
        
        return button; //RETURN STICK FOR EASY ACCESS
    }
})

how to use

Make sure you have copied or changed the necessarily graphic assets. Simply add a new touch controller layer to the scene. Add buttons and analog sticks as required.
I highly encourage you to check an manipulate the touchController.js script to fit your needs perfectly.

 var touchInput = new touchController();
    this.addChild(touchInput);
   
    this.lStick = touchInput.addStick(x,y);
    this.rStick = touchInput.addStick(x,y);

    this.button_1 =  touchInput.addButton(x,y)

conclusion

Cocos2d is a great cross device game engine, unfortunately it will take a lot of time to fully understand how cocos2d works and how to use the javascript version of it. Once you feel comfortable with cocos2d you can easily build 2d games for any target device natively and in html5.
Having a D-pad is a good starting point, you have to control the player somehow. Even better, this D-pad will work on Android, iOs, html5 and most desktop operating systems without any customization.