Archived
Directory cleanup.
This commit is contained in:
1 parent
d7f62d09bb
commit
6181fa6aee
4 files changed
-4127
No files matched your search
@@ -1,686 +0,0 @@
|
|||||||
/* http://mrcoles.com/media/js/tetris.js */
|
|
||||||
$.fn.safekeypress = function(func, cfg) {
|
|
||||||
|
|
||||||
cfg = $.extend({
|
|
||||||
stopKeys: {37:1, 38:1, 39:1, 40:1}
|
|
||||||
}, cfg);
|
|
||||||
|
|
||||||
function isStopKey(evt) {
|
|
||||||
var isStop = (cfg.stopKeys[evt.keyCode] || (cfg.moreStopKeys && cfg.moreStopKeys[evt.keyCode]));
|
|
||||||
if (isStop) evt.preventDefault();
|
|
||||||
return isStop;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getKey(evt) { return 'safekeypress.' + evt.keyCode; }
|
|
||||||
|
|
||||||
function keypress(evt) {
|
|
||||||
var key = getKey(evt),
|
|
||||||
val = ($.data(this, key) || 0) + 1;
|
|
||||||
$.data(this, key, val);
|
|
||||||
if (val > 0) return func.call(this, evt);
|
|
||||||
return isStopKey(evt);
|
|
||||||
}
|
|
||||||
|
|
||||||
function keydown(evt) {
|
|
||||||
var key = getKey(evt);
|
|
||||||
$.data(this, key, ($.data(this, key) || 0) - 1);
|
|
||||||
return func.call(this, evt);
|
|
||||||
}
|
|
||||||
|
|
||||||
function keyup(evt) {
|
|
||||||
$.data(this, getKey(evt), 0);
|
|
||||||
return isStopKey(evt);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $(this).keypress(keypress).keydown(keydown).keyup(keyup);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var getNiceShapes = function(shapeFactory, undefined) {
|
|
||||||
/*
|
|
||||||
* Things I need for this to work...
|
|
||||||
* - ability to test each shape with filled data
|
|
||||||
* - maybe give empty spots scores? and try to maximize the score?
|
|
||||||
*/
|
|
||||||
|
|
||||||
var shapes = {},
|
|
||||||
attr;
|
|
||||||
|
|
||||||
for (attr in shapeFactory) {
|
|
||||||
shapes[attr] = shapeFactory[attr]();
|
|
||||||
}
|
|
||||||
|
|
||||||
function scoreBlocks(possibles, blocks, x, y, filled, width, height) {
|
|
||||||
var i, len=blocks.length, score=0, bottoms = {}, tx, ty, overlaps;
|
|
||||||
|
|
||||||
// base score
|
|
||||||
for (i=0; i<len; i+=2) {
|
|
||||||
score += possibles[filled.asIndex(x + blocks[i], y + blocks[i+1])] || 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// overlap score -- //TODO - don't count overlaps if cleared?
|
|
||||||
for (i=0; i<len; i+=2) {
|
|
||||||
tx = blocks[i];
|
|
||||||
ty = blocks[i+1];
|
|
||||||
if (bottoms[tx] === undefined || bottoms[tx] < ty) {
|
|
||||||
bottoms[tx] = ty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
overlaps = 0;
|
|
||||||
for (tx in bottoms) {
|
|
||||||
tx = parseInt(tx);
|
|
||||||
for (ty=bottoms[tx]+1, i=0; y+ty<height; ty++, i++) {
|
|
||||||
if (!filled.check(x + tx, y + ty)) {
|
|
||||||
overlaps += i == 0 ? 2 : 1; //TODO-score better
|
|
||||||
//if (i == 0) overlaps += 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
score = score - overlaps;
|
|
||||||
|
|
||||||
return score;
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetShapes() {
|
|
||||||
for (var attr in shapes) {
|
|
||||||
shapes[attr].x = 0;
|
|
||||||
shapes[attr].y = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO -- evil mode needs to realize that overlap is bad...
|
|
||||||
var func = function(filled, checkCollisions, width, height, mode, _one_shape) {
|
|
||||||
if (!_one_shape) resetShapes();
|
|
||||||
|
|
||||||
var possibles = new Array(width * height),
|
|
||||||
evil = mode == 'evil',
|
|
||||||
x, y, py,
|
|
||||||
attr, shape, i, blocks, bounds,
|
|
||||||
score, best_shape, best_score = (evil ? 1 : -1) * 999, best_orientation, best_x,
|
|
||||||
best_score_for_shape, best_orientation_for_shape, best_x_for_shape;
|
|
||||||
|
|
||||||
for (x=0; x<width; x++) {
|
|
||||||
for (y=0; y<=height; y++) {
|
|
||||||
if (y == height || filled.check(x, y)) {
|
|
||||||
for (py=y-4; py<y; py++) {
|
|
||||||
possibles[filled.asIndex(x, py)] = py; //TODO - figure out better scoring?
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// for each shape...
|
|
||||||
var opts = _one_shape === undefined ? shapes : {cur: _one_shape}; //BOO
|
|
||||||
for (attr in opts) { //TODO - check in random order to prevent later shapes from winning
|
|
||||||
shape = opts[attr];
|
|
||||||
best_score_for_shape = -999;
|
|
||||||
|
|
||||||
// for each orientation...
|
|
||||||
for (i=0; i<(shape.symmetrical ? 2 : 4); i++) { //TODO - only look at unique orientations
|
|
||||||
blocks = shape.getBlocks(i);
|
|
||||||
bounds = shape.getBounds(blocks);
|
|
||||||
|
|
||||||
// try each possible position...
|
|
||||||
for (x=-bounds.left; x<width - bounds.width; x++) {
|
|
||||||
for (y=-1; y<height - bounds.bottom; y++) {
|
|
||||||
if (checkCollisions(x, y + 1, blocks, true)) {
|
|
||||||
// collision
|
|
||||||
score = scoreBlocks(possibles, blocks, x, y, filled, width, height);
|
|
||||||
if (score > best_score_for_shape) {
|
|
||||||
best_score_for_shape = score;
|
|
||||||
best_orientation_for_shape = i;
|
|
||||||
best_x_for_shape = x;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((evil && best_score_for_shape < best_score) ||
|
|
||||||
(!evil && best_score_for_shape > best_score)) {
|
|
||||||
best_shape = shape;
|
|
||||||
best_score = best_score_for_shape;
|
|
||||||
best_orientation = best_orientation_for_shape;
|
|
||||||
best_x = best_x_for_shape;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
best_shape.best_orientation = best_orientation;
|
|
||||||
best_shape.best_x = best_x;
|
|
||||||
|
|
||||||
return best_shape;
|
|
||||||
};
|
|
||||||
|
|
||||||
func.no_preview = true;
|
|
||||||
return func;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var undefined;
|
|
||||||
if (1) {
|
|
||||||
//(function(window, document, undefined) {
|
|
||||||
|
|
||||||
var canvas = document.getElementById('game'),
|
|
||||||
ctx = canvas.getContext('2d'),
|
|
||||||
info_canvas = document.getElementById('info'),
|
|
||||||
info_ctx = info_canvas.getContext('2d'),
|
|
||||||
WIDTH = 10,
|
|
||||||
HEIGHT = 20,
|
|
||||||
PIXEL_WIDTH = $(canvas).width(),
|
|
||||||
PIXEL_HEIGHT = $(canvas).height(),
|
|
||||||
block_size = Math.ceil(PIXEL_WIDTH / WIDTH),
|
|
||||||
bevel_size = Math.floor(block_size / 10),
|
|
||||||
border_width = 2;
|
|
||||||
|
|
||||||
function randInt(a, b) { return a + Math.floor(Math.random() * (1 + b - a)); }
|
|
||||||
function randSign() { return randInt(0, 1) * 2 - 1; }
|
|
||||||
function randChoice(choices) { return choices[randInt(0, choices.length-1)]; }
|
|
||||||
|
|
||||||
function drawBlock(x, y, color, _ctx) {
|
|
||||||
// convert x and y to pixel
|
|
||||||
_ctx = _ctx || ctx;
|
|
||||||
x = x * block_size;
|
|
||||||
y = y * block_size;
|
|
||||||
_ctx.fillStyle = color;
|
|
||||||
_ctx.globalAlpha = .5;
|
|
||||||
_ctx.fillRect(x, y, block_size, block_size);
|
|
||||||
_ctx.globalAlpha = .5;
|
|
||||||
_ctx.fillRect(x + bevel_size, y + bevel_size, block_size - 2*bevel_size, block_size - 2*bevel_size);
|
|
||||||
_ctx.globalAlpha = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Shape(orienations, color, symmetrical) {
|
|
||||||
|
|
||||||
$.extend(this, {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
symmetrical: symmetrical,
|
|
||||||
init: function() {
|
|
||||||
$.extend(this, {
|
|
||||||
orientation: 0,
|
|
||||||
x: Math.floor(WIDTH / 2) - 1,
|
|
||||||
y: -1
|
|
||||||
});
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
color: color,
|
|
||||||
blocksLen: orienations[0].length,
|
|
||||||
orientations: orienations,
|
|
||||||
orientation: 0, // 4 possible
|
|
||||||
rotate: function(right) {
|
|
||||||
var orientation = (this.orientation + (right ? 1 : -1) + 4) % 4;
|
|
||||||
|
|
||||||
//TODO - when past limit - auto shift and remember that too!
|
|
||||||
if (!checkCollisions(this.x, this.y, this.getBlocks(orientation)))
|
|
||||||
this.orientation = orientation;
|
|
||||||
},
|
|
||||||
moveRight: function() {
|
|
||||||
if (!checkCollisions(this.x + 1, this.y, this.getBlocks()))
|
|
||||||
this.x++;
|
|
||||||
},
|
|
||||||
moveLeft: function() {
|
|
||||||
if (!checkCollisions(this.x - 1, this.y, this.getBlocks()))
|
|
||||||
this.x--;
|
|
||||||
},
|
|
||||||
getBlocks: function(orientation) { // optional param
|
|
||||||
return this.orientations[orientation !== undefined ? orientation : this.orientation];
|
|
||||||
},
|
|
||||||
draw: function(drop, _x, _y, _orientation, _ctx) {
|
|
||||||
if (drop) this.y++;
|
|
||||||
|
|
||||||
var blocks = this.getBlocks(_orientation),
|
|
||||||
x = _x === undefined ? this.x : _x,
|
|
||||||
y = _y === undefined ? this.y : _y,
|
|
||||||
i = 0;
|
|
||||||
for (; i<this.blocksLen; i += 2) {
|
|
||||||
drawBlock(x + blocks[i], y + blocks[i+1], this.color, _ctx);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getBounds: function(_blocks) { // _blocks can be an array of blocks, an orientation index, or undefined
|
|
||||||
var blocks = $.isArray(_blocks) ? _blocks : this.getBlocks(_blocks),
|
|
||||||
i=0, len=blocks.length, minx=999, maxx=-999, miny=999, maxy=-999;
|
|
||||||
for (; i<len; i+=2) {
|
|
||||||
if (blocks[i] < minx) minx = blocks[i];
|
|
||||||
if (blocks[i] > maxx) maxx = blocks[i];
|
|
||||||
if (blocks[i+1] < miny) miny = blocks[i+1];
|
|
||||||
if (blocks[i+1] > maxy) maxy = blocks[i+1];
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
left: minx,
|
|
||||||
right: maxx,
|
|
||||||
top: miny,
|
|
||||||
bottom: maxy,
|
|
||||||
width: maxx - minx,
|
|
||||||
height: maxy - miny
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return this.init();
|
|
||||||
};
|
|
||||||
|
|
||||||
var shapeFactory = {
|
|
||||||
line: function() {
|
|
||||||
/*
|
|
||||||
* X X
|
|
||||||
* O XOXX O XOXX
|
|
||||||
* X X
|
|
||||||
* X X
|
|
||||||
*/
|
|
||||||
var ver = [0, -1, 0, -2, 0, -3, 0, -4],
|
|
||||||
hor = [-1, -2, 0, -2, 1, -2, 2, -2];
|
|
||||||
return new Shape([ver, hor, ver, hor], '#f90', true);
|
|
||||||
},
|
|
||||||
square: function() {
|
|
||||||
/*
|
|
||||||
* XX
|
|
||||||
* XX
|
|
||||||
*/
|
|
||||||
var s = [0, 0, 1, 0, 0, -1, 1, -1];
|
|
||||||
return new Shape([s, s, s, s], 'red', true);
|
|
||||||
},
|
|
||||||
arrow: function() {
|
|
||||||
/*
|
|
||||||
* X X X
|
|
||||||
* XOX OX XOX XO
|
|
||||||
* X X X
|
|
||||||
*/
|
|
||||||
return new Shape([
|
|
||||||
[0, -1, 1, -1, 2, -1, 1, -2],
|
|
||||||
[1, -2, 1, -1, 1, 0, 2, -1],
|
|
||||||
[0, -1, 1, -1, 2, -1, 1, 0],
|
|
||||||
[0, -1, 1, -1, 1, -2, 1, 0]
|
|
||||||
], 'yellow');
|
|
||||||
},
|
|
||||||
rightHook: function() {
|
|
||||||
/*
|
|
||||||
* XX X X
|
|
||||||
* XOX O XOX O
|
|
||||||
* X X XX
|
|
||||||
*/
|
|
||||||
return new Shape([
|
|
||||||
[0, 0, 0, -1, 1, -1, 2, -1],
|
|
||||||
[0, -2, 1, 0, 1, -1, 1, -2],
|
|
||||||
[0, -1, 1, -1, 2, -1, 2, -2],
|
|
||||||
[0, -2, 0, -1, 0, 0, 1, 0]
|
|
||||||
], 'blue');
|
|
||||||
},
|
|
||||||
leftHook: function() {
|
|
||||||
/*
|
|
||||||
* X X XX
|
|
||||||
* XOX O XOX O
|
|
||||||
* X XX X
|
|
||||||
*/
|
|
||||||
return new Shape([
|
|
||||||
[2, 0, 0, -1, 1, -1, 2, -1],
|
|
||||||
[0, 0, 1, 0, 1, -1, 1, -2],
|
|
||||||
[0, -2, 0, -1, 1, -1, 2, -1],
|
|
||||||
[0, 0, 0, -1, 0, -2, 1, -2]
|
|
||||||
], 'purple');
|
|
||||||
},
|
|
||||||
leftZag: function() {
|
|
||||||
/*
|
|
||||||
* X
|
|
||||||
* XO OX
|
|
||||||
* XX X
|
|
||||||
*/
|
|
||||||
var ver = [0, 0, 0, -1, 1, -1, 1, -2],
|
|
||||||
hor = [0, -1, 1, -1, 1, 0, 2, 0];
|
|
||||||
return new Shape([hor, ver, hor, ver], 'gray', true);
|
|
||||||
},
|
|
||||||
rightZag: function() {
|
|
||||||
/*
|
|
||||||
* X
|
|
||||||
* OX OX
|
|
||||||
* XX X
|
|
||||||
*/
|
|
||||||
var ver = [0, -2, 0, -1, 1, -1, 1, 0],
|
|
||||||
hor = [0, 0, 1, 0, 1, -1, 2, -1];
|
|
||||||
return new Shape([hor, ver, hor, ver], 'green', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var shapeFuncs = [];
|
|
||||||
$.each(shapeFactory, function(k,v) { shapeFuncs.push(v); });
|
|
||||||
|
|
||||||
var filled = {
|
|
||||||
data: new Array(WIDTH * HEIGHT),
|
|
||||||
toClear: {},
|
|
||||||
check: function(x, y) {
|
|
||||||
return this.data[this.asIndex(x, y)];
|
|
||||||
},
|
|
||||||
add: function(x, y, color) {
|
|
||||||
if (x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT)
|
|
||||||
this.data[this.asIndex(x, y)] = color;
|
|
||||||
},
|
|
||||||
asIndex: function(x, y) {
|
|
||||||
return x + y*WIDTH;
|
|
||||||
},
|
|
||||||
asX: function(index) {
|
|
||||||
return index % WIDTH;
|
|
||||||
},
|
|
||||||
asY: function(index) {
|
|
||||||
return Math.floor(index / WIDTH);
|
|
||||||
},
|
|
||||||
_popRow: function(row_to_pop) {
|
|
||||||
for (var i=WIDTH*(row_to_pop+1) - 1; i>=0; i--) {
|
|
||||||
this.data[i] = (i >= WIDTH ? this.data[i-WIDTH] : undefined);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
checkForClears: function() {
|
|
||||||
var rows = [], i, len, count, mod;
|
|
||||||
|
|
||||||
for (i=0, len=this.data.length; i<len; i++) {
|
|
||||||
mod = this.asX(i);
|
|
||||||
if (mod == 0) count = 0;
|
|
||||||
if (this.data[i] && typeof this.data[i] == 'string') {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
if (mod == WIDTH - 1 && count == WIDTH) rows.push(this.asY(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0, len=rows.length; i<len; i++) {
|
|
||||||
this._popRow(rows[i]);
|
|
||||||
board.lines++;
|
|
||||||
if (board.lines % 10 == 0 && board.dropDelay > 1) board.dropDelay -= 2;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
draw: function() {
|
|
||||||
for (var i=0, len=this.data.length, row, color; i<len; i++) {
|
|
||||||
if (this.data[i] !== undefined) {
|
|
||||||
row = this.asY(i);
|
|
||||||
color = this.data[i];
|
|
||||||
drawBlock(this.asX(i), row, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function checkCollisions(x, y, blocks, checkDownOnly) {
|
|
||||||
// x & y should be aspirational values
|
|
||||||
var i = 0, len = blocks.length, a, b;
|
|
||||||
for (; i<len; i += 2) {
|
|
||||||
a = x + blocks[i];
|
|
||||||
b = y + blocks[i+1];
|
|
||||||
|
|
||||||
if (b >= HEIGHT || filled.check(a, b)) {
|
|
||||||
return true;
|
|
||||||
} else if (!checkDownOnly && a < 0 || a >= WIDTH) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var niceShapes = getNiceShapes(shapeFactory);
|
|
||||||
|
|
||||||
var board = {
|
|
||||||
animateDelay: 50,
|
|
||||||
cur: null,
|
|
||||||
|
|
||||||
lines: 0,
|
|
||||||
|
|
||||||
dropCount: 0,
|
|
||||||
dropDelay: 24, //5,
|
|
||||||
|
|
||||||
init: function() {
|
|
||||||
this.cur = this.nextShape();
|
|
||||||
|
|
||||||
ctx.font = 'bold 30px/40px "lucida grande",helvetica,arial';
|
|
||||||
ctx.fillStyle = '#333';
|
|
||||||
ctx.fillText(' Click', 50, 120);
|
|
||||||
ctx.fillText('to start', 50, 160);
|
|
||||||
|
|
||||||
var start = [], colors = [], i, ilen, j, jlen, color;
|
|
||||||
|
|
||||||
for (i in shapeFactory) {
|
|
||||||
colors.push(shapeFactory[i]().color);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0, ilen=WIDTH; i<ilen; i++) {
|
|
||||||
for (j=0, jlen=randChoice([randInt(0, 8), randInt(5, 9)]); j<jlen; j++) {
|
|
||||||
if (!color || !randInt(0, 3)) color = randChoice(colors);
|
|
||||||
start.push([i, HEIGHT - j, color]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0, ilen=start.length; i<ilen; i++)
|
|
||||||
drawBlock.apply(drawBlock, start[i]);
|
|
||||||
},
|
|
||||||
nextShape: function(_set_next_only) {
|
|
||||||
var next = this.next,
|
|
||||||
func, shape, result;
|
|
||||||
|
|
||||||
if (shapeFactory[info.mode])
|
|
||||||
func = shapeFactory[info.mode];
|
|
||||||
else if (info.mode == 'nice' || info.mode == 'evil')
|
|
||||||
func = niceShapes;
|
|
||||||
else
|
|
||||||
func = randChoice(shapeFuncs);
|
|
||||||
|
|
||||||
if (func.no_preview) {
|
|
||||||
this.next = null;
|
|
||||||
if (_set_next_only) return null;
|
|
||||||
shape = func(filled, checkCollisions, WIDTH, HEIGHT, info.mode);
|
|
||||||
if (!shape) throw new Error('No shape returned from shape function!', func);
|
|
||||||
shape.init();
|
|
||||||
result = shape;
|
|
||||||
} else {
|
|
||||||
shape = func(filled, checkCollisions, WIDTH, HEIGHT, info.mode);
|
|
||||||
if (!shape) throw new Error('No shape returned from shape function!', func);
|
|
||||||
shape.init();
|
|
||||||
this.next = shape;
|
|
||||||
if (_set_next_only) return null;
|
|
||||||
result = next || this.nextShape();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.autopilot) { //fun little hack...
|
|
||||||
niceShapes(filled, checkCollisions, WIDTH, HEIGHT, 'nice', result);
|
|
||||||
$.extend(result, {
|
|
||||||
orientation: result.best_orientation,
|
|
||||||
x: result.best_x
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
animate: function() {
|
|
||||||
var drop = false,
|
|
||||||
gameOver = false;
|
|
||||||
|
|
||||||
if (!this.paused) {
|
|
||||||
this.dropCount++;
|
|
||||||
if (this.dropCount >= this.dropDelay || window.autopilot) {
|
|
||||||
drop = true;
|
|
||||||
this.dropCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// test for a collision
|
|
||||||
if (drop) {
|
|
||||||
var cur = this.cur, x = cur.x, y = cur.y, blocks = cur.getBlocks();
|
|
||||||
if (checkCollisions(x, y+1, blocks, true)) {
|
|
||||||
drop = false;
|
|
||||||
for (var i=0; i<cur.blocksLen; i+=2) {
|
|
||||||
filled.add(x + blocks[i], y + blocks[i+1], cur.color);
|
|
||||||
if (y + blocks[i] < 0) {
|
|
||||||
gameOver = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
filled.checkForClears();
|
|
||||||
this.cur = this.nextShape();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw it!
|
|
||||||
ctx.clearRect(0, 0, PIXEL_WIDTH, PIXEL_HEIGHT);
|
|
||||||
filled.draw();
|
|
||||||
this.cur.draw(drop);
|
|
||||||
info.draw();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gameOver)
|
|
||||||
window.setTimeout(function() { board.animate(); }, this.animateDelay);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var info = {
|
|
||||||
mode: null,
|
|
||||||
modes: [
|
|
||||||
'random',
|
|
||||||
'nice',
|
|
||||||
'evil'
|
|
||||||
],
|
|
||||||
modesY: 170,
|
|
||||||
autopilotY: null,
|
|
||||||
draw: function() {
|
|
||||||
info_ctx.clearRect(0, 0, info_canvas.width, info_canvas.height);
|
|
||||||
|
|
||||||
if (board.next) {
|
|
||||||
var bounds = board.next.getBounds(0), w = 5, h = 6;
|
|
||||||
info_ctx.fillStyle = '#000';
|
|
||||||
info_ctx.fillRect(0, 0, w*block_size, h*block_size);
|
|
||||||
info_ctx.fillStyle = '#fff';
|
|
||||||
info_ctx.fillRect(border_width, border_width, w*block_size - 2*border_width, h*block_size - 2*border_width);
|
|
||||||
board.next.draw(
|
|
||||||
false,
|
|
||||||
(w-bounds.width)/2 - bounds.left - .5, //1 - bounds.left,
|
|
||||||
(h-bounds.height)/2 + bounds.height - bounds.bottom - .5,
|
|
||||||
0,
|
|
||||||
info_ctx
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
info_ctx.font = 'bold 14px/20px "lucida grande",helvetica,arial';
|
|
||||||
info_ctx.fillStyle = '#333';
|
|
||||||
info_ctx.fillText('Lines: ' + board.lines, 0, 140);
|
|
||||||
|
|
||||||
info_ctx.fillText('Shape Mode:', 0, this.modesY);
|
|
||||||
for (var i=0, len=this.modes.length, selected, y; i<len; i++) {
|
|
||||||
selected = this.mode == this.modes[i];
|
|
||||||
y = this.modesY + (i+1)*20;
|
|
||||||
this.radio(0, y, selected);
|
|
||||||
info_ctx.fillStyle = selected ? '#930' : '#333';
|
|
||||||
info_ctx.fillText(this.modes[i], 20, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.autopilotY === null) this.autopilotY = y+30;
|
|
||||||
|
|
||||||
this.checkBox(0, this.autopilotY, window.autopilot);
|
|
||||||
info_ctx.fillStyle = window.autopilot ? '#930' : '#333';
|
|
||||||
info_ctx.fillText('autopilot', 20, this.autopilotY);
|
|
||||||
},
|
|
||||||
init: function() {
|
|
||||||
this.mode = this.modes[0];
|
|
||||||
|
|
||||||
for (var attr in shapeFactory)
|
|
||||||
this.modes.push(attr);
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
$(info_canvas).click(function(evt) {
|
|
||||||
evt.preventDefault();
|
|
||||||
var offset = $(info_canvas).offset(),
|
|
||||||
x = evt.pageX - offset.left,
|
|
||||||
y = evt.pageY - offset.top,
|
|
||||||
mode;
|
|
||||||
if (y > self.modesY) {
|
|
||||||
mode = self.modes[Math.floor((y - self.modesY) / 20)];
|
|
||||||
if (mode) {
|
|
||||||
self.mode = mode;
|
|
||||||
board.nextShape(true);
|
|
||||||
} else if (self.autopilotY - 20 <= y && y <= self.autopilotY) {
|
|
||||||
window.autopilot = !window.autopilot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
circle: function(x, y, r, color) {
|
|
||||||
info_ctx.beginPath();
|
|
||||||
if (color) info_ctx.fillStyle = color;
|
|
||||||
info_ctx.arc(x, y, r, 0, 2 * Math.PI, true);
|
|
||||||
info_ctx.closePath();
|
|
||||||
info_ctx.fill();
|
|
||||||
},
|
|
||||||
radio: function(x, y, selected) {
|
|
||||||
y -= 4;
|
|
||||||
x += 8;
|
|
||||||
this.circle(x, y, 6, '#333');
|
|
||||||
this.circle(x, y, 5, '#fff');
|
|
||||||
if (selected) this.circle(x, y, 4, '#333');
|
|
||||||
},
|
|
||||||
checkBox: function(x, y, selected) {
|
|
||||||
y -= 4;
|
|
||||||
x += 8;
|
|
||||||
info_ctx.fillStyle = '#333';
|
|
||||||
info_ctx.fillRect(x - 6, y - 6, 12, 12);
|
|
||||||
info_ctx.fillStyle = '#fff';
|
|
||||||
info_ctx.fillRect(x - 5, y - 5, 10, 10);
|
|
||||||
|
|
||||||
if (selected) {
|
|
||||||
info_ctx.strokeStyle = '#333';
|
|
||||||
info_ctx.beginPath();
|
|
||||||
info_ctx.moveTo(x - 6, y - 6);
|
|
||||||
info_ctx.lineTo(x + 6, y + 6);
|
|
||||||
info_ctx.moveTo(x - 6, y + 6);
|
|
||||||
info_ctx.lineTo(x + 6, y - 6);
|
|
||||||
info_ctx.closePath();
|
|
||||||
info_ctx.stroke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
info.init();
|
|
||||||
board.init();
|
|
||||||
|
|
||||||
function startBoard(evt) {
|
|
||||||
evt.preventDefault();
|
|
||||||
board.started = true;
|
|
||||||
board.animate();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$(document).keyup(function(evt) {
|
|
||||||
return (!board.started && (evt.keyCode == 13 || evt.keyCode == 32)) ? startBoard(evt) : true;
|
|
||||||
});
|
|
||||||
|
|
||||||
$(canvas).click(function(evt) {
|
|
||||||
return (!board.started) ? startBoard(evt) : true;
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).keyup(function(evt) {
|
|
||||||
if (evt.keyCode == 80) { /*p*/
|
|
||||||
board.paused = !board.paused;
|
|
||||||
} else if (evt.keyCode == 192) { /*`*/
|
|
||||||
window.autopilot = !window.autopilot;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).safekeypress(function(evt) {
|
|
||||||
var caught = false;
|
|
||||||
if (board.cur) {
|
|
||||||
caught = true;
|
|
||||||
switch(evt.keyCode) {
|
|
||||||
case 37: /*left*/ board.cur.moveLeft(); break;
|
|
||||||
case 38: /*up*/ board.cur.rotate(true); break;
|
|
||||||
case 39: /*right*/ board.cur.moveRight(); break;
|
|
||||||
case 40: /*down*/ board.dropCount = board.dropDelay; break;
|
|
||||||
case 88: /*x*/ board.cur.rotate(true); break;
|
|
||||||
case 90: /*z*/ board.cur.rotate(false); break;
|
|
||||||
default: caught = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (caught) evt.preventDefault();
|
|
||||||
return !caught;
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
//})(this, this.document);
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/* pasted from youtube API docs: http://code.google.com/apis/youtube/iframe_api_reference.html#Loading_a_Video_Player */
|
|
||||||
|
|
||||||
function insertYouTubeIFrame() {
|
|
||||||
// 2. This code loads the IFrame Player API code asynchronously.
|
|
||||||
var tag = document.createElement('script');
|
|
||||||
tag.src = "http://www.youtube.com/player_api";
|
|
||||||
var firstScriptTag = document.getElementsByTagName('script')[0];
|
|
||||||
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
|
||||||
|
|
||||||
}
|
|
||||||
// 3. This function creates an <iframe> (and YouTube player)
|
|
||||||
// after the API code downloads.
|
|
||||||
var player;
|
|
||||||
function onYouTubePlayerAPIReady() {
|
|
||||||
player = new YT.Player('player', {
|
|
||||||
height: '390',
|
|
||||||
width: '640',
|
|
||||||
videoId: 'u1zgFlCw8Aw',
|
|
||||||
events: {
|
|
||||||
'onReady': onPlayerReady,
|
|
||||||
'onStateChange': onPlayerStateChange
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. The API will call this function when the video player is ready.
|
|
||||||
function onPlayerReady(event) {
|
|
||||||
event.target.playVideo();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. The API calls this function when the player's state changes.
|
|
||||||
// The function indicates that when playing a video (state=1),
|
|
||||||
// the player should play for six seconds and then stop.
|
|
||||||
var done = false;
|
|
||||||
|
|
||||||
function onPlayerStateChange(event) {
|
|
||||||
if (event.data == YT.PlayerState.PLAYING && !done) {
|
|
||||||
setTimeout(stopVideo, 6000);
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function stopVideo() {
|
|
||||||
player.stopVideo();
|
|
||||||
}
|
|
||||||
@@ -30,5 +30,3 @@ class YouTubeVideo(models.Model):
|
|||||||
return self.artist + " - " + self.title + ": active"
|
return self.artist + " - " + self.title + ": active"
|
||||||
return self.artist +" - " + self.title + " : NOT active"
|
return self.artist +" - " + self.title + " : NOT active"
|
||||||
|
|
||||||
|
|
||||||
# TODO: cache current track. avoids overwriting video-iframe if the song is still the same.
|
|
||||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user