"FLASH游戏开发示例"学习:俄罗斯方块
在网上有很多俄罗斯方块的开源代码,作为一个AS的新手,俄罗斯方块也是有难度的,下面是我从这个例子中的一些粗见:
大家都知道,在玩俄罗斯方块时,是有随机产生的四格拼板随机变换在空的游戏区域垒起来的,然后消除一行行满的格子。
所以要考虑的就有(我是把tetrominoes称为四格拼板):
1.四格拼板有多少种类,每个种类有不同的变换方式。
2. 如何处理四格拼板到达棋盘底部:不能移动它,产生新的四格拼板;
3.如何处理四格拼板的碰撞:两个四格拼板间碰撞;
4.四格拼板的变形:该例子不是使用旋转;
5.移除掉形成一条线的格子:要把上面四格拼板落下,
6,游戏结束就是,四格拼板到顶。
这个游戏的设计充分的利用了数组,特别是四格拼板的类别,以及四格拼板的变形;
四格拼板应用4*4的数组,用0表示不填充任何颜色,用1表示填充颜色,如此,便可以更加容易的
表达出各种不同类似的四格拼板。
下面是完整的代码,我实在Flash Builder里面做的
package
{
import flash.display.*;
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.text.TextField;
import flash.utils.Timer;
[SWF(framerate = "30" ,backgroundColor = "0xFFFFFF" , width="400", height="490")]
public class Tetris extends Sprite
{
private const TS:uint = 24;//每格的大小
private var fieldArray : Array;
private var fieldSprite : Sprite;
//四个拼板
private var tetrominoes:Array = new Array();
private var colors:Array = new Array();
//放置第一个四个拼板
private var tetromino:Sprite;
private var currentTetromino:uint;//代表游戏中的七种四个拼板
private var currentRotation:uint;//代表每种四个拼板的变换形式
private var tRow:int;// 可以等于-1,为了把某些一开始位置不在顶部的四格拼板放置在顶部 四格拼板在游戏区域的水平
private var tCol:int;// 垂直位置
//间隔时间自动向下
private var timeCount:Timer = new Timer(500);
//游戏状态
private var gameOver:Boolean = false;
//显示下一个四个拼版
private var nextTetromino:uint;
private var playAgainBtn:Sprite;
public function Tetris()
{
startTetrisGame();
//timeCount.addEventListener(TimerEvent.TIMER,onTime);
//timeCount.start();
}
//开始游戏
private function startTetrisGame():void{
generateField();
initTetrominoes();
nextTetromino = Math.floor(Math.random()*7);
generateTetromino();
stage.addEventListener(KeyboardEvent.KEY_DOWN,onKDown);
}
//及时间隔
private function onTime(e:TimerEvent):void{
if(canFit(tRow+1,tCol,currentRotation)){
tRow++;
placeTetromino();
}else{
landTetromino();
generateTetromino();
}
}
private function drawNext():void{
if(getChildByName("next")!=null){
removeChild(getChildByName("next"));
}
var next_t:Sprite = new Sprite();
next_t.x = 300;
next_t.name = "next";
addChild(next_t);
next_t.graphics.lineStyle(0,0x000000);
for(var i:int=0;i<tetrominoes[nextTetromino][0].length;i++){
for(var j:int=0;j<tetrominoes[nextTetromino][0][i].length;j++){
if(tetrominoes[nextTetromino][0][i][j] == 1){
next_t.graphics.beginFill(colors[nextTetromino]);
next_t.graphics.drawRect(TS*j,TS*i,TS,TS);
next_t.graphics.endFill();
}
}
}
}
private function generateField():void{
//画上好的游戏背景
var color:Array= new Array("0x444444","0x555555");
//建立游戏背景格子 20*10
fieldArray = new Array();
fieldSprite = new Sprite();
addChild(fieldSprite);
fieldSprite.graphics.lineStyle(0,0x000000);
for(var i:uint=0;i<20;i++){
fieldArray[i] = new Array();
for(var j:uint=0;j<10;j++){
fieldArray[i][j] = 0;
//fieldSprite.graphics.beginFill(0x444444);//单一颜色
fieldSprite.graphics.beginFill(color[(j%2+i%2)%2]);
//按模计算画棋盘
fieldSprite.graphics.drawRect(TS*j,TS*i,TS,TS);
fieldSprite.graphics.endFill();
}
}
}
//四个拼版
private function initTetrominoes():void{
//I 0代表没颜色,1代表有颜色,两行说明 条状的拼板有横竖两种类型
tetrominoes[0] = [[[0,0,0,0],[1,1,1,1],[0,0,0,0],[0,0,0,0]],
[[0,1,0,0],[0,1,0,0],[0,1,0,0],[0,1,0,0]]];
colors[0] = 0x00ffff;
//T 四种旋转模式
tetrominoes[1] = [[[0,0,0,0],[1,1,1,0],[0,1,0,0],[0,0,0,0]],
[[0,1,0,0],[1,1,0,0],[0,1,0,0],[0,0,0,0]],
[[0,1,0,0],[1,1,1,0],[0,0,0,0],[0,0,0,0]],
[[0,1,0,0],[0,1,1,0],[0,1,0,0],[0,0,0,0]]];
colors[1] = 0xAA00FF;
//L
tetrominoes[2] = [[[0,0,0,0],[1,1,1,0],[1,0,0,0],[0,0,0,0]],
[[1,1,0,0],[0,1,0,0],[0,1,0,0],[0,0,0,0]],
[[0,0,1,0],[1,1,1,0],[0,0,0,0],[0,0,0,0]],
[[0,1,0,0],[0,1,0,0],[0,1,1,0],[0,0,0,0]]];
colors[2] = 0xFFA500;
// J
tetrominoes[3]=[[[1,0,0,0],[1,1,1,0],[0,0,0,0],[0,0,0,0]],
[[0,1,1,0],[0,1,0,0],[0,1,0,0],[0,0,0,0]],
[[0,0,0,0],[1,1,1,0],[0,0,1,0],[0,0,0,0]],
[[0,1,0,0],[0,1,0,0],[1,1,0,0],[0,0,0,0]]];
colors[3]=0x0000FF;
//z
tetrominoes[4] = [[[0,0,0,0],[1,1,0,0],[0,1,1,0],[0,0,0,0]],
[[0,0,1,0],[0,1,1,0],[0,1,0,0],[0,0,0,0]]];
colors[4] = 0xFF0000;
//s
tetrominoes[5] = [[[0,0,0,0],[0,1,1,0],[1,1,0,0],[0,0,0,0]],
[[0,1,0,0],[0,1,1,0],[0,0,1,0],[0,0,0,0]]];
colors[5] = 0x00FF00;
//o
tetrominoes[6] = [[[0,1,1,0],[0,1,1,0],[0,0,0,0],[0,0,0,0]]];
colors[6] = 0xFFFF00;
}
private function generateTetromino():void{
if(! gameOver){
currentTetromino = nextTetromino;
nextTetromino = Math.floor(Math.random()*7);
drawNext();
currentTetromino = Math.floor(Math.random()*7);
//随机获取任意一种四格拼板 即(0-6 )七个数字
currentRotation = 0;
tRow = 0;//在顶部
if(tetrominoes[currentTetromino][0][0].indexOf(1) == -1){
tRow = -1;
}
tCol = 3;//第三行
drawTetromino();//根据获取的四格拼板类型进行绘制
}
if(canFit(tRow,tCol,currentRotation)){
timeCount.addEventListener(TimerEvent.TIMER,onTime);
timeCount.start();
}else{
gameOver = true;
playAgainTetris();
}
}
private function playAgainTetris():void{
playAgainBtn = new Sprite();
playAgainBtn.graphics.beginFill(0x00ffff);
playAgainBtn.graphics.drawRect(100,200,100,30);
playAgainBtn.graphics.endFill();
addChild(playAgainBtn);
var playAgainText:TextField = new TextField();
playAgainText.text = "再玩一次";
playAgainBtn.addChild(playAgainText);
playAgainText.x = 130;
playAgainText.y = 205;
playAgainBtn.addEventListener(MouseEvent.CLICK,playAgainHandler);
playAgainBtn.buttonMode = true;
}
private function playAgainHandler(e:MouseEvent):void{
removeChild(playAgainBtn);
gameOver = false;
startTetrisGame();
}
private function drawTetromino():void{
var ct:uint = currentTetromino;
tetromino = new Sprite();
addChild(tetromino);
tetromino.graphics.lineStyle(0,0x000000);
for(var i: int = 0;i<tetrominoes[ct][currentRotation].length;i++){
//tetrominoes[ct] 最大为四,最小为一
//tetrominoes[ct][currentRotation] 每一个有四行
for(var j:int = 0;j<tetrominoes[ct][currentRotation][i].length;j++){
//每行有四个,都要遍历一遍,查询每一行中得每个数值
if(tetrominoes[ct][currentRotation][i][j] == 1){
//如果值为1,填色
tetromino.graphics.beginFill(colors[ct]);
tetromino.graphics.drawRect(TS*j,TS*i,TS,TS);
}
}
}
placeTetromino();
}
//摆放的位置
private function placeTetromino():void{
tetromino.x = tCol * TS;
tetromino.y = tRow * TS;
}
private function onKDown(e:KeyboardEvent):void{
//trace("go");
if(!gameOver){
switch(e.keyCode){
case 37 :
if(canFit(tRow,tCol-1,currentRotation)){
//为true是执行
tCol--;
placeTetromino();
}
break;
//变形处理
case 38:
var ct:uint = currentRotation;
//rot取决与【currentTetromino】
var rot:uint = (ct+1)%tetrominoes[currentTetromino].length;
if(canFit(tRow,tCol,rot)){
currentRotation = rot;
removeChild(tetromino);
drawTetromino();
placeTetromino();
}
break;
case 39:
if(canFit(tRow,tCol+1,currentRotation)){
tCol++;
placeTetromino();
}
break;
case 40:
if(canFit(tRow+1,tCol,currentRotation)){
tRow++;
placeTetromino();
}else{
landTetromino();
generateTetromino();
}
break;
}
}
}
//检测两个四格拼板的碰撞情况,以及不超出游戏区域
private function canFit(row:int,col:int,side:uint):Boolean{
var ct:uint = currentTetromino;
for(var i:int=0;i<tetrominoes[ct][side].length;i++){
for(var j:int=0;j<tetrominoes[ct][side][i].length;j++){
if(tetrominoes[ct][side][i][j] == 1){
//超过左边边界
if(col+j<0){
return false;
}
//超过右边边界
if(col+j>9){
return false;
}
//超出底部
if(row+i>19){
return false;
}
//解决碰撞
//到了另一个四个拼版
if(fieldArray[row+i][col+j] == 1){
return false;
}
}
}
}
return true;
}
//着落
private function landTetromino():void{
var ct:uint = currentTetromino;
var landed:Sprite;
for(var i:int=0;i<tetrominoes[ct][currentRotation].length;i++){
for(var j:int=0;j<tetrominoes[ct][currentRotation][i].length;j++){
if(tetrominoes[ct][currentRotation][i][j] == 1){
landed = new Sprite();
addChild(landed);
landed.graphics.lineStyle(0,0x000000);
landed.graphics.beginFill(colors[currentTetromino]);
landed.graphics.drawRect(TS*(tCol+j),TS*(tRow+i),TS,TS);
landed.graphics.endFill();
landed.name = "r"+(tRow+i)+"c"+(tCol+j);
fieldArray[tRow+i][tCol+j] = 1;
}
}
}
removeChild(tetromino);
timeCount.removeEventListener(TimerEvent.TIMER,onTime);
timeCount.stop();
checkForLines();
}
//检测是否形成一条线
private function checkForLines():void{
for(var i:int=0;i<20;i++){
if(fieldArray[i].indexOf(0) == -1){
for(var j:int=0;j<10;j++){
fieldArray[i][j] = 0;
removeChild(getChildByName("r"+i+"c"+j));
}
//*****************************************
for(j=i;j>=0;j--){
for(var k:int=0;k<10;k++){
if(fieldArray[j][k] == 1){
fieldArray[j][k] = 0;
fieldArray[j+1][k] =1;
getChildByName("r"+j+"c"+k).y += TS;
getChildByName("r"+j+"c"+k).name = "r"+(j+1)+"c"+k;
}
}
}
}
}
}
}
}
注:第一次写这种日志,请见谅。。。。。
Clience
浙公网安备 33010602011771号