JavaScript 寫遊戲 : 俄羅斯方塊

<title>dwin.net - web application - tetris</title>
<body>
Written by David NG @ <a href="http://dwin.net">http://dwin.net</a><BR>
Copyright(c) 1998-2007 dwin.net all rights reserved<BR>

<br><br><font color=red>press "s" button to Star or Stop<br>press "Space Bar" button to Change Quadrel into Another Shape<br>press "Page Up" to Speed up<br>press "Page Down" to Speed down</font>
<div id='Base' style='position:absolute;overflow:visible;'>
 <div id='GrowDiv' style='position:absolute;left:0;top:0;filter:glow(color=#ffff00,strength=5);'>
  <div id='DroppedBlockDiv' style='position:absolute;left:0;top:0'></div>
 </div>
 <div id='DroppingBlockDiv' style='position:absolute;'></div>
 <div id='ReadyBlockDiv' style='position:absolute;top:0;'></div>
 <div id='ScoreDiv' style='position:absolute;'>0</div>
</div>

 <script>
// firefox
if(typeof HTMLElement!="undefined" && !HTMLElement.prototype.insertAdjacentElement)
{
 HTMLElement.prototype.insertAdjacentElement = function(where,parsedNode)
 {
  switch( where )
  {
   case 'beforeBegin':
    this.parentNode.insertBefore(parsedNode,this)
    break;
   case 'afterBegin':
    this.insertBefore(parsedNode,this.firstChild);
    break;
   case 'beforeEnd':
    this.appendChild(parsedNode);
    break;
   case 'afterEnd':
    if (this.nextSibling)
     this.parentNode.insertBefore(parsedNode,this.nextSibling);
    else
     this.parentNode.appendChild(parsedNode);
    break;
  }
 }

 HTMLElement.prototype.insertAdjacentHTML = function(where,htmlStr)
 {
  var r = this.ownerDocument.createRange();
  r.setStartBefore(this);
  var parsedHTML = r.createContextualFragment(htmlStr);
  this.insertAdjacentElement(where,parsedHTML)
 }

 HTMLElement.prototype.insertAdjacentText = function(where,txtStr)
 {
  var parsedText = document.createTextNode(txtStr)
  this.insertAdjacentElement(where,parsedText)
 }
}

 

/*
Written by David NG @ http://dwin.net
Copyright(c) 1998-2004 dwin.net all rights reserved

Start:   2002-09-20 14:45
Finish:  2002-10-31 23:50

2003-08-14 01:25
Add Block[7]=['1'] function

2007-08-09 02:06
firefox support: as firefox don't support filter:flipv, so relate function has been modify to achive the same result.
Found a unfix bug: Change the shape of Block=['1111'] at the top right corner. (slow the oSpeed to test this bug)

*/
var Rows = 17;
var Cells = 10;
var ObjW = ObjH = 20;

var Scores= 0;
var Marks = [100,400,900,1600];

var BaseBW = 5;
var BaseBGColor = 'white';

var BlockBW = '1px';
var BlockBS = 'inset';
var BlockBC = 'orange';

var oSpeed = 300;

 

 

Block = [];
Block[0]=[
'   ',
'  1',
'111']
Block[0].change = 4;
Block[0].color = 'red';

Block[1]=[
'   ',
'1  ',
'111']
Block[1].change = 4;
Block[1].color = 'green';

Block[2]=[
'   ',
' 1 ',
'111']
Block[2].change = 4;
Block[2].color = 'blueviolet';

Block[3]=[
' 11',
'11 ']
Block[3].change = 2;
Block[3].color = 'fuchsia';

Block[4]=[
'11 ',
' 11']
Block[4].change = 2;
Block[4].color = 'yellow';

Block[5]=[
'1111']
Block[5].change = 2;
Block[5].color = 'lime';

Block[6]=[
'11',
'11']
Block[6].change = 1;
Block[6].color = 'blue';


Block[7]=[
'1']
Block[7].change = 1;
Block[7].color = 'gold';

Block[8]=[
'   ',
'1 1',
'111']
Block[8].change = 4;
Block[8].color = 'pink';

Block[9]=[
'111',
' 1 ',
' 1 ']
Block[9].change = 4;
Block[9].color = 'black';

Block[10]=[
'1  ',
' 1 ',
'  1']
Block[10].change = 2;
Block[10].color = 'cornflowerblue';

Block[11]=[
'   ',
' 1 ',
'1 1']
Block[11].change = 4;
Block[11].color = 'greenyellow';

 

 

 

 


function ReadyForDown( obj1, obj2 )
{
 obj1.k = (Math.random()*Block.length)|0;
 if( ! NewBlock[obj1.k].length )
 {
  switch( Block[obj1.k].change )
  {
   case 1 : Change0(obj1.k); break;
   case 2 : Change0(obj1.k); Change1(obj1.k); break;
   case 4 : Change0(obj1.k); Change1(obj1.k); Change2(obj1.k); break;
  }
 }
 obj1.Change = (Math.random()*Block[obj1.k].change)|0;
 obj2.innerHTML = NewBlock[obj1.k][obj1.Change].iHtml;
 obj1.GapX = (NewBlock[obj1.k][obj1.Change][0].length/2)|0;
 CheckObjGapY( obj1,NewBlock[obj1.k][obj1.Change].length );
 obj1.X = (Cells/2)|0;
 obj1.Y = 0;
}

 

function CheckObjGapY( obj, k )
{
 if( ! NewBlock[obj.k][obj.Change][k-1].join('').match(//d+/) )
 {
  obj.GapY = 1-k;
  CheckObjGapY(obj,k-1);
 }
 else
  obj.GapY = -k;
}

 

function ChangeBlock()
{
 if( Block[Obj1.k].change > 1 )
 {
  Obj1.TestChange = ((Obj1.Change|0)+1 >= Block[Obj1.k].change)?0:(Obj1.Change|0)+1;
  Obj1.TestGapX = (NewBlock[Obj1.k][Obj1.TestChange][0].length/2)|0;
  Obj1.TestGapY = -NewBlock[Obj1.k][Obj1.TestChange].length;
  Obj1.TestL = (Obj1.X|0)-(Obj1.TestGapX|0);
  Obj1.TestT = (Obj1.Y|0)+(Obj1.TestGapY|0);

  var k1 = k2 = Areas;
  for( var i=Obj1.TestL|0; i>=0 && i>(Obj1.TestL|0)-NewBlock[Obj1.k][Obj1.TestChange].lg; i-- )
  {
   if( (k1=CheckChangeBlock(i)) != Areas )
    break
  }
  for( var i=(Obj1.TestL|0)+1; i<Cells && i<(Obj1.TestL|0)+NewBlock[Obj1.k][Obj1.TestChange].lg; i++)
  {
   if( (k2=CheckChangeBlock(i)) != Areas )
    break
  }
  if( k1 == k2 )
   return;

  Obj1.L = (Math.abs((Obj1.TestL|0)-k1)>Math.abs((Obj1.TestL|0)-k2))?k2:k1;
  Obj1.T = Obj1.TestT;
  Obj1.GapX = Obj1.TestGapX;
  Obj1.GapY = Obj1.TestGapY;
  Obj1.X = (Obj1.L|0)+(Obj1.GapX|0);
  Obj1.Y = (Obj1.T|0)-(Obj1.GapY|0);
  Obj1.Change = Obj1.TestChange;
  document.getElementById('DroppingBlockDiv').style.left = ((Obj1.L|0)*ObjW)+'px';
  document.getElementById('DroppingBlockDiv').style.top = ((Obj1.T|0)*ObjH)+'px';
  document.getElementById('DroppingBlockDiv').innerHTML = NewBlock[Obj1.k][Obj1.Change].iHtml;
 }
}

 

function CheckChangeBlock(lefts)
{
 for( var y=0; y<NewBlock[Obj1.k][Obj1.TestChange].length; y++ )
 {
  for( var x=0; x<NewBlock[Obj1.k][Obj1.TestChange][0].length; x++ )
  {
   if( NewBlock[Obj1.k][Obj1.TestChange][y][x] == 1 )
   {
    try
    {
     if( Map[(Obj1.TestT|0)+y][lefts+x] != ' ' )
      return Areas;
    }
    catch(e){}
   }
  }
 }

 return lefts;
}

 

 

function Dir( xx, yy )
{
 var special = false
 if( NewBlock[Obj1.k][Obj1.Change].length==1 && NewBlock[Obj1.k][Obj1.Change][0]==1 )
 {
  for( var y=(Obj1.T|0)+1; y<Rows-1; y++ )
  {
   if( Map[y+yy][Obj1.L] == " " )
   {
    special = true;
    break;
   }
  }
 }
 for( var y=NewBlock[Obj1.k][Obj1.Change].length-1; y>=0; y-- )
 {
  for( var x=NewBlock[Obj1.k][Obj1.Change][0].length-1; x>=0; x-- )
  {
   if( NewBlock[Obj1.k][Obj1.Change][y][x] == 1 )
   {
    try
    {
     if( yy==0 && (((Obj1.L|0)+x+xx)<0 || ((Obj1.L|0)+x+xx)>=Cells || Map[(Obj1.T|0)+y][(Obj1.L|0)+x+xx]==1) )
      return; // horizontal
     if( ((Obj1.T|0)+y+yy)>=Rows || (!special && Map[(Obj1.T|0)+y+yy][(Obj1.L|0)+x+xx]==1) )
     {
      return CreateBlockInMap(); // vertical
     }
    }
    catch(e){}
   }
  }
 }
 document.getElementById('DroppingBlockDiv').style.left = ((Obj1.L=(Obj1.X+=xx)-(Obj1.GapX|0))*ObjW)+'px';
 document.getElementById('DroppingBlockDiv').style.top = ((Obj1.T=(Obj1.Y+=yy)+(Obj1.GapY|0))*ObjH)+'px';
}

 

function CreateBlockInMap()
{
 for( var y=0; y<NewBlock[Obj1.k][Obj1.Change].length; y++ )
 {
  for( var x=0; x<NewBlock[Obj1.k][Obj1.Change][0].length; x++ )
  {
   try
   {
    if( NewBlock[Obj1.k][Obj1.Change][y][x] == 1 )
    {
     Map[(Obj1.T|0)+y][(Obj1.L|0)+x] = NewBlock[Obj1.k][Obj1.Change][y][x];     
     document.getElementById('DroppedBlockDiv').childNodes[((Obj1.T|0)+y)*Cells+(Obj1.L|0)+x].style.background = Block[Obj1.k].color;
     document.getElementById('DroppedBlockDiv').childNodes[(Obj1.T+y)*Cells+Obj1.L+x].style.visibility = 'visible';
    }
   }
   catch(e)
   {
    return GameOver()
   }
  }
 }
 CheckBlockAppear();
 ReadyForDown( Obj2, document.getElementById('ReadyBlockDiv') );
}

 

function CheckBlockAppear()
{
 clearInterval(GoTime2);
 GoTime2=0
 var NewMap = [];
 var iHtml = '';
 var k = Rows-1;
 var kk = -1;
 var tmpObj;

 for( var y=Rows-1; y>=0; y-- )
 {
  if( Map[y].join('') != FullString )
  {
   NewMap[k--] = Map[y];
  }
  else
  {
   kk++;
   for( var x=0; x<Cells; x++ )
   {
    tmpObj = document.getElementById('DroppedBlockDiv').childNodes[(y)*Cells];
    tmpObj.parentNode.removeChild(tmpObj);

    iHtml += "<span style='width:"+ObjW+"px;height:"+ObjH+"px;border:"+BlockBW+" "+BlockBS+" "+BlockBC+";-moz-box-sizing:border-box;overflow:hidden;display:-moz-inline-box;visibility:hidden'></span>";
   }
  }
 }
 for( ; k>=0; k-- )
 {
  NewMap[k] = [];
  for( var x=0; x<Cells; x++ )
   NewMap[k][x] = ' ';
 }
 if( kk != -1 )
  document.getElementById('ScoreDiv').innerHTML = (Scores+=Marks[kk]); // Cal the Scores
 for( var i=0; i<Rows; i++ )
  Map[i] = NewMap[i];

 document.getElementById('DroppedBlockDiv').insertAdjacentHTML("afterBegin", iHtml);
 for( i in Obj2 )
  Obj1[i] = Obj2[i]; //Obj2 => Obj1

 document.getElementById('DroppingBlockDiv').innerHTML = NewBlock[Obj1.k][Obj1.Change].iHtml;
 document.getElementById('DroppingBlockDiv').style.left = ((Obj1.L = (Obj1.X|0)-(Obj1.GapX|0))*ObjW)+'px';
 document.getElementById('DroppingBlockDiv').style.top = ((Obj1.T = (Obj1.GapY|0))*ObjH)+'px';
}

 

function GameOver()
{
 if( confirm('Game Over , ReStart ?') )
  window.location.reload();
 else
  window.close();
}

 

 

function Change0( k )
{
 NewBlock[k] = [];
 NewBlock[k][0] = [];
 NewBlock[k][0].iHtml = '';

 for( var y=0; y<Block[k].length; y++ )
 {
  NewBlock[k][0][y] = [];
  for( var x=0; x<Block[k][0].length; x++ )
   NewBlock[k][0].iHtml += ((NewBlock[k][0][y][x]=Block[k][y].charAt(x)) == 1)?BlockHtml(x,y,k):"";
 }
 CheckBlockLong( k, 0 );
}

function Change1(k)
{
 NewBlock[k][1] = [];
 NewBlock[k][1].iHtml = '';

 for( var y=0; y<Block[k][0].length; y++ )
 {
  NewBlock[k][1][y] = [];
  for( var x=0; x<Block[k].length; x++ )
   NewBlock[k][1].iHtml += ((NewBlock[k][1][y][x]=Block[k][Block[k].length-x-1].charAt(y)) == 1)?BlockHtml(x,y,k):"";
 }
 CheckBlockLong( k, 1 );
}

function Change2(k)
{
 NewBlock[k][2] = [];
 NewBlock[k][3] = [];
 NewBlock[k][2].iHtml = '';
 NewBlock[k][3].iHtml = '';

 for(var y=0;y<Block[k].length;y++)
 {
  NewBlock[k][2][y] = [];
  for( var x=0; x<Block[k][0].length; x++ )
   NewBlock[k][2].iHtml += ((NewBlock[k][2][y][x]=Block[k][Block[k].length-y-1].charAt(Block[k][0].length-x-1)) == 1)?BlockHtml(x,y,k):"";
 }
 for( var y=0; y<Block[k][0].length; y++ )
 {
  NewBlock[k][3][y] = [];
  for( var x=0; x<Block[k].length; x++ )
   NewBlock[k][3].iHtml += ((NewBlock[k][3][y][x]=Block[k][x].charAt(Block[k][0].length-y-1)) == 1)?BlockHtml(x,y,k):"";
 }
 CheckBlockLong( k, 2 );
 CheckBlockLong( k, 3 );
}

function BlockHtml( x, y, k )
{
 return "<span style='position:absolute;left:"+(x*ObjW)+"px;top:"+(y*ObjH)+"px;width:"+ObjW+"px;height:"+ObjH+"px;background-color:"+Block[k].color+";border:"+BlockBW+" "+BlockBS+" "+BlockBC+";-moz-box-sizing:border-box;overflow:hidden;'></span>"
}

function CheckBlockLong( k, i )
{
 for( var y=0; y<NewBlock[k][i].length; y++ )
  NewBlock[k][i][y].lg = (NewBlock[k][i][y].toString().match(//d+/)==null) ? 0:NewBlock[k][i][y].join('').match(//d+/).toString().length;

 NewBlock[k][i].lg = 1;
 for( var y=0; y<NewBlock[k][i].length; y++ )
  NewBlock[k][i].lg = Math.max(NewBlock[k][i][y].lg, NewBlock[k][i].lg);

}

 

 

 

 

 

document.onkeydown = function( evt )
{
 if( typeof(evt) == 'undefined' )
  evt = window.event||window.Event;
 var keyCode = 0;
 if( evt.keyCode )
  keyCode = evt.keyCode;
 else if( typeof(evt.which) != 'undefined')
  keyCode = evt.which;

 switch( keyCode )
 {
  case 34 : clearInterval(GoTime);
     oSpeed += 20;
     if( GoTime > 0 )
     {
      Dir( 0, 1 );
      GoTime = setInterval('Dir(0,1)',oSpeed);
     };
     break; // page down
  case 33 : if( oSpeed-30 > 0 )
     {
      clearInterval(GoTime);
      oSpeed -= 20
     }
     if( GoTime > 0 )
     {
      Dir( 0, 1 );
      GoTime = setInterval('Dir(0,1)',oSpeed);
     };
     break; // page up
  case 38 : if( GoTime > 0 )
      GoTime2 = setInterval("Dir(0,1)",1);
     break; // up
  case 37 : CheckKeyDown(-1,0,150,20); break; // left
  case 39 : CheckKeyDown(1,0,150,20); break; // right
  case 40 : CheckKeyDown(0,1,150,20); break; // down
  //case 96:if(GoTime>0)ChangeBlock();break; // 0
  case 32 : if(GoTime>0)ChangeBlock(); break; // space
  case 83 : CheckStart(); break; // s
 }
}

 

document.onkeyup = function()
{
 DoKeyDown = false;
}

function CheckKeyDown( x, y, t1, t2 )
{
 if( GoTime>0 && !DoKeyDown )
 {
  Dir( x, y );
  DoKeyDown = true;
  setTimeout( "if(DoKeyDown)KeyDownAgain("+x+","+y+","+t2+");", t1 );
 }
}

function KeyDownAgain( x, y, t2 )
{
 if( GoTime>0 && DoKeyDown )
 {
  Dir( x, y );
  setTimeout( "KeyDownAgain("+x+","+y+","+t2+")", t2 );
 }
}

 


function CheckStart()
{
 if( GoTime == -1 )
 {
  CheckBlockAppear();
  GoTime = 0;
  ReadyForDown( Obj2, document.getElementById('ReadyBlockDiv') );
 }
 if( ! GoTime )
 {
  Dir( 0, 1 );
  GoTime = setInterval( 'Dir(0,1)', oSpeed );
 }
 else
 {
  clearInterval( GoTime );
  GoTime = 0;
 }
}


var Map = [];
var NewBlock = [];
var Areas = 0;
var GoTime = -1, GoTime2;
var FullString = '';
var Obj1 = new Object();
var Obj2 = new Object();
var DoKeyDown = false;


window.onload = function()
{
 window.focus();
 var obj
 var iHtml = '';
 var BaseWidth = Cells*ObjW;
 var BaseHeight = Rows*ObjH;
 var MainMapWidth = document.all ? 2*BaseBW+Cells*ObjW : Cells*ObjW;
 var MainMapHeight = document.all ? 2*BaseBW+Rows*ObjH : Rows*ObjH;

 obj = document.getElementById('Base');
 obj.style.left = (document.body.clientWidth-MainMapWidth)/2;
 obj.style.top = (document.body.clientHeight-MainMapHeight)/2;
 obj.style.width = MainMapWidth;
 obj.style.height = MainMapHeight;
 obj.style.borderWidth = BaseBW+'px';
 obj.style.borderStyle = 'inset';
 obj.style.borderColor = '#0000CC';
 
 obj = document.getElementById('GrowDiv');
 obj.style.width = BaseWidth+'px';
 obj.style.height = BaseHeight+'px';

 obj = document.getElementById('DroppedBlockDiv');
 obj.style.width = BaseWidth+'px';
 obj.style.height = BaseHeight+'px';

 obj = document.getElementById('ReadyBlockDiv');
 obj.style.left = (MainMapWidth+2*BaseBW)+'px';

 obj = document.getElementById('ScoreDiv');
 obj.style.left = (MainMapWidth+50)+'px';
 obj.style.top = (MainMapHeight-20)+'px';
 obj.innerHTML = "0";


 for( var i=0,k=Cells*Rows; i<k; i++)
  iHtml += "<span style='width:"+ObjW+"px;height:"+ObjH+"px;border:"+BlockBW+" "+BlockBS+" "+BlockBC+";-moz-box-sizing:border-box;overflow:hidden;display:-moz-inline-box;visibility:hidden;'></span>";

 for( var i=0; i<Block.length; i++ )
  NewBlock[i] = [];

 FullString = new Array(Cells+1).join("1");

 for( var y=0; y<Rows; y++ )
 {
  Map[y] = [];
  for( var x=0; x<Cells; x++ )
   Map[y][x] = ' ';
 }
 Areas = Cells*(Rows-1);
 document.getElementById('DroppedBlockDiv').innerHTML = iHtml;
 ReadyForDown( Obj2, document.getElementById('ReadyBlockDiv') );
 CheckStart();
}
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值