Skip to content

Instantly share code, notes, and snippets.

@tangentstorm
Created April 12, 2013 05:01
Show Gist options
  • Save tangentstorm/5369517 to your computer and use it in GitHub Desktop.
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
// == 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