connected orthogonally. This, like dominoes and pentominoes, is a particular type of polyomino. The corresponding polycube, called a tetracube, is a geometric shape composed of fourcubes connected orthogonally.
Tetromino([[1,0], [2,0], [0,1], [1, 1]]); }); ! describe('#new', function(){ ... it('sets a default color', function(){ expect(tetromino.color).toEqual('#FFFFFF') }) ... describe('#rotateRight', function(){ beforeEach(function(){ tetromino.rotateRight(); }) ! it('rotates the tetromino to the right', function(){ // - X X // X X - ! // X - // X X // - X expect(tetromino.grid[0][0]).toBe(1); expect(tetromino.grid[0][1]).toBe(0); ! expect(tetromino.grid[1][0]).toBe(1); expect(tetromino.grid[1][1]).toBe(1); ! expect(tetromino.grid[2][0]).toBe(0); expect(tetromino.grid[2][1]).toBe(1); }) It’s very easy to break things ( syntax issues, bad scoping, etc..). - Go mad on TDD. ! Jasmine is great for unit testing spec/tetromino_spec.js
currentY. ! - Increment currentY and check if the future game grid positions are 0. If so means the Tetromino can safely move. it('returns false when row 0th is all filled', function(){ // Fill the first row of grid with non-nil // values. moveDown returns false because // he can't move down. for(var i = 0; i < Game.HORIZONTAL_SPACES; ++i ) game.grid[0][i] = 1 ! expect(game.moveDown()).toBe(false); }) it('returns false when there is an obstacle on the way', function(){ game.moveDown(); game.moveDown(); // - - - X - - - - - - // - - - X X X - - - - ! // Introduce the obstacle // - - - X - - - - - - // - - o X X X - - - - // - - o o - - - - - - game.grid[1][2] = 1 game.grid[2][2] = 1 game.grid[2][3] = 1 ! expect(game.moveDown()).toBe(false) })
elements from the grid. This will be important for painting later. - Tetromino grid is still present on it’s inner object but it’s irrelevant tetromino will have 0 references so it will be garbage collected tetromino still has a reference so it’s kept
should have lowest complexity as possible > drawing needs to be snappy > Problem: only measurable through your experience ! Backend is all built > we just need to draw ! Options: > CSS and messing around with positions ( only if you are crazy ) > WebGL ( weird and unsupported APIs ) > Canvas
styling || Canvas || WebGL - Optimises concurrent animations into a single reflow and repaint cycle - If you are running the animation loop in a tab that’s not visible, the browser won’t keep it running
animFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || null ; ! if(animFrame !== null) { var recursiveAnim = function() { mainloop(); animFrame(recursiveAnim, canvas); }; animFrame(recursiveAnim, canvas); } else { var ONE_FRAME_TIME = 1000.0 / 60.0 ; setInterval(mainloop, ONE_FRAME_TIME); } ! function updateGame(){ if(!game.canMoveDown()){ game.removeCompletedRows(); game.next(); } } ! function drawGame(){ gamePresenter.clear(); gamePresenter.draw(); } All browsers have their variant of animation frame • Unsupported browsers it does still work but animation might be worse Easiest way to draw is in every loop just clean everything and draw again Mainloop • Do game logic ✓Handle user events (left, right, …) ✓Handle game events (completed rows) • Draw current game logic Drawing
tests, 179 assertions, 0 failures, 0 skipped! 1 language: node_js! 2 node_js:! 3 - "0.11"! Make it public and benefit from the easy testing provided by Travis CI that can run node out of the box. ! It installs all dependencies on the package.json and runs by default npm test. .travis.yml