最近在研究俄罗斯方块(主要用于怀旧~))。下载了别人的代码来参考,发现一些bug,修改后再进行了一些美化(就是改改颜色,改改格子的形状)。
有问题可以回帖提问!!尽力回答!!希望对你有用。
要点
0.用timer或者enterframe等来计时,每过一定时间就向下移动!
1.数组保存整个游戏的格子。
2.每种形状的格子用数组写死,定义好。另一个数组保存正在下落的形状格子。
3.我通过graphic来绘制整个游戏的格子。
5.剩下的主要就是一些能否旋转,能否移动,游戏是否结束的逻辑判断
6.如果你要用的话需要做一些简单的修改,把报错的地方删掉就行。不影响游戏逻辑和运行
贴上 demo演示地址 (个人网站,还在优化中。欢迎吐槽)。。
贴上 demo演示地址 (个人网站,还在优化中。欢迎吐槽)。。
有问题可以回帖提问!!尽力回答!!希望对你有用。
要点
0.用timer或者enterframe等来计时,每过一定时间就向下移动!
1.数组保存整个游戏的格子。
2.每种形状的格子用数组写死,定义好。另一个数组保存正在下落的形状格子。
3.我通过graphic来绘制整个游戏的格子。
5.剩下的主要就是一些能否旋转,能否移动,游戏是否结束的逻辑判断
6.如果你要用的话需要做一些简单的修改,把报错的地方删掉就行。不影响游戏逻辑和运行
贴上 demo演示地址 (个人网站,还在优化中。欢迎吐槽)。。
package Core {
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.TimerEvent;
import flash.system.System;
import flash.text.TextField;
import flash.ui.Keyboard;
import flash.utils.Timer;
import flash.utils.getTimer;
import flash.utils.setTimeout;
public class Tetris extends Sprite
{
/**
* 游戏每多少秒移动一次
*/
private var _gameSpeed:Number ;
/**
* 总分数
*/
private var _totalPoint:int;
/**分数的基数*/
private var _pointBase:Number;
/**当前消除的积分*/
private var _curPoint:int;
private var _totalPointLabel:TextField;
private var _cellDistance:Number;
private var _cellSize:Number;//边长
private var numRows:int;//行数
private var numCols:int;//列数
private var _sceneArr:Array;//场景(格子的世界)
/**网格偏移值*/
private var _netOffsetX:int;
/**网格偏移值*/
private var _netOffsetY:int;
/**正在下落的砖头数组*/
private var _movingBrickArr:Array;//砖头数组
private var brickX:int;//砖头的坐标(格子世界数组下标)
private var brickY:int;
private var downSpeed:int = 1;//向下移动速度
private var xSpeed:int = 1;
private var ticker:Timer;//计时器
private var moveType:String = "down"; //移动类型
private var canMove:Array = new Array(); //该方向上可否移动 数组索引012分别表示为左右下,
private var p_stage:Stage;
private var curNum:int;
public function Tetris(_stage:Stage)
{
p_stage = _stage;
_totalPointLabel = new TextField();
_totalPointLabel.x = 50;
_totalPointLabel.y = 10;
addChild(_totalPointLabel);
_cellDistance = 3;
init();
}
//初始化数据
private function init():void
{
_totalPoint = 0;
_pointBase = 100;
_cellSize = 30
_gameSpeed = 0.5;
//行值=舞台高/边长
numRows = 20//Math.floor(p_stage.stageHeight / side);
numCols = 10//Math.floor(p_stage.stageWidth / side);
var netWidth:int = numCols * (_cellSize + _cellDistance);
var netHeight:int = numRows * (_cellSize + _cellDistance);
_netOffsetX = p_stage.stageWidth - netWidth >> 1;
_netOffsetY = p_stage.stageHeight - netHeight >> 1;
//初始化世界
_sceneArr = new Array();
for (var i:int=0; i<numRows; i++)
{
_sceneArr[i] = [];
for (var j:int=0; j<numCols; j++)
{
_sceneArr[i][j] = 0;
}
}
p_stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);//监听按下
//创建计时器
ticker = new Timer(500);
// ticker.addEventListener(TimerEvent.TIMER, onTick);//用这个玩久了会出bug..
ticker.start();
this.addEventListener(Event.ENTER_FRAME,onTick);
createBrick();
initScene();
}
private function onTick(ev:Event):void {
//trace("D"+blankD+" U"+blankU+" L"+blankL+" R"+blankR);
if(curNum == p_stage.frameRate / (1 / _gameSpeed) )
{
curNum = 0;
checkHit("down");
moveBrick("down");
}
else
{
curNum ++;
}
}
//刷新场景
private function initScene():void
{
graphics.clear();
for (var i:int=0; i<numRows; i++)
{
for (var j:int=0; j<numCols; j++)
{
graphics.lineStyle(0,0,0);
if (_sceneArr[i][j] == 0)
{
graphics.beginFill(0xf8f8f8);
}
else if (_sceneArr[i][j] == 1)
{
graphics.beginFill(0x04B3D3);
}
else if (_sceneArr[i][j]==2)
{
graphics.beginFill(0x575657);
}
graphics.drawRoundRect(j*(_cellSize + _cellDistance) + _netOffsetX, i*(_cellDistance+_cellSize) + _netOffsetY, _cellSize, _cellSize,8,8);
}
graphics.endFill();
}
}
//创建砖块
private function createBrick():void {
//砖块数组
_movingBrickArr= new Array();
var randNum:Number = Math.random();
_movingBrickArr = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]];
if (randNum < 0.2) {
_movingBrickArr = [
[0,0,0,0],
[0,1,0,0],
[0,1,0,0],
[0,1,1,0]
];
} else if (randNum <0.4) {
_movingBrickArr = [
[0,0,0,0],
[0,1,1,0],
[0,1,1,0],
[0,0,0,0],
];
} else if (randNum <0.6) {
_movingBrickArr = [
[0,1,0,0],
[0,1,0,0],
[0,1,0,0],
[0,1,0,0]
];
} else if (randNum <0.7) {
_movingBrickArr = [
[0,0,0,0],
[0,1,0,0],
[1,1,1,0],
[0,0,0,0]
];
} else if (randNum<0.8) {
_movingBrickArr = [
[0,0,0,0],
[1,1,0,0],
[0,1,1,0],
[0,0,0,0],
];
} else {
_movingBrickArr = [
[0,0,0,0],
[0,1,1,0],
[1,1,0,0],
[0,0,0,0]
];
}
brickX = 5;
brickY = 0;
updateToScene();
}
//===================控制砖块移动模块=========================================================
//键盘按下控制方向
private function onKeyDown(ev:KeyboardEvent):void
{
switch (ev.keyCode)
{
case Keyboard.UP ://旋转
//trace(canRoll());
moveType = "roll";
break;
case Keyboard.DOWN :
moveType = "down";
break;
case Keyboard.LEFT :
moveType = "left";
break;
case Keyboard.RIGHT :
moveType = "right";
break;
default :
break;
}
checkHit(moveType);
moveBrick(moveType);
}
//移动砖块
private function moveBrick(moveType:String):void
{
//trace("canMove "+canMove);
switch (moveType)
{
case "roll" ://旋转整个砖块数组
if(canRoll())
{
_movingBrickArr = roll(_movingBrickArr);
for (var i:int=0; i<4; i++)
{
for (var j:int=0; j<4; j++)
{
_sceneArr[brickY + i][brickX + j] = _movingBrickArr[i][j];
}
}
}
break;
case "down" ://下
if (canMove[2] == 1)
{
clearBrick();
brickY += downSpeed;
//trace(getTimer());
updateToScene();
}
break;
case "left" ://左
if (canMove[0]==1)
{
clearBrick();
brickX-=downSpeed;
updateToScene();
}
break;
case "right" ://右
if (canMove[1]==1)
{
clearBrick();
brickX+=downSpeed;
updateToScene();
}
break;
default :
break;
}
initScene();
}
//砖块数组的里的 1 更新到场景里
private function updateToScene():void
{
//trace(blankD,blankR);
for (var i:int=blankU; i<4/*-blankD*/; i++)
{
for (var j:int=blankL; j<4/*-blankR*/; j++)
{
if (_movingBrickArr[i][j]==1)
{
_sceneArr[brickY+i][brickX+j]=_movingBrickArr[i][j];
//trace("brickY",brickY);
}
}
}
}
//清楚移动前的砖块
private function clearBrick():void
{
for (var i:int=blankU; i<4/*-blankD*/; i++)
{
for (var j:int=blankL; j<4/*-blankR*/; j++)
{
if (_movingBrickArr[i][j]==1)
{
_sceneArr[brickY+i][brickX+j]=0;
}
}
}
}
//旋转矩阵
private function roll(oldArr:Array):Array
{
var newArr:Array = new Array();
for (var i:int=0; i<4; i++)
{
newArr[i]=new Array(4);
for (var j:int=0; j<4; j++)
{
newArr[i][j]=oldArr[j][3-i];
}
}
return newArr;
}
//======================================检测模块===========================
//------------检测空白行数---------------------------
//检测砖块数组下方的空白行数
private function get blankD():int {
var blankD:int=0;
for (var i:int=3; i>1; i--) {
for (var j:int=0; j<4; j++) {
if (_movingBrickArr[i][j]==1) {
return blankD;
}
}
blankD++;
}
return blankD;
}
//检测砖块数组上方的空白行数
private function get blankU():int {
var blankU:int=0;
for (var i:int=0; i<4; i++) {
for (var j:int=0; j<4; j++) {
if (_movingBrickArr[i][j]==1) {
return blankU;
}
}
blankU++;
}
return blankU;
}
/**
* //检测砖块数组右方的空白行数
* @return
*
*/
private function get blankR():int {
var blankR:int=0;
for (var j:int=3; j>1; j--) {
for (var i:int=0; i<4; i++) {
if (_movingBrickArr[i][j]==1) {
return blankR;
}
}
blankR++;
}
return blankR;
}
//检测砖块数组左方的空白行数
private function get blankL():int {
var blankL:int=0;
for (var j:int=0; j<3; j++) {
for (var i:int=0; i<4; i++) {
if (_movingBrickArr[i][j]==1) {
return blankL;
}
}
blankL++;
}
return blankL;
}
//------------碰撞检测模块---------------------------
//碰撞检测
public function checkHit(moveType:String):void
{
canMove=[1,1,1];//先初始化1,全能移动。哪个方向检测到将碰撞,则该方向为0
for (var i:int=blankU; i<4-blankD; i++)
{
for (var j:int=blankL; j<4-blankR; j++)
{
if (_movingBrickArr[i][j]==1)
{//检测砖块里1的单元格附近的单元格
switch (moveType)
{
case "left" :
var hitL:Boolean=checkCell(brickY+i,brickX+j-1,"hitL");//左
break;
case "right" :
var hitR:Boolean=checkCell(brickY+i,brickX+j+1,"hitR");//右
break;
case "down" :
var hitD:Boolean=checkCell(brickY+i+1,brickX+j,"hitD");//下
break;
default :
break;
}
if (hitL)
{
canMove[0]=0;
}//左 只要砖块中有一个说左不能走,就不能走
if (hitR)
{
canMove[1]=0;
}//右
if (hitD)
{
canMove[2]=0;
}//下
}
}
}
}
//检测该单元格可否移动
private function checkCell(i:int,j:int,hitType:String):Boolean
{
switch (hitType)
{
case "hitL" :
if (j<0||_sceneArr[i][j]==null||_sceneArr[i][j]==2)
{
//trace("hitL");
return true;
}
return false;
break;
case "hitR" :
if (j>=numCols||_sceneArr[i][j]==null||_sceneArr[i][j]==2)
{
//trace("hitR");
return true;
}
return false;
break;
case "hitD" :
if (i>=numRows||_sceneArr[i][j]==null||_sceneArr[i][j]==2) {
//trace("hitD");
floor();
return true;
}
return false;
break;
default :
break;
}
return false;
}
//砖块着陆后的各种反应,玩过的懂的
private function floor():void
{
for (var i:int=blankU; i<4-blankD; i++)
{
for (var j:int=blankL; j<4-blankR; j++)
{
if (_movingBrickArr[i][j]==1)
{
_movingBrickArr[i][j]=2;
1;
_sceneArr[brickY+i][brickX+j]=_movingBrickArr[i][j];
}
}
}
checkLine(); //检测消行
createBrick(); //创建新的方块
checkLose(); //检测游戏结束
}
//---------------检测可否旋转----------------------
//检测砖块可否旋转
private function canRoll():Boolean
{
if(brickX<=0 || brickX+3 >=numCols || brickY+3 >= numRows || brickX <= 0) {//靠近边缘
return false;
}
for(var i:int=0; i<4; i++)
{
if(brickY+4 >= numRows || _sceneArr[brickY+4][brickX+i]==2){ //下 ps brickY+4 >= numRows || 增加了上下边缘的判断。
return false;
}
}
for(i=0; i<4; i++)
{
if(_sceneArr[brickY+i][brickX-1]==2){ //左
return false;
}
}
for(i=0; i<4; i++)
{
if(_sceneArr[brickY+i][brickX+4]==2){ //右
return false;
}
}
for(i=0; i<4; i++)
{
if(brickY <= 0 || _sceneArr[brickY-1][brickX+i]==2){ //上 ps brickY+4 >= numRows || 增加了上下边缘的判断。
return false;
}
}
return true;
}
//=====================游戏规则模块======================================================
//-------------------------消行-------------------------
//行检测,检测出哪些行要消
private function checkLine():void
{
var totalLine:int = 0;
_curPoint = 0;
for (var i:int=numRows-1; i>=0; i--)
{
var canClear:Boolean=true;
for (var j:int=0; j<numCols; j++)
{
if (_sceneArr[i][j]!=2) {
canClear=false; //这行只要有一个不是2,则不消,全是2才消行
}
}
if (canClear)
{
totalLine ++;
clearLine(i);
i++; //这个i++很必要,这行被消,上面那行下来,必须重新检测这行
}
}
_curPoint = totalLine * totalLine * _pointBase;
_totalPoint += _curPoint;
_totalPointLabel.text = "" + _totalPoint;
}
//得到该行,消之;上面的2都下降index行
private function clearLine(index:int):void
{
for (var k:int=0; k<numCols; k++)
{
_sceneArr[index][k]=0;
}
for (var i:int=index-1; i>=0; i--)
{
for (var j:int=0; j<numCols; j++)
{
if (_sceneArr[i][j]==2)
{
_sceneArr[i+1][j]=_sceneArr[i][j];
_sceneArr[i][j]=0;
}
}
}
}
//-------------------------游戏结束-------------------------
private function checkLose():void {
var isLost:Boolean = false;
for (var i:int=3; i>=0; i--) {
for (var j:int=0; j<numCols; j++) {
if (_sceneArr[i][j]==2) {
isLost = true;
}
}
}
if(isLost)
{
PhpCC.UpdateNewRank("testnew"+Math.round(Math.random()*100),_totalPoint);
init();
}
}
}
}
贴上 demo演示地址 (个人网站,还在优化中。欢迎吐槽)。。