--- /dev/null
+{
+ "excludeFiles": ["node_modules/**", "bower_components/**"],
+ "validateIndentation": 2,
+ "disallowKeywords": ["with", "eval", "continue", "void"],
+ "disallowKeywordsOnNewLine": ["else"],
+ "disallowMixedSpacesAndTabs": true,
+ "disallowMultipleLineStrings": true,
+ "disallowNewlineBeforeBlockStatements": true,
+ "disallowSpaceAfterObjectKeys": true,
+ "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"],
+ "disallowSpaceBeforeBinaryOperators": [","],
+ "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"],
+ "disallowSpacesInAnonymousFunctionExpression": {
+ "beforeOpeningRoundBrace": true
+ },
+ "disallowSpacesInCallExpression": true,
+ "disallowSpacesInFunctionDeclaration": {
+ "beforeOpeningRoundBrace": true
+ },
+ "disallowSpacesInNamedFunctionExpression": {
+ "beforeOpeningRoundBrace": true
+ },
+ "disallowSpacesInsideArrayBrackets": true,
+ "requireSpaceBeforeKeywords": [
+ "else",
+ "while",
+ "catch"
+ ],
+ "disallowSpacesInsideParentheses": true,
+ "disallowTrailingComma": true,
+ "disallowTrailingWhitespace": true,
+ "requireCommaBeforeLineBreak": true,
+ "requireSpaceAfterBinaryOperators": ["?", ":", "+", "-", "/", "*", "%", "==", "===", "!=", "!==", ">", ">=", "<", "<=", "&&", "||"],
+ "requireSpaceBeforeBinaryOperators": ["?", ":", "+", "-", "/", "*", "%", "==", "===", "!=", "!==", ">", ">=", "<", "<=", "&&", "||"],
+ "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"],
+ "requireSpaceBeforeBlockStatements": true,
+ "requireSpacesInConditionalExpression": {
+ "afterTest": true,
+ "beforeConsequent": true,
+ "afterConsequent": true,
+ "beforeAlternate": true
+ },
+ "requireSpacesInForStatement": true,
+ "requireSpacesInFunction": {
+ "beforeOpeningCurlyBrace": true
+ }
+}
--- /dev/null
+" *************************** Code-analysis engine for JavaScript ***************************
+
+"http://ternjs.net/
+filetype plugin indent on
+"let g:tern#command = ["node", '~/.vim/bundle/tern_for_vim/autoload' . '/../node_modules/tern/bin/tern', '--persistent']
+"Hay que buscar algo mejor: node ~/.vim/bundle/tern_for_vim/node_modules/tern/bin/tern --persistent --verbose
+let g:tern#command = ["nothing"]
+let g:tern_request_timeout = 10
+
+"https://github.com/marijnh/tern_for_vim
+let g:tern_show_argument_hints='on_hold'
+let g:tern_map_keys=1
+
+
+
+
+" *************************** https://github.com/burnettk/vim-angular ***************************
+
+
+"https://github.com/othree/javascript-libraries-syntax.vim
+let g:used_javascript_libs = 'angularjs,angularui,jasmine,jquery'
+
+"https://github.com/pangloss/vim-javascript
+set regexpengine=1
+
+"https://github.com/scrooloose/syntastic
+let oldstatusline=&statusline "save current configuration
+set statusline=
+set statusline+=%#WarningMsg# "switch to 'WarningMsg' default theme color. See available colors with command :highlight
+set statusline+=%{SyntasticStatuslineFlag()}
+set statusline+=%*
+let &statusline.=oldstatusline "concatenate configuration
+unlet oldstatusline
+let g:syntastic_always_populate_loc_list = 1
+let g:syntastic_auto_loc_list = 1
+let g:syntastic_check_on_open = 1
+let g:syntastic_check_on_wq = 0
+"http://jshint.com
+let g:syntastic_javascript_checkers = ['jshint', 'jscs']
+
+
+" *************************** Line numbers ***************************
+set number
+
+
+" *************************** Because broken editors are being used by some naïve developers ***************************
+" set binary
+" set noeol
+
+
+" *************************** Save session on quitting Vim ***************************
+autocmd VimLeave * NERDTreeClose
+autocmd VimLeave * call MakeSession()
+
+" *************************** Restore session on starting Vim ***************************
+" autocmd VimEnter * call MySessionRestoreFunction()
+autocmd VimEnter * call LoadSession()
+autocmd VimEnter * NERDTree
+
+function! MakeSession()
+ let b:sessiondir = $HOME . "/.vim/sessions" . getcwd()
+ if (filewritable(b:sessiondir) != 2)
+ exe 'silent !mkdir -p ' b:sessiondir
+ redraw!
+ endif
+ let b:filename = b:sessiondir . '/session.vim'
+ exe "mksession! " . b:filename
+endfunction
+
+function! LoadSession()
+ let b:sessiondir = $HOME . "/.vim/sessions" . getcwd()
+ let b:sessionfile = b:sessiondir . "/session.vim"
+ if (filereadable(b:sessionfile))
+ exe 'source ' b:sessionfile
+ else
+ echo "No session loaded."
+ endif
+endfunction
+
+map <lt>r :NERDTreeFind<cr>
+
+
+" *************************** Indentation ***************************
+set tabstop=2
+set shiftwidth=2
+set expandtab
+
+
+" *************************** Spelling ***************************
+"Corrección ortográfica. En consola :setlocal spell spelllang=es
+"Los diccionarios en español hay que bajárselos de aquí: http://ftp.vim.org/vim/runtime/spell/
+"y dejarlos en esta ruta: /usr/share/vim/vim72/spell
+"Ver http://plagatux.es/2008/12/correcion-ortografica-en-vim/
+"si queremos tener un fichero donde se vayan agregando las palabras que no sean reconocidas
+set spellfile=~/.vim/dict.add
+"Para habilitarlo siempre:
+"runtime plugins/spellfile.vim <----- Esto no parece necesario :(
+"setlocal spell spelllang=es
+setlocal spell spelllang=en
+" * ]s – Siguiente falta ortográfica
+" * [s - Anterior falta ortográfica
+" * z= - Mostrar sugerencias para una palabra incorrecta.
+" * zg - Añadir una palabra al diccionario.
+" * zug - Deshacer la adición de una palabra al diccionario.
+" * zw - Eliminar una palabra del diccionario.
+"set nospell para deshabilitarlo
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Javascript Tetris</title>
+ <style>
+ body { font-family: Helvetica, sans-serif; }
+ #tetris { margin: 1em auto; padding: 1em; border: 4px solid black; border-radius: 10px; background-color: #F8F8F8; }
+ #stats { display: inline-block; vertical-align: top; }
+ #canvas { display: inline-block; vertical-align: top; background-color: black; box-shadow: 10px 10px 10px #999; border: 2px solid #333; }
+ #menu { display: table-cell; vertical-align: top; position: relative; }
+ #menu p { margin: 0.5em 0; text-align: center; }
+ #menu p a { text-decoration: none; color: black; }
+ #upcoming { display: block; margin: 0 auto; background-color: black; box-shadow: 10px 10px 10px #999; border: 2px solid #333; }
+ #score { color: red; font-weight: bold; vertical-align: middle; }
+ #rows { color: blue; font-weight: bold; vertical-align: middle; }
+ #stats { position: absolute; bottom: 0em; right: 1em; }
+ @media screen and (min-width: 0px) and (min-height: 0px)
+ { #tetris { font-size: 0.75em; width: 400px; }
+ #menu { width: 200px; height: 200px; }
+ #upcoming { width: 50px; height: 50px; }
+ #canvas { width: 100px; height: 200px; }
+ } /* 10px chunks */
+ @media screen and (min-width: 400px) and (min-height: 400px)
+ { #tetris { font-size: 1.00em; width: 500px; }
+ #menu { width: 300px; height: 300px; }
+ #upcoming { width: 75px; height: 75px; }
+ #canvas { width: 150px; height: 300px; }
+ } /* 15px chunks */
+ @media screen and (min-width: 500px) and (min-height: 500px)
+ { #tetris { font-size: 1.25em; width: 600px; }
+ #menu { width: 400px; height: 400px; }
+ #upcoming { width: 100px; height: 100px; }
+ #canvas { width: 200px; height: 400px; }
+ } /* 20px chunks */
+ @media screen and (min-width: 600px) and (min-height: 600px)
+ { #tetris { font-size: 1.50em; width: 700px; }
+ #menu { width: 500px; height: 500px; }
+ #upcoming { width: 125px; height: 125px; }
+ #canvas { width: 250px; height: 500px; }
+ } /* 25px chunks */
+ @media screen and (min-width: 700px) and (min-height: 700px)
+ { #tetris { font-size: 1.75em; width: 800px; }
+ #menu { width: 600px; height: 600px; }
+ #upcoming { width: 150px; height: 150px; }
+ #canvas { width: 300px; height: 600px; }
+ } /* 30px chunks */
+ @media screen and (min-width: 800px) and (min-height: 800px)
+ { #tetris { font-size: 2.00em; width: 900px; }
+ #menu { width: 700px; height: 700px; }
+ #upcoming { width: 175px; height: 175px; }
+ #canvas { width: 350px; height: 700px; }
+ } /* 35px chunks */
+ @media screen and (min-width: 900px) and (min-height: 900px)
+ { #tetris { font-size: 2.25em; width: 1000px; }
+ #menu { width: 800px; height: 800px; }
+ #upcoming { width: 200px; height: 200px; }
+ #canvas { width: 400px; height: 800px; }
+ } /* 40px chunks */
+ </style>
+</head>
+
+<body>
+
+ <div id="tetris">
+ <div id="menu">
+ <p><canvas id="upcoming"></canvas></p>
+ </div>
+ <div style="display: table-cell">
+ <canvas id="canvas">
+ Your browser does not support the <canvas> element
+ </canvas>
+ </div>
+ <div id="menu">
+ <p>score <span id="score">00000</span></p>
+ <p>rows <span id="rows">0</span></p>
+ </div>
+ </div>
+
+ <script src="src/functions.js"></script>
+
+
+</body>
+</html>
+
--- /dev/null
+'use strict';
+
+var KEY = { ESC: 27, SPACE: 32, LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40 };
+var MAPWIDTH = 10;
+var MAPHEIGHT = 20;
+var TILEWIDTH;
+var TILEHEIGHT;
+var board;
+var boardCanvas;
+var boardContext;
+var boardUpComingCanvas;
+var upComingContext;
+var play = false;
+var score;
+var rows;
+
+
+var shapes = [
+ // Tower piece: I
+ { blocks: [0x0F00, 0x2222, 0x00F0, 0x4444], color: 'red' },
+ // The right knight piece: J
+ { blocks: [0x44C0, 0x8E00, 0x6440, 0x0E20], color: 'white' },
+ // The left knight piece: L
+ { blocks: [0x4460, 0x0E80, 0xC440, 0x2E00], color: 'purple' },
+ // The box piece: O
+ { blocks: [0xCC00, 0xCC00, 0xCC00, 0xCC00], color: 'blue' },
+ // The right leaner piece: S
+ { blocks: [0x06C0, 0x8C40, 0x6C00, 0x4620], color: 'green' },
+ // The pyramid piece: T
+ { blocks: [0x0E40, 0x4C40, 0x4E00, 0x4640], color: 'yellow' },
+ // The left leaner piece: Z
+ { blocks: [0x0C60, 0x4C80, 0xC600, 0x2640], color: 'cyan' }
+];
+
+
+
+
+
+function emptyBoard(m, n) {
+ var i;
+ var mat = [];
+ for (i = 0; i < n; i+= 1) {
+ mat[i] = [];
+ }
+
+ return mat;
+}
+
+function resize() {
+ boardCanvas = document.getElementById('canvas');
+ boardCanvas.width = boardCanvas.clientWidth;
+ boardCanvas.height = boardCanvas.clientHeight;
+ TILEWIDTH = boardCanvas.width / MAPWIDTH;
+ TILEHEIGHT = boardCanvas.height / MAPHEIGHT;
+ boardContext = boardCanvas.getContext('2d');
+
+
+ boardUpComingCanvas = document.getElementById('upcoming');
+ boardUpComingCanvas.width = boardUpComingCanvas.clientWidth;
+ boardUpComingCanvas.height = boardUpComingCanvas.clientHeight;
+ upComingContext = boardUpComingCanvas.getContext('2d');
+}
+
+function drawTile(context, color, x, y) {
+ context.fillStyle = color;
+ context.fillRect(x * TILEWIDTH, y * TILEHEIGHT, TILEWIDTH, TILEHEIGHT);
+}
+
+function getPositions(piece) {
+ var positions = [];
+ var bit;
+ var row = 0, col = 0;
+ var blocks = shapes[piece.shape].blocks[piece.rotation];
+
+ for(bit = 0x8000; bit >= 0x0001; bit = bit >> 1) {
+
+ if (blocks & bit) {
+ var position = {
+ x : piece.x + col,
+ y : piece.y + row
+ };
+ positions.push(position);
+ }
+
+ col++;
+ if (col === 4) {
+ row++;
+ col = 0;
+ }
+ }
+
+ return positions;
+}
+
+function pieceBlocks(piece, fn) {
+ var i;
+ var positions = getPositions(piece);
+ for(i = 0; i < positions.length; i += 1) {
+ if (fn(positions[i])) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+function drawPiece(context, piece) {
+ var color = shapes[piece.shape].color;
+ pieceBlocks(piece, function(position) {
+ drawTile(context, color, position.x, position.y);
+ });
+}
+
+function setPiece(board, piece) {
+ var color = shapes[piece.shape].color;
+ pieceBlocks(piece, function(position) {
+ board[position.x][position.y] = color;
+ });
+}
+
+function checkBoardBoundaries(x, y) {
+ return x === MAPWIDTH ||
+ x < 0 ||
+ y === MAPHEIGHT;
+}
+
+function checkOtherPieces(board, x, y) {
+
+ if(typeof board[x][y] !== 'undefined') {
+ return true;
+ }
+
+ return false;
+}
+
+function checkColision(board, piece) {
+ return pieceBlocks(piece, function(position) {
+ if (checkBoardBoundaries(position.x, position.y) ||
+ checkOtherPieces(board, position.x, position.y)) {
+ return true;
+ }
+
+ return false;
+ });
+}
+
+function drawBoard(board, context, m, n) {
+ var x, y;
+
+ for (x = 0; x < m; x += 1) {
+ for (y = 0; y < n; y += 1) {
+ if(typeof board[x][y] !== 'undefined') {
+ drawTile(context, board[x][y], x, y);
+ }
+ }
+ }
+
+}
+
+function checkRows(board, m, n, fn) {
+ var filled, x, y, filledLines;
+
+ filledLines = 0;
+ for (y = 0; y < n; y += 1) {
+
+ filled = true;
+ for (x = 0; x< m; x += 1) {
+ if(typeof board[x][y] === 'undefined') {
+ filled = false;
+ }
+ }
+
+ if (filled) {
+ filledLines++;
+ fn(board, m, y);
+ }
+ }
+
+ if (filledLines !== 0) {
+ updateScore(filledLines);
+ updateRows(filledLines);
+ }
+}
+
+function removeRow(board, m, n) {
+ var x, y;
+ for(x = 0; x< m; x += 1) {
+ for (y = n; y > 0; y -= 1) {
+ board[x][y] = board[x][y - 1];
+ }
+ }
+}
+
+function updateScore(n) {
+ // 1: 100
+ // 2: 200
+ // 3: 400
+ // 4: 800
+ var newScore = (100*Math.pow(2,n-1));
+ score = score + newScore;
+ document.getElementById('score').innerHTML = ('00000' + Math.floor(score)).slice(-5);
+}
+
+function updateRows(n) {
+ rows = rows + n;
+ document.getElementById('rows').innerHTML = rows;
+}
+
+function move(piece, x, y) {
+ piece.x = piece.x + x;
+ piece.y = piece.y + y;
+}
+
+function getRandomInt(min, max) {
+ return Math.floor(Math.random() * (max - min)) + min;
+}
+
+function makeRandomPiece() {
+ var shape = getRandomInt(0, 7);
+ var rotation = getRandomInt(0, 4);
+ var piece = {
+ shape: shape,
+ rotation: rotation
+ };
+
+ return piece;
+}
+
+// 10 secs
+var last = null;
+var step = 1000;
+var currentPiece;
+var upComingPiece;
+
+
+
+// TODO: polyfill
+function frame(timestamp) {
+ if (!play) {
+ return;
+ }
+
+ if (!last) {
+ last = timestamp;
+ }
+ var progress = timestamp - last;
+ if (progress >= step) {
+
+ var forwardPiece = {
+ shape: currentPiece.shape,
+ rotation: currentPiece.rotation,
+ x: currentPiece.x,
+ y: currentPiece.y + 1
+ };
+
+
+ if (checkColision(board, forwardPiece)) {
+ setPiece(board, currentPiece);
+
+ checkRows(board, MAPWIDTH, MAPHEIGHT, function(board, m, n) {
+ removeRow(board, m, n);
+ });
+
+
+ currentPiece = upComingPiece;
+ currentPiece.x = 2;
+ currentPiece.y = -1;
+
+ upComingPiece = makeRandomPiece();
+ upComingPiece.x = 1;
+ upComingPiece.y = 1;
+ }
+
+ move(currentPiece, 0, 1);
+
+ boardContext.clearRect(0, 0, boardCanvas.width, boardCanvas.height);
+ drawBoard(board, boardContext, MAPWIDTH, MAPHEIGHT);
+ drawPiece(boardContext, currentPiece);
+
+ upComingContext.clearRect(0, 0, boardUpComingCanvas.width, boardUpComingCanvas.height);
+ drawPiece(upComingContext, upComingPiece);
+
+ last = timestamp;
+ }
+ window.requestAnimationFrame(frame);
+}
+
+function init() {
+ currentPiece = makeRandomPiece();
+ currentPiece.x = 2;
+ currentPiece.y = -1;
+ upComingPiece = makeRandomPiece();
+ upComingPiece.x = 1;
+ upComingPiece.y = 1;
+
+ score = 0;
+ document.getElementById('score').innerHTML = '00000';
+
+ rows = 0;
+ document.getElementById('rows').innerHTML = '0';
+
+ board = emptyBoard(MAPWIDTH, MAPHEIGHT);
+ resize();
+
+ window.requestAnimationFrame(frame);
+}
+
+function keydown(ev) {
+
+ switch(ev.keyCode) {
+ case KEY.ESC:
+ play = false;
+ ev.preventDefault();
+ break;
+ case KEY.SPACE:
+ play = true;
+ init();
+ ev.preventDefault();
+ break;
+ }
+
+ if (!play) {
+ return;
+ }
+ var forwardPiece = {
+ shape: currentPiece.shape,
+ rotation: currentPiece.rotation,
+ x: currentPiece.x,
+ y: currentPiece.y
+ };
+ switch(ev.keyCode) {
+ case KEY.LEFT:
+ move(forwardPiece, -1, 0);
+ if (!checkColision(board, forwardPiece)) {
+ move(currentPiece, -1, 0);
+ boardContext.clearRect(0, 0, boardCanvas.width, boardCanvas.height);
+ drawBoard(board, boardContext, MAPWIDTH, MAPHEIGHT);
+ drawPiece(boardContext, currentPiece);
+ }
+ ev.preventDefault();
+ break;
+ case KEY.RIGHT:
+ move(forwardPiece, 1, 0);
+ if (!checkColision(board, forwardPiece)) {
+ move(currentPiece, 1, 0);
+ boardContext.clearRect(0, 0, boardCanvas.width, boardCanvas.height);
+ drawBoard(board, boardContext, MAPWIDTH, MAPHEIGHT);
+ drawPiece(boardContext, currentPiece);
+ }
+ ev.preventDefault();
+ break;
+ case KEY.UP:
+ var rotation = (forwardPiece.rotation + 1) % 4;
+ forwardPiece.rotation = rotation;
+ if (!checkColision(board, forwardPiece)) {
+ currentPiece.rotation = rotation;
+ boardContext.clearRect(0, 0, boardCanvas.width, boardCanvas.height);
+ drawBoard(board, boardContext, MAPWIDTH, MAPHEIGHT);
+ drawPiece(boardContext, currentPiece);
+ }
+ ev.preventDefault();
+ break;
+ case KEY.DOWN:
+ move(forwardPiece, 0, 1);
+ if (checkColision(board, forwardPiece)) {
+ setPiece(board, currentPiece);
+
+ checkRows(board, MAPWIDTH, MAPHEIGHT, function(board, m, n) {
+ removeRow(board, m, n);
+ });
+
+ currentPiece = upComingPiece;
+ currentPiece.x = 2;
+ currentPiece.y = -1;
+
+ upComingPiece = makeRandomPiece();
+ upComingPiece.x = 1;
+ upComingPiece.y = 1;
+ }
+
+ move(currentPiece, 0, 1);
+
+ boardContext.clearRect(0, 0, boardCanvas.width, boardCanvas.height);
+ drawBoard(board, boardContext, MAPWIDTH, MAPHEIGHT);
+ drawPiece(boardContext, currentPiece);
+
+ upComingContext.clearRect(0, 0, boardUpComingCanvas.width, boardUpComingCanvas.height);
+ drawPiece(upComingContext, upComingPiece);
+
+ ev.preventDefault();
+ break;
+ }
+}
+
+function addEvents() {
+ document.addEventListener('keydown', keydown, false);
+ window.addEventListener('resize', resize, false);
+}
+
+addEvents();
+
+
+