Created
April 12, 2013 05:01
-
-
Save tangentstorm/5369517 to your computer and use it in GitHub Desktop.
ancient actionscript 2 code for blockdown (tetris clone)... this is just the main game logic. the game is playable at http://www.kongregate.com/games/tangentstorm/blockdown
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// == declarations ========================================== | |
var level:Number = 0; | |
var score:Number = 0; | |
var cleared:Number = 0; // number of lines cleared | |
var justDropped:Boolean = false; // did they just force a drop? (Enter key) | |
var board:MovieClip; | |
var EMPTY:Number = -1; | |
var hold:Number = EMPTY; // block type for the hold; | |
var SHAPES:Array = Array(7); | |
var COLORS:Array = Array(7); | |
var BLOCKCOUNT = 1; // autonumbering for the blocks | |
var queue:Array = Array(3); | |
// game states: | |
var States = { | |
needShape:0, | |
falling: 1, | |
gameOver: 2, | |
cascade: 3, | |
paused: 4 | |
} | |
var state:Number = States.needShape; | |
var counter = 0; | |
var shape; | |
// rotation moved really fast, so I set up this little | |
// thing to make it wait for the key to come back up | |
// before rotating again. | |
var already:Object = {rotRight:false, rotLeft:false, swapped:false}; | |
// == initialization ====================================== | |
COLORS[0] = "gold" // the box | |
SHAPES[0] = [[1,1],[1,1]] | |
COLORS[1] = "red" // the zig | |
SHAPES[1] = [[1,1,0],[0,1,1],[0,0,0]] | |
COLORS[2] = "green" // the zag | |
SHAPES[2] = [[0,1,1],[1,1,0],[0,0,0]] | |
COLORS[3] = "magenta" // the T | |
SHAPES[3] = [[0,1,0],[1,1,1],[0,0,0]] | |
COLORS[4] = "cyan" // the bar | |
SHAPES[4] = [[0,1,0,0],[0,1,0,0],[0,1,0,0],[0,1,0,0]] | |
COLORS[5] = "blue" // the L | |
SHAPES[5] = [[0,0,1],[1,1,1],[0,0,0]] | |
COLORS[6] = "orange" // the J | |
SHAPES[6] = [[1,0,0],[1,1,1],[0,0,0]] | |
for (var i=0; i<queue.length; i++) { | |
queue[i] = pickShape(); | |
} | |
board = _root.createEmptyMovieClip("board", 10); | |
board._x = 130; | |
board._y = 60; | |
board.top = 0; | |
board.left = 0; | |
board.cellsize = 20; | |
board.bottom = board.top + 20*board.cellsize; | |
board.right = board.left+ 10*board.cellsize; | |
// draw the board: | |
_root.held.gotoAndStop("empty"); | |
_root.glassClip.swapDepths(500000); | |
_root.pausedClip.swapDepths(500001); | |
_root.gameOverClip.swapDepths(500002); | |
_root.levelUpClip.swapDepths(500003); | |
_root.pausedClip._visible=false; | |
_root.gameOverClip._visible=false; | |
playMusic("tetris"); | |
var grid:Array; | |
grid = Array(20); | |
grid._collapseFrame = 0; | |
for (var i=0; i<20; i++) { | |
grid[i] = Array(10); | |
for (var j=0; j<10; j++){ | |
grid[i][j] = 0; | |
} | |
} | |
grid.isFull = function (row,col) { | |
var res:Boolean; | |
if (row >= 20) { | |
res = ((col< 0) or (col >=10)); | |
} else { | |
res = (row < 0) | |
|| ((col < 0) or (col >= 10)) | |
|| this[row][col] != 0; | |
} | |
//trace ("isFull(" + row + "," + col + ") = " + res); | |
return res; | |
} | |
grid.collapse = function () { | |
this._collapseFrame++; | |
if (this._collapseFrame < 10) { | |
for (var row = this._markLo; row <= this._markHi; row++) { | |
for (var col = 0; col < 10; col++) { | |
var val = this[row][col]; | |
board["block" + val]._alpha -= 11; | |
} | |
} | |
} else if (this._collapseFrame < 10 + this._marked) { | |
for (var row = this._markLo; row < 20; row++) { | |
for (var col = 0; col < 10; col++) { | |
var val = this[row][col]; | |
if (val !=0) { | |
board["block" + val]._y += board.cellsize; | |
} | |
} | |
} | |
} else { | |
for (var row = this._markLo; row <= this._markHi; row++ ){ | |
for (var col = 0; col < 10; col++) { | |
var id= this[row][col]; | |
board[id].removeMovieClip(); | |
delete board[id]; | |
} | |
} | |
this.splice(this._markLo, this._marked); | |
for (var i=0; i< this._marked; i++) { | |
this.push([0,0,0,0,0,0,0,0,0,0]); | |
} | |
this._collapseFrame = 0; | |
return false; // stop | |
} | |
return true; // keep going | |
} | |
grid.rowIsFull = function(row) { | |
var count = 0; | |
for (var i=0; i<10; i++) { | |
if (this[row][i] > 0) { count++; } | |
} | |
return (count == 10); | |
} | |
grid.checkClearedLines = function() { | |
grid._markLo = 20; | |
grid._markHi = 0; | |
grid._marked = 0; | |
for (var i=0; i<this.length; i++) { | |
if (this.rowIsFull(i)) { | |
this._markLo = Math.min(this._markLo, i); | |
this._markHi = Math.max(this._markHi, i); | |
this._marked = this._markHi - this._markLo + 1; | |
} | |
} | |
//trace("marked " + this._marked + " lines!"); | |
if (this._marked > 0) { | |
addToScore(this._marked); | |
cleared += this._marked; | |
var tmplevel:Number = level; | |
level = Math.min(Math.floor(cleared / 10), 15); | |
if (level > tmplevel) { | |
_root.levelUpClip.gotoAndPlay("animation"); | |
playSound("levelUp"); | |
} | |
return true; | |
} else { | |
return false; | |
} | |
} | |
assert( grid.isFull(0,-1), "left"); | |
assert( grid.isFull(0,10), "right"); | |
assert( grid.isFull(-1,0), "bottom"); | |
assert( ! grid.isFull(20, 0), "top"); | |
function addToScore(lines:Number) { | |
var points:Number; | |
switch(lines) { | |
case 1: points = 10; break; | |
case 2: points = 30; break; | |
case 3: points = 50; break; | |
case 4: points = 80; break; | |
} | |
score += (points * (level + 1 )); | |
} | |
function assert(test, msg) { | |
if (!test) { | |
trace ( "assertion failed: " + msg ); | |
} | |
} | |
// a falling block | |
function newBlock (r,c, tile) { | |
assert(r <= 25, "bad r:" + r); | |
assert(c <= 10, "bad c:" + c); | |
b = board.attachMovie(tile, "block" + BLOCKCOUNT, BLOCKCOUNT); | |
b.row = r; | |
b.col = c; | |
b.id = BLOCKCOUNT++; | |
b.draw = function() { | |
this._x = board.left + (this.col * board.cellsize); | |
this._y = board.top + ((19 - this.row) * board.cellsize); | |
} | |
b.nudge = function(dir) { | |
if (!grid.isFull(this.row, this.col+dir)) { | |
this.col += dir; | |
} | |
} | |
b.drop = function() { | |
this.row--; | |
} | |
b.stick = function(g) { | |
g[this.row][this.col] = this.id; | |
} | |
b.detach = function() { | |
this.removeMovieClip() | |
} | |
return b; | |
} | |
function pickShape() { | |
return Math.ceil(Math.random() * SHAPES.length)-1; | |
} | |
function getShapeFromQueue() { | |
var i:Number = Number(queue.shift()); | |
queue.push(pickShape()); | |
_root.next0.gotoAndStop(Number(queue[0]) + 1); | |
_root.next1.gotoAndStop(Number(queue[1]) + 1); | |
_root.next2.gotoAndStop(Number(queue[2]) + 1); | |
return newShape(i); | |
} | |
function newShape(i:Number) { | |
var s = Array(); | |
s.cells = [] | |
// track upper left corner: | |
s.row = 19+SHAPES[i].length; | |
s.startedAt = s.row; | |
s.col = 4; | |
s.shapeNumber = i; | |
// initialize the array from the template | |
for (var row=0; row<SHAPES[i].length; row++){ | |
s.push(Array()); | |
for (var col=0; col<SHAPES[i].length; col++){ | |
if (SHAPES[i][row][col]){ | |
var cell = newBlock(s.row-row,s.col+col,COLORS[i]); | |
s[row].push(cell); | |
s.cells.push(cell); | |
} else { | |
s[row].push(0); | |
} | |
} | |
} | |
s.canMove = function(y,x) { | |
var answer:Boolean = true; | |
for (var i in this.cells) { | |
var cell=this.cells[i]; | |
answer = answer and (! grid.isFull(cell.row+y, cell.col+x)) | |
} | |
return answer; | |
} | |
s.drop = function() { | |
this.row--; | |
for (var i in this.cells) { | |
this.cells[i].drop(); | |
} | |
} | |
s.nudge = function(dir) { | |
if (this.canMove(0,dir)) { | |
this.col += dir; | |
for (var i in this.cells) { | |
this.cells[i].nudge(dir); | |
} | |
} | |
} | |
s.stick = function(g) { | |
for (var i in this.cells) { | |
this.cells[i].stick(g); | |
} | |
} | |
s.draw = function() { | |
for (var i in this.cells) { | |
this.cells[i].draw(); | |
} | |
} | |
s.detach = function() { | |
for (var i in this.cells) { | |
this.cells[i].detach(); | |
} | |
} | |
s._finishRotation = function() { | |
// shared code for rotate right/left | |
var blocked:Boolean = false; | |
for (var i in this.cells) { | |
var cell = this.cells[i]; | |
if (grid.isFull(cell.newRow, cell.newCol)) { | |
blocked = true; | |
break; | |
} | |
} | |
if (blocked) { | |
playSound("blocked"); | |
} else { | |
for (var i in this.cells) { | |
var cell=this.cells[i]; | |
cell.row = cell.newRow; | |
cell.col = cell.newCol; | |
} | |
} | |
} | |
s.rotateRight = function() { | |
for (var i in this.cells) { | |
var cell = this.cells[i]; | |
cell.newRow = this.row - (this.length -1 -(cell.col-this.col)); | |
cell.newCol = this.col + (this.row - cell.row); | |
} | |
this._finishRotation(); | |
} | |
s.rotateLeft = function() { | |
for (var i in this.cells) { | |
var cell = this.cells[i]; | |
cell.newRow = this.row - (cell.col - this.col); | |
cell.newCol = this.col + (this.length -1 -(this.row - cell.row)); | |
} | |
this._finishRotation(); | |
} | |
return s; | |
} | |
function swapWithHold() { | |
if ((shape.row < shape.startedAt) && (! already.swapped)) { | |
var n:Number = shape.shapeNumber; | |
shape.detach(); | |
if (hold == EMPTY) { | |
state = States.needShape; | |
} else { | |
shape = newShape(hold); | |
} | |
hold = n; | |
_root.held.gotoAndStop(hold + 1); | |
playSound("swap"); | |
already.swapped = true; | |
} | |
} | |
board.onEnterFrame = function() { | |
counter ++; | |
switch (state) { | |
case States.gameOver: | |
break; | |
case States.cascade: | |
if (! grid.collapse()) { | |
state = States.needShape; | |
} | |
break; | |
case States.needShape: | |
counter = 0; | |
shape = getShapeFromQueue(); | |
state = States.falling; | |
already.swapped = false; | |
shape.draw(); | |
break; | |
case States.paused: | |
if (Key.isDown(Key.SPACE)) { | |
_root.pausedClip._visible=false; | |
playSound("pause"); | |
state = States.falling; | |
} | |
break; | |
case States.falling: | |
if (counter % 2) { | |
if (Key.isDown(80)) { // p | |
state = States.paused; | |
_root.pausedClip._visible=true; | |
playSound("pause"); | |
return; | |
} | |
if (Key.isDown(Key.ENTER) && (shape.row < shape.startedAt)) { | |
while (shape.canMove(-1,0)) { | |
shape.drop(); | |
justDropped=true; | |
} | |
} | |
if (Key.isDown(Key.DOWN)) { | |
if (shape.canMove(-1,0)) { | |
shape.drop(); | |
} else { | |
justDropped = true; | |
} | |
} | |
if (Key.isDown(Key.CONTROL)) { | |
swapWithHold(); | |
} | |
if (Key.isDown(Key.RIGHT)) { | |
shape.nudge(+1); | |
} | |
if (Key.isDown(Key.LEFT)) { | |
shape.nudge(-1); | |
} | |
if (Key.isDown(83)) { // S | |
if (! already.rotatedLeft) { | |
shape.rotateLeft(); | |
already.rotatedLeft = true; | |
} | |
} else { | |
already.rotatedLeft = false; | |
} | |
if (Key.isDown(70) || Key.isDown(Key.SPACE)) { // F | |
if (! already.rotatedRight) { | |
shape.rotateRight(); | |
already.rotatedRight = true; | |
} | |
} else { | |
already.rotatedRight = false; | |
} | |
} | |
if (justDropped or (counter % (2*(16-level)) == 0)) { | |
counter = 0; | |
justDropped = false; | |
if (shape.canMove(-1,0)) { | |
shape.drop(); | |
} else if (shape.row >= 20) { | |
_root.gameOverClip._visible=true; | |
stopAllSounds(); | |
playSound("gameOver"); | |
state = States.gameOver; | |
return; | |
} else { | |
state = States.needShape; | |
shape.stick(grid); | |
playSound("land"); | |
if (grid.checkClearedLines()) { | |
playSound("clearLine"); | |
state=States.cascade; | |
} | |
} | |
} | |
shape.draw(); | |
break; | |
default: break; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment