In the previous parts of our series on detecting collisions we discussed HTML and CSS. Then, we analysed what exactly JS should do. Today, we’ll look into the keypad support. Even though it isn’t very innovative, it may help you incorporate handling the user input in your project. Let’s get started!
3. Support for the keypad
We won’t write anything new here – it’s just a standard support for JavaScript events.
/* On key down event */
function isKeyDown(e) {
/* left */
if (e.keyCode === 37 ) {
e.preventDefault();
movingObj.isMovingLeft = true;
}
/* right */
if (e.keyCode === 39) {
e.preventDefault();
movingObj.isMovingRight = true;
}
/* top */
if( e.keyCode === 38) {
e.preventDefault();
movingObj.isMovingTop = true;
}
/* down */
if(e.keyCode === 40) {
e.preventDefault();
movingObj.isMovingDown = true;
}
}
/* On key up event */
function isKeyUp(e) {
/* left */
if (e.keyCode === 37 ) {
e.preventDefault();
movingObj.isMovingLeft = false;
}
/* right */
if (e.keyCode === 39) {
e.preventDefault();
movingObj.isMovingRight = false;
}
/* top */
if( e.keyCode === 38) {
e.preventDefault();
movingObj.isMovingTop = false;
}
/* down */
if(e.keyCode === 40) {
e.preventDefault();
movingObj.isMovingDown = false;
}
}
/* Add key events to document */
function addKeyEvents() {
$(document)
.on('keydown', isKeyDown)
.on('keyup', isKeyUp);
}
/* Initiate key events */
addKeyEvents();
A few words of explanation to start with:
e.preventDefault() – prevents the default behaviour of keypad cursors;
movingObj – a movable JS object, which we’ll soon create and control using a keypad;
isMovingLeft, isMovingRight, isMovingTop, isMovingDown – attributes of the above-mentioned movingObj object which determine whether the object is to move in a specific direction or to stay in place;
addKeyEvents() – function linking a document with defined events related to the moment of pressing a key and releasing it. Don’t forget to call it!
4. Creating a JS class characterising all fetched elements
At this point, we need to define a class constructor common for all elements:
/* General JS class for all elements */
var collisionClass = function(obj) {
this.cssObj = obj;
this.cssWidth = parseInt(this.cssObj.css("width"));
this.cssHeight = parseInt(this.cssObj.css("height"));
this.matrix = this.cssObj.css("transform"); // returns matrix(1, 0, 0, 1, x, y)
this.arrayPos = this.matrix.match(/(-?[0-9\.]+)/g); // get values from brackets
this.posXmin = parseInt(this.arrayPos[4]); // returns position X - top left
this.posYmin = parseInt(this.arrayPos[5]); // returns position Y - top left
this.posXmax = this.posXmin + this.cssWidth; // bottom right
this.posYmax = this.posYmin + this.cssHeight; // bottom right
this.isMovingLeft = false;
this.isMovingRight = false;
this.isMovingTop = false;
this.isMovingDown = false;
}
The class consists of a few fields, which should be briefly explained:
cssObj – a jQuery object transmitted as a constructor’s argument;
cssWidth, cssHeight – width and height of CSS in the form of an integer;
matrix – a matrix fetched by jQuery containing transform3d parameters; it takes the form of a String, e.g. matrix(1, 0, 0, 1, 0, 0), in which the two last values are the coordinates that we’re interested in: x and y respectively;
arrayPos – a field containing an attribute of the matrix in the form of an array with values, including the required x and y coordinates; after processing the value of the matrix attribute by regular expressions, the arrayPos field takes a form such as [ 1, 0, 0, 1, 0, 0];
posXmin, posYmin – the x and y coordinates fetched from arrayPos (the left top corner of a <div>); they will be used for checking occurrence of collisions;
posXmax, posYmax – the x and y coordinates of the right bottom corner of a <div>; they will also be used for checking occurrence of collisions;
isMovingLeft, isMovingRight, isMovingTop, isMovingDown – attributes which define the direction of the object’s movement in relation to keypad events.
5. Method displaying and refreshing the new position of the objects
Each time we press the cursor, the movingObj referred to in point 3 should cover a predetermined distance. We’ll set this distance (in pixels) using a global variable “speed”:
/* Global variable */
var speed = 8; // pixels
In accordance with the above, every time the cursor is pressed, the object will change its position by 8 pixels. You can increase or reduce the value of the variable speed as you wish.
Then, having the variable in place, we should add a draw() method responsible for refreshing the movingObj position systematically in the context of the control loop:
/* Draw new position of moving element */
collisionClass.prototype.draw = function() {
/* Left */
if (this.isMovingLeft) {
this.posXmin -= speed;
}
/* Right */
if (this.isMovingRight) {
this.posXmin += speed;
}
/* Top */
if (this.isMovingTop) {
this.posYmin -= speed;
}
/* Down */
if (this.isMovingDown) {
this.posYmin += speed;
}
/* Use our function to draw new position of moving element */
setPosition(this.cssObj, this.posXmin+'px', this.posYmin+'px', 0);
/* Call the posXmax and posYmax refresh */
this.refreshXYmax();
}
As you can see, this method is not complicated. After pressing the cursor, the isMovingLeft, isMovingRight, isMovingTop or isMovingDown attribute is given the value TRUE. The draw() method makes sure that the value actually is TRUE and, when it gets a confirmation in the form of e.g. this.isMovingLeft === TRUE, it knows whether the horizontal position should be changed: whether it should be increased or reduced by the value of the speed global variable. Releasing a keypad key will reset the attribute to FALSE and stop the movement. The whole operation will be performed in every iteration of the main control loop and as a result we’ll get an impression of movement of the movingObj object.
At the end of the method’s body we can see the following fragment of the code:
/* Use our function to draw new position of moving element */
setPosition(this.cssObj, this.posXmin+'px', this.posYmin+'px', 0);
/* Call the posXmax and posYmax refresh */
this.refreshXYmax();
We’re already familiar with the first function. It’s the setPosition() function that sets transform3d of the jQuery object. We haven’t learned about the implementation of the refreshXYmax() method yet, so let’s do it next:
/* Refresh posXmax and posYmax after movement */
collisionClass.prototype.refreshXYmax = function() {
this.posXmax = this.posXmin + this.cssWidth; // bottom right
this.posYmax = this.posYmin + this.cssHeight; // bottom right
}
The method is responsible for refreshing the posXmax and posYmax attributes, since only the posXmin and posYmin attributes are related to the setPosition() function. Just to remind you: the posXmin and posYmin attributes will be used for checking geometrical conditions in order to detect collisions.
At the end of this stage, let’s specify all our objects:
/* Instantiate moving object */
movingObj = new collisionClass($objInMotion);
/* Global variable */
var staticObjArray = []; // there will be stored all static elements
/* Define array of all static objects and instantiate them */
$objs.each(function(index) {
if ($(this).hasClass('static')) {
staticObjArray.push(new collisionClass($(this)));
}
});
We’ll store all static objects in the array staticObjArray, since checking collisions should take place via iterations. However, please note that the iterations won’t be strictly referring to the main control loop.
The last part of tips on detecting jQuery collisions is coming soon, so stay tuned!