├── .gitignore
├── share-image.png
├── ambient
├── css
│ └── styles.css
├── index.html
├── custom
│ ├── color_manager.js
│ ├── random_piece_generator.js
│ └── piece.js
└── js
│ └── index.js
├── classic
├── css
│ └── styles.css
├── index.html
├── custom
│ ├── random_piece_generator.js
│ ├── piece.js
│ ├── game_manager.js
│ └── draw_functions.js
└── js
│ └── index.js
├── colored_classic
├── css
│ └── styles.css
├── index.html
├── custom
│ ├── random_piece_generator.js
│ ├── piece.js
│ ├── game_manager.js
│ └── draw_functions.js
└── js
│ └── index.js
├── readme.md
├── package.json
├── core
└── js
│ ├── random_piece_generator.js
│ ├── updater.js
│ ├── ai.js
│ ├── utils.js
│ ├── piece.js
│ ├── game_manager.js
│ └── grid.js
├── gulpfile.js
├── styles.css
└── index.html
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
--------------------------------------------------------------------------------
/share-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tholman/tetris-pieces/HEAD/share-image.png
--------------------------------------------------------------------------------
/ambient/css/styles.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Styles!
3 | */
4 |
5 | * {
6 | box-sizing: border-box;
7 | }
8 |
9 | html, body {
10 | min-height: 100%;
11 | min-width: 100%;
12 | margin: 0px;
13 | width: 0px;
14 | height: 100%;
15 | overflow: hidden;
16 | }
17 |
18 | canvas {
19 | background: #fff;
20 | position: absolute;
21 | bottom: 0px;
22 | }
23 |
--------------------------------------------------------------------------------
/classic/css/styles.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Styles!
3 | */
4 |
5 | * {
6 | box-sizing: border-box;
7 | }
8 |
9 | html, body {
10 | min-height: 100%;
11 | min-width: 100%;
12 | margin: 0px;
13 | width: 0px;
14 | height: 100%;
15 | overflow: hidden;
16 | }
17 |
18 | canvas {
19 | background: #C6CFA4;
20 | position: absolute;
21 | bottom: 0px;
22 | }
23 |
--------------------------------------------------------------------------------
/colored_classic/css/styles.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Styles!
3 | */
4 |
5 | * {
6 | box-sizing: border-box;
7 | }
8 |
9 | html, body {
10 | min-height: 100%;
11 | min-width: 100%;
12 | margin: 0px;
13 | width: 0px;
14 | height: 100%;
15 | overflow: hidden;
16 | }
17 |
18 | canvas {
19 | background: #fff;
20 | position: absolute;
21 | bottom: 0px;
22 | }
23 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Tetris Pieces, for the electric object
2 |
3 | A visual artificially intelligent tetris, built to be displayed on your wall. You can see them in action [here](http://tholman.com/tetris-pieces).
4 |
5 | This is the source for the styalized version for the electric object.
6 |
7 | The source of the AI running behind the scenes is built by the incredible Yiyuan
8 |
9 | 
10 |
--------------------------------------------------------------------------------
/ambient/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Tetris AI
7 |
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/ambient/custom/color_manager.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Color Manager
3 | * - Handles the slow hue rotations of colors
4 | */
5 |
6 | function ColorManager( baseColor ){
7 | this.hueRotation = 0;
8 | this.rotationSpeed = 4;
9 | this.baseColor = '#F0C9DD'; // Light pink
10 | };
11 |
12 | ColorManager.prototype.getColor = function(){
13 |
14 | // Rotate hue's for every new piece.
15 | this.hueRotation += this.rotationSpeed;
16 | if( this.hueRotation > 360 ) {
17 | this.hueRotation = 0;
18 | }
19 |
20 | return changeHue(this.baseColor, this.hueRotation);
21 | };
--------------------------------------------------------------------------------
/classic/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Tetris AI
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/colored_classic/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Tetris AI
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tetris",
3 | "version": "1.0.0",
4 | "description": "Tetris Sims for the Electric Object",
5 | "main": "gulpfile.js",
6 | "dependencies": {},
7 | "devDependencies": {
8 | "gulp": "^3.9.1"
9 | },
10 | "scripts": {
11 | "test": "echo \"Error: no test specified\" && exit 1"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "git+https://github.com/tholman/electric-object-tetris.git"
16 | },
17 | "author": "",
18 | "license": "ISC",
19 | "bugs": {
20 | "url": "https://github.com/tholman/electric-object-tetris/issues"
21 | },
22 | "homepage": "https://github.com/tholman/electric-object-tetris#readme"
23 | }
24 |
--------------------------------------------------------------------------------
/core/js/random_piece_generator.js:
--------------------------------------------------------------------------------
1 | function RandomPieceGenerator(){
2 | Math.seed
3 | this.bag = [0, 1, 2, 3, 4, 5, 6];
4 | this.shuffleBag();
5 | this.index = -1;
6 |
7 | this.colorManager = new ColorManager();
8 | };
9 |
10 | RandomPieceGenerator.prototype.nextPiece = function(){
11 |
12 | this.index++;
13 | if (this.index >= this.bag.length){
14 | this.shuffleBag();
15 | this.index = 0;
16 | }
17 |
18 | var color = this.colorManager.getColor();
19 |
20 | return Piece.fromIndex(this.bag[this.index], color);
21 |
22 | };
23 |
24 | RandomPieceGenerator.prototype.shuffleBag = function() {
25 | var currentIndex = this.bag.length
26 | , temporaryValue
27 | , randomIndex
28 | ;
29 |
30 | // While there remain elements to shuffle...
31 | while (0 !== currentIndex) {
32 |
33 | // Pick a remaining element...
34 | randomIndex = Math.floor(Math.random() * currentIndex);
35 | currentIndex -= 1;
36 |
37 | // And swap it with the current element.
38 | temporaryValue = this.bag[currentIndex];
39 | this.bag[currentIndex] = this.bag[randomIndex];
40 | this.bag[randomIndex] = temporaryValue;
41 | }
42 | };
--------------------------------------------------------------------------------
/classic/custom/random_piece_generator.js:
--------------------------------------------------------------------------------
1 | function RandomPieceGenerator(){
2 | Math.seed
3 | this.bag = [0, 1, 2, 3, 4, 5, 6];
4 | this.shuffleBag();
5 | this.index = -1;
6 |
7 | this.drawFunctions = new DrawFunctions();
8 | };
9 |
10 | RandomPieceGenerator.prototype.nextPiece = function(){
11 |
12 | this.index++;
13 | if (this.index >= this.bag.length){
14 | this.shuffleBag();
15 | this.index = 0;
16 | }
17 |
18 | return Piece.fromIndex(this.bag[this.index], this.drawFunctions.getDrawFunction(this.bag[this.index]));
19 |
20 | };
21 |
22 | RandomPieceGenerator.prototype.shuffleBag = function() {
23 | var currentIndex = this.bag.length
24 | , temporaryValue
25 | , randomIndex
26 | ;
27 |
28 | // While there remain elements to shuffle...
29 | while (0 !== currentIndex) {
30 |
31 | // Pick a remaining element...
32 | randomIndex = Math.floor(Math.random() * currentIndex);
33 | currentIndex -= 1;
34 |
35 | // And swap it with the current element.
36 | temporaryValue = this.bag[currentIndex];
37 | this.bag[currentIndex] = this.bag[randomIndex];
38 | this.bag[randomIndex] = temporaryValue;
39 | }
40 | };
--------------------------------------------------------------------------------
/ambient/custom/random_piece_generator.js:
--------------------------------------------------------------------------------
1 | function RandomPieceGenerator(){
2 | Math.seed
3 | this.bag = [0, 1, 2, 3, 4, 5, 6];
4 | this.shuffleBag();
5 | this.index = -1;
6 |
7 | this.colorManager = new ColorManager();
8 | };
9 |
10 | RandomPieceGenerator.prototype.nextPiece = function(){
11 |
12 | this.index++;
13 | if (this.index >= this.bag.length){
14 | this.shuffleBag();
15 | this.index = 0;
16 | }
17 |
18 | var color = this.colorManager.getColor();
19 |
20 | return Piece.fromIndex(this.bag[this.index], color);
21 |
22 | };
23 |
24 | RandomPieceGenerator.prototype.shuffleBag = function() {
25 | var currentIndex = this.bag.length
26 | , temporaryValue
27 | , randomIndex
28 | ;
29 |
30 | // While there remain elements to shuffle...
31 | while (0 !== currentIndex) {
32 |
33 | // Pick a remaining element...
34 | randomIndex = Math.floor(Math.random() * currentIndex);
35 | currentIndex -= 1;
36 |
37 | // And swap it with the current element.
38 | temporaryValue = this.bag[currentIndex];
39 | this.bag[currentIndex] = this.bag[randomIndex];
40 | this.bag[randomIndex] = temporaryValue;
41 | }
42 | };
--------------------------------------------------------------------------------
/colored_classic/custom/random_piece_generator.js:
--------------------------------------------------------------------------------
1 | function RandomPieceGenerator(){
2 | Math.seed
3 | this.bag = [0, 1, 2, 3, 4, 5, 6];
4 | this.shuffleBag();
5 | this.index = -1;
6 |
7 | this.drawFunctions = new DrawFunctions();
8 | };
9 |
10 | RandomPieceGenerator.prototype.nextPiece = function(){
11 |
12 | this.index++;
13 | if (this.index >= this.bag.length){
14 | this.shuffleBag();
15 | this.index = 0;
16 | }
17 |
18 | return Piece.fromIndex(this.bag[this.index], this.drawFunctions.getDrawFunction(this.bag[this.index]));
19 |
20 | };
21 |
22 | RandomPieceGenerator.prototype.shuffleBag = function() {
23 | var currentIndex = this.bag.length
24 | , temporaryValue
25 | , randomIndex
26 | ;
27 |
28 | // While there remain elements to shuffle...
29 | while (0 !== currentIndex) {
30 |
31 | // Pick a remaining element...
32 | randomIndex = Math.floor(Math.random() * currentIndex);
33 | currentIndex -= 1;
34 |
35 | // And swap it with the current element.
36 | temporaryValue = this.bag[currentIndex];
37 | this.bag[currentIndex] = this.bag[randomIndex];
38 | this.bag[randomIndex] = temporaryValue;
39 | }
40 | };
--------------------------------------------------------------------------------
/core/js/updater.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Updater, controls time and speed.
3 | */
4 |
5 | function Updater() {
6 | this.lastUpdateTime = Date.now();
7 | this.deltaThreshold = 250; // MS before each update
8 | this.updateCallback = null;
9 |
10 | window.requestAnimFrame = (function() {
11 | // Polyfill
12 | return (
13 | window.requestAnimationFrame ||
14 | window.webkitRequestAnimationFrame ||
15 | window.mozRequestAnimationFrame ||
16 | window.oRequestAnimationFrame ||
17 | window.msRequestAnimationFrame ||
18 | function(callback) {
19 | window.setTimeout(callback, 1000 / 60);
20 | }
21 | );
22 | })();
23 | }
24 |
25 | Updater.prototype.onUpdate = function(callback) {
26 | this.updateCallback = callback;
27 | };
28 |
29 | Updater.prototype.doUpdate = function(timestamp) {
30 | if (this.updateCallback != null) {
31 | this.updateCallback();
32 | }
33 |
34 | this.lastUpdateTime = timestamp;
35 | };
36 |
37 | Updater.prototype.checkUpdate = function(timestamp) {
38 | var self = this;
39 | var delta = timestamp - this.lastUpdateTime;
40 |
41 | if (delta > this.deltaThreshold) {
42 | this.doUpdate(timestamp);
43 | }
44 |
45 | window.requestAnimFrame(function() {
46 | self.checkUpdate(Date.now());
47 | });
48 | };
49 |
--------------------------------------------------------------------------------
/core/js/ai.js:
--------------------------------------------------------------------------------
1 | function AI(heightWeight, linesWeight, holesWeight, bumpinessWeight){
2 |
3 | this.heightWeight = heightWeight;
4 | this.linesWeight = linesWeight;
5 | this.holesWeight = holesWeight;
6 | this.bumpinessWeight = bumpinessWeight;
7 |
8 | };
9 |
10 | AI.prototype.best = function(grid, workingPieces, workingPieceIndex){
11 |
12 | var best = null;
13 | var bestScore = null;
14 | var workingPiece = workingPieces[workingPieceIndex];
15 |
16 | for(var rotation = 0; rotation < 4; rotation++){
17 | var _piece = workingPiece.clone();
18 | _piece.rotate(rotation);
19 |
20 | while(grid.canMoveLeft(_piece)){
21 | _piece.column --;
22 | }
23 |
24 | while(grid.valid(_piece)){
25 | var _pieceSet = _piece.clone();
26 | while(grid.canMoveDown(_pieceSet)){
27 | _pieceSet.row++;
28 | }
29 |
30 | var _grid = grid.clone();
31 | _grid.addPiece(_pieceSet);
32 |
33 | var score = null;
34 | if (workingPieceIndex == (workingPieces.length - 1)) {
35 | score = -this.heightWeight * _grid.aggregateHeight() + this.linesWeight * _grid.lines() - this.holesWeight * _grid.holes() - this.bumpinessWeight * _grid.bumpiness();
36 | }else{
37 | score = this.best(_grid, workingPieces, workingPieceIndex + 1).score;
38 | }
39 |
40 | if (score > bestScore || bestScore == null){
41 | bestScore = score;
42 | best = _piece.clone();
43 | }
44 |
45 | _piece.column++;
46 | }
47 | }
48 |
49 | return {piece:best, score:bestScore};
50 | };
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Tetris Concats
3 | *
4 | */
5 |
6 | var gulp = require('gulp');
7 | var concat = require('gulp-concat');
8 |
9 | gulp.task('ambient-tetris', function() {
10 | gulp
11 | .src([
12 | './core/js/utils.js',
13 | './ambient/custom/color_manager.js',
14 | './core/js/grid.js',
15 | './ambient/custom/piece.js',
16 | './core/js/game_manager.js',
17 | './ambient/custom/random_piece_generator.js',
18 | './core/js/ai.js',
19 | './core/js/updater.js'
20 | ])
21 | .pipe(concat('index.js'))
22 | .pipe(gulp.dest('./ambient/js/'));
23 | });
24 |
25 | gulp.task('classic-tetris', function() {
26 | gulp
27 | .src([
28 | './classic/custom/draw_functions.js',
29 | './core/js/grid.js',
30 | './classic/custom/piece.js',
31 | './classic/custom/game_manager.js',
32 | './classic/custom/random_piece_generator.js',
33 | './core/js/ai.js',
34 | './core/js/updater.js'
35 | ])
36 | .pipe(concat('index.js'))
37 | .pipe(gulp.dest('./classic/js/'));
38 | });
39 |
40 | gulp.task('colored-classic-tetris', function() {
41 | gulp
42 | .src([
43 | './colored_classic/custom/draw_functions.js',
44 | './core/js/grid.js',
45 | './colored_classic/custom/piece.js',
46 | './colored_classic/custom/game_manager.js',
47 | './colored_classic/custom/random_piece_generator.js',
48 | './core/js/ai.js',
49 | './core/js/updater.js'
50 | ])
51 | .pipe(concat('index.js'))
52 | .pipe(gulp.dest('./colored_classic/js/'));
53 | });
54 |
55 | gulp.task('watch', function() {
56 | gulp.watch(['./ambient/custom/*', './core/js/*'], ['ambient-tetris']);
57 | gulp.watch(['./classic/custom/*', './core/js/*'], ['classic-tetris']);
58 | gulp.watch(
59 | ['./colored_classic/custom/*', './core/js/*'],
60 | ['colored-classic-tetris']
61 | );
62 | });
63 |
--------------------------------------------------------------------------------
/styles.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | html,
6 | body {
7 | margin: 0px;
8 | padding: 0px;
9 | }
10 |
11 | body {
12 | font-family: 'Open Sans', sans-serif;
13 | border: 20px solid #fff;
14 | background: #eee;
15 | padding-top: 80px;
16 | }
17 |
18 | section {
19 | width: 100%;
20 | }
21 |
22 | iframe {
23 | box-sizing: content-box;
24 | border: 20px solid #fff;
25 | height: 390px;
26 | width: 240px;
27 | }
28 |
29 | h1,
30 | h2 {
31 | font-weight: normal;
32 | margin-top: 0px;
33 | }
34 |
35 | h1 {
36 | margin-bottom: 50px;
37 | margin-top: 20px;
38 | font-size: 60px;
39 | }
40 |
41 | h2 {
42 | margin-bottom: 0px;
43 | }
44 |
45 | a {
46 | color: #335fff;
47 | text-decoration: none;
48 | }
49 |
50 | header {
51 | line-height: 28px;
52 | text-align: center;
53 | max-width: 620px;
54 | font-size: 18px;
55 | margin: auto;
56 | margin-bottom: 100px;
57 | padding-left: 20px;
58 | padding-right: 20px;
59 | }
60 |
61 | section {
62 | display: flex;
63 | max-width: 940px;
64 | margin: auto;
65 | margin-bottom: 100px;
66 | padding-left: 20px;
67 | padding-right: 20px;
68 | }
69 |
70 | .showcase {
71 | display: flex;
72 | flex-direction: row;
73 | justify-content: space-between;
74 | }
75 |
76 | .explaination {
77 | padding-left: 100px;
78 | display: flex;
79 | flex-direction: column;
80 | justify-content: center;
81 | }
82 |
83 | footer {
84 | padding-left: 50px;
85 | margin: auto;
86 | text-align: center;
87 | padding-right: 50px;
88 | padding-bottom: 50px;
89 | }
90 |
91 | /**
92 | * Responsive
93 | */
94 |
95 | @media (max-width: 800px) {
96 | .explaination {
97 | padding-left: 50px;
98 | }
99 | }
100 |
101 | @media (max-width: 650px) {
102 | h1 {
103 | line-height: 66px;
104 | }
105 |
106 | header {
107 | margin-bottom: 50px;
108 | }
109 |
110 | header p {
111 | font-size: 16px;
112 | }
113 |
114 | .showcase {
115 | flex-direction: column;
116 | }
117 |
118 | .frame {
119 | margin: auto;
120 | margin-bottom: 50px;
121 | }
122 |
123 | .explaination {
124 | padding-left: 0px;
125 | }
126 |
127 | section:nth-child(odd) {
128 | background: rgba(255, 255, 255, 0.5);
129 | padding-bottom: 50px;
130 | margin-bottom: 50px;
131 | padding-top: 50px;
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/core/js/utils.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | // http://stackoverflow.com/questions/17433015/change-the-hue-of-a-rgb-color-in-javascript
4 | // TODO: Clean up
5 |
6 | function changeHue(rgb, degree) {
7 | var hsl = rgbToHSL(rgb);
8 | hsl.h += degree;
9 | if (hsl.h > 360) {
10 | hsl.h -= 360;
11 | }
12 | else if (hsl.h < 0) {
13 | hsl.h += 360;
14 | }
15 | return hslToRGB(hsl);
16 | }
17 |
18 | // exepcts a string and returns an object
19 | function rgbToHSL(rgb) {
20 | // strip the leading # if it's there
21 | rgb = rgb.replace(/^\s*#|\s*$/g, '');
22 |
23 | // convert 3 char codes --> 6, e.g. `E0F` --> `EE00FF`
24 | if(rgb.length == 3){
25 | rgb = rgb.replace(/(.)/g, '$1$1');
26 | }
27 |
28 | var r = parseInt(rgb.substr(0, 2), 16) / 255,
29 | g = parseInt(rgb.substr(2, 2), 16) / 255,
30 | b = parseInt(rgb.substr(4, 2), 16) / 255,
31 | cMax = Math.max(r, g, b),
32 | cMin = Math.min(r, g, b),
33 | delta = cMax - cMin,
34 | l = (cMax + cMin) / 2,
35 | h = 0,
36 | s = 0;
37 |
38 | if (delta == 0) {
39 | h = 0;
40 | }
41 | else if (cMax == r) {
42 | h = 60 * (((g - b) / delta) % 6);
43 | }
44 | else if (cMax == g) {
45 | h = 60 * (((b - r) / delta) + 2);
46 | }
47 | else {
48 | h = 60 * (((r - g) / delta) + 4);
49 | }
50 |
51 | if (delta == 0) {
52 | s = 0;
53 | }
54 | else {
55 | s = (delta/(1-Math.abs(2*l - 1)))
56 | }
57 |
58 | return {
59 | h: h,
60 | s: s,
61 | l: l
62 | }
63 | }
64 |
65 | // expects an object and returns a string
66 | function hslToRGB(hsl) {
67 | var h = hsl.h,
68 | s = hsl.s,
69 | l = hsl.l,
70 | c = (1 - Math.abs(2*l - 1)) * s,
71 | x = c * ( 1 - Math.abs((h / 60 ) % 2 - 1 )),
72 | m = l - c/ 2,
73 | r, g, b;
74 |
75 | if (h < 60) {
76 | r = c;
77 | g = x;
78 | b = 0;
79 | }
80 | else if (h < 120) {
81 | r = x;
82 | g = c;
83 | b = 0;
84 | }
85 | else if (h < 180) {
86 | r = 0;
87 | g = c;
88 | b = x;
89 | }
90 | else if (h < 240) {
91 | r = 0;
92 | g = x;
93 | b = c;
94 | }
95 | else if (h < 300) {
96 | r = x;
97 | g = 0;
98 | b = c;
99 | }
100 | else {
101 | r = c;
102 | g = 0;
103 | b = x;
104 | }
105 |
106 | r = normalize_rgb_value(r, m);
107 | g = normalize_rgb_value(g, m);
108 | b = normalize_rgb_value(b, m);
109 |
110 | return rgbToHex(r,g,b);
111 | }
112 |
113 | function normalize_rgb_value(color, m) {
114 | color = Math.floor((color + m) * 255);
115 | if (color < 0) {
116 | color = 0;
117 | }
118 | return color;
119 | }
120 |
121 | function rgbToHex(r, g, b) {
122 | return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
123 | }
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Tetris Pieces
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | Tetris Pieces
32 |
33 | A visual artificially intelligent tetris, built to be displayed on your wall.
34 |
35 | You can fork this, or check out the code on GitHub ... or look at the original (and smart!) source of the AI running behind the scenes, built by the incredible Yiyuan
36 |
37 | These pieces can be displayed via Electric Object (here ).
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
58 |
59 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/core/js/piece.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Piece
3 | * - Represents a single piece on the board.
4 | */
5 |
6 | // Object that represents a single piece & its properties.
7 | function Piece(cells, color){
8 | this.cells = cells;
9 | this.dimension = this.cells.length;
10 | this.row = 0;
11 | this.column = 0;
12 | this.color = color;
13 | };
14 |
15 | Piece.fromIndex = function(index, color){
16 |
17 | var cells
18 |
19 | switch (index){
20 | case 0:// O
21 | cells = [
22 | [1, 1],
23 | [1, 1]
24 | ];
25 | break;
26 | case 1: // J
27 | cells = [
28 | [1, 0, 0],
29 | [1, 1, 1],
30 | [0, 0, 0]
31 | ];
32 | break;
33 | case 2: // L
34 | cells = [
35 | [0, 0, 1],
36 | [1, 1, 1],
37 | [0, 0, 0]
38 | ];
39 | break;
40 | case 3: // Z
41 | cells = [
42 | [1, 1, 0],
43 | [0, 1, 1],
44 | [0, 0, 0]
45 | ];
46 | break;
47 | case 4: // S
48 | cells = [
49 | [0, 1, 1],
50 | [1, 1, 0],
51 | [0, 0, 0]
52 | ];
53 | break;
54 | case 5: // T
55 | cells = [
56 | [0, 1, 0],
57 | [1, 1, 1],
58 | [0, 0, 0]
59 | ];
60 | break;
61 | case 6: // I
62 | cells = [
63 | [0, 0, 0, 0],
64 | [1, 1, 1, 1],
65 | [0, 0, 0, 0],
66 | [0, 0, 0, 0]
67 | ];
68 | break;
69 |
70 | }
71 |
72 | var piece = new Piece(cells, color);
73 |
74 | piece.row = 0;
75 | piece.column = Math.floor((10 - piece.dimension) / 2); // Centralize
76 | return piece;
77 | };
78 |
79 | Piece.prototype.clone = function(){
80 |
81 | var _cells = new Array(this.dimension);
82 | for (var r = 0; r < this.dimension; r++) {
83 | _cells[r] = new Array(this.dimension);
84 | for(var c = 0; c < this.dimension; c++){
85 | _cells[r][c] = this.cells[r][c];
86 | }
87 | }
88 |
89 | var piece = new Piece(_cells, this.color);
90 | piece.row = this.row;
91 | piece.column = this.column;
92 | return piece;
93 | };
94 |
95 | Piece.prototype.rotate = function(rotations){
96 | for(var i = 0; i < rotations; i++) {
97 | var _cells = new Array(this.dimension);
98 | for (var r = 0; r < this.dimension; r++) {
99 | _cells[r] = new Array(this.dimension);
100 | }
101 |
102 | switch (this.dimension) { // Assumed square matrix
103 | case 2:
104 | _cells[0][0] = this.cells[1][0];
105 | _cells[0][1] = this.cells[0][0];
106 | _cells[1][0] = this.cells[1][1];
107 | _cells[1][1] = this.cells[0][1];
108 | break;
109 | case 3:
110 | _cells[0][0] = this.cells[2][0];
111 | _cells[0][1] = this.cells[1][0];
112 | _cells[0][2] = this.cells[0][0];
113 | _cells[1][0] = this.cells[2][1];
114 | _cells[1][1] = this.cells[1][1];
115 | _cells[1][2] = this.cells[0][1];
116 | _cells[2][0] = this.cells[2][2];
117 | _cells[2][1] = this.cells[1][2];
118 | _cells[2][2] = this.cells[0][2];
119 | break;
120 | case 4:
121 | _cells[0][0] = this.cells[3][0];
122 | _cells[0][1] = this.cells[2][0];
123 | _cells[0][2] = this.cells[1][0];
124 | _cells[0][3] = this.cells[0][0];
125 | _cells[1][3] = this.cells[0][1];
126 | _cells[2][3] = this.cells[0][2];
127 | _cells[3][3] = this.cells[0][3];
128 | _cells[3][2] = this.cells[1][3];
129 | _cells[3][1] = this.cells[2][3];
130 | _cells[3][0] = this.cells[3][3];
131 | _cells[2][0] = this.cells[3][2];
132 | _cells[1][0] = this.cells[3][1];
133 |
134 | _cells[1][1] = this.cells[2][1];
135 | _cells[1][2] = this.cells[1][1];
136 | _cells[2][2] = this.cells[1][2];
137 | _cells[2][1] = this.cells[2][2];
138 | break;
139 | }
140 |
141 | this.cells = _cells;
142 | }
143 | };
144 |
--------------------------------------------------------------------------------
/ambient/custom/piece.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Piece
3 | * - Represents a single piece on the board.
4 | */
5 |
6 | // Object that represents a single piece & its properties.
7 | function Piece(cells, color){
8 | this.cells = cells;
9 | this.dimension = this.cells.length;
10 | this.row = 0;
11 | this.column = 0;
12 | this.color = color;
13 | };
14 |
15 | Piece.fromIndex = function(index, color){
16 |
17 | var cells
18 |
19 | switch (index){
20 | case 0:// O
21 | cells = [
22 | [1, 1],
23 | [1, 1]
24 | ];
25 | break;
26 | case 1: // J
27 | cells = [
28 | [1, 0, 0],
29 | [1, 1, 1],
30 | [0, 0, 0]
31 | ];
32 | break;
33 | case 2: // L
34 | cells = [
35 | [0, 0, 1],
36 | [1, 1, 1],
37 | [0, 0, 0]
38 | ];
39 | break;
40 | case 3: // Z
41 | cells = [
42 | [1, 1, 0],
43 | [0, 1, 1],
44 | [0, 0, 0]
45 | ];
46 | break;
47 | case 4: // S
48 | cells = [
49 | [0, 1, 1],
50 | [1, 1, 0],
51 | [0, 0, 0]
52 | ];
53 | break;
54 | case 5: // T
55 | cells = [
56 | [0, 1, 0],
57 | [1, 1, 1],
58 | [0, 0, 0]
59 | ];
60 | break;
61 | case 6: // I
62 | cells = [
63 | [0, 0, 0, 0],
64 | [1, 1, 1, 1],
65 | [0, 0, 0, 0],
66 | [0, 0, 0, 0]
67 | ];
68 | break;
69 |
70 | }
71 |
72 | var piece = new Piece(cells, color);
73 |
74 | piece.row = 0;
75 | piece.column = Math.floor((10 - piece.dimension) / 2); // Centralize
76 | return piece;
77 | };
78 |
79 | Piece.prototype.clone = function(){
80 |
81 | var _cells = new Array(this.dimension);
82 | for (var r = 0; r < this.dimension; r++) {
83 | _cells[r] = new Array(this.dimension);
84 | for(var c = 0; c < this.dimension; c++){
85 | _cells[r][c] = this.cells[r][c];
86 | }
87 | }
88 |
89 | var piece = new Piece(_cells, this.color);
90 | piece.row = this.row;
91 | piece.column = this.column;
92 | return piece;
93 | };
94 |
95 | Piece.prototype.rotate = function(rotations){
96 | for(var i = 0; i < rotations; i++) {
97 | var _cells = new Array(this.dimension);
98 | for (var r = 0; r < this.dimension; r++) {
99 | _cells[r] = new Array(this.dimension);
100 | }
101 |
102 | switch (this.dimension) { // Assumed square matrix
103 | case 2:
104 | _cells[0][0] = this.cells[1][0];
105 | _cells[0][1] = this.cells[0][0];
106 | _cells[1][0] = this.cells[1][1];
107 | _cells[1][1] = this.cells[0][1];
108 | break;
109 | case 3:
110 | _cells[0][0] = this.cells[2][0];
111 | _cells[0][1] = this.cells[1][0];
112 | _cells[0][2] = this.cells[0][0];
113 | _cells[1][0] = this.cells[2][1];
114 | _cells[1][1] = this.cells[1][1];
115 | _cells[1][2] = this.cells[0][1];
116 | _cells[2][0] = this.cells[2][2];
117 | _cells[2][1] = this.cells[1][2];
118 | _cells[2][2] = this.cells[0][2];
119 | break;
120 | case 4:
121 | _cells[0][0] = this.cells[3][0];
122 | _cells[0][1] = this.cells[2][0];
123 | _cells[0][2] = this.cells[1][0];
124 | _cells[0][3] = this.cells[0][0];
125 | _cells[1][3] = this.cells[0][1];
126 | _cells[2][3] = this.cells[0][2];
127 | _cells[3][3] = this.cells[0][3];
128 | _cells[3][2] = this.cells[1][3];
129 | _cells[3][1] = this.cells[2][3];
130 | _cells[3][0] = this.cells[3][3];
131 | _cells[2][0] = this.cells[3][2];
132 | _cells[1][0] = this.cells[3][1];
133 |
134 | _cells[1][1] = this.cells[2][1];
135 | _cells[1][2] = this.cells[1][1];
136 | _cells[2][2] = this.cells[1][2];
137 | _cells[2][1] = this.cells[2][2];
138 | break;
139 | }
140 |
141 | this.cells = _cells;
142 | }
143 | };
144 |
--------------------------------------------------------------------------------
/classic/custom/piece.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Piece
3 | * - Represents a single piece on the board.
4 | */
5 |
6 | // Object that represents a single piece & its properties.
7 | function Piece(cells, color){
8 | this.cells = cells;
9 | this.dimension = this.cells.length;
10 | this.row = 0;
11 | this.column = 0;
12 | this.color = color;
13 | };
14 |
15 | Piece.fromIndex = function(index, color){
16 |
17 | var cells
18 |
19 | switch (index){
20 | case 0:// O
21 | cells = [
22 | [1, 1],
23 | [1, 1]
24 | ];
25 | break;
26 | case 1: // J
27 | cells = [
28 | [1, 0, 0],
29 | [1, 1, 1],
30 | [0, 0, 0]
31 | ];
32 | break;
33 | case 2: // L
34 | cells = [
35 | [0, 0, 1],
36 | [1, 1, 1],
37 | [0, 0, 0]
38 | ];
39 | break;
40 | case 3: // Z
41 | cells = [
42 | [1, 1, 0],
43 | [0, 1, 1],
44 | [0, 0, 0]
45 | ];
46 | break;
47 | case 4: // S
48 | cells = [
49 | [0, 1, 1],
50 | [1, 1, 0],
51 | [0, 0, 0]
52 | ];
53 | break;
54 | case 5: // T
55 | cells = [
56 | [0, 1, 0],
57 | [1, 1, 1],
58 | [0, 0, 0]
59 | ];
60 | break;
61 | case 6: // I
62 | cells = [
63 | [0, 0, 0, 0],
64 | [2, 3, 4, 5],
65 | [0, 0, 0, 0],
66 | [0, 0, 0, 0]
67 | ];
68 | break;
69 |
70 | }
71 |
72 | var piece = new Piece(cells, color);
73 |
74 | piece.row = 0;
75 | piece.column = Math.floor((10 - piece.dimension) / 2); // Centralize
76 | return piece;
77 | };
78 |
79 | Piece.prototype.clone = function(){
80 |
81 | var _cells = new Array(this.dimension);
82 | for (var r = 0; r < this.dimension; r++) {
83 | _cells[r] = new Array(this.dimension);
84 | for(var c = 0; c < this.dimension; c++){
85 | _cells[r][c] = this.cells[r][c];
86 | }
87 | }
88 |
89 | var piece = new Piece(_cells, this.color);
90 | piece.row = this.row;
91 | piece.column = this.column;
92 | return piece;
93 | };
94 |
95 | Piece.prototype.rotate = function(rotations){
96 | for(var i = 0; i < rotations; i++) {
97 | var _cells = new Array(this.dimension);
98 | for (var r = 0; r < this.dimension; r++) {
99 | _cells[r] = new Array(this.dimension);
100 | }
101 |
102 | switch (this.dimension) { // Assumed square matrix
103 | case 2:
104 | _cells[0][0] = this.cells[1][0];
105 | _cells[0][1] = this.cells[0][0];
106 | _cells[1][0] = this.cells[1][1];
107 | _cells[1][1] = this.cells[0][1];
108 | break;
109 | case 3:
110 | _cells[0][0] = this.cells[2][0];
111 | _cells[0][1] = this.cells[1][0];
112 | _cells[0][2] = this.cells[0][0];
113 | _cells[1][0] = this.cells[2][1];
114 | _cells[1][1] = this.cells[1][1];
115 | _cells[1][2] = this.cells[0][1];
116 | _cells[2][0] = this.cells[2][2];
117 | _cells[2][1] = this.cells[1][2];
118 | _cells[2][2] = this.cells[0][2];
119 | break;
120 | case 4:
121 | _cells[0][0] = this.cells[3][0];
122 | _cells[0][1] = this.cells[2][0];
123 | _cells[0][2] = this.cells[1][0];
124 | _cells[0][3] = this.cells[0][0];
125 | _cells[1][3] = this.cells[0][1];
126 | _cells[2][3] = this.cells[0][2];
127 | _cells[3][3] = this.cells[0][3];
128 | _cells[3][2] = this.cells[1][3];
129 | _cells[3][1] = this.cells[2][3];
130 | _cells[3][0] = this.cells[3][3];
131 | _cells[2][0] = this.cells[3][2];
132 | _cells[1][0] = this.cells[3][1];
133 |
134 | _cells[1][1] = this.cells[2][1];
135 | _cells[1][2] = this.cells[1][1];
136 | _cells[2][2] = this.cells[1][2];
137 | _cells[2][1] = this.cells[2][2];
138 | break;
139 | }
140 |
141 | this.cells = _cells;
142 | }
143 | };
144 |
--------------------------------------------------------------------------------
/colored_classic/custom/piece.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Piece
3 | * - Represents a single piece on the board.
4 | */
5 |
6 | // Object that represents a single piece & its properties.
7 | function Piece(cells, color){
8 | this.cells = cells;
9 | this.dimension = this.cells.length;
10 | this.row = 0;
11 | this.column = 0;
12 | this.color = color;
13 | };
14 |
15 | Piece.fromIndex = function(index, color){
16 |
17 | var cells
18 |
19 | switch (index){
20 | case 0:// O
21 | cells = [
22 | [1, 1],
23 | [1, 1]
24 | ];
25 | break;
26 | case 1: // J
27 | cells = [
28 | [1, 0, 0],
29 | [1, 1, 1],
30 | [0, 0, 0]
31 | ];
32 | break;
33 | case 2: // L
34 | cells = [
35 | [0, 0, 1],
36 | [1, 1, 1],
37 | [0, 0, 0]
38 | ];
39 | break;
40 | case 3: // Z
41 | cells = [
42 | [1, 1, 0],
43 | [0, 1, 1],
44 | [0, 0, 0]
45 | ];
46 | break;
47 | case 4: // S
48 | cells = [
49 | [0, 1, 1],
50 | [1, 1, 0],
51 | [0, 0, 0]
52 | ];
53 | break;
54 | case 5: // T
55 | cells = [
56 | [0, 1, 0],
57 | [1, 1, 1],
58 | [0, 0, 0]
59 | ];
60 | break;
61 | case 6: // I
62 | cells = [
63 | [0, 0, 0, 0],
64 | [2, 3, 4, 5],
65 | [0, 0, 0, 0],
66 | [0, 0, 0, 0]
67 | ];
68 | break;
69 |
70 | }
71 |
72 | var piece = new Piece(cells, color);
73 |
74 | piece.row = 0;
75 | piece.column = Math.floor((10 - piece.dimension) / 2); // Centralize
76 | return piece;
77 | };
78 |
79 | Piece.prototype.clone = function(){
80 |
81 | var _cells = new Array(this.dimension);
82 | for (var r = 0; r < this.dimension; r++) {
83 | _cells[r] = new Array(this.dimension);
84 | for(var c = 0; c < this.dimension; c++){
85 | _cells[r][c] = this.cells[r][c];
86 | }
87 | }
88 |
89 | var piece = new Piece(_cells, this.color);
90 | piece.row = this.row;
91 | piece.column = this.column;
92 | return piece;
93 | };
94 |
95 | Piece.prototype.rotate = function(rotations){
96 | for(var i = 0; i < rotations; i++) {
97 | var _cells = new Array(this.dimension);
98 | for (var r = 0; r < this.dimension; r++) {
99 | _cells[r] = new Array(this.dimension);
100 | }
101 |
102 | switch (this.dimension) { // Assumed square matrix
103 | case 2:
104 | _cells[0][0] = this.cells[1][0];
105 | _cells[0][1] = this.cells[0][0];
106 | _cells[1][0] = this.cells[1][1];
107 | _cells[1][1] = this.cells[0][1];
108 | break;
109 | case 3:
110 | _cells[0][0] = this.cells[2][0];
111 | _cells[0][1] = this.cells[1][0];
112 | _cells[0][2] = this.cells[0][0];
113 | _cells[1][0] = this.cells[2][1];
114 | _cells[1][1] = this.cells[1][1];
115 | _cells[1][2] = this.cells[0][1];
116 | _cells[2][0] = this.cells[2][2];
117 | _cells[2][1] = this.cells[1][2];
118 | _cells[2][2] = this.cells[0][2];
119 | break;
120 | case 4:
121 | _cells[0][0] = this.cells[3][0];
122 | _cells[0][1] = this.cells[2][0];
123 | _cells[0][2] = this.cells[1][0];
124 | _cells[0][3] = this.cells[0][0];
125 | _cells[1][3] = this.cells[0][1];
126 | _cells[2][3] = this.cells[0][2];
127 | _cells[3][3] = this.cells[0][3];
128 | _cells[3][2] = this.cells[1][3];
129 | _cells[3][1] = this.cells[2][3];
130 | _cells[3][0] = this.cells[3][3];
131 | _cells[2][0] = this.cells[3][2];
132 | _cells[1][0] = this.cells[3][1];
133 |
134 | _cells[1][1] = this.cells[2][1];
135 | _cells[1][2] = this.cells[1][1];
136 | _cells[2][2] = this.cells[1][2];
137 | _cells[2][1] = this.cells[2][2];
138 | break;
139 | }
140 |
141 | this.cells = _cells;
142 | }
143 | };
144 |
--------------------------------------------------------------------------------
/classic/custom/game_manager.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Game manager, manages flow and updating of game.
3 | */
4 |
5 | function GameManager(){
6 |
7 | this.gridCanvas = document.getElementById('grid-canvas');
8 |
9 | this.gravityUpdater = new Updater();
10 |
11 | this.gravityUpdater.onUpdate(function(){
12 | self.applyGravity();
13 | self.actuate();
14 | });
15 |
16 | var self = this;
17 | this.setup();
18 | this.startAI();
19 | this.gravityUpdater.checkUpdate(Date.now());
20 | };
21 |
22 | GameManager.prototype.setup = function(){
23 |
24 | this.baseColumns = 8;
25 |
26 | this.pieceWidth = window.innerWidth / this.baseColumns;
27 | this.pieceHeight = this.pieceWidth;
28 |
29 | this.displacementWidth = Math.floor(this.pieceWidth / 4);
30 |
31 | var canvasHeightPieces = Math.ceil(window.innerHeight / this.pieceHeight) + 2;
32 |
33 | this.gridCanvas.width = window.innerWidth;
34 | this.gridCanvas.height = canvasHeightPieces * this.pieceHeight;
35 |
36 | this.grid = new Grid(canvasHeightPieces, this.baseColumns);
37 | this.rpg = new RandomPieceGenerator();
38 | this.ai = new AI(0.510066, 0.760666, 0.35663, 0.184483);
39 |
40 | this.workingPieces = [this.rpg.nextPiece(), this.rpg.nextPiece()];
41 | this.workingPiece = this.workingPieces[0];
42 |
43 | this.isOver = true;
44 |
45 | this.stopAI();
46 | this.actuate();
47 | };
48 |
49 | GameManager.prototype.actuate = function(){
50 |
51 | var _grid = this.grid.clone();
52 |
53 | if (this.workingPiece != null) {
54 | _grid.addPiece(this.workingPiece);
55 | }
56 |
57 | var context = this.gridCanvas.getContext('2d');
58 | context.save();
59 |
60 | context.clearRect(0, 0, this.gridCanvas.width, this.gridCanvas.height);
61 |
62 | for(var r = 2; r < _grid.rows; r++){
63 |
64 | for(var c = 0; c < _grid.columns; c++){
65 |
66 | if (_grid.cells[r][c] != 0){
67 |
68 |
69 | // console.log(_grid.cells[r], _grid.cells[r][c]);
70 | _grid.cells[r][c](context, c, r, this.pieceWidth, this.pieceHeight);
71 |
72 | }
73 | }
74 | }
75 |
76 | context.restore();
77 | };
78 |
79 | GameManager.prototype.startAI = function(){
80 | this.aiActive = true;
81 | };
82 |
83 | GameManager.prototype.stopAI = function(){
84 | this.aiActive = false;
85 | };
86 |
87 | GameManager.prototype.setWorkingPiece = function(){
88 |
89 | this.grid.addPiece(this.workingPiece);
90 | this.grid.clearLines();
91 |
92 | if (!this.grid.exceeded()){
93 |
94 | for(var i = 0; i < this.workingPieces.length - 1; i++){
95 | this.workingPieces[i] = this.workingPieces[i + 1];
96 | }
97 |
98 | this.workingPieces[this.workingPieces.length - 1] = this.rpg.nextPiece();
99 | this.workingPiece = this.workingPieces[0];
100 |
101 | if (this.aiActive) {
102 | this.aiMove();
103 | }
104 |
105 | // I piece
106 | if( this.workingPiece.cells.length > 3) {
107 |
108 | if( this.workingPiece.cells[0][2] !== 0 ) {
109 | this.workingPiece.cells[0][2] = 6;
110 | this.workingPiece.cells[1][2] = 7;
111 | this.workingPiece.cells[2][2] = 8;
112 | this.workingPiece.cells[3][2] = 9;
113 | }
114 | }
115 | }
116 |
117 | // TODO: NO WAYYYY
118 | else{
119 |
120 | }
121 | };
122 |
123 | GameManager.prototype.applyGravity = function(){
124 |
125 | if (this.grid.canMoveDown(this.workingPiece)) {
126 | this.workingPiece.row++;
127 | }else{
128 | this.setWorkingPiece();
129 | }
130 |
131 | };
132 |
133 | GameManager.prototype.drop = function(){
134 | while(this.grid.canMoveDown(this.workingPiece)){
135 | this.workingPiece.row++;
136 | }
137 | };
138 |
139 | GameManager.prototype.moveLeft = function(){
140 | if (this.grid.canMoveLeft(this.workingPiece)){
141 | this.workingPiece.column--;
142 | }
143 | };
144 |
145 | GameManager.prototype.moveRight = function(){
146 | if (this.grid.canMoveRight(this.workingPiece)){
147 | this.workingPiece.column++;
148 | }
149 | };
150 |
151 | GameManager.prototype.rotate = function(){
152 | var offset = this.grid.rotateOffset(this.workingPiece);
153 | if (offset != null){
154 | this.workingPiece.rotate(1);
155 | this.workingPiece.row += offset.rowOffset;
156 | this.workingPiece.column += offset.columnOffset;
157 | }
158 | };
159 |
160 | GameManager.prototype.aiMove = function(){
161 | this.workingPiece = this.ai.best(this.grid, this.workingPieces, 0).piece;
162 | };
163 |
--------------------------------------------------------------------------------
/colored_classic/custom/game_manager.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Game manager, manages flow and updating of game.
3 | */
4 |
5 | function GameManager(){
6 |
7 | this.gridCanvas = document.getElementById('grid-canvas');
8 |
9 | this.gravityUpdater = new Updater();
10 |
11 | this.gravityUpdater.onUpdate(function(){
12 | self.applyGravity();
13 | self.actuate();
14 | });
15 |
16 | var self = this;
17 | this.setup();
18 | this.startAI();
19 | this.gravityUpdater.checkUpdate(Date.now());
20 | };
21 |
22 | GameManager.prototype.setup = function(){
23 |
24 | this.baseColumns = 8;
25 |
26 | this.pieceWidth = window.innerWidth / this.baseColumns;
27 | this.pieceHeight = this.pieceWidth;
28 |
29 | this.displacementWidth = Math.floor(this.pieceWidth / 4);
30 |
31 | var canvasHeightPieces = Math.ceil(window.innerHeight / this.pieceHeight) + 2;
32 |
33 | this.gridCanvas.width = window.innerWidth;
34 | this.gridCanvas.height = canvasHeightPieces * this.pieceHeight;
35 |
36 | this.grid = new Grid(canvasHeightPieces, this.baseColumns);
37 | this.rpg = new RandomPieceGenerator();
38 | this.ai = new AI(0.510066, 0.760666, 0.35663, 0.184483);
39 |
40 | this.workingPieces = [this.rpg.nextPiece(), this.rpg.nextPiece()];
41 | this.workingPiece = this.workingPieces[0];
42 |
43 | this.isOver = true;
44 |
45 | this.stopAI();
46 | this.actuate();
47 | };
48 |
49 | GameManager.prototype.actuate = function(){
50 |
51 | var _grid = this.grid.clone();
52 |
53 | if (this.workingPiece != null) {
54 | _grid.addPiece(this.workingPiece);
55 | }
56 |
57 | var context = this.gridCanvas.getContext('2d');
58 | context.save();
59 |
60 | context.clearRect(0, 0, this.gridCanvas.width, this.gridCanvas.height);
61 |
62 | for(var r = 2; r < _grid.rows; r++){
63 |
64 | for(var c = 0; c < _grid.columns; c++){
65 |
66 | if (_grid.cells[r][c] != 0){
67 |
68 |
69 | // console.log(_grid.cells[r], _grid.cells[r][c]);
70 | _grid.cells[r][c](context, c, r, this.pieceWidth, this.pieceHeight);
71 |
72 | }
73 | }
74 | }
75 |
76 | context.restore();
77 | };
78 |
79 | GameManager.prototype.startAI = function(){
80 | this.aiActive = true;
81 | };
82 |
83 | GameManager.prototype.stopAI = function(){
84 | this.aiActive = false;
85 | };
86 |
87 | GameManager.prototype.setWorkingPiece = function(){
88 |
89 | this.grid.addPiece(this.workingPiece);
90 | this.grid.clearLines();
91 |
92 | if (!this.grid.exceeded()){
93 |
94 | for(var i = 0; i < this.workingPieces.length - 1; i++){
95 | this.workingPieces[i] = this.workingPieces[i + 1];
96 | }
97 |
98 | this.workingPieces[this.workingPieces.length - 1] = this.rpg.nextPiece();
99 | this.workingPiece = this.workingPieces[0];
100 |
101 | if (this.aiActive) {
102 | this.aiMove();
103 | }
104 |
105 | // I piece
106 | if( this.workingPiece.cells.length > 3) {
107 |
108 | if( this.workingPiece.cells[0][2] !== 0 ) {
109 | this.workingPiece.cells[0][2] = 6;
110 | this.workingPiece.cells[1][2] = 7;
111 | this.workingPiece.cells[2][2] = 8;
112 | this.workingPiece.cells[3][2] = 9;
113 | }
114 | }
115 | }
116 |
117 | // TODO: NO WAYYYY
118 | else{
119 |
120 | }
121 | };
122 |
123 | GameManager.prototype.applyGravity = function(){
124 |
125 | if (this.grid.canMoveDown(this.workingPiece)) {
126 | this.workingPiece.row++;
127 | }else{
128 | this.setWorkingPiece();
129 | }
130 |
131 | };
132 |
133 | GameManager.prototype.drop = function(){
134 | while(this.grid.canMoveDown(this.workingPiece)){
135 | this.workingPiece.row++;
136 | }
137 | };
138 |
139 | GameManager.prototype.moveLeft = function(){
140 | if (this.grid.canMoveLeft(this.workingPiece)){
141 | this.workingPiece.column--;
142 | }
143 | };
144 |
145 | GameManager.prototype.moveRight = function(){
146 | if (this.grid.canMoveRight(this.workingPiece)){
147 | this.workingPiece.column++;
148 | }
149 | };
150 |
151 | GameManager.prototype.rotate = function(){
152 | var offset = this.grid.rotateOffset(this.workingPiece);
153 | if (offset != null){
154 | this.workingPiece.rotate(1);
155 | this.workingPiece.row += offset.rowOffset;
156 | this.workingPiece.column += offset.columnOffset;
157 | }
158 | };
159 |
160 | GameManager.prototype.aiMove = function(){
161 | this.workingPiece = this.ai.best(this.grid, this.workingPieces, 0).piece;
162 | };
163 |
--------------------------------------------------------------------------------
/core/js/game_manager.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Game manager, manages flow and updating of game.
3 | */
4 |
5 | function GameManager(){
6 |
7 | this.gridCanvas = document.getElementById('grid-canvas');
8 |
9 | this.gravityUpdater = new Updater();
10 |
11 | this.gravityUpdater.onUpdate(function(){
12 | self.applyGravity();
13 | self.actuate();
14 | });
15 |
16 | var self = this;
17 | this.setup();
18 | this.startAI();
19 | this.gravityUpdater.checkUpdate(Date.now());
20 | };
21 |
22 | GameManager.prototype.setup = function(){
23 |
24 | this.baseColumns = 8;
25 |
26 | this.pieceWidth = window.innerWidth / this.baseColumns;
27 | this.pieceHeight = this.pieceWidth;
28 |
29 | this.displacementWidth = Math.floor(this.pieceWidth / 4);
30 | this.strokeThickness = 20;
31 |
32 | var canvasHeightPieces = Math.ceil(window.innerHeight / this.pieceHeight) + 2;
33 |
34 | this.gridCanvas.width = window.innerWidth;
35 | this.gridCanvas.height = canvasHeightPieces * this.pieceHeight;
36 |
37 | this.grid = new Grid(canvasHeightPieces, this.baseColumns);
38 | this.rpg = new RandomPieceGenerator();
39 | this.ai = new AI(0.510066, 0.760666, 0.35663, 0.184483);
40 |
41 | this.workingPieces = [this.rpg.nextPiece(), this.rpg.nextPiece()];
42 | this.workingPiece = this.workingPieces[0];
43 |
44 | this.isOver = true;
45 |
46 | this.stopAI();
47 | this.actuate();
48 | };
49 |
50 | GameManager.prototype.actuate = function(){
51 |
52 | var _grid = this.grid.clone();
53 |
54 | if (this.workingPiece != null) {
55 | _grid.addPiece(this.workingPiece);
56 | }
57 |
58 | var context = this.gridCanvas.getContext('2d');
59 | context.save();
60 |
61 | context.clearRect(0, 0, this.gridCanvas.width, this.gridCanvas.height);
62 |
63 | for(var r = 2; r < _grid.rows; r++){
64 |
65 | for(var c = 0; c < _grid.columns; c++){
66 |
67 | if (_grid.cells[r][c] != 0){
68 |
69 | context.fillStyle = _grid.cells[r][c];
70 | context.strokeStyle = _grid.cells[r][c];
71 | context.fillRect(this.pieceWidth * c, this.pieceHeight * r, this.pieceWidth, this.pieceHeight);
72 |
73 | // Border?
74 | context.fillStyle = "rgba(255, 255, 255, 0.3)";
75 | context.fillRect(this.pieceWidth * c + this.displacementWidth, this.pieceHeight * r + this.displacementWidth, this.pieceWidth / 2, this.strokeThickness);
76 | context.fillRect(this.pieceWidth * c + this.displacementWidth, this.pieceHeight * r + this.displacementWidth + this.strokeThickness, this.strokeThickness, this.pieceWidth / 2 - this.strokeThickness );
77 | }
78 | }
79 | }
80 |
81 | context.restore();
82 | };
83 |
84 | GameManager.prototype.startAI = function(){
85 | this.aiActive = true;
86 | };
87 |
88 | GameManager.prototype.stopAI = function(){
89 | this.aiActive = false;
90 | };
91 |
92 | GameManager.prototype.setWorkingPiece = function(){
93 |
94 | this.grid.addPiece(this.workingPiece);
95 | this.grid.clearLines();
96 |
97 | if (!this.grid.exceeded()){
98 |
99 | for(var i = 0; i < this.workingPieces.length - 1; i++){
100 | this.workingPieces[i] = this.workingPieces[i + 1];
101 | }
102 |
103 | this.workingPieces[this.workingPieces.length - 1] = this.rpg.nextPiece();
104 | this.workingPiece = this.workingPieces[0];
105 |
106 | if (this.aiActive) {
107 | this.aiMove();
108 | }
109 | }
110 |
111 | // TODO: NO WAYYYY
112 | else{
113 |
114 | }
115 | };
116 |
117 | GameManager.prototype.applyGravity = function(){
118 |
119 | if (this.grid.canMoveDown(this.workingPiece)) {
120 | this.workingPiece.row++;
121 | }else{
122 | this.setWorkingPiece();
123 | }
124 |
125 | };
126 |
127 | GameManager.prototype.drop = function(){
128 | while(this.grid.canMoveDown(this.workingPiece)){
129 | this.workingPiece.row++;
130 | }
131 | };
132 |
133 | GameManager.prototype.moveLeft = function(){
134 | if (this.grid.canMoveLeft(this.workingPiece)){
135 | this.workingPiece.column--;
136 | }
137 | };
138 |
139 | GameManager.prototype.moveRight = function(){
140 | if (this.grid.canMoveRight(this.workingPiece)){
141 | this.workingPiece.column++;
142 | }
143 | };
144 |
145 | GameManager.prototype.rotate = function(){
146 | var offset = this.grid.rotateOffset(this.workingPiece);
147 | if (offset != null){
148 | this.workingPiece.rotate(1);
149 | this.workingPiece.row += offset.rowOffset;
150 | this.workingPiece.column += offset.columnOffset;
151 | }
152 | };
153 |
154 | GameManager.prototype.aiMove = function(){
155 | this.workingPiece = this.ai.best(this.grid, this.workingPieces, 0).piece;
156 | };
157 |
--------------------------------------------------------------------------------
/core/js/grid.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Grid
3 | * - Manages the state of the grid
4 | */
5 |
6 | // Init
7 | function Grid(rows, columns){
8 |
9 | this.rows = rows;
10 | this.columns = columns;
11 | this.cells = new Array(rows);
12 |
13 | // For each row!
14 | // Has a column
15 | // Which has X cells in it.
16 | for (var r = 0; r < this.rows; r++) {
17 |
18 | this.cells[r] = new Array(this.columns);
19 | for(var c = 0; c < this.columns; c++){
20 | this.cells[r][c] = 0;
21 | }
22 | }
23 |
24 | };
25 |
26 | // Methods
27 | Grid.prototype.clone = function(){
28 | var _grid = new Grid(this.rows, this.columns);
29 | for (var r = 0; r < this.rows; r++) {
30 | for(var c = 0; c < this.columns; c++){
31 | _grid.cells[r][c] = this.cells[r][c];
32 | }
33 | }
34 | return _grid;
35 | };
36 |
37 | // Clear spaces in the grid, including when the blocks "fall"
38 | Grid.prototype.clearLines = function(){
39 |
40 | var distance = 0;
41 | var row = new Array(this.columns);
42 |
43 | for(var r = this.rows - 1; r >= 0; r--){
44 |
45 | // Clear full line
46 | if (this.isLine(r)){
47 |
48 | distance++;
49 | for(var c = 0; c < this.columns; c++){
50 | this.cells[r][c] = 0;
51 | }
52 |
53 | // Clear moved spaces
54 | } else if (distance > 0) {
55 |
56 | for(var c = 0; c < this.columns; c++){
57 | this.cells[r + distance][c] = this.cells[r][c];
58 | this.cells[r][c] = 0;
59 | }
60 | }
61 | }
62 | };
63 |
64 | // If every item in the row has an item!
65 | Grid.prototype.isLine = function(row){
66 | for(var c = 0; c < this.columns; c++){
67 | if (this.cells[row][c] == 0){
68 | return false;
69 | }
70 | }
71 | return true;
72 | };
73 |
74 | Grid.prototype.isEmptyRow = function(row){
75 | for(var c = 0; c < this.columns; c++){
76 |
77 | // TH: != 0 rather than == 1
78 | if (this.cells[row][c] != 0){
79 | return false;
80 | }
81 | }
82 | return true;
83 | };
84 |
85 | Grid.prototype.exceeded = function(){
86 | return !this.isEmptyRow(0) || !this.isEmptyRow(1);
87 | };
88 |
89 | Grid.prototype.height = function(){
90 | var r = 0;
91 | for(; r < this.rows && this.isEmptyRow(r); r++);
92 | return this.rows - r;
93 | };
94 |
95 | Grid.prototype.lines = function(){
96 | var count = 0;
97 | for(var r = 0; r < this.rows; r++){
98 | if (this.isLine(r)){
99 | count++;
100 | }
101 | }
102 | return count;
103 | };
104 |
105 | Grid.prototype.holes = function(){
106 | var count = 0;
107 |
108 | for(var c = 0; c < this.columns; c++){
109 | var block = false;
110 | for(var r = 0; r < this.rows; r++){
111 |
112 | // TH: != 0 rather than == 1
113 | if (this.cells[r][c] != 0) {
114 | block = true;
115 | }else if (this.cells[r][c] == 0 && block){
116 | count++;
117 | }
118 | }
119 | }
120 | return count;
121 | };
122 |
123 | Grid.prototype.blockades = function(){
124 | var count = 0;
125 |
126 | for(var c = 0; c < this.columns; c++){
127 | var hole = false;
128 | for(var r = this.rows - 1; r >= 0; r--){
129 | if (this.cells[r][c] == 0){
130 | hole = true;
131 |
132 | // TH: != 0 rather than == 1
133 | }else if (this.cells[r][c] != 0 && hole){
134 | count++;
135 | }
136 | }
137 | }
138 | return count;
139 | }
140 |
141 | Grid.prototype.aggregateHeight = function(){
142 | var total = 0;
143 |
144 | for(var c = 0; c < this.columns; c++){
145 | total += this.columnHeight(c);
146 | }
147 | return total;
148 | };
149 |
150 | Grid.prototype.bumpiness = function(){
151 | var total = 0;
152 | for(var c = 0; c < this.columns - 1; c++){
153 | total += Math.abs(this.columnHeight(c) - this.columnHeight(c+ 1));
154 | }
155 | return total;
156 | }
157 |
158 | Grid.prototype.columnHeight = function(column){
159 | var r = 0;
160 |
161 | for(; r < this.rows && this.cells[r][column] == 0; r++);
162 | return this.rows - r;
163 | };
164 |
165 | // Piece
166 | Grid.prototype.addPiece = function(piece) {
167 |
168 | for(var r = 0; r < piece.cells.length; r++) {
169 | for (var c = 0; c < piece.cells[r].length; c++) {
170 |
171 | var _r = piece.row + r;
172 | var _c = piece.column + c;
173 |
174 | // TH: != 0 rather than == 1
175 | if (piece.cells[r][c] != 0 && _r >= 0){
176 |
177 | // TH: Updates color, rather than 1
178 | if (piece.cells[r][c] > 1) {
179 | var num = piece.cells[r][c] - 2;
180 | this.cells[_r][_c] = piece.color[num];
181 | } else {
182 | this.cells[_r][_c] = piece.color;
183 | }
184 | }
185 |
186 | }
187 | }
188 | };
189 |
190 | Grid.prototype.valid = function(piece){
191 |
192 | for(var r = 0; r < piece.cells.length; r++){
193 | for(var c = 0; c < piece.cells[r].length; c++){
194 | var _r = piece.row + r;
195 | var _c = piece.column + c;
196 |
197 | // TH: != 0 rather than == 1
198 | if (piece.cells[r][c] != 0){
199 | if (!(_c < this.columns && _r < this.rows && this.cells[_r][_c] == 0)){
200 | return false;
201 | }
202 | }
203 | }
204 | }
205 | return true;
206 | };
207 |
208 | Grid.prototype.canMoveDown = function(piece){
209 | for(var r = 0; r < piece.cells.length; r++){
210 | for(var c = 0; c < piece.cells[r].length; c++){
211 | var _r = piece.row + r + 1;
212 | var _c = piece.column + c;
213 |
214 | // TH: != 0 rather than == 1
215 | if (piece.cells[r][c] != 0 && _r >= 0){
216 |
217 | if (!(_r < this.rows && this.cells[_r][_c] == 0)){
218 | return false;
219 | }
220 | }
221 | }
222 | }
223 | return true;
224 | };
225 |
226 | Grid.prototype.canMoveLeft = function(piece){
227 | for(var r = 0; r < piece.cells.length; r++){
228 | for(var c = 0; c < piece.cells[r].length; c++){
229 | var _r = piece.row + r;
230 | var _c = piece.column + c - 1;
231 |
232 | // TH: != 0 rather than == 1
233 | if (piece.cells[r][c] != 0){
234 | if (!(_c >= 0 && this.cells[_r][_c] == 0)){
235 | return false;
236 | }
237 | }
238 | }
239 | }
240 | return true;
241 | };
242 |
243 | Grid.prototype.canMoveRight = function(piece){
244 | for(var r = 0; r < piece.cells.length; r++){
245 | for(var c = 0; c < piece.cells[r].length; c++){
246 | var _r = piece.row + r;
247 | var _c = piece.column + c + 1;
248 |
249 | // TH: != 0 rather than == 1
250 | if (piece.cells[r][c] != 0){
251 | if (!(_c >= 0 && this.cells[_r][_c] == 0)){
252 | return false;
253 | }
254 | }
255 | }
256 | }
257 | return true;
258 | };
259 |
260 | Grid.prototype.rotateOffset = function(piece){
261 |
262 | console.log("rotate?");
263 |
264 | var _piece = piece.clone();
265 | _piece.rotate(1);
266 | if (this.valid(_piece)) {
267 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
268 | }
269 |
270 | // Kicking
271 | var initialRow = _piece.row;
272 | var initialCol = _piece.column;
273 |
274 | for (var i = 0; i < _piece.dimension - 1; i++) {
275 | _piece.column = initialCol + i;
276 | if (this.valid(_piece)) {
277 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
278 | }
279 |
280 | for (var j = 0; j < _piece.dimension - 1; j++) {
281 | _piece.row = initialRow - j;
282 | if (this.valid(_piece)) {
283 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
284 | }
285 | }
286 | _piece.row = initialRow;
287 | }
288 | _piece.column = initialCol;
289 |
290 | for (var i = 0; i < _piece.dimension - 1; i++) {
291 | _piece.column = initialCol - i;
292 | if (this.valid(_piece)) {
293 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
294 | }
295 |
296 | for (var j = 0; j < _piece.dimension - 1; j++) {
297 | _piece.row = initialRow - j;
298 | if (this.valid(_piece)) {
299 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
300 | }
301 | }
302 | _piece.row = initialRow;
303 | }
304 | _piece.column = initialCol;
305 |
306 | return null;
307 | };
308 |
--------------------------------------------------------------------------------
/classic/custom/draw_functions.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | function square(context, x, y, width, height) {
4 |
5 | var unitWidth = 0.125 * width;
6 |
7 | // Border
8 | context.fillStyle = "#000";
9 | context.fillRect(width * x, height * y, width, height);
10 |
11 | context.fillStyle = "#C6CFA4";
12 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
13 |
14 | context.fillStyle = "#000";
15 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, width - unitWidth * 4, height - unitWidth * 4);
16 |
17 | }
18 |
19 | function jay(context, x, y, width, height) {
20 |
21 | var unitWidth = 0.125 * width;
22 |
23 | // Border
24 | context.fillStyle = "#000";
25 | context.fillRect(width * x, height * y, width, height);
26 |
27 | context.fillStyle = "#92BE7C";
28 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
29 |
30 | context.fillStyle = "#000";
31 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, width - unitWidth * 4, height - unitWidth * 4);
32 |
33 | context.fillStyle = "#C6CFA4";
34 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 3, width - unitWidth * 6, height - unitWidth * 6);
35 | }
36 |
37 | function ell(context, x, y, width, height) {
38 |
39 | var unitWidth = 0.125 * width;
40 |
41 | context.fillStyle = "#000";
42 | context.fillRect(width * x, height * y, width, height);
43 |
44 | context.fillStyle = "#3C6A4E";
45 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
46 |
47 | }
48 |
49 | function zee(context, x, y, width, height) {
50 |
51 | var unitWidth = 0.125 * width;
52 |
53 | context.fillStyle = "#000";
54 | context.fillRect(width * x, height * y, width, height);
55 |
56 | context.fillStyle = "#92BE7C";
57 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
58 |
59 | context.fillStyle = "#000";
60 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 3, width - unitWidth * 6, height - unitWidth * 6);
61 |
62 | }
63 |
64 | function ess(context, x, y, width, height) {
65 |
66 | var unitWidth = 0.125 * width;
67 |
68 | context.fillStyle = "#000";
69 | context.fillRect(width * x, height * y, width, height);
70 |
71 | context.fillStyle = "#3C6A4E";
72 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
73 |
74 | context.fillStyle = "#000";
75 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, width - unitWidth * 4, height - unitWidth * 4);
76 |
77 | context.fillStyle = "#C6CFA4";
78 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 3, width - unitWidth * 6, height - unitWidth * 6);
79 | }
80 |
81 | function tee(context, x, y, width, height) {
82 |
83 | var unitWidth = 0.125 * width;
84 |
85 | context.fillStyle = "#000";
86 | context.fillRect(width * x, height * y, width, height);
87 |
88 | context.fillStyle = "#92BE7C";
89 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
90 |
91 | context.fillStyle = "#C6CFA4";
92 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, unitWidth, height - unitWidth * 4);
93 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, unitWidth * 4, unitWidth);
94 |
95 | context.fillStyle = "#000";
96 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 5, unitWidth * 4, unitWidth);
97 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 3, unitWidth, unitWidth * 3);
98 |
99 | }
100 |
101 | var eyes = [
102 | //h1
103 | function(context, x, y, width, height) {
104 |
105 | var unitWidth = 0.125 * width;
106 | context.fillStyle = "#000";
107 | context.fillRect(width * x, height * y, width, height);
108 |
109 | context.fillStyle = "#92BE7C";
110 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth, height - unitWidth * 2);
111 |
112 | // Dots
113 | context.fillStyle = "#3C6A4E";
114 |
115 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 1, unitWidth, unitWidth);
116 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 1, unitWidth, unitWidth);
117 |
118 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 3, unitWidth, unitWidth);
119 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 3, unitWidth, unitWidth);
120 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 3, unitWidth, unitWidth);
121 |
122 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 5, unitWidth, unitWidth);
123 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 5, unitWidth, unitWidth);
124 |
125 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 6, unitWidth, unitWidth);
126 |
127 |
128 | },
129 | function(context, x, y, width, height) {
130 |
131 | var unitWidth = 0.125 * width;
132 |
133 | context.fillStyle = "#000";
134 | context.fillRect(width * x, height * y, width, height);
135 |
136 | context.fillStyle = "#92BE7C";
137 | context.fillRect(width * x, height * y + unitWidth, width, height - unitWidth * 2);
138 |
139 | // Dots
140 | context.fillStyle = "#3C6A4E";
141 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 1, unitWidth, unitWidth);
142 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 1, unitWidth, unitWidth);
143 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 1, unitWidth, unitWidth);
144 |
145 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
146 |
147 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 3, unitWidth, unitWidth);
148 |
149 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 4, unitWidth, unitWidth);
150 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 4, unitWidth, unitWidth);
151 |
152 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 5, unitWidth, unitWidth);
153 | context.fillRect(width * x + unitWidth * 7, height * y + unitWidth * 5, unitWidth, unitWidth);
154 |
155 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 6, unitWidth, unitWidth);
156 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 6, unitWidth, unitWidth);
157 |
158 |
159 | },
160 | function(context, x, y, width, height) {
161 |
162 | var unitWidth = 0.125 * width;
163 |
164 | context.fillStyle = "#000";
165 | context.fillRect(width * x, height * y, width, height);
166 |
167 | context.fillStyle = "#92BE7C";
168 | context.fillRect(width * x, height * y + unitWidth, width, height - unitWidth * 2);
169 |
170 | // Dots
171 | context.fillStyle = "#3C6A4E";
172 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 1, unitWidth, unitWidth);
173 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 1, unitWidth, unitWidth);
174 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 1, unitWidth, unitWidth);
175 |
176 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
177 |
178 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 3, unitWidth, unitWidth);
179 |
180 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 4, unitWidth, unitWidth);
181 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 4, unitWidth, unitWidth);
182 |
183 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 5, unitWidth, unitWidth);
184 | context.fillRect(width * x + unitWidth * 7, height * y + unitWidth * 5, unitWidth, unitWidth);
185 |
186 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 6, unitWidth, unitWidth);
187 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 6, unitWidth, unitWidth);
188 |
189 | },
190 | function(context, x, y, width, height) {
191 |
192 | var unitWidth = 0.125 * width;
193 |
194 | context.fillStyle = "#000";
195 | context.fillRect(width * x, height * y, width, height);
196 |
197 | context.fillStyle = "#92BE7C";
198 | context.fillRect(width * x, height * y + unitWidth, width - unitWidth, height - unitWidth * 2);
199 |
200 | // Dots
201 | context.fillStyle = "#3C6A4E";
202 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 1, unitWidth, unitWidth);
203 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 1, unitWidth, unitWidth);
204 |
205 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, unitWidth, unitWidth);
206 |
207 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 3, unitWidth, unitWidth);
208 |
209 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 4, unitWidth, unitWidth);
210 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 4, unitWidth, unitWidth);
211 |
212 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 5, unitWidth, unitWidth);
213 |
214 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 6, unitWidth, unitWidth);
215 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 6, unitWidth, unitWidth);
216 | },
217 |
218 | // v1
219 | function(context, x, y, width, height) {
220 |
221 | var unitWidth = 0.125 * width;
222 | context.fillStyle = "#000";
223 | context.fillRect(width * x, height * y, width, height);
224 |
225 | context.fillStyle = "#92BE7C";
226 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth);
227 |
228 | // Dots
229 | context.fillStyle = "#3C6A4E";
230 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth, unitWidth, unitWidth);
231 |
232 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, unitWidth, unitWidth);
233 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
234 |
235 | context.fillRect(width * x + unitWidth, height * y + unitWidth * 4, unitWidth, unitWidth);
236 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 4, unitWidth, unitWidth);
237 |
238 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 5, unitWidth, unitWidth);
239 |
240 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 6, unitWidth, unitWidth);
241 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 6, unitWidth, unitWidth);
242 |
243 | },
244 | function(context, x, y, width, height) {
245 |
246 | var unitWidth = 0.125 * width;
247 |
248 | context.fillStyle = "#000";
249 | context.fillRect(width * x, height * y, width, height);
250 |
251 | context.fillStyle = "#92BE7C";
252 | context.fillRect(width * x + unitWidth, height * y, width - unitWidth * 2, height);
253 |
254 | // Dots
255 | context.fillStyle = "#3C6A4E";
256 |
257 | context.fillRect(width * x + unitWidth * 3, height * y, unitWidth, unitWidth);
258 | context.fillRect(width * x + unitWidth * 6, height * y, unitWidth, unitWidth);
259 |
260 | context.fillRect(width * x + unitWidth, height * y + unitWidth * 1, unitWidth, unitWidth);
261 |
262 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 2, unitWidth, unitWidth);
263 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
264 |
265 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 3, unitWidth, unitWidth);
266 |
267 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 4, unitWidth, unitWidth);
268 |
269 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 5, unitWidth, unitWidth);
270 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 5, unitWidth, unitWidth);
271 |
272 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 6, unitWidth, unitWidth);
273 |
274 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 7, unitWidth, unitWidth);
275 |
276 | },
277 | function(context, x, y, width, height) {
278 |
279 | var unitWidth = 0.125 * width;
280 |
281 | context.fillStyle = "#000";
282 | context.fillRect(width * x, height * y, width, height);
283 |
284 | context.fillStyle = "#92BE7C";
285 | context.fillRect(width * x + unitWidth, height * y, width - unitWidth * 2, height);
286 |
287 | // Dots
288 | context.fillStyle = "#3C6A4E";
289 |
290 | context.fillRect(width * x + unitWidth * 3, height * y, unitWidth, unitWidth);
291 | context.fillRect(width * x + unitWidth * 6, height * y, unitWidth, unitWidth);
292 |
293 | context.fillRect(width * x + unitWidth, height * y + unitWidth * 1, unitWidth, unitWidth);
294 |
295 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 2, unitWidth, unitWidth);
296 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
297 |
298 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 3, unitWidth, unitWidth);
299 |
300 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 4, unitWidth, unitWidth);
301 |
302 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 5, unitWidth, unitWidth);
303 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 5, unitWidth, unitWidth);
304 |
305 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 6, unitWidth, unitWidth);
306 |
307 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 7, unitWidth, unitWidth);
308 | },
309 | function(context, x, y, width, height) {
310 |
311 | var unitWidth = 0.125 * width;
312 |
313 | context.fillStyle = "#000";
314 | context.fillRect(width * x, height * y, width, height);
315 |
316 | context.fillStyle = "#92BE7C";
317 | context.fillRect(width * x + unitWidth, height * y, width - unitWidth * 2, height - unitWidth);
318 |
319 | // Dots
320 | context.fillStyle = "#3C6A4E";
321 |
322 | context.fillRect(width * x + unitWidth * 6, height * y, unitWidth, unitWidth);
323 |
324 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 1, unitWidth, unitWidth);
325 |
326 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 2, unitWidth, unitWidth);
327 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 2, unitWidth, unitWidth);
328 |
329 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 3, unitWidth, unitWidth);
330 |
331 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 4, unitWidth, unitWidth);
332 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 4, unitWidth, unitWidth);
333 |
334 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 5, unitWidth, unitWidth);
335 |
336 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 6, unitWidth, unitWidth);
337 | }
338 | ]
339 |
340 | var drawFunctions = [
341 |
342 | square,
343 |
344 | jay,
345 |
346 | ell,
347 |
348 | zee,
349 |
350 | ess,
351 |
352 | tee,
353 |
354 | eyes
355 |
356 | ]
357 |
358 | function DrawFunctions(){};
359 |
360 | DrawFunctions.prototype.getDrawFunction = function(index){
361 |
362 | if( drawFunctions[index]) {
363 | return drawFunctions[index];
364 | } else {
365 | return drawFunctions[5];
366 | }
367 | }
--------------------------------------------------------------------------------
/colored_classic/custom/draw_functions.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | function square(context, x, y, width, height) {
4 |
5 | var unitWidth = 0.125 * width;
6 |
7 | // Border
8 | context.fillStyle = "#000";
9 | context.fillRect(width * x, height * y, width, height);
10 |
11 | context.fillStyle = "#EDBF3B";
12 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
13 |
14 | context.fillStyle = "#000";
15 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, width - unitWidth * 4, height - unitWidth * 4);
16 |
17 | }
18 |
19 | function jay(context, x, y, width, height) {
20 |
21 | var unitWidth = 0.125 * width;
22 |
23 | // Border
24 | context.fillStyle = "#000";
25 | context.fillRect(width * x, height * y, width, height);
26 |
27 | context.fillStyle = "#3B78A7";
28 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
29 |
30 | context.fillStyle = "#000";
31 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, width - unitWidth * 4, height - unitWidth * 4);
32 |
33 | context.fillStyle = "#fff";
34 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 3, width - unitWidth * 6, height - unitWidth * 6);
35 | }
36 |
37 | function ell(context, x, y, width, height) {
38 |
39 | var unitWidth = 0.125 * width;
40 |
41 | context.fillStyle = "#000";
42 | context.fillRect(width * x, height * y, width, height);
43 |
44 | context.fillStyle = "#B82C2D";
45 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
46 |
47 | }
48 |
49 | function zee(context, x, y, width, height) {
50 |
51 | var unitWidth = 0.125 * width;
52 |
53 | context.fillStyle = "#000";
54 | context.fillRect(width * x, height * y, width, height);
55 |
56 | context.fillStyle = "#EDBF3B";
57 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
58 |
59 | context.fillStyle = "#000";
60 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 3, width - unitWidth * 6, height - unitWidth * 6);
61 |
62 | }
63 |
64 | function ess(context, x, y, width, height) {
65 |
66 | var unitWidth = 0.125 * width;
67 |
68 | context.fillStyle = "#000";
69 | context.fillRect(width * x, height * y, width, height);
70 |
71 | context.fillStyle = "#C24175";
72 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
73 |
74 | context.fillStyle = "#000";
75 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, width - unitWidth * 4, height - unitWidth * 4);
76 |
77 | context.fillStyle = "#fff";
78 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 3, width - unitWidth * 6, height - unitWidth * 6);
79 | }
80 |
81 | function tee(context, x, y, width, height) {
82 |
83 | var unitWidth = 0.125 * width;
84 |
85 | context.fillStyle = "#000";
86 | context.fillRect(width * x, height * y, width, height);
87 |
88 | context.fillStyle = "#498E4D";
89 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
90 |
91 | context.fillStyle = "#fff";
92 |
93 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, unitWidth, height - unitWidth * 4);
94 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, unitWidth * 4, unitWidth);
95 |
96 | context.fillStyle = "#000";
97 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 5, unitWidth * 4, unitWidth);
98 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 3, unitWidth, unitWidth * 3);
99 |
100 | }
101 |
102 | var eyes = [
103 | //h1
104 | function(context, x, y, width, height) {
105 |
106 | var unitWidth = 0.125 * width;
107 | context.fillStyle = "#000";
108 | context.fillRect(width * x, height * y, width, height);
109 |
110 | context.fillStyle = "#C28549";
111 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth, height - unitWidth * 2);
112 |
113 | // Dots
114 | context.fillStyle = "#874437";
115 |
116 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 1, unitWidth, unitWidth);
117 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 1, unitWidth, unitWidth);
118 |
119 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 3, unitWidth, unitWidth);
120 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 3, unitWidth, unitWidth);
121 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 3, unitWidth, unitWidth);
122 |
123 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 5, unitWidth, unitWidth);
124 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 5, unitWidth, unitWidth);
125 |
126 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 6, unitWidth, unitWidth);
127 |
128 |
129 | },
130 | function(context, x, y, width, height) {
131 |
132 | var unitWidth = 0.125 * width;
133 |
134 | context.fillStyle = "#000";
135 | context.fillRect(width * x, height * y, width, height);
136 |
137 | context.fillStyle = "#C28549";
138 | context.fillRect(width * x, height * y + unitWidth, width, height - unitWidth * 2);
139 |
140 | // Dots
141 | context.fillStyle = "#874437";
142 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 1, unitWidth, unitWidth);
143 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 1, unitWidth, unitWidth);
144 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 1, unitWidth, unitWidth);
145 |
146 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
147 |
148 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 3, unitWidth, unitWidth);
149 |
150 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 4, unitWidth, unitWidth);
151 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 4, unitWidth, unitWidth);
152 |
153 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 5, unitWidth, unitWidth);
154 | context.fillRect(width * x + unitWidth * 7, height * y + unitWidth * 5, unitWidth, unitWidth);
155 |
156 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 6, unitWidth, unitWidth);
157 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 6, unitWidth, unitWidth);
158 |
159 |
160 | },
161 | function(context, x, y, width, height) {
162 |
163 | var unitWidth = 0.125 * width;
164 |
165 | context.fillStyle = "#000";
166 | context.fillRect(width * x, height * y, width, height);
167 |
168 | context.fillStyle = "#C28549";
169 | context.fillRect(width * x, height * y + unitWidth, width, height - unitWidth * 2);
170 |
171 | // Dots
172 | context.fillStyle = "#874437";
173 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 1, unitWidth, unitWidth);
174 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 1, unitWidth, unitWidth);
175 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 1, unitWidth, unitWidth);
176 |
177 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
178 |
179 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 3, unitWidth, unitWidth);
180 |
181 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 4, unitWidth, unitWidth);
182 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 4, unitWidth, unitWidth);
183 |
184 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 5, unitWidth, unitWidth);
185 | context.fillRect(width * x + unitWidth * 7, height * y + unitWidth * 5, unitWidth, unitWidth);
186 |
187 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 6, unitWidth, unitWidth);
188 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 6, unitWidth, unitWidth);
189 |
190 | },
191 | function(context, x, y, width, height) {
192 |
193 | var unitWidth = 0.125 * width;
194 |
195 | context.fillStyle = "#000";
196 | context.fillRect(width * x, height * y, width, height);
197 |
198 | context.fillStyle = "#C28549";
199 | context.fillRect(width * x, height * y + unitWidth, width - unitWidth, height - unitWidth * 2);
200 |
201 | // Dots
202 | context.fillStyle = "#874437";
203 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 1, unitWidth, unitWidth);
204 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 1, unitWidth, unitWidth);
205 |
206 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, unitWidth, unitWidth);
207 |
208 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 3, unitWidth, unitWidth);
209 |
210 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 4, unitWidth, unitWidth);
211 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 4, unitWidth, unitWidth);
212 |
213 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 5, unitWidth, unitWidth);
214 |
215 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 6, unitWidth, unitWidth);
216 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 6, unitWidth, unitWidth);
217 | },
218 |
219 | // v1
220 | function(context, x, y, width, height) {
221 |
222 | var unitWidth = 0.125 * width;
223 | context.fillStyle = "#000";
224 | context.fillRect(width * x, height * y, width, height);
225 |
226 | context.fillStyle = "#C28549";
227 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth);
228 |
229 | // Dots
230 | context.fillStyle = "#874437";
231 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth, unitWidth, unitWidth);
232 |
233 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, unitWidth, unitWidth);
234 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
235 |
236 | context.fillRect(width * x + unitWidth, height * y + unitWidth * 4, unitWidth, unitWidth);
237 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 4, unitWidth, unitWidth);
238 |
239 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 5, unitWidth, unitWidth);
240 |
241 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 6, unitWidth, unitWidth);
242 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 6, unitWidth, unitWidth);
243 |
244 | },
245 | function(context, x, y, width, height) {
246 |
247 | var unitWidth = 0.125 * width;
248 |
249 | context.fillStyle = "#000";
250 | context.fillRect(width * x, height * y, width, height);
251 |
252 | context.fillStyle = "#C28549";
253 | context.fillRect(width * x + unitWidth, height * y, width - unitWidth * 2, height);
254 |
255 | // Dots
256 | context.fillStyle = "#874437";
257 |
258 | context.fillRect(width * x + unitWidth * 3, height * y, unitWidth, unitWidth);
259 | context.fillRect(width * x + unitWidth * 6, height * y, unitWidth, unitWidth);
260 |
261 | context.fillRect(width * x + unitWidth, height * y + unitWidth * 1, unitWidth, unitWidth);
262 |
263 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 2, unitWidth, unitWidth);
264 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
265 |
266 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 3, unitWidth, unitWidth);
267 |
268 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 4, unitWidth, unitWidth);
269 |
270 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 5, unitWidth, unitWidth);
271 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 5, unitWidth, unitWidth);
272 |
273 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 6, unitWidth, unitWidth);
274 |
275 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 7, unitWidth, unitWidth);
276 |
277 | },
278 | function(context, x, y, width, height) {
279 |
280 | var unitWidth = 0.125 * width;
281 |
282 | context.fillStyle = "#000";
283 | context.fillRect(width * x, height * y, width, height);
284 |
285 | context.fillStyle = "#C28549";
286 | context.fillRect(width * x + unitWidth, height * y, width - unitWidth * 2, height);
287 |
288 | // Dots
289 | context.fillStyle = "#874437";
290 |
291 | context.fillRect(width * x + unitWidth * 3, height * y, unitWidth, unitWidth);
292 | context.fillRect(width * x + unitWidth * 6, height * y, unitWidth, unitWidth);
293 |
294 | context.fillRect(width * x + unitWidth, height * y + unitWidth * 1, unitWidth, unitWidth);
295 |
296 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 2, unitWidth, unitWidth);
297 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
298 |
299 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 3, unitWidth, unitWidth);
300 |
301 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 4, unitWidth, unitWidth);
302 |
303 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 5, unitWidth, unitWidth);
304 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 5, unitWidth, unitWidth);
305 |
306 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 6, unitWidth, unitWidth);
307 |
308 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 7, unitWidth, unitWidth);
309 | },
310 | function(context, x, y, width, height) {
311 |
312 | var unitWidth = 0.125 * width;
313 |
314 | context.fillStyle = "#000";
315 | context.fillRect(width * x, height * y, width, height);
316 |
317 | context.fillStyle = "#C28549";
318 | context.fillRect(width * x + unitWidth, height * y, width - unitWidth * 2, height - unitWidth);
319 |
320 | // Dots
321 | context.fillStyle = "#874437";
322 |
323 | context.fillRect(width * x + unitWidth * 6, height * y, unitWidth, unitWidth);
324 |
325 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 1, unitWidth, unitWidth);
326 |
327 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 2, unitWidth, unitWidth);
328 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 2, unitWidth, unitWidth);
329 |
330 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 3, unitWidth, unitWidth);
331 |
332 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 4, unitWidth, unitWidth);
333 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 4, unitWidth, unitWidth);
334 |
335 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 5, unitWidth, unitWidth);
336 |
337 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 6, unitWidth, unitWidth);
338 | }
339 | ]
340 |
341 | var drawFunctions = [
342 |
343 | square,
344 |
345 | jay,
346 |
347 | ell,
348 |
349 | zee,
350 |
351 | ess,
352 |
353 | tee,
354 |
355 | eyes
356 |
357 | ]
358 |
359 | function DrawFunctions(){};
360 |
361 | DrawFunctions.prototype.getDrawFunction = function(index){
362 |
363 | if( drawFunctions[index]) {
364 | return drawFunctions[index];
365 | } else {
366 | return drawFunctions[5];
367 | }
368 | }
--------------------------------------------------------------------------------
/ambient/js/index.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | // http://stackoverflow.com/questions/17433015/change-the-hue-of-a-rgb-color-in-javascript
4 | // TODO: Clean up
5 |
6 | function changeHue(rgb, degree) {
7 | var hsl = rgbToHSL(rgb);
8 | hsl.h += degree;
9 | if (hsl.h > 360) {
10 | hsl.h -= 360;
11 | }
12 | else if (hsl.h < 0) {
13 | hsl.h += 360;
14 | }
15 | return hslToRGB(hsl);
16 | }
17 |
18 | // exepcts a string and returns an object
19 | function rgbToHSL(rgb) {
20 | // strip the leading # if it's there
21 | rgb = rgb.replace(/^\s*#|\s*$/g, '');
22 |
23 | // convert 3 char codes --> 6, e.g. `E0F` --> `EE00FF`
24 | if(rgb.length == 3){
25 | rgb = rgb.replace(/(.)/g, '$1$1');
26 | }
27 |
28 | var r = parseInt(rgb.substr(0, 2), 16) / 255,
29 | g = parseInt(rgb.substr(2, 2), 16) / 255,
30 | b = parseInt(rgb.substr(4, 2), 16) / 255,
31 | cMax = Math.max(r, g, b),
32 | cMin = Math.min(r, g, b),
33 | delta = cMax - cMin,
34 | l = (cMax + cMin) / 2,
35 | h = 0,
36 | s = 0;
37 |
38 | if (delta == 0) {
39 | h = 0;
40 | }
41 | else if (cMax == r) {
42 | h = 60 * (((g - b) / delta) % 6);
43 | }
44 | else if (cMax == g) {
45 | h = 60 * (((b - r) / delta) + 2);
46 | }
47 | else {
48 | h = 60 * (((r - g) / delta) + 4);
49 | }
50 |
51 | if (delta == 0) {
52 | s = 0;
53 | }
54 | else {
55 | s = (delta/(1-Math.abs(2*l - 1)))
56 | }
57 |
58 | return {
59 | h: h,
60 | s: s,
61 | l: l
62 | }
63 | }
64 |
65 | // expects an object and returns a string
66 | function hslToRGB(hsl) {
67 | var h = hsl.h,
68 | s = hsl.s,
69 | l = hsl.l,
70 | c = (1 - Math.abs(2*l - 1)) * s,
71 | x = c * ( 1 - Math.abs((h / 60 ) % 2 - 1 )),
72 | m = l - c/ 2,
73 | r, g, b;
74 |
75 | if (h < 60) {
76 | r = c;
77 | g = x;
78 | b = 0;
79 | }
80 | else if (h < 120) {
81 | r = x;
82 | g = c;
83 | b = 0;
84 | }
85 | else if (h < 180) {
86 | r = 0;
87 | g = c;
88 | b = x;
89 | }
90 | else if (h < 240) {
91 | r = 0;
92 | g = x;
93 | b = c;
94 | }
95 | else if (h < 300) {
96 | r = x;
97 | g = 0;
98 | b = c;
99 | }
100 | else {
101 | r = c;
102 | g = 0;
103 | b = x;
104 | }
105 |
106 | r = normalize_rgb_value(r, m);
107 | g = normalize_rgb_value(g, m);
108 | b = normalize_rgb_value(b, m);
109 |
110 | return rgbToHex(r,g,b);
111 | }
112 |
113 | function normalize_rgb_value(color, m) {
114 | color = Math.floor((color + m) * 255);
115 | if (color < 0) {
116 | color = 0;
117 | }
118 | return color;
119 | }
120 |
121 | function rgbToHex(r, g, b) {
122 | return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
123 | }
124 | /**
125 | * Color Manager
126 | * - Handles the slow hue rotations of colors
127 | */
128 |
129 | function ColorManager( baseColor ){
130 | this.hueRotation = 0;
131 | this.rotationSpeed = 4;
132 | this.baseColor = '#F0C9DD'; // Light pink
133 | };
134 |
135 | ColorManager.prototype.getColor = function(){
136 |
137 | // Rotate hue's for every new piece.
138 | this.hueRotation += this.rotationSpeed;
139 | if( this.hueRotation > 360 ) {
140 | this.hueRotation = 0;
141 | }
142 |
143 | return changeHue(this.baseColor, this.hueRotation);
144 | };
145 | /**
146 | * Grid
147 | * - Manages the state of the grid
148 | */
149 |
150 | // Init
151 | function Grid(rows, columns){
152 |
153 | this.rows = rows;
154 | this.columns = columns;
155 | this.cells = new Array(rows);
156 |
157 | // For each row!
158 | // Has a column
159 | // Which has X cells in it.
160 | for (var r = 0; r < this.rows; r++) {
161 |
162 | this.cells[r] = new Array(this.columns);
163 | for(var c = 0; c < this.columns; c++){
164 | this.cells[r][c] = 0;
165 | }
166 | }
167 |
168 | };
169 |
170 | // Methods
171 | Grid.prototype.clone = function(){
172 | var _grid = new Grid(this.rows, this.columns);
173 | for (var r = 0; r < this.rows; r++) {
174 | for(var c = 0; c < this.columns; c++){
175 | _grid.cells[r][c] = this.cells[r][c];
176 | }
177 | }
178 | return _grid;
179 | };
180 |
181 | // Clear spaces in the grid, including when the blocks "fall"
182 | Grid.prototype.clearLines = function(){
183 |
184 | var distance = 0;
185 | var row = new Array(this.columns);
186 |
187 | for(var r = this.rows - 1; r >= 0; r--){
188 |
189 | // Clear full line
190 | if (this.isLine(r)){
191 |
192 | distance++;
193 | for(var c = 0; c < this.columns; c++){
194 | this.cells[r][c] = 0;
195 | }
196 |
197 | // Clear moved spaces
198 | } else if (distance > 0) {
199 |
200 | for(var c = 0; c < this.columns; c++){
201 | this.cells[r + distance][c] = this.cells[r][c];
202 | this.cells[r][c] = 0;
203 | }
204 | }
205 | }
206 | };
207 |
208 | // If every item in the row has an item!
209 | Grid.prototype.isLine = function(row){
210 | for(var c = 0; c < this.columns; c++){
211 | if (this.cells[row][c] == 0){
212 | return false;
213 | }
214 | }
215 | return true;
216 | };
217 |
218 | Grid.prototype.isEmptyRow = function(row){
219 | for(var c = 0; c < this.columns; c++){
220 |
221 | // TH: != 0 rather than == 1
222 | if (this.cells[row][c] != 0){
223 | return false;
224 | }
225 | }
226 | return true;
227 | };
228 |
229 | Grid.prototype.exceeded = function(){
230 | return !this.isEmptyRow(0) || !this.isEmptyRow(1);
231 | };
232 |
233 | Grid.prototype.height = function(){
234 | var r = 0;
235 | for(; r < this.rows && this.isEmptyRow(r); r++);
236 | return this.rows - r;
237 | };
238 |
239 | Grid.prototype.lines = function(){
240 | var count = 0;
241 | for(var r = 0; r < this.rows; r++){
242 | if (this.isLine(r)){
243 | count++;
244 | }
245 | }
246 | return count;
247 | };
248 |
249 | Grid.prototype.holes = function(){
250 | var count = 0;
251 |
252 | for(var c = 0; c < this.columns; c++){
253 | var block = false;
254 | for(var r = 0; r < this.rows; r++){
255 |
256 | // TH: != 0 rather than == 1
257 | if (this.cells[r][c] != 0) {
258 | block = true;
259 | }else if (this.cells[r][c] == 0 && block){
260 | count++;
261 | }
262 | }
263 | }
264 | return count;
265 | };
266 |
267 | Grid.prototype.blockades = function(){
268 | var count = 0;
269 |
270 | for(var c = 0; c < this.columns; c++){
271 | var hole = false;
272 | for(var r = this.rows - 1; r >= 0; r--){
273 | if (this.cells[r][c] == 0){
274 | hole = true;
275 |
276 | // TH: != 0 rather than == 1
277 | }else if (this.cells[r][c] != 0 && hole){
278 | count++;
279 | }
280 | }
281 | }
282 | return count;
283 | }
284 |
285 | Grid.prototype.aggregateHeight = function(){
286 | var total = 0;
287 |
288 | for(var c = 0; c < this.columns; c++){
289 | total += this.columnHeight(c);
290 | }
291 | return total;
292 | };
293 |
294 | Grid.prototype.bumpiness = function(){
295 | var total = 0;
296 | for(var c = 0; c < this.columns - 1; c++){
297 | total += Math.abs(this.columnHeight(c) - this.columnHeight(c+ 1));
298 | }
299 | return total;
300 | }
301 |
302 | Grid.prototype.columnHeight = function(column){
303 | var r = 0;
304 |
305 | for(; r < this.rows && this.cells[r][column] == 0; r++);
306 | return this.rows - r;
307 | };
308 |
309 | // Piece
310 | Grid.prototype.addPiece = function(piece) {
311 |
312 | for(var r = 0; r < piece.cells.length; r++) {
313 | for (var c = 0; c < piece.cells[r].length; c++) {
314 |
315 | var _r = piece.row + r;
316 | var _c = piece.column + c;
317 |
318 | // TH: != 0 rather than == 1
319 | if (piece.cells[r][c] != 0 && _r >= 0){
320 |
321 | // TH: Updates color, rather than 1
322 | if (piece.cells[r][c] > 1) {
323 | var num = piece.cells[r][c] - 2;
324 | this.cells[_r][_c] = piece.color[num];
325 | } else {
326 | this.cells[_r][_c] = piece.color;
327 | }
328 | }
329 |
330 | }
331 | }
332 | };
333 |
334 | Grid.prototype.valid = function(piece){
335 |
336 | for(var r = 0; r < piece.cells.length; r++){
337 | for(var c = 0; c < piece.cells[r].length; c++){
338 | var _r = piece.row + r;
339 | var _c = piece.column + c;
340 |
341 | // TH: != 0 rather than == 1
342 | if (piece.cells[r][c] != 0){
343 | if (!(_c < this.columns && _r < this.rows && this.cells[_r][_c] == 0)){
344 | return false;
345 | }
346 | }
347 | }
348 | }
349 | return true;
350 | };
351 |
352 | Grid.prototype.canMoveDown = function(piece){
353 | for(var r = 0; r < piece.cells.length; r++){
354 | for(var c = 0; c < piece.cells[r].length; c++){
355 | var _r = piece.row + r + 1;
356 | var _c = piece.column + c;
357 |
358 | // TH: != 0 rather than == 1
359 | if (piece.cells[r][c] != 0 && _r >= 0){
360 |
361 | if (!(_r < this.rows && this.cells[_r][_c] == 0)){
362 | return false;
363 | }
364 | }
365 | }
366 | }
367 | return true;
368 | };
369 |
370 | Grid.prototype.canMoveLeft = function(piece){
371 | for(var r = 0; r < piece.cells.length; r++){
372 | for(var c = 0; c < piece.cells[r].length; c++){
373 | var _r = piece.row + r;
374 | var _c = piece.column + c - 1;
375 |
376 | // TH: != 0 rather than == 1
377 | if (piece.cells[r][c] != 0){
378 | if (!(_c >= 0 && this.cells[_r][_c] == 0)){
379 | return false;
380 | }
381 | }
382 | }
383 | }
384 | return true;
385 | };
386 |
387 | Grid.prototype.canMoveRight = function(piece){
388 | for(var r = 0; r < piece.cells.length; r++){
389 | for(var c = 0; c < piece.cells[r].length; c++){
390 | var _r = piece.row + r;
391 | var _c = piece.column + c + 1;
392 |
393 | // TH: != 0 rather than == 1
394 | if (piece.cells[r][c] != 0){
395 | if (!(_c >= 0 && this.cells[_r][_c] == 0)){
396 | return false;
397 | }
398 | }
399 | }
400 | }
401 | return true;
402 | };
403 |
404 | Grid.prototype.rotateOffset = function(piece){
405 |
406 | console.log("rotate?");
407 |
408 | var _piece = piece.clone();
409 | _piece.rotate(1);
410 | if (this.valid(_piece)) {
411 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
412 | }
413 |
414 | // Kicking
415 | var initialRow = _piece.row;
416 | var initialCol = _piece.column;
417 |
418 | for (var i = 0; i < _piece.dimension - 1; i++) {
419 | _piece.column = initialCol + i;
420 | if (this.valid(_piece)) {
421 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
422 | }
423 |
424 | for (var j = 0; j < _piece.dimension - 1; j++) {
425 | _piece.row = initialRow - j;
426 | if (this.valid(_piece)) {
427 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
428 | }
429 | }
430 | _piece.row = initialRow;
431 | }
432 | _piece.column = initialCol;
433 |
434 | for (var i = 0; i < _piece.dimension - 1; i++) {
435 | _piece.column = initialCol - i;
436 | if (this.valid(_piece)) {
437 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
438 | }
439 |
440 | for (var j = 0; j < _piece.dimension - 1; j++) {
441 | _piece.row = initialRow - j;
442 | if (this.valid(_piece)) {
443 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
444 | }
445 | }
446 | _piece.row = initialRow;
447 | }
448 | _piece.column = initialCol;
449 |
450 | return null;
451 | };
452 |
453 | /**
454 | * Piece
455 | * - Represents a single piece on the board.
456 | */
457 |
458 | // Object that represents a single piece & its properties.
459 | function Piece(cells, color){
460 | this.cells = cells;
461 | this.dimension = this.cells.length;
462 | this.row = 0;
463 | this.column = 0;
464 | this.color = color;
465 | };
466 |
467 | Piece.fromIndex = function(index, color){
468 |
469 | var cells
470 |
471 | switch (index){
472 | case 0:// O
473 | cells = [
474 | [1, 1],
475 | [1, 1]
476 | ];
477 | break;
478 | case 1: // J
479 | cells = [
480 | [1, 0, 0],
481 | [1, 1, 1],
482 | [0, 0, 0]
483 | ];
484 | break;
485 | case 2: // L
486 | cells = [
487 | [0, 0, 1],
488 | [1, 1, 1],
489 | [0, 0, 0]
490 | ];
491 | break;
492 | case 3: // Z
493 | cells = [
494 | [1, 1, 0],
495 | [0, 1, 1],
496 | [0, 0, 0]
497 | ];
498 | break;
499 | case 4: // S
500 | cells = [
501 | [0, 1, 1],
502 | [1, 1, 0],
503 | [0, 0, 0]
504 | ];
505 | break;
506 | case 5: // T
507 | cells = [
508 | [0, 1, 0],
509 | [1, 1, 1],
510 | [0, 0, 0]
511 | ];
512 | break;
513 | case 6: // I
514 | cells = [
515 | [0, 0, 0, 0],
516 | [1, 1, 1, 1],
517 | [0, 0, 0, 0],
518 | [0, 0, 0, 0]
519 | ];
520 | break;
521 |
522 | }
523 |
524 | var piece = new Piece(cells, color);
525 |
526 | piece.row = 0;
527 | piece.column = Math.floor((10 - piece.dimension) / 2); // Centralize
528 | return piece;
529 | };
530 |
531 | Piece.prototype.clone = function(){
532 |
533 | var _cells = new Array(this.dimension);
534 | for (var r = 0; r < this.dimension; r++) {
535 | _cells[r] = new Array(this.dimension);
536 | for(var c = 0; c < this.dimension; c++){
537 | _cells[r][c] = this.cells[r][c];
538 | }
539 | }
540 |
541 | var piece = new Piece(_cells, this.color);
542 | piece.row = this.row;
543 | piece.column = this.column;
544 | return piece;
545 | };
546 |
547 | Piece.prototype.rotate = function(rotations){
548 | for(var i = 0; i < rotations; i++) {
549 | var _cells = new Array(this.dimension);
550 | for (var r = 0; r < this.dimension; r++) {
551 | _cells[r] = new Array(this.dimension);
552 | }
553 |
554 | switch (this.dimension) { // Assumed square matrix
555 | case 2:
556 | _cells[0][0] = this.cells[1][0];
557 | _cells[0][1] = this.cells[0][0];
558 | _cells[1][0] = this.cells[1][1];
559 | _cells[1][1] = this.cells[0][1];
560 | break;
561 | case 3:
562 | _cells[0][0] = this.cells[2][0];
563 | _cells[0][1] = this.cells[1][0];
564 | _cells[0][2] = this.cells[0][0];
565 | _cells[1][0] = this.cells[2][1];
566 | _cells[1][1] = this.cells[1][1];
567 | _cells[1][2] = this.cells[0][1];
568 | _cells[2][0] = this.cells[2][2];
569 | _cells[2][1] = this.cells[1][2];
570 | _cells[2][2] = this.cells[0][2];
571 | break;
572 | case 4:
573 | _cells[0][0] = this.cells[3][0];
574 | _cells[0][1] = this.cells[2][0];
575 | _cells[0][2] = this.cells[1][0];
576 | _cells[0][3] = this.cells[0][0];
577 | _cells[1][3] = this.cells[0][1];
578 | _cells[2][3] = this.cells[0][2];
579 | _cells[3][3] = this.cells[0][3];
580 | _cells[3][2] = this.cells[1][3];
581 | _cells[3][1] = this.cells[2][3];
582 | _cells[3][0] = this.cells[3][3];
583 | _cells[2][0] = this.cells[3][2];
584 | _cells[1][0] = this.cells[3][1];
585 |
586 | _cells[1][1] = this.cells[2][1];
587 | _cells[1][2] = this.cells[1][1];
588 | _cells[2][2] = this.cells[1][2];
589 | _cells[2][1] = this.cells[2][2];
590 | break;
591 | }
592 |
593 | this.cells = _cells;
594 | }
595 | };
596 |
597 | /**
598 | * Game manager, manages flow and updating of game.
599 | */
600 |
601 | function GameManager(){
602 |
603 | this.gridCanvas = document.getElementById('grid-canvas');
604 |
605 | this.gravityUpdater = new Updater();
606 |
607 | this.gravityUpdater.onUpdate(function(){
608 | self.applyGravity();
609 | self.actuate();
610 | });
611 |
612 | var self = this;
613 | this.setup();
614 | this.startAI();
615 | this.gravityUpdater.checkUpdate(Date.now());
616 | };
617 |
618 | GameManager.prototype.setup = function(){
619 |
620 | this.baseColumns = 8;
621 |
622 | this.pieceWidth = window.innerWidth / this.baseColumns;
623 | this.pieceHeight = this.pieceWidth;
624 |
625 | this.displacementWidth = Math.floor(this.pieceWidth / 4);
626 | this.strokeThickness = 20;
627 |
628 | var canvasHeightPieces = Math.ceil(window.innerHeight / this.pieceHeight) + 2;
629 |
630 | this.gridCanvas.width = window.innerWidth;
631 | this.gridCanvas.height = canvasHeightPieces * this.pieceHeight;
632 |
633 | this.grid = new Grid(canvasHeightPieces, this.baseColumns);
634 | this.rpg = new RandomPieceGenerator();
635 | this.ai = new AI(0.510066, 0.760666, 0.35663, 0.184483);
636 |
637 | this.workingPieces = [this.rpg.nextPiece(), this.rpg.nextPiece()];
638 | this.workingPiece = this.workingPieces[0];
639 |
640 | this.isOver = true;
641 |
642 | this.stopAI();
643 | this.actuate();
644 | };
645 |
646 | GameManager.prototype.actuate = function(){
647 |
648 | var _grid = this.grid.clone();
649 |
650 | if (this.workingPiece != null) {
651 | _grid.addPiece(this.workingPiece);
652 | }
653 |
654 | var context = this.gridCanvas.getContext('2d');
655 | context.save();
656 |
657 | context.clearRect(0, 0, this.gridCanvas.width, this.gridCanvas.height);
658 |
659 | for(var r = 2; r < _grid.rows; r++){
660 |
661 | for(var c = 0; c < _grid.columns; c++){
662 |
663 | if (_grid.cells[r][c] != 0){
664 |
665 | context.fillStyle = _grid.cells[r][c];
666 | context.strokeStyle = _grid.cells[r][c];
667 | context.fillRect(this.pieceWidth * c, this.pieceHeight * r, this.pieceWidth, this.pieceHeight);
668 |
669 | // Border?
670 | context.fillStyle = "rgba(255, 255, 255, 0.3)";
671 | context.fillRect(this.pieceWidth * c + this.displacementWidth, this.pieceHeight * r + this.displacementWidth, this.pieceWidth / 2, this.strokeThickness);
672 | context.fillRect(this.pieceWidth * c + this.displacementWidth, this.pieceHeight * r + this.displacementWidth + this.strokeThickness, this.strokeThickness, this.pieceWidth / 2 - this.strokeThickness );
673 | }
674 | }
675 | }
676 |
677 | context.restore();
678 | };
679 |
680 | GameManager.prototype.startAI = function(){
681 | this.aiActive = true;
682 | };
683 |
684 | GameManager.prototype.stopAI = function(){
685 | this.aiActive = false;
686 | };
687 |
688 | GameManager.prototype.setWorkingPiece = function(){
689 |
690 | this.grid.addPiece(this.workingPiece);
691 | this.grid.clearLines();
692 |
693 | if (!this.grid.exceeded()){
694 |
695 | for(var i = 0; i < this.workingPieces.length - 1; i++){
696 | this.workingPieces[i] = this.workingPieces[i + 1];
697 | }
698 |
699 | this.workingPieces[this.workingPieces.length - 1] = this.rpg.nextPiece();
700 | this.workingPiece = this.workingPieces[0];
701 |
702 | if (this.aiActive) {
703 | this.aiMove();
704 | }
705 | }
706 |
707 | // TODO: NO WAYYYY
708 | else{
709 |
710 | }
711 | };
712 |
713 | GameManager.prototype.applyGravity = function(){
714 |
715 | if (this.grid.canMoveDown(this.workingPiece)) {
716 | this.workingPiece.row++;
717 | }else{
718 | this.setWorkingPiece();
719 | }
720 |
721 | };
722 |
723 | GameManager.prototype.drop = function(){
724 | while(this.grid.canMoveDown(this.workingPiece)){
725 | this.workingPiece.row++;
726 | }
727 | };
728 |
729 | GameManager.prototype.moveLeft = function(){
730 | if (this.grid.canMoveLeft(this.workingPiece)){
731 | this.workingPiece.column--;
732 | }
733 | };
734 |
735 | GameManager.prototype.moveRight = function(){
736 | if (this.grid.canMoveRight(this.workingPiece)){
737 | this.workingPiece.column++;
738 | }
739 | };
740 |
741 | GameManager.prototype.rotate = function(){
742 | var offset = this.grid.rotateOffset(this.workingPiece);
743 | if (offset != null){
744 | this.workingPiece.rotate(1);
745 | this.workingPiece.row += offset.rowOffset;
746 | this.workingPiece.column += offset.columnOffset;
747 | }
748 | };
749 |
750 | GameManager.prototype.aiMove = function(){
751 | this.workingPiece = this.ai.best(this.grid, this.workingPieces, 0).piece;
752 | };
753 |
754 | function RandomPieceGenerator(){
755 | Math.seed
756 | this.bag = [0, 1, 2, 3, 4, 5, 6];
757 | this.shuffleBag();
758 | this.index = -1;
759 |
760 | this.colorManager = new ColorManager();
761 | };
762 |
763 | RandomPieceGenerator.prototype.nextPiece = function(){
764 |
765 | this.index++;
766 | if (this.index >= this.bag.length){
767 | this.shuffleBag();
768 | this.index = 0;
769 | }
770 |
771 | var color = this.colorManager.getColor();
772 |
773 | return Piece.fromIndex(this.bag[this.index], color);
774 |
775 | };
776 |
777 | RandomPieceGenerator.prototype.shuffleBag = function() {
778 | var currentIndex = this.bag.length
779 | , temporaryValue
780 | , randomIndex
781 | ;
782 |
783 | // While there remain elements to shuffle...
784 | while (0 !== currentIndex) {
785 |
786 | // Pick a remaining element...
787 | randomIndex = Math.floor(Math.random() * currentIndex);
788 | currentIndex -= 1;
789 |
790 | // And swap it with the current element.
791 | temporaryValue = this.bag[currentIndex];
792 | this.bag[currentIndex] = this.bag[randomIndex];
793 | this.bag[randomIndex] = temporaryValue;
794 | }
795 | };
796 | function AI(heightWeight, linesWeight, holesWeight, bumpinessWeight){
797 |
798 | this.heightWeight = heightWeight;
799 | this.linesWeight = linesWeight;
800 | this.holesWeight = holesWeight;
801 | this.bumpinessWeight = bumpinessWeight;
802 |
803 | };
804 |
805 | AI.prototype.best = function(grid, workingPieces, workingPieceIndex){
806 |
807 | var best = null;
808 | var bestScore = null;
809 | var workingPiece = workingPieces[workingPieceIndex];
810 |
811 | for(var rotation = 0; rotation < 4; rotation++){
812 | var _piece = workingPiece.clone();
813 | _piece.rotate(rotation);
814 |
815 | while(grid.canMoveLeft(_piece)){
816 | _piece.column --;
817 | }
818 |
819 | while(grid.valid(_piece)){
820 | var _pieceSet = _piece.clone();
821 | while(grid.canMoveDown(_pieceSet)){
822 | _pieceSet.row++;
823 | }
824 |
825 | var _grid = grid.clone();
826 | _grid.addPiece(_pieceSet);
827 |
828 | var score = null;
829 | if (workingPieceIndex == (workingPieces.length - 1)) {
830 | score = -this.heightWeight * _grid.aggregateHeight() + this.linesWeight * _grid.lines() - this.holesWeight * _grid.holes() - this.bumpinessWeight * _grid.bumpiness();
831 | }else{
832 | score = this.best(_grid, workingPieces, workingPieceIndex + 1).score;
833 | }
834 |
835 | if (score > bestScore || bestScore == null){
836 | bestScore = score;
837 | best = _piece.clone();
838 | }
839 |
840 | _piece.column++;
841 | }
842 | }
843 |
844 | return {piece:best, score:bestScore};
845 | };
846 | /**
847 | * Updater, controls time and speed.
848 | */
849 |
850 | function Updater() {
851 | this.lastUpdateTime = Date.now();
852 | this.deltaThreshold = 250; // MS before each update
853 | this.updateCallback = null;
854 |
855 | window.requestAnimFrame = (function() {
856 | // Polyfill
857 | return (
858 | window.requestAnimationFrame ||
859 | window.webkitRequestAnimationFrame ||
860 | window.mozRequestAnimationFrame ||
861 | window.oRequestAnimationFrame ||
862 | window.msRequestAnimationFrame ||
863 | function(callback) {
864 | window.setTimeout(callback, 1000 / 60);
865 | }
866 | );
867 | })();
868 | }
869 |
870 | Updater.prototype.onUpdate = function(callback) {
871 | this.updateCallback = callback;
872 | };
873 |
874 | Updater.prototype.doUpdate = function(timestamp) {
875 | if (this.updateCallback != null) {
876 | this.updateCallback();
877 | }
878 |
879 | this.lastUpdateTime = timestamp;
880 | };
881 |
882 | Updater.prototype.checkUpdate = function(timestamp) {
883 | var self = this;
884 | var delta = timestamp - this.lastUpdateTime;
885 |
886 | if (delta > this.deltaThreshold) {
887 | this.doUpdate(timestamp);
888 | }
889 |
890 | window.requestAnimFrame(function() {
891 | self.checkUpdate(Date.now());
892 | });
893 | };
894 |
--------------------------------------------------------------------------------
/classic/js/index.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | function square(context, x, y, width, height) {
4 |
5 | var unitWidth = 0.125 * width;
6 |
7 | // Border
8 | context.fillStyle = "#000";
9 | context.fillRect(width * x, height * y, width, height);
10 |
11 | context.fillStyle = "#C6CFA4";
12 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
13 |
14 | context.fillStyle = "#000";
15 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, width - unitWidth * 4, height - unitWidth * 4);
16 |
17 | }
18 |
19 | function jay(context, x, y, width, height) {
20 |
21 | var unitWidth = 0.125 * width;
22 |
23 | // Border
24 | context.fillStyle = "#000";
25 | context.fillRect(width * x, height * y, width, height);
26 |
27 | context.fillStyle = "#92BE7C";
28 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
29 |
30 | context.fillStyle = "#000";
31 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, width - unitWidth * 4, height - unitWidth * 4);
32 |
33 | context.fillStyle = "#C6CFA4";
34 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 3, width - unitWidth * 6, height - unitWidth * 6);
35 | }
36 |
37 | function ell(context, x, y, width, height) {
38 |
39 | var unitWidth = 0.125 * width;
40 |
41 | context.fillStyle = "#000";
42 | context.fillRect(width * x, height * y, width, height);
43 |
44 | context.fillStyle = "#3C6A4E";
45 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
46 |
47 | }
48 |
49 | function zee(context, x, y, width, height) {
50 |
51 | var unitWidth = 0.125 * width;
52 |
53 | context.fillStyle = "#000";
54 | context.fillRect(width * x, height * y, width, height);
55 |
56 | context.fillStyle = "#92BE7C";
57 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
58 |
59 | context.fillStyle = "#000";
60 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 3, width - unitWidth * 6, height - unitWidth * 6);
61 |
62 | }
63 |
64 | function ess(context, x, y, width, height) {
65 |
66 | var unitWidth = 0.125 * width;
67 |
68 | context.fillStyle = "#000";
69 | context.fillRect(width * x, height * y, width, height);
70 |
71 | context.fillStyle = "#3C6A4E";
72 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
73 |
74 | context.fillStyle = "#000";
75 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, width - unitWidth * 4, height - unitWidth * 4);
76 |
77 | context.fillStyle = "#C6CFA4";
78 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 3, width - unitWidth * 6, height - unitWidth * 6);
79 | }
80 |
81 | function tee(context, x, y, width, height) {
82 |
83 | var unitWidth = 0.125 * width;
84 |
85 | context.fillStyle = "#000";
86 | context.fillRect(width * x, height * y, width, height);
87 |
88 | context.fillStyle = "#92BE7C";
89 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
90 |
91 | context.fillStyle = "#C6CFA4";
92 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, unitWidth, height - unitWidth * 4);
93 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, unitWidth * 4, unitWidth);
94 |
95 | context.fillStyle = "#000";
96 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 5, unitWidth * 4, unitWidth);
97 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 3, unitWidth, unitWidth * 3);
98 |
99 | }
100 |
101 | var eyes = [
102 | //h1
103 | function(context, x, y, width, height) {
104 |
105 | var unitWidth = 0.125 * width;
106 | context.fillStyle = "#000";
107 | context.fillRect(width * x, height * y, width, height);
108 |
109 | context.fillStyle = "#92BE7C";
110 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth, height - unitWidth * 2);
111 |
112 | // Dots
113 | context.fillStyle = "#3C6A4E";
114 |
115 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 1, unitWidth, unitWidth);
116 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 1, unitWidth, unitWidth);
117 |
118 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 3, unitWidth, unitWidth);
119 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 3, unitWidth, unitWidth);
120 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 3, unitWidth, unitWidth);
121 |
122 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 5, unitWidth, unitWidth);
123 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 5, unitWidth, unitWidth);
124 |
125 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 6, unitWidth, unitWidth);
126 |
127 |
128 | },
129 | function(context, x, y, width, height) {
130 |
131 | var unitWidth = 0.125 * width;
132 |
133 | context.fillStyle = "#000";
134 | context.fillRect(width * x, height * y, width, height);
135 |
136 | context.fillStyle = "#92BE7C";
137 | context.fillRect(width * x, height * y + unitWidth, width, height - unitWidth * 2);
138 |
139 | // Dots
140 | context.fillStyle = "#3C6A4E";
141 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 1, unitWidth, unitWidth);
142 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 1, unitWidth, unitWidth);
143 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 1, unitWidth, unitWidth);
144 |
145 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
146 |
147 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 3, unitWidth, unitWidth);
148 |
149 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 4, unitWidth, unitWidth);
150 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 4, unitWidth, unitWidth);
151 |
152 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 5, unitWidth, unitWidth);
153 | context.fillRect(width * x + unitWidth * 7, height * y + unitWidth * 5, unitWidth, unitWidth);
154 |
155 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 6, unitWidth, unitWidth);
156 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 6, unitWidth, unitWidth);
157 |
158 |
159 | },
160 | function(context, x, y, width, height) {
161 |
162 | var unitWidth = 0.125 * width;
163 |
164 | context.fillStyle = "#000";
165 | context.fillRect(width * x, height * y, width, height);
166 |
167 | context.fillStyle = "#92BE7C";
168 | context.fillRect(width * x, height * y + unitWidth, width, height - unitWidth * 2);
169 |
170 | // Dots
171 | context.fillStyle = "#3C6A4E";
172 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 1, unitWidth, unitWidth);
173 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 1, unitWidth, unitWidth);
174 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 1, unitWidth, unitWidth);
175 |
176 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
177 |
178 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 3, unitWidth, unitWidth);
179 |
180 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 4, unitWidth, unitWidth);
181 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 4, unitWidth, unitWidth);
182 |
183 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 5, unitWidth, unitWidth);
184 | context.fillRect(width * x + unitWidth * 7, height * y + unitWidth * 5, unitWidth, unitWidth);
185 |
186 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 6, unitWidth, unitWidth);
187 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 6, unitWidth, unitWidth);
188 |
189 | },
190 | function(context, x, y, width, height) {
191 |
192 | var unitWidth = 0.125 * width;
193 |
194 | context.fillStyle = "#000";
195 | context.fillRect(width * x, height * y, width, height);
196 |
197 | context.fillStyle = "#92BE7C";
198 | context.fillRect(width * x, height * y + unitWidth, width - unitWidth, height - unitWidth * 2);
199 |
200 | // Dots
201 | context.fillStyle = "#3C6A4E";
202 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 1, unitWidth, unitWidth);
203 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 1, unitWidth, unitWidth);
204 |
205 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, unitWidth, unitWidth);
206 |
207 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 3, unitWidth, unitWidth);
208 |
209 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 4, unitWidth, unitWidth);
210 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 4, unitWidth, unitWidth);
211 |
212 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 5, unitWidth, unitWidth);
213 |
214 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 6, unitWidth, unitWidth);
215 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 6, unitWidth, unitWidth);
216 | },
217 |
218 | // v1
219 | function(context, x, y, width, height) {
220 |
221 | var unitWidth = 0.125 * width;
222 | context.fillStyle = "#000";
223 | context.fillRect(width * x, height * y, width, height);
224 |
225 | context.fillStyle = "#92BE7C";
226 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth);
227 |
228 | // Dots
229 | context.fillStyle = "#3C6A4E";
230 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth, unitWidth, unitWidth);
231 |
232 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, unitWidth, unitWidth);
233 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
234 |
235 | context.fillRect(width * x + unitWidth, height * y + unitWidth * 4, unitWidth, unitWidth);
236 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 4, unitWidth, unitWidth);
237 |
238 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 5, unitWidth, unitWidth);
239 |
240 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 6, unitWidth, unitWidth);
241 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 6, unitWidth, unitWidth);
242 |
243 | },
244 | function(context, x, y, width, height) {
245 |
246 | var unitWidth = 0.125 * width;
247 |
248 | context.fillStyle = "#000";
249 | context.fillRect(width * x, height * y, width, height);
250 |
251 | context.fillStyle = "#92BE7C";
252 | context.fillRect(width * x + unitWidth, height * y, width - unitWidth * 2, height);
253 |
254 | // Dots
255 | context.fillStyle = "#3C6A4E";
256 |
257 | context.fillRect(width * x + unitWidth * 3, height * y, unitWidth, unitWidth);
258 | context.fillRect(width * x + unitWidth * 6, height * y, unitWidth, unitWidth);
259 |
260 | context.fillRect(width * x + unitWidth, height * y + unitWidth * 1, unitWidth, unitWidth);
261 |
262 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 2, unitWidth, unitWidth);
263 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
264 |
265 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 3, unitWidth, unitWidth);
266 |
267 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 4, unitWidth, unitWidth);
268 |
269 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 5, unitWidth, unitWidth);
270 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 5, unitWidth, unitWidth);
271 |
272 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 6, unitWidth, unitWidth);
273 |
274 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 7, unitWidth, unitWidth);
275 |
276 | },
277 | function(context, x, y, width, height) {
278 |
279 | var unitWidth = 0.125 * width;
280 |
281 | context.fillStyle = "#000";
282 | context.fillRect(width * x, height * y, width, height);
283 |
284 | context.fillStyle = "#92BE7C";
285 | context.fillRect(width * x + unitWidth, height * y, width - unitWidth * 2, height);
286 |
287 | // Dots
288 | context.fillStyle = "#3C6A4E";
289 |
290 | context.fillRect(width * x + unitWidth * 3, height * y, unitWidth, unitWidth);
291 | context.fillRect(width * x + unitWidth * 6, height * y, unitWidth, unitWidth);
292 |
293 | context.fillRect(width * x + unitWidth, height * y + unitWidth * 1, unitWidth, unitWidth);
294 |
295 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 2, unitWidth, unitWidth);
296 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
297 |
298 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 3, unitWidth, unitWidth);
299 |
300 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 4, unitWidth, unitWidth);
301 |
302 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 5, unitWidth, unitWidth);
303 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 5, unitWidth, unitWidth);
304 |
305 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 6, unitWidth, unitWidth);
306 |
307 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 7, unitWidth, unitWidth);
308 | },
309 | function(context, x, y, width, height) {
310 |
311 | var unitWidth = 0.125 * width;
312 |
313 | context.fillStyle = "#000";
314 | context.fillRect(width * x, height * y, width, height);
315 |
316 | context.fillStyle = "#92BE7C";
317 | context.fillRect(width * x + unitWidth, height * y, width - unitWidth * 2, height - unitWidth);
318 |
319 | // Dots
320 | context.fillStyle = "#3C6A4E";
321 |
322 | context.fillRect(width * x + unitWidth * 6, height * y, unitWidth, unitWidth);
323 |
324 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 1, unitWidth, unitWidth);
325 |
326 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 2, unitWidth, unitWidth);
327 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 2, unitWidth, unitWidth);
328 |
329 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 3, unitWidth, unitWidth);
330 |
331 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 4, unitWidth, unitWidth);
332 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 4, unitWidth, unitWidth);
333 |
334 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 5, unitWidth, unitWidth);
335 |
336 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 6, unitWidth, unitWidth);
337 | }
338 | ]
339 |
340 | var drawFunctions = [
341 |
342 | square,
343 |
344 | jay,
345 |
346 | ell,
347 |
348 | zee,
349 |
350 | ess,
351 |
352 | tee,
353 |
354 | eyes
355 |
356 | ]
357 |
358 | function DrawFunctions(){};
359 |
360 | DrawFunctions.prototype.getDrawFunction = function(index){
361 |
362 | if( drawFunctions[index]) {
363 | return drawFunctions[index];
364 | } else {
365 | return drawFunctions[5];
366 | }
367 | }
368 | /**
369 | * Grid
370 | * - Manages the state of the grid
371 | */
372 |
373 | // Init
374 | function Grid(rows, columns){
375 |
376 | this.rows = rows;
377 | this.columns = columns;
378 | this.cells = new Array(rows);
379 |
380 | // For each row!
381 | // Has a column
382 | // Which has X cells in it.
383 | for (var r = 0; r < this.rows; r++) {
384 |
385 | this.cells[r] = new Array(this.columns);
386 | for(var c = 0; c < this.columns; c++){
387 | this.cells[r][c] = 0;
388 | }
389 | }
390 |
391 | };
392 |
393 | // Methods
394 | Grid.prototype.clone = function(){
395 | var _grid = new Grid(this.rows, this.columns);
396 | for (var r = 0; r < this.rows; r++) {
397 | for(var c = 0; c < this.columns; c++){
398 | _grid.cells[r][c] = this.cells[r][c];
399 | }
400 | }
401 | return _grid;
402 | };
403 |
404 | // Clear spaces in the grid, including when the blocks "fall"
405 | Grid.prototype.clearLines = function(){
406 |
407 | var distance = 0;
408 | var row = new Array(this.columns);
409 |
410 | for(var r = this.rows - 1; r >= 0; r--){
411 |
412 | // Clear full line
413 | if (this.isLine(r)){
414 |
415 | distance++;
416 | for(var c = 0; c < this.columns; c++){
417 | this.cells[r][c] = 0;
418 | }
419 |
420 | // Clear moved spaces
421 | } else if (distance > 0) {
422 |
423 | for(var c = 0; c < this.columns; c++){
424 | this.cells[r + distance][c] = this.cells[r][c];
425 | this.cells[r][c] = 0;
426 | }
427 | }
428 | }
429 | };
430 |
431 | // If every item in the row has an item!
432 | Grid.prototype.isLine = function(row){
433 | for(var c = 0; c < this.columns; c++){
434 | if (this.cells[row][c] == 0){
435 | return false;
436 | }
437 | }
438 | return true;
439 | };
440 |
441 | Grid.prototype.isEmptyRow = function(row){
442 | for(var c = 0; c < this.columns; c++){
443 |
444 | // TH: != 0 rather than == 1
445 | if (this.cells[row][c] != 0){
446 | return false;
447 | }
448 | }
449 | return true;
450 | };
451 |
452 | Grid.prototype.exceeded = function(){
453 | return !this.isEmptyRow(0) || !this.isEmptyRow(1);
454 | };
455 |
456 | Grid.prototype.height = function(){
457 | var r = 0;
458 | for(; r < this.rows && this.isEmptyRow(r); r++);
459 | return this.rows - r;
460 | };
461 |
462 | Grid.prototype.lines = function(){
463 | var count = 0;
464 | for(var r = 0; r < this.rows; r++){
465 | if (this.isLine(r)){
466 | count++;
467 | }
468 | }
469 | return count;
470 | };
471 |
472 | Grid.prototype.holes = function(){
473 | var count = 0;
474 |
475 | for(var c = 0; c < this.columns; c++){
476 | var block = false;
477 | for(var r = 0; r < this.rows; r++){
478 |
479 | // TH: != 0 rather than == 1
480 | if (this.cells[r][c] != 0) {
481 | block = true;
482 | }else if (this.cells[r][c] == 0 && block){
483 | count++;
484 | }
485 | }
486 | }
487 | return count;
488 | };
489 |
490 | Grid.prototype.blockades = function(){
491 | var count = 0;
492 |
493 | for(var c = 0; c < this.columns; c++){
494 | var hole = false;
495 | for(var r = this.rows - 1; r >= 0; r--){
496 | if (this.cells[r][c] == 0){
497 | hole = true;
498 |
499 | // TH: != 0 rather than == 1
500 | }else if (this.cells[r][c] != 0 && hole){
501 | count++;
502 | }
503 | }
504 | }
505 | return count;
506 | }
507 |
508 | Grid.prototype.aggregateHeight = function(){
509 | var total = 0;
510 |
511 | for(var c = 0; c < this.columns; c++){
512 | total += this.columnHeight(c);
513 | }
514 | return total;
515 | };
516 |
517 | Grid.prototype.bumpiness = function(){
518 | var total = 0;
519 | for(var c = 0; c < this.columns - 1; c++){
520 | total += Math.abs(this.columnHeight(c) - this.columnHeight(c+ 1));
521 | }
522 | return total;
523 | }
524 |
525 | Grid.prototype.columnHeight = function(column){
526 | var r = 0;
527 |
528 | for(; r < this.rows && this.cells[r][column] == 0; r++);
529 | return this.rows - r;
530 | };
531 |
532 | // Piece
533 | Grid.prototype.addPiece = function(piece) {
534 |
535 | for(var r = 0; r < piece.cells.length; r++) {
536 | for (var c = 0; c < piece.cells[r].length; c++) {
537 |
538 | var _r = piece.row + r;
539 | var _c = piece.column + c;
540 |
541 | // TH: != 0 rather than == 1
542 | if (piece.cells[r][c] != 0 && _r >= 0){
543 |
544 | // TH: Updates color, rather than 1
545 | if (piece.cells[r][c] > 1) {
546 | var num = piece.cells[r][c] - 2;
547 | this.cells[_r][_c] = piece.color[num];
548 | } else {
549 | this.cells[_r][_c] = piece.color;
550 | }
551 | }
552 |
553 | }
554 | }
555 | };
556 |
557 | Grid.prototype.valid = function(piece){
558 |
559 | for(var r = 0; r < piece.cells.length; r++){
560 | for(var c = 0; c < piece.cells[r].length; c++){
561 | var _r = piece.row + r;
562 | var _c = piece.column + c;
563 |
564 | // TH: != 0 rather than == 1
565 | if (piece.cells[r][c] != 0){
566 | if (!(_c < this.columns && _r < this.rows && this.cells[_r][_c] == 0)){
567 | return false;
568 | }
569 | }
570 | }
571 | }
572 | return true;
573 | };
574 |
575 | Grid.prototype.canMoveDown = function(piece){
576 | for(var r = 0; r < piece.cells.length; r++){
577 | for(var c = 0; c < piece.cells[r].length; c++){
578 | var _r = piece.row + r + 1;
579 | var _c = piece.column + c;
580 |
581 | // TH: != 0 rather than == 1
582 | if (piece.cells[r][c] != 0 && _r >= 0){
583 |
584 | if (!(_r < this.rows && this.cells[_r][_c] == 0)){
585 | return false;
586 | }
587 | }
588 | }
589 | }
590 | return true;
591 | };
592 |
593 | Grid.prototype.canMoveLeft = function(piece){
594 | for(var r = 0; r < piece.cells.length; r++){
595 | for(var c = 0; c < piece.cells[r].length; c++){
596 | var _r = piece.row + r;
597 | var _c = piece.column + c - 1;
598 |
599 | // TH: != 0 rather than == 1
600 | if (piece.cells[r][c] != 0){
601 | if (!(_c >= 0 && this.cells[_r][_c] == 0)){
602 | return false;
603 | }
604 | }
605 | }
606 | }
607 | return true;
608 | };
609 |
610 | Grid.prototype.canMoveRight = function(piece){
611 | for(var r = 0; r < piece.cells.length; r++){
612 | for(var c = 0; c < piece.cells[r].length; c++){
613 | var _r = piece.row + r;
614 | var _c = piece.column + c + 1;
615 |
616 | // TH: != 0 rather than == 1
617 | if (piece.cells[r][c] != 0){
618 | if (!(_c >= 0 && this.cells[_r][_c] == 0)){
619 | return false;
620 | }
621 | }
622 | }
623 | }
624 | return true;
625 | };
626 |
627 | Grid.prototype.rotateOffset = function(piece){
628 |
629 | console.log("rotate?");
630 |
631 | var _piece = piece.clone();
632 | _piece.rotate(1);
633 | if (this.valid(_piece)) {
634 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
635 | }
636 |
637 | // Kicking
638 | var initialRow = _piece.row;
639 | var initialCol = _piece.column;
640 |
641 | for (var i = 0; i < _piece.dimension - 1; i++) {
642 | _piece.column = initialCol + i;
643 | if (this.valid(_piece)) {
644 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
645 | }
646 |
647 | for (var j = 0; j < _piece.dimension - 1; j++) {
648 | _piece.row = initialRow - j;
649 | if (this.valid(_piece)) {
650 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
651 | }
652 | }
653 | _piece.row = initialRow;
654 | }
655 | _piece.column = initialCol;
656 |
657 | for (var i = 0; i < _piece.dimension - 1; i++) {
658 | _piece.column = initialCol - i;
659 | if (this.valid(_piece)) {
660 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
661 | }
662 |
663 | for (var j = 0; j < _piece.dimension - 1; j++) {
664 | _piece.row = initialRow - j;
665 | if (this.valid(_piece)) {
666 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
667 | }
668 | }
669 | _piece.row = initialRow;
670 | }
671 | _piece.column = initialCol;
672 |
673 | return null;
674 | };
675 |
676 | /**
677 | * Piece
678 | * - Represents a single piece on the board.
679 | */
680 |
681 | // Object that represents a single piece & its properties.
682 | function Piece(cells, color){
683 | this.cells = cells;
684 | this.dimension = this.cells.length;
685 | this.row = 0;
686 | this.column = 0;
687 | this.color = color;
688 | };
689 |
690 | Piece.fromIndex = function(index, color){
691 |
692 | var cells
693 |
694 | switch (index){
695 | case 0:// O
696 | cells = [
697 | [1, 1],
698 | [1, 1]
699 | ];
700 | break;
701 | case 1: // J
702 | cells = [
703 | [1, 0, 0],
704 | [1, 1, 1],
705 | [0, 0, 0]
706 | ];
707 | break;
708 | case 2: // L
709 | cells = [
710 | [0, 0, 1],
711 | [1, 1, 1],
712 | [0, 0, 0]
713 | ];
714 | break;
715 | case 3: // Z
716 | cells = [
717 | [1, 1, 0],
718 | [0, 1, 1],
719 | [0, 0, 0]
720 | ];
721 | break;
722 | case 4: // S
723 | cells = [
724 | [0, 1, 1],
725 | [1, 1, 0],
726 | [0, 0, 0]
727 | ];
728 | break;
729 | case 5: // T
730 | cells = [
731 | [0, 1, 0],
732 | [1, 1, 1],
733 | [0, 0, 0]
734 | ];
735 | break;
736 | case 6: // I
737 | cells = [
738 | [0, 0, 0, 0],
739 | [2, 3, 4, 5],
740 | [0, 0, 0, 0],
741 | [0, 0, 0, 0]
742 | ];
743 | break;
744 |
745 | }
746 |
747 | var piece = new Piece(cells, color);
748 |
749 | piece.row = 0;
750 | piece.column = Math.floor((10 - piece.dimension) / 2); // Centralize
751 | return piece;
752 | };
753 |
754 | Piece.prototype.clone = function(){
755 |
756 | var _cells = new Array(this.dimension);
757 | for (var r = 0; r < this.dimension; r++) {
758 | _cells[r] = new Array(this.dimension);
759 | for(var c = 0; c < this.dimension; c++){
760 | _cells[r][c] = this.cells[r][c];
761 | }
762 | }
763 |
764 | var piece = new Piece(_cells, this.color);
765 | piece.row = this.row;
766 | piece.column = this.column;
767 | return piece;
768 | };
769 |
770 | Piece.prototype.rotate = function(rotations){
771 | for(var i = 0; i < rotations; i++) {
772 | var _cells = new Array(this.dimension);
773 | for (var r = 0; r < this.dimension; r++) {
774 | _cells[r] = new Array(this.dimension);
775 | }
776 |
777 | switch (this.dimension) { // Assumed square matrix
778 | case 2:
779 | _cells[0][0] = this.cells[1][0];
780 | _cells[0][1] = this.cells[0][0];
781 | _cells[1][0] = this.cells[1][1];
782 | _cells[1][1] = this.cells[0][1];
783 | break;
784 | case 3:
785 | _cells[0][0] = this.cells[2][0];
786 | _cells[0][1] = this.cells[1][0];
787 | _cells[0][2] = this.cells[0][0];
788 | _cells[1][0] = this.cells[2][1];
789 | _cells[1][1] = this.cells[1][1];
790 | _cells[1][2] = this.cells[0][1];
791 | _cells[2][0] = this.cells[2][2];
792 | _cells[2][1] = this.cells[1][2];
793 | _cells[2][2] = this.cells[0][2];
794 | break;
795 | case 4:
796 | _cells[0][0] = this.cells[3][0];
797 | _cells[0][1] = this.cells[2][0];
798 | _cells[0][2] = this.cells[1][0];
799 | _cells[0][3] = this.cells[0][0];
800 | _cells[1][3] = this.cells[0][1];
801 | _cells[2][3] = this.cells[0][2];
802 | _cells[3][3] = this.cells[0][3];
803 | _cells[3][2] = this.cells[1][3];
804 | _cells[3][1] = this.cells[2][3];
805 | _cells[3][0] = this.cells[3][3];
806 | _cells[2][0] = this.cells[3][2];
807 | _cells[1][0] = this.cells[3][1];
808 |
809 | _cells[1][1] = this.cells[2][1];
810 | _cells[1][2] = this.cells[1][1];
811 | _cells[2][2] = this.cells[1][2];
812 | _cells[2][1] = this.cells[2][2];
813 | break;
814 | }
815 |
816 | this.cells = _cells;
817 | }
818 | };
819 |
820 | /**
821 | * Game manager, manages flow and updating of game.
822 | */
823 |
824 | function GameManager(){
825 |
826 | this.gridCanvas = document.getElementById('grid-canvas');
827 |
828 | this.gravityUpdater = new Updater();
829 |
830 | this.gravityUpdater.onUpdate(function(){
831 | self.applyGravity();
832 | self.actuate();
833 | });
834 |
835 | var self = this;
836 | this.setup();
837 | this.startAI();
838 | this.gravityUpdater.checkUpdate(Date.now());
839 | };
840 |
841 | GameManager.prototype.setup = function(){
842 |
843 | this.baseColumns = 8;
844 |
845 | this.pieceWidth = window.innerWidth / this.baseColumns;
846 | this.pieceHeight = this.pieceWidth;
847 |
848 | this.displacementWidth = Math.floor(this.pieceWidth / 4);
849 |
850 | var canvasHeightPieces = Math.ceil(window.innerHeight / this.pieceHeight) + 2;
851 |
852 | this.gridCanvas.width = window.innerWidth;
853 | this.gridCanvas.height = canvasHeightPieces * this.pieceHeight;
854 |
855 | this.grid = new Grid(canvasHeightPieces, this.baseColumns);
856 | this.rpg = new RandomPieceGenerator();
857 | this.ai = new AI(0.510066, 0.760666, 0.35663, 0.184483);
858 |
859 | this.workingPieces = [this.rpg.nextPiece(), this.rpg.nextPiece()];
860 | this.workingPiece = this.workingPieces[0];
861 |
862 | this.isOver = true;
863 |
864 | this.stopAI();
865 | this.actuate();
866 | };
867 |
868 | GameManager.prototype.actuate = function(){
869 |
870 | var _grid = this.grid.clone();
871 |
872 | if (this.workingPiece != null) {
873 | _grid.addPiece(this.workingPiece);
874 | }
875 |
876 | var context = this.gridCanvas.getContext('2d');
877 | context.save();
878 |
879 | context.clearRect(0, 0, this.gridCanvas.width, this.gridCanvas.height);
880 |
881 | for(var r = 2; r < _grid.rows; r++){
882 |
883 | for(var c = 0; c < _grid.columns; c++){
884 |
885 | if (_grid.cells[r][c] != 0){
886 |
887 |
888 | // console.log(_grid.cells[r], _grid.cells[r][c]);
889 | _grid.cells[r][c](context, c, r, this.pieceWidth, this.pieceHeight);
890 |
891 | }
892 | }
893 | }
894 |
895 | context.restore();
896 | };
897 |
898 | GameManager.prototype.startAI = function(){
899 | this.aiActive = true;
900 | };
901 |
902 | GameManager.prototype.stopAI = function(){
903 | this.aiActive = false;
904 | };
905 |
906 | GameManager.prototype.setWorkingPiece = function(){
907 |
908 | this.grid.addPiece(this.workingPiece);
909 | this.grid.clearLines();
910 |
911 | if (!this.grid.exceeded()){
912 |
913 | for(var i = 0; i < this.workingPieces.length - 1; i++){
914 | this.workingPieces[i] = this.workingPieces[i + 1];
915 | }
916 |
917 | this.workingPieces[this.workingPieces.length - 1] = this.rpg.nextPiece();
918 | this.workingPiece = this.workingPieces[0];
919 |
920 | if (this.aiActive) {
921 | this.aiMove();
922 | }
923 |
924 | // I piece
925 | if( this.workingPiece.cells.length > 3) {
926 |
927 | if( this.workingPiece.cells[0][2] !== 0 ) {
928 | this.workingPiece.cells[0][2] = 6;
929 | this.workingPiece.cells[1][2] = 7;
930 | this.workingPiece.cells[2][2] = 8;
931 | this.workingPiece.cells[3][2] = 9;
932 | }
933 | }
934 | }
935 |
936 | // TODO: NO WAYYYY
937 | else{
938 |
939 | }
940 | };
941 |
942 | GameManager.prototype.applyGravity = function(){
943 |
944 | if (this.grid.canMoveDown(this.workingPiece)) {
945 | this.workingPiece.row++;
946 | }else{
947 | this.setWorkingPiece();
948 | }
949 |
950 | };
951 |
952 | GameManager.prototype.drop = function(){
953 | while(this.grid.canMoveDown(this.workingPiece)){
954 | this.workingPiece.row++;
955 | }
956 | };
957 |
958 | GameManager.prototype.moveLeft = function(){
959 | if (this.grid.canMoveLeft(this.workingPiece)){
960 | this.workingPiece.column--;
961 | }
962 | };
963 |
964 | GameManager.prototype.moveRight = function(){
965 | if (this.grid.canMoveRight(this.workingPiece)){
966 | this.workingPiece.column++;
967 | }
968 | };
969 |
970 | GameManager.prototype.rotate = function(){
971 | var offset = this.grid.rotateOffset(this.workingPiece);
972 | if (offset != null){
973 | this.workingPiece.rotate(1);
974 | this.workingPiece.row += offset.rowOffset;
975 | this.workingPiece.column += offset.columnOffset;
976 | }
977 | };
978 |
979 | GameManager.prototype.aiMove = function(){
980 | this.workingPiece = this.ai.best(this.grid, this.workingPieces, 0).piece;
981 | };
982 |
983 | function RandomPieceGenerator(){
984 | Math.seed
985 | this.bag = [0, 1, 2, 3, 4, 5, 6];
986 | this.shuffleBag();
987 | this.index = -1;
988 |
989 | this.drawFunctions = new DrawFunctions();
990 | };
991 |
992 | RandomPieceGenerator.prototype.nextPiece = function(){
993 |
994 | this.index++;
995 | if (this.index >= this.bag.length){
996 | this.shuffleBag();
997 | this.index = 0;
998 | }
999 |
1000 | return Piece.fromIndex(this.bag[this.index], this.drawFunctions.getDrawFunction(this.bag[this.index]));
1001 |
1002 | };
1003 |
1004 | RandomPieceGenerator.prototype.shuffleBag = function() {
1005 | var currentIndex = this.bag.length
1006 | , temporaryValue
1007 | , randomIndex
1008 | ;
1009 |
1010 | // While there remain elements to shuffle...
1011 | while (0 !== currentIndex) {
1012 |
1013 | // Pick a remaining element...
1014 | randomIndex = Math.floor(Math.random() * currentIndex);
1015 | currentIndex -= 1;
1016 |
1017 | // And swap it with the current element.
1018 | temporaryValue = this.bag[currentIndex];
1019 | this.bag[currentIndex] = this.bag[randomIndex];
1020 | this.bag[randomIndex] = temporaryValue;
1021 | }
1022 | };
1023 | function AI(heightWeight, linesWeight, holesWeight, bumpinessWeight){
1024 |
1025 | this.heightWeight = heightWeight;
1026 | this.linesWeight = linesWeight;
1027 | this.holesWeight = holesWeight;
1028 | this.bumpinessWeight = bumpinessWeight;
1029 |
1030 | };
1031 |
1032 | AI.prototype.best = function(grid, workingPieces, workingPieceIndex){
1033 |
1034 | var best = null;
1035 | var bestScore = null;
1036 | var workingPiece = workingPieces[workingPieceIndex];
1037 |
1038 | for(var rotation = 0; rotation < 4; rotation++){
1039 | var _piece = workingPiece.clone();
1040 | _piece.rotate(rotation);
1041 |
1042 | while(grid.canMoveLeft(_piece)){
1043 | _piece.column --;
1044 | }
1045 |
1046 | while(grid.valid(_piece)){
1047 | var _pieceSet = _piece.clone();
1048 | while(grid.canMoveDown(_pieceSet)){
1049 | _pieceSet.row++;
1050 | }
1051 |
1052 | var _grid = grid.clone();
1053 | _grid.addPiece(_pieceSet);
1054 |
1055 | var score = null;
1056 | if (workingPieceIndex == (workingPieces.length - 1)) {
1057 | score = -this.heightWeight * _grid.aggregateHeight() + this.linesWeight * _grid.lines() - this.holesWeight * _grid.holes() - this.bumpinessWeight * _grid.bumpiness();
1058 | }else{
1059 | score = this.best(_grid, workingPieces, workingPieceIndex + 1).score;
1060 | }
1061 |
1062 | if (score > bestScore || bestScore == null){
1063 | bestScore = score;
1064 | best = _piece.clone();
1065 | }
1066 |
1067 | _piece.column++;
1068 | }
1069 | }
1070 |
1071 | return {piece:best, score:bestScore};
1072 | };
1073 | /**
1074 | * Updater, controls time and speed.
1075 | */
1076 |
1077 | function Updater() {
1078 | this.lastUpdateTime = Date.now();
1079 | this.deltaThreshold = 250; // MS before each update
1080 | this.updateCallback = null;
1081 |
1082 | window.requestAnimFrame = (function() {
1083 | // Polyfill
1084 | return (
1085 | window.requestAnimationFrame ||
1086 | window.webkitRequestAnimationFrame ||
1087 | window.mozRequestAnimationFrame ||
1088 | window.oRequestAnimationFrame ||
1089 | window.msRequestAnimationFrame ||
1090 | function(callback) {
1091 | window.setTimeout(callback, 1000 / 60);
1092 | }
1093 | );
1094 | })();
1095 | }
1096 |
1097 | Updater.prototype.onUpdate = function(callback) {
1098 | this.updateCallback = callback;
1099 | };
1100 |
1101 | Updater.prototype.doUpdate = function(timestamp) {
1102 | if (this.updateCallback != null) {
1103 | this.updateCallback();
1104 | }
1105 |
1106 | this.lastUpdateTime = timestamp;
1107 | };
1108 |
1109 | Updater.prototype.checkUpdate = function(timestamp) {
1110 | var self = this;
1111 | var delta = timestamp - this.lastUpdateTime;
1112 |
1113 | if (delta > this.deltaThreshold) {
1114 | this.doUpdate(timestamp);
1115 | }
1116 |
1117 | window.requestAnimFrame(function() {
1118 | self.checkUpdate(Date.now());
1119 | });
1120 | };
1121 |
--------------------------------------------------------------------------------
/colored_classic/js/index.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | function square(context, x, y, width, height) {
4 |
5 | var unitWidth = 0.125 * width;
6 |
7 | // Border
8 | context.fillStyle = "#000";
9 | context.fillRect(width * x, height * y, width, height);
10 |
11 | context.fillStyle = "#EDBF3B";
12 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
13 |
14 | context.fillStyle = "#000";
15 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, width - unitWidth * 4, height - unitWidth * 4);
16 |
17 | }
18 |
19 | function jay(context, x, y, width, height) {
20 |
21 | var unitWidth = 0.125 * width;
22 |
23 | // Border
24 | context.fillStyle = "#000";
25 | context.fillRect(width * x, height * y, width, height);
26 |
27 | context.fillStyle = "#3B78A7";
28 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
29 |
30 | context.fillStyle = "#000";
31 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, width - unitWidth * 4, height - unitWidth * 4);
32 |
33 | context.fillStyle = "#fff";
34 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 3, width - unitWidth * 6, height - unitWidth * 6);
35 | }
36 |
37 | function ell(context, x, y, width, height) {
38 |
39 | var unitWidth = 0.125 * width;
40 |
41 | context.fillStyle = "#000";
42 | context.fillRect(width * x, height * y, width, height);
43 |
44 | context.fillStyle = "#B82C2D";
45 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
46 |
47 | }
48 |
49 | function zee(context, x, y, width, height) {
50 |
51 | var unitWidth = 0.125 * width;
52 |
53 | context.fillStyle = "#000";
54 | context.fillRect(width * x, height * y, width, height);
55 |
56 | context.fillStyle = "#EDBF3B";
57 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
58 |
59 | context.fillStyle = "#000";
60 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 3, width - unitWidth * 6, height - unitWidth * 6);
61 |
62 | }
63 |
64 | function ess(context, x, y, width, height) {
65 |
66 | var unitWidth = 0.125 * width;
67 |
68 | context.fillStyle = "#000";
69 | context.fillRect(width * x, height * y, width, height);
70 |
71 | context.fillStyle = "#C24175";
72 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
73 |
74 | context.fillStyle = "#000";
75 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, width - unitWidth * 4, height - unitWidth * 4);
76 |
77 | context.fillStyle = "#fff";
78 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 3, width - unitWidth * 6, height - unitWidth * 6);
79 | }
80 |
81 | function tee(context, x, y, width, height) {
82 |
83 | var unitWidth = 0.125 * width;
84 |
85 | context.fillStyle = "#000";
86 | context.fillRect(width * x, height * y, width, height);
87 |
88 | context.fillStyle = "#498E4D";
89 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth * 2);
90 |
91 | context.fillStyle = "#fff";
92 |
93 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, unitWidth, height - unitWidth * 4);
94 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, unitWidth * 4, unitWidth);
95 |
96 | context.fillStyle = "#000";
97 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 5, unitWidth * 4, unitWidth);
98 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 3, unitWidth, unitWidth * 3);
99 |
100 | }
101 |
102 | var eyes = [
103 | //h1
104 | function(context, x, y, width, height) {
105 |
106 | var unitWidth = 0.125 * width;
107 | context.fillStyle = "#000";
108 | context.fillRect(width * x, height * y, width, height);
109 |
110 | context.fillStyle = "#C28549";
111 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth, height - unitWidth * 2);
112 |
113 | // Dots
114 | context.fillStyle = "#874437";
115 |
116 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 1, unitWidth, unitWidth);
117 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 1, unitWidth, unitWidth);
118 |
119 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 3, unitWidth, unitWidth);
120 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 3, unitWidth, unitWidth);
121 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 3, unitWidth, unitWidth);
122 |
123 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 5, unitWidth, unitWidth);
124 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 5, unitWidth, unitWidth);
125 |
126 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 6, unitWidth, unitWidth);
127 |
128 |
129 | },
130 | function(context, x, y, width, height) {
131 |
132 | var unitWidth = 0.125 * width;
133 |
134 | context.fillStyle = "#000";
135 | context.fillRect(width * x, height * y, width, height);
136 |
137 | context.fillStyle = "#C28549";
138 | context.fillRect(width * x, height * y + unitWidth, width, height - unitWidth * 2);
139 |
140 | // Dots
141 | context.fillStyle = "#874437";
142 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 1, unitWidth, unitWidth);
143 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 1, unitWidth, unitWidth);
144 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 1, unitWidth, unitWidth);
145 |
146 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
147 |
148 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 3, unitWidth, unitWidth);
149 |
150 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 4, unitWidth, unitWidth);
151 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 4, unitWidth, unitWidth);
152 |
153 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 5, unitWidth, unitWidth);
154 | context.fillRect(width * x + unitWidth * 7, height * y + unitWidth * 5, unitWidth, unitWidth);
155 |
156 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 6, unitWidth, unitWidth);
157 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 6, unitWidth, unitWidth);
158 |
159 |
160 | },
161 | function(context, x, y, width, height) {
162 |
163 | var unitWidth = 0.125 * width;
164 |
165 | context.fillStyle = "#000";
166 | context.fillRect(width * x, height * y, width, height);
167 |
168 | context.fillStyle = "#C28549";
169 | context.fillRect(width * x, height * y + unitWidth, width, height - unitWidth * 2);
170 |
171 | // Dots
172 | context.fillStyle = "#874437";
173 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 1, unitWidth, unitWidth);
174 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 1, unitWidth, unitWidth);
175 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 1, unitWidth, unitWidth);
176 |
177 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
178 |
179 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 3, unitWidth, unitWidth);
180 |
181 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 4, unitWidth, unitWidth);
182 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 4, unitWidth, unitWidth);
183 |
184 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 5, unitWidth, unitWidth);
185 | context.fillRect(width * x + unitWidth * 7, height * y + unitWidth * 5, unitWidth, unitWidth);
186 |
187 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 6, unitWidth, unitWidth);
188 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 6, unitWidth, unitWidth);
189 |
190 | },
191 | function(context, x, y, width, height) {
192 |
193 | var unitWidth = 0.125 * width;
194 |
195 | context.fillStyle = "#000";
196 | context.fillRect(width * x, height * y, width, height);
197 |
198 | context.fillStyle = "#C28549";
199 | context.fillRect(width * x, height * y + unitWidth, width - unitWidth, height - unitWidth * 2);
200 |
201 | // Dots
202 | context.fillStyle = "#874437";
203 | context.fillRect(width * x + unitWidth * 0, height * y + unitWidth * 1, unitWidth, unitWidth);
204 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 1, unitWidth, unitWidth);
205 |
206 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, unitWidth, unitWidth);
207 |
208 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 3, unitWidth, unitWidth);
209 |
210 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 4, unitWidth, unitWidth);
211 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 4, unitWidth, unitWidth);
212 |
213 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 5, unitWidth, unitWidth);
214 |
215 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 6, unitWidth, unitWidth);
216 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 6, unitWidth, unitWidth);
217 | },
218 |
219 | // v1
220 | function(context, x, y, width, height) {
221 |
222 | var unitWidth = 0.125 * width;
223 | context.fillStyle = "#000";
224 | context.fillRect(width * x, height * y, width, height);
225 |
226 | context.fillStyle = "#C28549";
227 | context.fillRect(width * x + unitWidth, height * y + unitWidth, width - unitWidth * 2, height - unitWidth);
228 |
229 | // Dots
230 | context.fillStyle = "#874437";
231 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth, unitWidth, unitWidth);
232 |
233 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 2, unitWidth, unitWidth);
234 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
235 |
236 | context.fillRect(width * x + unitWidth, height * y + unitWidth * 4, unitWidth, unitWidth);
237 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 4, unitWidth, unitWidth);
238 |
239 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 5, unitWidth, unitWidth);
240 |
241 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 6, unitWidth, unitWidth);
242 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 6, unitWidth, unitWidth);
243 |
244 | },
245 | function(context, x, y, width, height) {
246 |
247 | var unitWidth = 0.125 * width;
248 |
249 | context.fillStyle = "#000";
250 | context.fillRect(width * x, height * y, width, height);
251 |
252 | context.fillStyle = "#C28549";
253 | context.fillRect(width * x + unitWidth, height * y, width - unitWidth * 2, height);
254 |
255 | // Dots
256 | context.fillStyle = "#874437";
257 |
258 | context.fillRect(width * x + unitWidth * 3, height * y, unitWidth, unitWidth);
259 | context.fillRect(width * x + unitWidth * 6, height * y, unitWidth, unitWidth);
260 |
261 | context.fillRect(width * x + unitWidth, height * y + unitWidth * 1, unitWidth, unitWidth);
262 |
263 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 2, unitWidth, unitWidth);
264 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
265 |
266 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 3, unitWidth, unitWidth);
267 |
268 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 4, unitWidth, unitWidth);
269 |
270 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 5, unitWidth, unitWidth);
271 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 5, unitWidth, unitWidth);
272 |
273 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 6, unitWidth, unitWidth);
274 |
275 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 7, unitWidth, unitWidth);
276 |
277 | },
278 | function(context, x, y, width, height) {
279 |
280 | var unitWidth = 0.125 * width;
281 |
282 | context.fillStyle = "#000";
283 | context.fillRect(width * x, height * y, width, height);
284 |
285 | context.fillStyle = "#C28549";
286 | context.fillRect(width * x + unitWidth, height * y, width - unitWidth * 2, height);
287 |
288 | // Dots
289 | context.fillStyle = "#874437";
290 |
291 | context.fillRect(width * x + unitWidth * 3, height * y, unitWidth, unitWidth);
292 | context.fillRect(width * x + unitWidth * 6, height * y, unitWidth, unitWidth);
293 |
294 | context.fillRect(width * x + unitWidth, height * y + unitWidth * 1, unitWidth, unitWidth);
295 |
296 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 2, unitWidth, unitWidth);
297 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 2, unitWidth, unitWidth);
298 |
299 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 3, unitWidth, unitWidth);
300 |
301 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 4, unitWidth, unitWidth);
302 |
303 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 5, unitWidth, unitWidth);
304 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 5, unitWidth, unitWidth);
305 |
306 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 6, unitWidth, unitWidth);
307 |
308 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 7, unitWidth, unitWidth);
309 | },
310 | function(context, x, y, width, height) {
311 |
312 | var unitWidth = 0.125 * width;
313 |
314 | context.fillStyle = "#000";
315 | context.fillRect(width * x, height * y, width, height);
316 |
317 | context.fillStyle = "#C28549";
318 | context.fillRect(width * x + unitWidth, height * y, width - unitWidth * 2, height - unitWidth);
319 |
320 | // Dots
321 | context.fillStyle = "#874437";
322 |
323 | context.fillRect(width * x + unitWidth * 6, height * y, unitWidth, unitWidth);
324 |
325 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 1, unitWidth, unitWidth);
326 |
327 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 2, unitWidth, unitWidth);
328 | context.fillRect(width * x + unitWidth * 5, height * y + unitWidth * 2, unitWidth, unitWidth);
329 |
330 | context.fillRect(width * x + unitWidth * 3, height * y + unitWidth * 3, unitWidth, unitWidth);
331 |
332 | context.fillRect(width * x + unitWidth * 1, height * y + unitWidth * 4, unitWidth, unitWidth);
333 | context.fillRect(width * x + unitWidth * 6, height * y + unitWidth * 4, unitWidth, unitWidth);
334 |
335 | context.fillRect(width * x + unitWidth * 4, height * y + unitWidth * 5, unitWidth, unitWidth);
336 |
337 | context.fillRect(width * x + unitWidth * 2, height * y + unitWidth * 6, unitWidth, unitWidth);
338 | }
339 | ]
340 |
341 | var drawFunctions = [
342 |
343 | square,
344 |
345 | jay,
346 |
347 | ell,
348 |
349 | zee,
350 |
351 | ess,
352 |
353 | tee,
354 |
355 | eyes
356 |
357 | ]
358 |
359 | function DrawFunctions(){};
360 |
361 | DrawFunctions.prototype.getDrawFunction = function(index){
362 |
363 | if( drawFunctions[index]) {
364 | return drawFunctions[index];
365 | } else {
366 | return drawFunctions[5];
367 | }
368 | }
369 | /**
370 | * Grid
371 | * - Manages the state of the grid
372 | */
373 |
374 | // Init
375 | function Grid(rows, columns){
376 |
377 | this.rows = rows;
378 | this.columns = columns;
379 | this.cells = new Array(rows);
380 |
381 | // For each row!
382 | // Has a column
383 | // Which has X cells in it.
384 | for (var r = 0; r < this.rows; r++) {
385 |
386 | this.cells[r] = new Array(this.columns);
387 | for(var c = 0; c < this.columns; c++){
388 | this.cells[r][c] = 0;
389 | }
390 | }
391 |
392 | };
393 |
394 | // Methods
395 | Grid.prototype.clone = function(){
396 | var _grid = new Grid(this.rows, this.columns);
397 | for (var r = 0; r < this.rows; r++) {
398 | for(var c = 0; c < this.columns; c++){
399 | _grid.cells[r][c] = this.cells[r][c];
400 | }
401 | }
402 | return _grid;
403 | };
404 |
405 | // Clear spaces in the grid, including when the blocks "fall"
406 | Grid.prototype.clearLines = function(){
407 |
408 | var distance = 0;
409 | var row = new Array(this.columns);
410 |
411 | for(var r = this.rows - 1; r >= 0; r--){
412 |
413 | // Clear full line
414 | if (this.isLine(r)){
415 |
416 | distance++;
417 | for(var c = 0; c < this.columns; c++){
418 | this.cells[r][c] = 0;
419 | }
420 |
421 | // Clear moved spaces
422 | } else if (distance > 0) {
423 |
424 | for(var c = 0; c < this.columns; c++){
425 | this.cells[r + distance][c] = this.cells[r][c];
426 | this.cells[r][c] = 0;
427 | }
428 | }
429 | }
430 | };
431 |
432 | // If every item in the row has an item!
433 | Grid.prototype.isLine = function(row){
434 | for(var c = 0; c < this.columns; c++){
435 | if (this.cells[row][c] == 0){
436 | return false;
437 | }
438 | }
439 | return true;
440 | };
441 |
442 | Grid.prototype.isEmptyRow = function(row){
443 | for(var c = 0; c < this.columns; c++){
444 |
445 | // TH: != 0 rather than == 1
446 | if (this.cells[row][c] != 0){
447 | return false;
448 | }
449 | }
450 | return true;
451 | };
452 |
453 | Grid.prototype.exceeded = function(){
454 | return !this.isEmptyRow(0) || !this.isEmptyRow(1);
455 | };
456 |
457 | Grid.prototype.height = function(){
458 | var r = 0;
459 | for(; r < this.rows && this.isEmptyRow(r); r++);
460 | return this.rows - r;
461 | };
462 |
463 | Grid.prototype.lines = function(){
464 | var count = 0;
465 | for(var r = 0; r < this.rows; r++){
466 | if (this.isLine(r)){
467 | count++;
468 | }
469 | }
470 | return count;
471 | };
472 |
473 | Grid.prototype.holes = function(){
474 | var count = 0;
475 |
476 | for(var c = 0; c < this.columns; c++){
477 | var block = false;
478 | for(var r = 0; r < this.rows; r++){
479 |
480 | // TH: != 0 rather than == 1
481 | if (this.cells[r][c] != 0) {
482 | block = true;
483 | }else if (this.cells[r][c] == 0 && block){
484 | count++;
485 | }
486 | }
487 | }
488 | return count;
489 | };
490 |
491 | Grid.prototype.blockades = function(){
492 | var count = 0;
493 |
494 | for(var c = 0; c < this.columns; c++){
495 | var hole = false;
496 | for(var r = this.rows - 1; r >= 0; r--){
497 | if (this.cells[r][c] == 0){
498 | hole = true;
499 |
500 | // TH: != 0 rather than == 1
501 | }else if (this.cells[r][c] != 0 && hole){
502 | count++;
503 | }
504 | }
505 | }
506 | return count;
507 | }
508 |
509 | Grid.prototype.aggregateHeight = function(){
510 | var total = 0;
511 |
512 | for(var c = 0; c < this.columns; c++){
513 | total += this.columnHeight(c);
514 | }
515 | return total;
516 | };
517 |
518 | Grid.prototype.bumpiness = function(){
519 | var total = 0;
520 | for(var c = 0; c < this.columns - 1; c++){
521 | total += Math.abs(this.columnHeight(c) - this.columnHeight(c+ 1));
522 | }
523 | return total;
524 | }
525 |
526 | Grid.prototype.columnHeight = function(column){
527 | var r = 0;
528 |
529 | for(; r < this.rows && this.cells[r][column] == 0; r++);
530 | return this.rows - r;
531 | };
532 |
533 | // Piece
534 | Grid.prototype.addPiece = function(piece) {
535 |
536 | for(var r = 0; r < piece.cells.length; r++) {
537 | for (var c = 0; c < piece.cells[r].length; c++) {
538 |
539 | var _r = piece.row + r;
540 | var _c = piece.column + c;
541 |
542 | // TH: != 0 rather than == 1
543 | if (piece.cells[r][c] != 0 && _r >= 0){
544 |
545 | // TH: Updates color, rather than 1
546 | if (piece.cells[r][c] > 1) {
547 | var num = piece.cells[r][c] - 2;
548 | this.cells[_r][_c] = piece.color[num];
549 | } else {
550 | this.cells[_r][_c] = piece.color;
551 | }
552 | }
553 |
554 | }
555 | }
556 | };
557 |
558 | Grid.prototype.valid = function(piece){
559 |
560 | for(var r = 0; r < piece.cells.length; r++){
561 | for(var c = 0; c < piece.cells[r].length; c++){
562 | var _r = piece.row + r;
563 | var _c = piece.column + c;
564 |
565 | // TH: != 0 rather than == 1
566 | if (piece.cells[r][c] != 0){
567 | if (!(_c < this.columns && _r < this.rows && this.cells[_r][_c] == 0)){
568 | return false;
569 | }
570 | }
571 | }
572 | }
573 | return true;
574 | };
575 |
576 | Grid.prototype.canMoveDown = function(piece){
577 | for(var r = 0; r < piece.cells.length; r++){
578 | for(var c = 0; c < piece.cells[r].length; c++){
579 | var _r = piece.row + r + 1;
580 | var _c = piece.column + c;
581 |
582 | // TH: != 0 rather than == 1
583 | if (piece.cells[r][c] != 0 && _r >= 0){
584 |
585 | if (!(_r < this.rows && this.cells[_r][_c] == 0)){
586 | return false;
587 | }
588 | }
589 | }
590 | }
591 | return true;
592 | };
593 |
594 | Grid.prototype.canMoveLeft = function(piece){
595 | for(var r = 0; r < piece.cells.length; r++){
596 | for(var c = 0; c < piece.cells[r].length; c++){
597 | var _r = piece.row + r;
598 | var _c = piece.column + c - 1;
599 |
600 | // TH: != 0 rather than == 1
601 | if (piece.cells[r][c] != 0){
602 | if (!(_c >= 0 && this.cells[_r][_c] == 0)){
603 | return false;
604 | }
605 | }
606 | }
607 | }
608 | return true;
609 | };
610 |
611 | Grid.prototype.canMoveRight = function(piece){
612 | for(var r = 0; r < piece.cells.length; r++){
613 | for(var c = 0; c < piece.cells[r].length; c++){
614 | var _r = piece.row + r;
615 | var _c = piece.column + c + 1;
616 |
617 | // TH: != 0 rather than == 1
618 | if (piece.cells[r][c] != 0){
619 | if (!(_c >= 0 && this.cells[_r][_c] == 0)){
620 | return false;
621 | }
622 | }
623 | }
624 | }
625 | return true;
626 | };
627 |
628 | Grid.prototype.rotateOffset = function(piece){
629 |
630 | console.log("rotate?");
631 |
632 | var _piece = piece.clone();
633 | _piece.rotate(1);
634 | if (this.valid(_piece)) {
635 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
636 | }
637 |
638 | // Kicking
639 | var initialRow = _piece.row;
640 | var initialCol = _piece.column;
641 |
642 | for (var i = 0; i < _piece.dimension - 1; i++) {
643 | _piece.column = initialCol + i;
644 | if (this.valid(_piece)) {
645 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
646 | }
647 |
648 | for (var j = 0; j < _piece.dimension - 1; j++) {
649 | _piece.row = initialRow - j;
650 | if (this.valid(_piece)) {
651 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
652 | }
653 | }
654 | _piece.row = initialRow;
655 | }
656 | _piece.column = initialCol;
657 |
658 | for (var i = 0; i < _piece.dimension - 1; i++) {
659 | _piece.column = initialCol - i;
660 | if (this.valid(_piece)) {
661 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
662 | }
663 |
664 | for (var j = 0; j < _piece.dimension - 1; j++) {
665 | _piece.row = initialRow - j;
666 | if (this.valid(_piece)) {
667 | return {rowOffset: _piece.row - piece.row, columnOffset:_piece.column - piece.column};
668 | }
669 | }
670 | _piece.row = initialRow;
671 | }
672 | _piece.column = initialCol;
673 |
674 | return null;
675 | };
676 |
677 | /**
678 | * Piece
679 | * - Represents a single piece on the board.
680 | */
681 |
682 | // Object that represents a single piece & its properties.
683 | function Piece(cells, color){
684 | this.cells = cells;
685 | this.dimension = this.cells.length;
686 | this.row = 0;
687 | this.column = 0;
688 | this.color = color;
689 | };
690 |
691 | Piece.fromIndex = function(index, color){
692 |
693 | var cells
694 |
695 | switch (index){
696 | case 0:// O
697 | cells = [
698 | [1, 1],
699 | [1, 1]
700 | ];
701 | break;
702 | case 1: // J
703 | cells = [
704 | [1, 0, 0],
705 | [1, 1, 1],
706 | [0, 0, 0]
707 | ];
708 | break;
709 | case 2: // L
710 | cells = [
711 | [0, 0, 1],
712 | [1, 1, 1],
713 | [0, 0, 0]
714 | ];
715 | break;
716 | case 3: // Z
717 | cells = [
718 | [1, 1, 0],
719 | [0, 1, 1],
720 | [0, 0, 0]
721 | ];
722 | break;
723 | case 4: // S
724 | cells = [
725 | [0, 1, 1],
726 | [1, 1, 0],
727 | [0, 0, 0]
728 | ];
729 | break;
730 | case 5: // T
731 | cells = [
732 | [0, 1, 0],
733 | [1, 1, 1],
734 | [0, 0, 0]
735 | ];
736 | break;
737 | case 6: // I
738 | cells = [
739 | [0, 0, 0, 0],
740 | [2, 3, 4, 5],
741 | [0, 0, 0, 0],
742 | [0, 0, 0, 0]
743 | ];
744 | break;
745 |
746 | }
747 |
748 | var piece = new Piece(cells, color);
749 |
750 | piece.row = 0;
751 | piece.column = Math.floor((10 - piece.dimension) / 2); // Centralize
752 | return piece;
753 | };
754 |
755 | Piece.prototype.clone = function(){
756 |
757 | var _cells = new Array(this.dimension);
758 | for (var r = 0; r < this.dimension; r++) {
759 | _cells[r] = new Array(this.dimension);
760 | for(var c = 0; c < this.dimension; c++){
761 | _cells[r][c] = this.cells[r][c];
762 | }
763 | }
764 |
765 | var piece = new Piece(_cells, this.color);
766 | piece.row = this.row;
767 | piece.column = this.column;
768 | return piece;
769 | };
770 |
771 | Piece.prototype.rotate = function(rotations){
772 | for(var i = 0; i < rotations; i++) {
773 | var _cells = new Array(this.dimension);
774 | for (var r = 0; r < this.dimension; r++) {
775 | _cells[r] = new Array(this.dimension);
776 | }
777 |
778 | switch (this.dimension) { // Assumed square matrix
779 | case 2:
780 | _cells[0][0] = this.cells[1][0];
781 | _cells[0][1] = this.cells[0][0];
782 | _cells[1][0] = this.cells[1][1];
783 | _cells[1][1] = this.cells[0][1];
784 | break;
785 | case 3:
786 | _cells[0][0] = this.cells[2][0];
787 | _cells[0][1] = this.cells[1][0];
788 | _cells[0][2] = this.cells[0][0];
789 | _cells[1][0] = this.cells[2][1];
790 | _cells[1][1] = this.cells[1][1];
791 | _cells[1][2] = this.cells[0][1];
792 | _cells[2][0] = this.cells[2][2];
793 | _cells[2][1] = this.cells[1][2];
794 | _cells[2][2] = this.cells[0][2];
795 | break;
796 | case 4:
797 | _cells[0][0] = this.cells[3][0];
798 | _cells[0][1] = this.cells[2][0];
799 | _cells[0][2] = this.cells[1][0];
800 | _cells[0][3] = this.cells[0][0];
801 | _cells[1][3] = this.cells[0][1];
802 | _cells[2][3] = this.cells[0][2];
803 | _cells[3][3] = this.cells[0][3];
804 | _cells[3][2] = this.cells[1][3];
805 | _cells[3][1] = this.cells[2][3];
806 | _cells[3][0] = this.cells[3][3];
807 | _cells[2][0] = this.cells[3][2];
808 | _cells[1][0] = this.cells[3][1];
809 |
810 | _cells[1][1] = this.cells[2][1];
811 | _cells[1][2] = this.cells[1][1];
812 | _cells[2][2] = this.cells[1][2];
813 | _cells[2][1] = this.cells[2][2];
814 | break;
815 | }
816 |
817 | this.cells = _cells;
818 | }
819 | };
820 |
821 | /**
822 | * Game manager, manages flow and updating of game.
823 | */
824 |
825 | function GameManager(){
826 |
827 | this.gridCanvas = document.getElementById('grid-canvas');
828 |
829 | this.gravityUpdater = new Updater();
830 |
831 | this.gravityUpdater.onUpdate(function(){
832 | self.applyGravity();
833 | self.actuate();
834 | });
835 |
836 | var self = this;
837 | this.setup();
838 | this.startAI();
839 | this.gravityUpdater.checkUpdate(Date.now());
840 | };
841 |
842 | GameManager.prototype.setup = function(){
843 |
844 | this.baseColumns = 8;
845 |
846 | this.pieceWidth = window.innerWidth / this.baseColumns;
847 | this.pieceHeight = this.pieceWidth;
848 |
849 | this.displacementWidth = Math.floor(this.pieceWidth / 4);
850 |
851 | var canvasHeightPieces = Math.ceil(window.innerHeight / this.pieceHeight) + 2;
852 |
853 | this.gridCanvas.width = window.innerWidth;
854 | this.gridCanvas.height = canvasHeightPieces * this.pieceHeight;
855 |
856 | this.grid = new Grid(canvasHeightPieces, this.baseColumns);
857 | this.rpg = new RandomPieceGenerator();
858 | this.ai = new AI(0.510066, 0.760666, 0.35663, 0.184483);
859 |
860 | this.workingPieces = [this.rpg.nextPiece(), this.rpg.nextPiece()];
861 | this.workingPiece = this.workingPieces[0];
862 |
863 | this.isOver = true;
864 |
865 | this.stopAI();
866 | this.actuate();
867 | };
868 |
869 | GameManager.prototype.actuate = function(){
870 |
871 | var _grid = this.grid.clone();
872 |
873 | if (this.workingPiece != null) {
874 | _grid.addPiece(this.workingPiece);
875 | }
876 |
877 | var context = this.gridCanvas.getContext('2d');
878 | context.save();
879 |
880 | context.clearRect(0, 0, this.gridCanvas.width, this.gridCanvas.height);
881 |
882 | for(var r = 2; r < _grid.rows; r++){
883 |
884 | for(var c = 0; c < _grid.columns; c++){
885 |
886 | if (_grid.cells[r][c] != 0){
887 |
888 |
889 | // console.log(_grid.cells[r], _grid.cells[r][c]);
890 | _grid.cells[r][c](context, c, r, this.pieceWidth, this.pieceHeight);
891 |
892 | }
893 | }
894 | }
895 |
896 | context.restore();
897 | };
898 |
899 | GameManager.prototype.startAI = function(){
900 | this.aiActive = true;
901 | };
902 |
903 | GameManager.prototype.stopAI = function(){
904 | this.aiActive = false;
905 | };
906 |
907 | GameManager.prototype.setWorkingPiece = function(){
908 |
909 | this.grid.addPiece(this.workingPiece);
910 | this.grid.clearLines();
911 |
912 | if (!this.grid.exceeded()){
913 |
914 | for(var i = 0; i < this.workingPieces.length - 1; i++){
915 | this.workingPieces[i] = this.workingPieces[i + 1];
916 | }
917 |
918 | this.workingPieces[this.workingPieces.length - 1] = this.rpg.nextPiece();
919 | this.workingPiece = this.workingPieces[0];
920 |
921 | if (this.aiActive) {
922 | this.aiMove();
923 | }
924 |
925 | // I piece
926 | if( this.workingPiece.cells.length > 3) {
927 |
928 | if( this.workingPiece.cells[0][2] !== 0 ) {
929 | this.workingPiece.cells[0][2] = 6;
930 | this.workingPiece.cells[1][2] = 7;
931 | this.workingPiece.cells[2][2] = 8;
932 | this.workingPiece.cells[3][2] = 9;
933 | }
934 | }
935 | }
936 |
937 | // TODO: NO WAYYYY
938 | else{
939 |
940 | }
941 | };
942 |
943 | GameManager.prototype.applyGravity = function(){
944 |
945 | if (this.grid.canMoveDown(this.workingPiece)) {
946 | this.workingPiece.row++;
947 | }else{
948 | this.setWorkingPiece();
949 | }
950 |
951 | };
952 |
953 | GameManager.prototype.drop = function(){
954 | while(this.grid.canMoveDown(this.workingPiece)){
955 | this.workingPiece.row++;
956 | }
957 | };
958 |
959 | GameManager.prototype.moveLeft = function(){
960 | if (this.grid.canMoveLeft(this.workingPiece)){
961 | this.workingPiece.column--;
962 | }
963 | };
964 |
965 | GameManager.prototype.moveRight = function(){
966 | if (this.grid.canMoveRight(this.workingPiece)){
967 | this.workingPiece.column++;
968 | }
969 | };
970 |
971 | GameManager.prototype.rotate = function(){
972 | var offset = this.grid.rotateOffset(this.workingPiece);
973 | if (offset != null){
974 | this.workingPiece.rotate(1);
975 | this.workingPiece.row += offset.rowOffset;
976 | this.workingPiece.column += offset.columnOffset;
977 | }
978 | };
979 |
980 | GameManager.prototype.aiMove = function(){
981 | this.workingPiece = this.ai.best(this.grid, this.workingPieces, 0).piece;
982 | };
983 |
984 | function RandomPieceGenerator(){
985 | Math.seed
986 | this.bag = [0, 1, 2, 3, 4, 5, 6];
987 | this.shuffleBag();
988 | this.index = -1;
989 |
990 | this.drawFunctions = new DrawFunctions();
991 | };
992 |
993 | RandomPieceGenerator.prototype.nextPiece = function(){
994 |
995 | this.index++;
996 | if (this.index >= this.bag.length){
997 | this.shuffleBag();
998 | this.index = 0;
999 | }
1000 |
1001 | return Piece.fromIndex(this.bag[this.index], this.drawFunctions.getDrawFunction(this.bag[this.index]));
1002 |
1003 | };
1004 |
1005 | RandomPieceGenerator.prototype.shuffleBag = function() {
1006 | var currentIndex = this.bag.length
1007 | , temporaryValue
1008 | , randomIndex
1009 | ;
1010 |
1011 | // While there remain elements to shuffle...
1012 | while (0 !== currentIndex) {
1013 |
1014 | // Pick a remaining element...
1015 | randomIndex = Math.floor(Math.random() * currentIndex);
1016 | currentIndex -= 1;
1017 |
1018 | // And swap it with the current element.
1019 | temporaryValue = this.bag[currentIndex];
1020 | this.bag[currentIndex] = this.bag[randomIndex];
1021 | this.bag[randomIndex] = temporaryValue;
1022 | }
1023 | };
1024 | function AI(heightWeight, linesWeight, holesWeight, bumpinessWeight){
1025 |
1026 | this.heightWeight = heightWeight;
1027 | this.linesWeight = linesWeight;
1028 | this.holesWeight = holesWeight;
1029 | this.bumpinessWeight = bumpinessWeight;
1030 |
1031 | };
1032 |
1033 | AI.prototype.best = function(grid, workingPieces, workingPieceIndex){
1034 |
1035 | var best = null;
1036 | var bestScore = null;
1037 | var workingPiece = workingPieces[workingPieceIndex];
1038 |
1039 | for(var rotation = 0; rotation < 4; rotation++){
1040 | var _piece = workingPiece.clone();
1041 | _piece.rotate(rotation);
1042 |
1043 | while(grid.canMoveLeft(_piece)){
1044 | _piece.column --;
1045 | }
1046 |
1047 | while(grid.valid(_piece)){
1048 | var _pieceSet = _piece.clone();
1049 | while(grid.canMoveDown(_pieceSet)){
1050 | _pieceSet.row++;
1051 | }
1052 |
1053 | var _grid = grid.clone();
1054 | _grid.addPiece(_pieceSet);
1055 |
1056 | var score = null;
1057 | if (workingPieceIndex == (workingPieces.length - 1)) {
1058 | score = -this.heightWeight * _grid.aggregateHeight() + this.linesWeight * _grid.lines() - this.holesWeight * _grid.holes() - this.bumpinessWeight * _grid.bumpiness();
1059 | }else{
1060 | score = this.best(_grid, workingPieces, workingPieceIndex + 1).score;
1061 | }
1062 |
1063 | if (score > bestScore || bestScore == null){
1064 | bestScore = score;
1065 | best = _piece.clone();
1066 | }
1067 |
1068 | _piece.column++;
1069 | }
1070 | }
1071 |
1072 | return {piece:best, score:bestScore};
1073 | };
1074 | /**
1075 | * Updater, controls time and speed.
1076 | */
1077 |
1078 | function Updater() {
1079 | this.lastUpdateTime = Date.now();
1080 | this.deltaThreshold = 250; // MS before each update
1081 | this.updateCallback = null;
1082 |
1083 | window.requestAnimFrame = (function() {
1084 | // Polyfill
1085 | return (
1086 | window.requestAnimationFrame ||
1087 | window.webkitRequestAnimationFrame ||
1088 | window.mozRequestAnimationFrame ||
1089 | window.oRequestAnimationFrame ||
1090 | window.msRequestAnimationFrame ||
1091 | function(callback) {
1092 | window.setTimeout(callback, 1000 / 60);
1093 | }
1094 | );
1095 | })();
1096 | }
1097 |
1098 | Updater.prototype.onUpdate = function(callback) {
1099 | this.updateCallback = callback;
1100 | };
1101 |
1102 | Updater.prototype.doUpdate = function(timestamp) {
1103 | if (this.updateCallback != null) {
1104 | this.updateCallback();
1105 | }
1106 |
1107 | this.lastUpdateTime = timestamp;
1108 | };
1109 |
1110 | Updater.prototype.checkUpdate = function(timestamp) {
1111 | var self = this;
1112 | var delta = timestamp - this.lastUpdateTime;
1113 |
1114 | if (delta > this.deltaThreshold) {
1115 | this.doUpdate(timestamp);
1116 | }
1117 |
1118 | window.requestAnimFrame(function() {
1119 | self.checkUpdate(Date.now());
1120 | });
1121 | };
1122 |
--------------------------------------------------------------------------------