ControllerPad Tutorial

The tabageos ControllerPad Class is used to handle keyboard, touch, and usb game pad input, and optional mouse input.
It is used in conjunction with css that is applied to the page.
There are 3 built in controller pad images that can be accessed, and you can use your own custom image.
This tutorial will go over basic defalt use of the ConttrollerPad and how to make your own custom pad.

-------


For basic default use of the ControllerPad include tbgs_min.js, ControllerPad.js and ControllerPad.css in your html,
Then make a div for the controller, giving it an id of 'controller' for example.
The controller div should be inside of an overall 'container' div, but not inside of the 'root' games' div.
Below is an example of a basic layout:
		...
			<script type="text/javascript" src="tbgs_min.js"></script>
			<link rel="stylesheet" href="ControllerPad.css" />
			<script type="text/javascript" src="ControllerPad.js"></script>
			    
			...
			
			<div id="container" style="position:absolute;left:0px;top:0px;margin:0px">
				<div id="root" style="position:relative;top:0px;left:0px;overflow:hidden"> </div>
				<div id="controller" > </div>
			</div>
		
		

Basic use of the ControllerPad:
	
			
			//An instance of ControllerPad is created with a reference to the controller div.
			var controller = new tabageos.ControllerPad(document.getElementById("controller"),0, 0, 640, 144);
			
			//the x and y and width and height passed during instantiation are place holders, they dont actually position the controller, just sets its own properties.
			//the css you give the 'container' div, and the show method together with the tabageos static ResizeGame method are what are used to position the controller.
			//when making a custom image the important specs are sent via the customControllerButtonSetup method as we will see below.
			
			
			//we call establish to establish all events that the controller will use.
			controller.establish( );
			//basicControllerButtonSetup is one of the default methods we can use to set up the image and associated button positions for the controller.
			//there is also directionalsControllerButtonSetup, standardControllerButtonSetup, rotationalControllerButtonSetup and customControllerButtonSetup which we will use below.
			controller.basicControllerButtonSetup();
			//acceptWASDAndArrows does what it says, we call this function to quickly set up the capture of both wasd and the arrow keys for movement.
			controller.acceptWASDAndArrows();
			
			
			//for usb game input we handle it in a loop with two methods from the ControllerPad Class.
			//configureGamePadButtons and handleGamePad, in our loop we check for if the gamePadButtonsUserDefined property is 1.
			//if not then we call configureGamePadButtons.
			//and when it is 1 we call handleGamePad instead.
			
			//There can only be one instance of the ControllerPad, in this tutorial we are using the instance to create a SimonSays game, which is the last example below.
			//therefore what is here is the basic code needed to set up the controller, and what each default controller image looks like.
			
			//The following is what the basicController looks like.
			
		};
		



Directionals controller:
			var controller = new tabageos.ControllerPad(document.getElementById("controller"),0, 0, 640, 191);
			controller.establish( );
			controller.directionalsControllerButtonSetup();
			controller.acceptWASDAndArrows();
		
			//this is what the directionals controller looks like.
		



Standard Controller:
		
			var controller = new tabageos.ControllerPad(document.getElementById("controller"),0, 0, 737, 144);
			controller.establish( );
			controller.standardControllerButtonSetup();
			controller.acceptWASDAndArrows();
		
			//this is what the standard controller looks like.
		
		


Rotation Controller:
		
			var controller = new tabageos.ControllerPad(document.getElementById("controller"),0, 0, 737, 192);
			controller.establish( );
			controller.rotationalControllerButtonSetup();
			controller.acceptWASDAndArrows();
			
			controller.centerRotationX = 0 (if the game is fullscreen) or ((window.innerWidth/2) - halfGameWidth)  + 80;  (roughly 32 to 80, you need to test it with dev tools)
			controller.centerRotationY = 0 (if the game is fullscreen) or (whatever amount of space is above the game) + (the game height) + 72; (roughly 32 to 80, test it with dev tools)
		
			//centerRotationX and centerRotationY should define the middle point of the rotation circle on the whole screen.
		
			//this is what the rotationcontroller looks like.
		
		




A simple Simon Says game using the ControllerPad with a custom controller image:

		
			(function() {
		
				var sequence = [1,1,4];
				var sequences = [  [1,1,4,4], [1,1,4,4], [1,1,4,4,3], [1,1,4,4,3,4], [1,1,4,4,3,4,1], [1,1,4,4,3,4,1,2]  ];
				var nextSeq = -1;
				var seqLett = {l1:"A",l2:"B",l3:"C",l4:"D"};
				var seqI = -1;
				var pressDelay = 1200;
				var pressTime = 0;
				var turn = 0;
				var tally = [];
				
				var _aid;
				var _thrott = 0;
				var pr;

				function SimonSays() {
					//a simon says game using the ControllerPads custom functionalities.
					this._event = new tabageos.Event("mousedown");//not a JavaScript Event. 
					//It just has basic properties to fake an event when needed including preventDefault, and for the tabageos simple event system.
				}
				SimonSays.prototype = new Object();
				SimonSays.prototype._event;
				SimonSays.prototype.init = function(e) {
					
					
					controller = new tabageos.ControllerPad(document.getElementById("simonsayscontroller"),0, 0,  491, 345);
					controller.enableMouseControl();//enableMouseControl must be called before establish. 
					//By default there is no mouse controll, using enableMouseControl enables the controller to be clicked also.
					//Establish actually adds the events to be used. 
					controller.establish( );
					
					controller.addCustomImage("simonerImg.png", "simonSays");//load the custom image for the controller, in this case its the image of our simon says game.
					//we could instead edit the css file directly if we want. 
					//The base 64 code for the default images is part of the css, that is how those images are handled.
					//addCustomImage adds the image we pass to be the background of the controllers containing div, editing the css for us.
					//the 'controller' div will be given the id of 'simonSays' instead, and css for 'simonSays' divs will be applied to the page with the image as its no-repeat background.
					//we can pass the image location or the stringed base64 code.
						
					var np = new tabageos.MoverPoint(-7777,-7777);
						
						//we define the top left point of each button in our image, the top left corner of the image being 0,0. A program like Gimp is good for getting these points.
						//the ControllerPad class will automatically size and move all the buttons, we're not passing the position of the buttons on the page, but the positions as they are in our image.
						//and we pass in the width and height for the buttons, and then the overall width and height of the whole image.
						//The ControllerPad.show method along with tabageos.ResizeGame method will take care of all repositioning/resizing that is needed.
						//tabageos.ResizeGame method would call .show for us, in this example we do not need to call ResizeGame, to see the ControllerPad in gameplay action see some of the examples. https://tabageos.com/examples
						
						//in this example the directionals  and back button are not being used so we pass in off screen points for them, and make their width and height 1.
						
						//the params of the customControllerButtonSetup method are..
						//left right up down start back abutton bbutton cbutton dbutton directionalWidth directionalHeight startAndBackW startAndBackH buttonW buttonH imageWidth imageHeight.
						
						
					controller.customControllerButtonSetup(np, np, np, np,new tabageos.MoverPoint(180,11),np, 
						new tabageos.MoverPoint(5,11), new tabageos.MoverPoint(366,11), new tabageos.MoverPoint(5,227), new tabageos.MoverPoint(366, 227),
						1,1,125,58, 119,107, 491, 345 );
							
					controller._dontAbsolutePositionHolder = 1;//dont change the position style attribute of the div that is holding the controller.
					//because in this case the controller needs to be relative positioned since its under relative content.
					
					controller.acceptWASDAndArrows();
					
					controller.showButtons(1);//this method is used to display the actual rectangle hit regions of each button, when we pass 1 it will only show the region of the button that is pressed. 
					//to turn off the button show when pressed functionality we would pass -1 to showButtons.
					//by default the buttons do not change when pressed, but for this tutorial we will actively utilize this feature.
					//You could choose to use it too in your games if you wanted, or if your game needs it, and the following two properties are availble for such cases.
					
					controller._buttonRectColor = "#c8c8c855";//we change the color of the button rectangles.
					//the last two numbers are alpha values, we give it a 55 alpha which blends it into the button images nicely.
					
					//_addedButtonRectStyle lets us add whatever css we want, it gets added to each non directional button rectangle.
					//so in this case we add a high border-raidus and it makes the rects become circles.
					controller._addedButtonRectStyle = "border-radius: 500%;";
					
					
					//assignStartAndBackMethods assigns methods for start and back that get called whenever start or back is pressed.
					//in this case the back button is not being used.
					//these are simple tabageos.Events that fire causing the method to happen, not normal JavaScript events.
					//ControllerPad extends tabageos EventDispatcher.
					controller.assignStartAndBackMethods("beginSimonSays","beginSimonSays", SimonSays.game);
					
					//show displays the controller at the given size, with the given style.
					//in this case the controller is positioned by the div that it is inside of.
					controller.show(491,345,"simonSays");//if we pass numbers that are different than the original width height of our image it will scale.
					//the buttons and their positions will automatically scale as well.
					
					
					//we only want one definite press per touch so we remove touch move handling.			
					controller.removeTouchMove();
				};
				
				SimonSays.prototype.beginSimonSays = function() { //triggered by start being clicked or touched or shift being pressed.
					seqI = -1; pressTime = 0; turn = 0; tally.length = 0;
					sequence = [1,1,4]; nextSeq = -1;
					document.getElementById("tallyDisplay").innerText = "Simon Says";
					if(_aid) window.cancelAnimationFrame(_aid);
					_aid = window.requestAnimationFrame(this.loop);
				};
				
				SimonSays.game = null;
				SimonSays.device = 0;
				
				SimonSays.establish = function() {
					SimonSays.game = new SimonSays();
					SimonSays.game.init(null);
					SimonSays.resize();
					window.addEventListener('resize', SimonSays.resize, false);
					window.addEventListener('orientationchange', SimonSays.resize, false);
				};
				
				SimonSays.prototype.loop = function(ts) {
					if(_thrott == 0) _thrott = ts;pr = ts - _thrott;//manual looping with the timestamp.
					if(pr >= 15) {
						
						if(pressTime >= pressDelay && turn == 0) {	//when its computers turn, after some milliseconds of delay.
							seqI += 1;//increment the current sequence.
							if(seqI <= sequence.length-1) { //if there is a button to press remaining in the sequence
								//press that button
								SimonSays.game._event.type = "mousedown";
								SimonSays.game._event.target = controller["button"+seqLett["l"+sequence[seqI]]];//for example controller.buttonA, which is an html div.
								controller.dispatch(SimonSays.game._event);//manual dispatch of a 'mousedown' event, the event is a tabagoes.Event and not an actual JavaScript Event.
								
							} else { //when current sequence has finished its the users turn.
								turn = 1;
								tally.length = 0;//at this point the whole length of the sequence is over, turn is changed to 1 and press time is set back to 0, but not used again until the player is finished.
							}
							pressTime = 0;//reset pressTime so that there is a delay in between each computer press, otherwise would not be able to see multiple presses of the same button.
							//while there is still length to the sequence, the pressTime count starts over, 1200 milliseconds, then the next button to be pressed is pressed.
							//and halfway through the count, the previous button is released.
							//thereby the effect of a button being pressed and released by the computer is achieved.
							
						} else {
						
							if(turn == 0) { //if computer turn.
								pressTime += 33.3; //delay between each press.
								if(pressTime >= pressDelay/2) { 
									SimonSays.game._event.type = "mouseup";//let go of last press.
									controller.dispatch(SimonSays.game._event);
								}
							
							} else { //if users turn, track what they press and tally it.
							
								if(controller.buttons.a) { //if a button is pressed.
									tally.push(1);controller.buttons.a = 0;//set to 0 because we are in a loop, so we set to 0 so that it does not continually push into tally.
								}
								if(controller.buttons.b) {
									tally.push(2);controller.buttons.b = 0;
								}
								if(controller.buttons.c) {
									tally.push(3);controller.buttons.c = 0;
								}
								if(controller.buttons.d) {
									tally.push(4);controller.buttons.d = 0;
								}
								if(tally.length >= sequence.length) { //if amount of buttons pressed is the same as sequence amount.
								
									var i = 0; var l = tally.length;
									for(i; i < l; i++) { //if tally mismatch from sequence, game over.
										if(tally[i] != sequence[i]) {
											document.getElementById("tallyDisplay").innerText = "Incorrect, press start to try again"; 
											//return will exist out of the whole loop function, requestAnimationFrame is not called again, therefore start needs to be pressed to start the loop method again.
											return;
										}
									}
									
									nextSeq += 1;
									if(nextSeq >= 6) {//if all sequences have been run, game complete.
										document.getElementById("tallyDisplay").innerText = "You've matched all the sequences! Press start to play again"; return;
									}
									//otherwise ready the next sequence.
									sequence = sequences[nextSeq];
									
									i = 0; l = sequence.length;
									for(i;i < l;i++) { //make it random.
										sequence[i] = Math.floor(Math.random() * 4) + 1;
									}
									//show that seqence was matched.
									document.getElementById("tallyDisplay").innerText = "Correct!" + " You've matched "+ (nextSeq + 1) + ". Now try this sequence:";
									//reset variables to run the next sequence.
									turn = 0;
									seqI = -1;
									tally.length = 0;
									pressTime = -1240;//give an extra second before starting.
								}
							}
						}
						_thrott = ts;
						
					}
					_aid = window.requestAnimationFrame(SimonSays.game.loop);
				
				};
					
				SimonSays.resize = function() { 
					SimonSays.device = tabageos.seekTouch();
					var scaleRatio = ((window.innerWidth / 800) / 100)  + 1;
					
						
					
					
					if(!SimonSays.device) { 
						document.querySelector("#codeexplane").setAttribute("style", "position:relative;top:75px;width:100%;margin: 0 auto;text-align:center");
						document.querySelector("#tutorial").setAttribute("style", "position:relative;top:75px;width:99%;font-size:18px;font-family:'serif';margin: 0 auto"); 
					} else { 
						document.querySelector("#codeexplane").setAttribute("style", "position:relative;top:75px;width:99%;margin: 0 auto;text-align:center");
						document.querySelector("#tutorial").setAttribute("style", "position:relative;top:175px;width:99%;font-size:18px;font-family:'serif';margin: 0 auto"); 
					}
				};
				
				SimonSays.establish();
	
			})();
		
		


Simon Says









back to top