var canvas = document.getElementById('fuTris'); var context = canvas.getContext('2d'); canvas.width = 10*20*2+10+(5*20); canvas.height = 16*20*2; var field = []; var background = []; var game_running = true; var subframe = 0; var moved_steps = 0; var speed = 100; var points = 0; var level = 0; var stones = 0; var pos = {left: 4, top: 0}; var angle = 0; var shapes = [ // J [[[0,1], [0,1], [1,1]], [[1,0,0], [1,1,1]], [[1,1], [1,0], [1,0]], [[1,1,1], [0,0,1]]], // [] [[[2,2], [2,2]]], // T [[[3,3,3], [0,3,0]], [[0,3], [3,3], [0,3]], [[0,3,0], [3,3,3]], [[3,0], [3,3], [3,0]]], // L [[[4,4], [0,4], [0,4]], [[0,0,4], [4,4,4]], [[4,0], [4,0], [4,4]], [[4,4,4], [4,0,0]]], // 5 [[[0,5,5], [5,5,0]], [[5,0], [5,5], [0,5]]], // Z [[[6,6,0], [0,6,6]], [[0,6], [6,6], [6,0]]], // ---- [[[7,7,7,7]], [[7], [7], [7], [7]]] ]; var colors = ['c1e184', '4f6c19', '699021', '8fc32e', '1a2308']; var assets = { rotate: document.getElementById('rotate-sound'), drop: document.getElementById('drop-sound'), move: document.getElementById('move-sound'), point: document.getElementById('point-sound') }; var audio_chanels = []; var current_shape_type = 0; var next_shape_type = Math.ceil(Math.random()*shapes.length-1); var current_shape = shapes[current_shape_type]; function shape(type, angle) { var s = shapes[type]; switch (s.length) { case 1: return s[0]; case 2: return s[angle%2]; case 4: return s[angle]; } } function rect(x, y, w, h, scale, color) { context.fillStyle = '#'+color; context.fillRect(x*scale, y*scale, w*scale, h*scale); } function draw_shape(x, y, scale, type, angle) { for (var xi=0; xi 1 ? 2 : 0; rect(x*20+1, y*20+1, 18, 18, scale, colors[color_offset+1]); rect(x*20+2, y*20+2, 16, 16, scale, colors[color_offset]); // J, L, Z if ([0, 3, 5].indexOf(i) != -1) { rect(x*20+5, y*20+5, 10, 10, scale, colors[{0: 2, 3: 0, 5: 4}[i]]); rect(x*20+8, y*20+8, 4, 4, scale, colors[{0: 0, 3: 2, 5: 0}[i]]); } // [] if (i == 1) rect(x*20+5, y*20+5, 10, 10, scale, colors[4]); // 5 if (i ==4) rect(x*20+8, y*20+8, 4, 4, scale, colors[4]); // T if (i == 2) { rect(x*20+5, y*20+5, 8, 8, scale, colors[0]); rect(x*20+7, y*20+7, 8, 8, scale, colors[4]); rect(x*20+7, y*20+7, 6, 6, scale, colors[2]); } // ---- if (i == 6) { rect(x*20+5, y*20+6, 3, 3, scale, colors[0]); rect(x*20+5, y*20+12, 3, 3, scale, colors[0]); rect(x*20+11, y*20+4, 3, 3, scale, colors[0]); rect(x*20+13, y*20+12, 3, 3, scale, colors[0]); } } function draw() { // game background rect(0, 0, canvas.width, canvas.height, 1, '000'); // game field background for (var x=0; x<10; x++) for (var y=0; y<16; y++) { rect(x*20, y*20, 20, 20, 2, background[x][y]); if (field[x][y] !== 0) draw_brick(x, y, 2, field[x][y]-1); } // Current shape draw_shape(pos.left, pos.top, 2, current_shape_type, angle); // Next shape draw_shape(21, 1, 1, next_shape_type, 0); // Score draw_text(points, 30, 420, 130); draw_text('Points', 13, 420, 150); // Level draw_text(level, 30, 420, 230); draw_text('Level', 13, 420, 250); // Game over? if (!game_running) { draw_text("Game over", 60, 40, 250); draw_text("Press R for a new game", 20, 140, 270); } } function noice(offset, level) { return offset+~~(Math.random()*level); } function freeze() { for (var x=0; x0; yy--) for (var xx=0; xx<10; xx++) field[xx][yy] = field[xx][yy-1]; for (var xx=0; xx<10; xx++) field[xx][0] = 0; } } if (number_of_lines == 1) points += 10; if (number_of_lines == 2) points += 25; if (number_of_lines == 3) points += 50; if (number_of_lines == 4) points += 100; if (number_of_lines > 0) play_sound('point'); } function play_sound(name) { // Search for a free audio channel to play the sound for (var a=0; a 20) { level++; stones = 0; } pos.left = 4; pos.top = 0; current_shape_type = next_shape_type; next_shape_type = Math.ceil(Math.random()*shapes.length-1); current_shape = shapes[current_shape_type]; } function will_collide(_angle, _pos) { for (var x=0; x= 16 || shape(current_shape_type, _angle)[y][x] !== 0 && field[_pos.left+x][_pos.top+y+1] !== 0) return true; } addEventListener('keydown', function(event) { if (game_running) { // Move left if ((event.keyCode == 37 || event.keyCode == 72) && pos.left > 0 && !will_collide(angle, {left: pos.left-1, top: pos.top})) { pos.left--; play_sound('move'); draw(); } // Move right if ((event.keyCode == 39 || event.keyCode == 76) && pos.left < 10-shape(current_shape_type, angle)[0].length && !will_collide(angle, {left: pos.left+1, top: pos.top})) { pos.left++; play_sound('move'); draw(); } // Rotate if (event.keyCode == 38 || event.keyCode == 75) { var new_angle = angle === 0 ? 3 : angle-1; if (pos.left+shape(current_shape_type, new_angle)[0].length <= 10 && !will_collide(new_angle, pos)) angle = new_angle; play_sound('rotate'); draw(); } // Drop if (event.keyCode == 40 || event.keyCode == 74) { while(!will_collide(angle, {left: pos.left, top: pos.top+1})) pos.top++; pos.top++; points += 2; freeze(); clear_full_lines(); next_shape(); play_sound('drop'); draw(); } } // Pause the game if (event.keyCode == 13 || event.keyCode == 80) { game_running = !game_running; if (game_running) loop(); } // Restart the game if (event.keyCode == 82 && !game_running) { init(); } }); function init() { speed = 100; points = 0; level = 0; stones = 0; game_running = true; subframe = 0; moved_steps = 0; for (var x=0; x<10; x++) for (var y=0; y<16; y++) field[x][y] = 0; // Start the game next_shape(); loop(); } function loop() { // Move the next step subframe++; if (subframe-speed > 0.0) { subframe = 0; speed = 100-(level*15); // Check if we get blocked by the already dropped shapes +function() { if (will_collide(angle, pos)) { freeze(); clear_full_lines(); next_shape(); // Game over? if (moved_steps === 0 || will_collide(0, {left: 4, top: 0})) game_running = false; moved_steps = 0; return true; } return false; }() || (pos.top++ && moved_steps++); draw(); } if (game_running) setTimeout(loop, 5); } function setup() { // Load the assets assets.rotate.load(); assets.drop.load(); assets.move.load(); assets.point.load(); // Init the audio chanels for (var a=0; a<10; a++) { audio_chanels[a] = { channel: new Audio(), finished: -1 }; } // Initialize the game field and the background for (var x=0; x<10; x++) { field[x] = []; background[x] = []; for (var y=0; y<16; y++) { var mod = noice(15, 15); background[x][y] = '' + mod + mod + mod; field[x][y] = 0; } } } setup(); init();