[转]Flash ActionScript2.0面向对象游戏开发-推箱子

时间:2023-03-09 04:31:07
[转]Flash ActionScript2.0面向对象游戏开发-推箱子

本文转自:http://www.alixixi.com/Dev/W3C/Flash/2007/2007070868666.html

概述:

Flash ActionScript2.0是一种面向对向的编程语言,利用它可以开发出功能强大的应用程序.以早期的ActionScript 1.0相比,它在结构化编程上具有明显的优势,可以使程序具有更强的可移植性,可重性,和伸缩性.

本文通过一个推箱子游戏的开发过程来逐步讲述如何利用ActionScript2.0 进行开发.

结构分析:

在进行一个项目的开发前,项目规化是必不可少的.我们先来思考一下推箱子游戏包含哪些必要的元素呢?

  • 一个玩家(Player)
  • 至少一个箱子(Box)
  • 和箱子数目一样的目标地(Target)
  • 数目不定的砖块(Brick)
  • 砖块连在一下组成了墙壁(Wall)
  • 一个游戏管理者(Manager)
  • 一些显示游戏信息的控件

我们都需要将这些元素抽象化为对象(Object),各个对象包含有各自特有的属性和方法.比如,玩家具有位置属性(currentPos),它表示玩家当全的位置,玩家还有move方法,它使玩家移到下一个位置.等腰三角形这些问题搞清楚了,我们就要进行具体的实现.

实现过程:

  1. 打开Flash,新建"动作脚本文件",依次建立如下.as文件,注意要把它们放在同一个目录下.源文件如下:
  2. //*********Pos.as********* //用来表示游戏中物体位置的类 //游戏中所有对象的位置都为此类的实例 //用col,row 两个量确定物体的位置 class Pos { var col:Number;// 列值 var row:Number;// 行值
    //构造函数 function Pos(c, r) { col = c; row = r; }
    //判断两个位置是否重合 function equals(t):Boolean { return (col == t.col && row == t.row); }
    //根据方向值,取得此位置的下一个位置 function getNextPos(d):Pos{ var nextPos:Pos; nextPos=new Pos(col,row); switch (d) { case 0 : nextPos.col++;
    break; case 1 : nextPos.row++; break; case 2 : nextPos.col--; break; case 3 : nextPos.row--; break; } return nextPos; } }
  3. //************Wall.as************ //用来构建游戏中的墙壁 class Wall extends MovieClip { var brickMatrix:Array;//表示墙壁形状的数组 var left:Number;//左偏移量 var top:Number;//上偏移量 var bricks:Array;//用来存放砖块电影剪辑的数组 var _stepSize:Number;//每块砖的偏移量
    //构造函数 function Wall() { left = 0; top = 0; _stepSize = 40;
    }
    //设置墙壁形状数组 function setMatrix(b) {
    bricks = new Array(); brickMatrix = b; }
    //按照墙壁形状数组修墙 function build():Void { var index = 0; for (var i = 0; i<brickMatrix.length; i++) { for (var j = 0; j<brickMatrix[0].length; j++) { if (brickMatrix[i][j] == 1) { //数组值为1,画一块砖 bricks[index] = attachMovie("Brick", "bricks"+index, this.getNextHighestDepth()); bricks[index]._x = left+j*_stepSize; bricks[index]._y = top+i*_stepSize; index++; } } } } }
  4. //*************Target.as***************** class Target extends MovieClip{ var pos:Pos; var finished:Boolean; var left:Number; var top:Number; var _stepSize:Number; function Target(){ finished=false; left=0; top=0; _stepSize=40;
    } function setPos(p){ pos=p; this._x=left+pos.col*_stepSize; this._y=top+pos.row*_stepSize; } }
  5. //*************Player.as************** //游戏中的player class Player extends MovieClip {

    var _stepSize:Number;//步长 var _wall:MovieClip;//墙壁电影剪彩辑 var startPos:Pos;//初始置 var currentPos:Pos;//当前位置 var left:Number;//左边距 var top:Number;//上边距 var dir:Number;//移动方向 var boxes:Array; var player_path_stack:Array;//玩家移动的路线 var boxes_path_stack:Array;//箱子移动的路线
    //构造函数,初始化 function Player() { _stepSize = 40; currentPos = null; left = 0; top = 0; dir = 0; player_path_stack=new Array(); boxes_path_stack=new Array();
    boxes = new Array(); }
    //设置玩家的起始位置 function setStartPos(p) { startPos = new Pos(p.col, p.row); currentPos = startPos; this._x = currentPos.col*_stepSize+left; this._y = currentPos.row*_stepSize+top;

    }
    //为玩家指定一个wall实例 function setWall(w) { _wall = w; }
    //为玩家指定一个boxes数组,存有所有的箱子实例 function setBoxes(b) { boxes = b; }
    //通过按键控制玩家 function setKeyHandle() { this.onKeyDown = function() {
    if (Key.isDown(Key.LEFT)) { dir = 2;//左键
    } else if (Key.isDown(Key.RIGHT)) { dir = 0;//右键
    } else if (Key.isDown(Key.UP)) { dir = 3;//上键
    } else if (Key.isDown(Key.DOWN)) { dir = 1;//下键
    } var nextObject = this.getNextObject(); //取得玩家下一个位置上的物体
    if (nextObject == "BOX") { //玩家下一个位置上是个箱子 var box_pushed = getPushedBox();//取得此位置上的这个箱子
    //被推到的箱子存在 if (box_pushed) {
    if (box_pushed.getNextObject() == "NOTHING") {//被推箱子的下个位置没有障碍
    boxes_path_stack.push({box:box_pushed,pos:new Pos(box_pushed.pos.col,box_pushed.pos.row)}); box_pushed.move();//被推箱子移一步 this.move();//玩家移一步
    }
    }
    } else if (nextObject == "NOTHING") {//玩家的下个位置玩障碍 this.move(); boxes_path_stack.push(null); }
    }; Key.addListener(this); //监听按键输入 }

    //取得被推到的箱子 function getPushedBox() { var nextPos:Pos; nextPos =currentPos.getNextPos(dir);
    for (var i = 0; i<boxes.length; i++) { if (boxes[i].pos.equals(nextPos)) { return boxes[i]; break; //trace(box_pushed); } } return null; }
    //取得玩家下个位置上的物块类型( 墙壁, 箱子, 无障碍) function getNextObject():String { //var obj:String; var nextPos:Pos; nextPos = currentPos.getNextPos(dir);
    if (_wall.brickMatrix[nextPos.row][nextPos.col] == 1) { return "WALL"; } for (var i = 0; i<boxes.length; i++) { if (boxes[i].pos.equals(nextPos)) { return "BOX"; } } return "NOTHING"; }
    //移到下个位置 function move() { player_path_stack.push(currentPos);
    var c=currentPos.getNextPos(dir); currentPos=c; this._x = left+this.currentPos.col*_stepSize; this._y = top+this.currentPos.row*_stepSize;
    }
    //返回上一步 function reback(){ if(player_path_stack.length>0){ var pre=player_path_stack.pop(); currentPos=pre; this._x = left+this.currentPos.col*_stepSize; this._y = top+this.currentPos.row*_stepSize; } if(boxes_path_stack.length>0 ){ var obj=boxes_path_stack.pop(); if(obj!=null){ var box=obj.box; var pos=obj.pos; box.pos=pos; box._x=box.left+box.pos.col*box._stepSize; box._y=box.top+box.pos.row*box._stepSize; } } } }

  6. class Box extends MovieClip { var pos:Pos; var left:Number; var top:Number; var _wall:MovieClip; var player:MovieClip; var _stepSize:Number; var _targets:Array; var finished:Boolean;//此箱子是否到达目标地
    function Box() { left = 0; top = 0; finished = false; _stepSize = 40; }
    //设置目标地 function setTargets(t) { _targets = new Array(); _targets = t; }
    //设置箱子的起始位置若罔闻 function setStartPos(p) { pos = new Pos(p.col, p.row); this._x = pos.col*_stepSize+left; this._y = pos.row*_stepSize+top; }
    //移到下一个位置 function move() { var c = pos.getNextPos(player.dir); pos = c; this._x = left+pos.col*_stepSize; this._y = top+pos.row*_stepSize; gotTarget(); }
    //是否到达目标地 function gotTarget() { for (var i = 0; i<_targets.length; i++) { if (this.pos.equals(_targets[i].pos)) { if (this.getDepth()>_targets[i].getDepth()) { this.swapDepths(_targets[i]); } this.finished = true; return; } } this.finished = false; }
    //取得一下个位置上物体的类型 function getNextObject():String { //var obj:String; var nextPos:Pos; nextPos = pos.getNextPos(player.dir); if (_wall.brickMatrix[nextPos.row][nextPos.col] == 1) { return "WALL"; } for (var i = 0; i<player.boxes.length; i++) { if (player.boxes[i].pos.equals(nextPos)) { return "BOX"; } } return "NOTHING"; } }
  7. class Matrix{ //用来存放游戏各关中初始界面 static var matrixs:Array;
    function Matrix(){ matrixs=new Array(); //0:null //1:wall //2:player //3:box //4:target //5:target and box //1 2 3 4 5 6 7 8 9 matrixs[0]= [[0, 0, 0, 0, 0, 0, 0, 0, 0],//1 [0, 0, 0, 0, 0, 0, 0, 0, 0],//2 [0, 0, 0, 0, 0, 0, 0, 0, 0],//3 [0, 0, 0, 0, 0, 0, 0, 0, 0],//4 [0, 0, 0, 0, 0, 0, 0, 0, 0],//5 [0, 0, 0, 0, 0, 0, 0, 0, 0],//6 [0, 0, 0, 0, 0, 0, 0, 0, 0],//7 [0, 0, 0, 0, 0, 0, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ];
    //1 2 3 4 5 6 7 8 9 matrixs[1]= [[0, 1, 1, 1, 1, 1, 1, 0, 0],//1 [1, 1, 1, 0, 0, 0, 1, 0, 0],//2 [1, 0, 3, 0, 1, 0, 1, 1, 0],//3 [1, 0, 1, 0, 0, 4, 0, 1, 0],//4 [1, 0, 0, 0, 0, 1, 0, 1, 0],//5 [1, 1, 0, 1, 0, 0, 0, 1, 0],//6 [0, 1, 2, 0, 0, 1, 1, 1, 0],//7 [0, 1, 1, 1, 1, 1, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[2]= [[0, 0, 1, 1, 1, 1, 1, 0, 0],//1 [1, 1, 1, 0, 0, 0, 1, 0, 0],//2 [1, 0, 3, 0, 1, 0, 1, 1, 0],//3 [1, 0, 1, 0, 0, 4, 0, 1, 0],//4 [1, 0, 0, 0, 0, 1, 0, 1, 0],//5 [1, 1, 3, 1, 4, 0, 0, 1, 0],//6 [0, 1, 2, 0, 0, 1, 1, 1, 0],//7 [0, 1, 1, 1, 1, 1, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ];

    //1 2 3 4 5 6 7 8 9 matrixs[3]= [[1, 1, 1, 1, 1, 1, 1, 1, 0],//1 [1, 0, 0, 0, 1, 0, 0, 1, 0],//2 [1, 0, 0, 0, 0, 0, 0, 1, 0],//3 [1, 1, 3, 1, 1, 0, 0, 1, 0],//4 [0, 1, 0, 4, 1, 0, 1, 1, 1],//5 [0, 1, 0, 0, 0, 0, 2, 0, 1],//6 [0, 1, 0, 0, 1, 0, 0, 0, 1],//7 [0, 1, 1, 1, 1, 1, 1, 1, 1],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ];

    //1 2 3 4 5 6 7 8 9 matrixs[4]= [[1, 1, 1, 1, 1, 1, 1, 1, 0],//1 [1, 0, 0, 0, 1, 0, 0, 1, 0],//2 [1, 0, 0, 0, 0, 0, 0, 1, 0],//3 [1, 1, 5, 1, 1, 0, 0, 1, 0],//4 [0, 1, 0, 4, 1, 0, 1, 1, 1],//5 [0, 1, 0, 5, 0, 3, 2, 0, 1],//6 [0, 1, 0, 0, 1, 0, 0, 0, 1],//7 [0, 1, 1, 1, 1, 1, 1, 1, 1],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[5]= [[0, 0, 1, 1, 1, 1, 0, 0, 0],//1 [0, 1, 1, 0, 0, 1, 1, 1, 1],//2 [1, 1, 0, 0, 0, 0, 0, 0, 1],//3 [1, 0, 3, 0, 1, 2, 1, 0, 1],//4 [1, 0, 1, 0, 4, 0, 0, 0, 1],//5 [1, 0, 0, 3, 0, 1, 1, 1, 1],//6 [1, 1, 1, 0, 4, 1, 0, 0, 0],//7 [0, 0, 1, 1, 1, 1, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[6]= [[0, 0, 1, 1, 1, 1, 0, 0, 0],//1 [0, 1, 1, 0, 0, 1, 1, 1, 1],//2 [1, 1, 0, 0, 3, 0, 0, 0, 1],//3 [1, 0, 3, 0, 1, 2, 1, 0, 1],//4 [1, 0, 1, 0, 4, 0, 0, 0, 1],//5 [1, 0, 4, 3, 0, 1, 1, 1, 1],//6 [1, 1, 1, 0, 4, 1, 0, 0, 0],//7 [0, 0, 1, 1, 1, 1, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[7]= [[0, 1, 1, 1, 1, 1, 0, 0, 0],//1 [0, 1, 0, 0, 0, 1, 0, 0, 0],//2 [1, 1, 3, 1, 0, 1, 1, 1, 0],//3 [1, 0, 0, 0, 3, 2, 0, 1, 0],//4 [1, 0, 1, 0, 0, 1, 0, 1, 0],//5 [1, 0, 1, 4, 0, 4, 0, 1, 0],//6 [1, 0, 0, 0, 1, 1, 1, 1, 0],//7 [1, 1, 1, 1, 1, 0, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[8]= [[0, 1, 1, 1, 1, 1, 0, 0, 0],//1 [0, 1, 0, 0, 0, 1, 0, 0, 0],//2 [1, 1, 3, 1, 0, 1, 1, 1, 0],//3 [1, 0, 0, 4, 3, 2, 0, 1, 0],//4 [1, 0, 1, 0, 0, 1, 0, 1, 0],//5 [1, 0, 1, 4, 4, 3, 0, 1, 0],//6 [1, 0, 0, 0, 1, 1, 1, 1, 0],//7 [1, 1, 1, 1, 1, 0, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[9]= [[0, 1, 1, 1, 1, 1, 1, 1, 0],//1 [0, 1, 0, 2, 4, 4, 4, 1, 0],//2 [0, 1, 0, 0, 0, 1, 1, 1, 1],//3 [1, 1, 1, 3, 0, 0, 0, 0, 1],//4 [1, 0, 0, 0, 1, 3, 1, 0, 1],//5 [1, 0, 3, 0, 1, 0, 0, 0, 1],//6 [1, 0, 0, 0, 1, 1, 1, 1, 1],//7 [1, 1, 1, 1, 1, 0, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; //1 2 3 4 5 6 7 8 9 matrixs[10]= [[0, 0, 1, 1, 1, 1, 0, 0, 0],//1 [0, 0, 1, 0, 0, 1, 0, 0, 0],//2 [0, 0, 1, 0, 0, 1, 0, 0, 0],//3 [0, 0, 1, 0, 0, 1, 1, 1, 0],//4 [0, 0, 1, 4, 3, 3, 2, 1, 0],//5 [0, 0, 1, 0, 0, 4, 0, 1, 0],//6 [0, 0, 1, 0, 0, 1, 1, 1, 0],//7 [0, 0, 1, 1, 1, 1, 0, 0, 0],//8 [0, 0, 0, 0, 0, 0, 0, 0, 0] //9 ]; }

    function getMatrix(d){ return matrixs[d]; }
    }

  8. //****************Manager.as************* //用来管理游戏 //所有的对象都入其中 //MovieClip类的子类 class Manager extends MovieClip { var wall:MovieClip; var player:MovieClip; var boxes:Array; var targets:Array; var stageNum:Number;//游戏的当前关数
    function Manager() { _x=50; _y=50; }
    //游戏初始化 function init(s) { stageNum = s;
    boxes = new Array(); targets = new Array();
    var brickMatrixT = new Matrix().getMatrix(stageNum);//根据关数从矩阵类中取得相应的矩阵
    //修墙 wall = attachMovie("Wall", "wall", this.getNextHighestDepth()); wall.setMatrix(brickMatrixT); wall.build();
    //创建一个玩家 player = attachMovie("Player", "plyaer", this.getNextHighestDepth()); player.setWall(wall); player.setKeyHandle();//监听键盘输入
    for (var i = 0; i<brickMatrixT.length; i++) { for (var j = 0; j<brickMatrixT[0].length; j++) { if (brickMatrixT[i][j] == 2) { player.setStartPos(new Pos(j, i)); } if (brickMatrixT[i][j] == 3) { var d = this.getNextHighestDepth(); var box = attachMovie("Box", "box"+i+j, d); box.setStartPos(new Pos(j, i)); box.player = player; box._wall = wall; boxes.push(box); } if (brickMatrixT[i][j] == 4) { var d = this.getNextHighestDepth(); var t = attachMovie("Target", "target"+i+j, d); t.setPos(new Pos(j, i)); targets.push(t); } if (brickMatrixT[i][j] == 5) { var d = this.getNextHighestDepth(); var box = attachMovie("Box", "box"+i+j, d); box.setStartPos(new Pos(j, i)); box.player = player; box._wall = wall; box.finished = true; boxes.push(box); var d1 = this.getNextHighestDepth(); var t = attachMovie("Target", "target"+i+j, d1); t.setPos(new Pos(j, i)); targets.push(t); } } }
    for (var i = 0; i<boxes.length; i++) { boxes[i].setTargets(targets); }
    player.setBoxes(boxes); player.swapDepths(this.getNextHighestDepth()); } //判断游戏是否结束 function ifWin() { var win = true; for (var i = 0; i<boxes.length; i++) { win = boxes[i].finished && win; }
    return win; } }
  9. 新建"Flash文档",命名为"push_box",并将它和以上脚本文件存在同一目录下.以下要做的就是建立要用到的电影剪辑,并将其和相应的脚本文件建立链接.
  10. 按"Ctrl+F8",新建一个电影剪辑,命名为"Player",在编辑状态下画一个长,宽都为40象素的小人(_stepSize=40),注意,小人的注册点放在左上脚.画完后在电影库中,右击"Player",选择"为动作脚下本导出",其它不选."标识符","As 2.0类"都为电影剪辑名"Player".要注意,大小写不能搞错,否则会出错.
  11. 按上述方法依次建立"Box","Target"剪辑.
  12. 按10建立名为"Brick"的剪辑,不过由于它不需要外部脚本文件,故"As 2.0"中不要添.
  13. 按10建立"Wall"剪辑,稍有不同的是,在编辑状态下,第一帧中加"stop()",第二帧中加入一个"Brick"剪辑.这样做是因为"Wall"在修建时需要用到"Brick".
  14. 按12建立"Manager"剪辑,不同的是需要点中“在第一帧导出”,而且第二帧加入的不是"Brick",而是"Wall","Player","Box","Target".
  15. 好了,一切就绪,我们可以测试一下了.在主时间轴上第一帧中中入语句:attachMovie("Manager","game1",_root.getNextHighestDepth()); game1.init(1);就可以运行第一关了.
  16. 至于如何建立友好的用户界面,我们只需稍花点力气就搞定了.

  示例:

点击这里下载源文件

  如果你还有任何不明白之处,可发邮件或QQ给我.xiake1860@ncepubj.edu.cn