Flash ActionScript2.0面向对象游戏开发
概述:
Flash ActionScript2.0是一种面向对向的编程语言,利用它可以开发出功能强大的应用程序.以早期的ActionScript 1.0相比,它在结构化编程上具有明显的优势,可以使程序具有更强的可移植性,可重性,和伸缩性.
本文通过一个推箱子游戏的开发过程来逐步讲述如何利用ActionScript2.0 进行开发.
结构分析:
在进行一个项目的开发前,项目规化是必不可少的.我们先来思考一下推箱子游戏包含哪些必要的元素呢?
- 一个玩家(Player)
- 至少一个箱子(Box)
- 和箱子数目一样的目标地(Target)
- 数目不定的砖块(Brick)
- 砖块连在一下组成了墙壁(Wall)
- 一个游戏管理者(Manager)
- 一些显示游戏信息的控件
我们都需要将这些元素抽象化为对象(Object),各个对象包含有各自特有的属性和方法.比如,玩家具有位置属性(currentPos),它表示玩家当全的位置,玩家还有move方法,它使玩家移到下一个位置.等腰三角形这些问题搞清楚了,我们就要进行具体的实现.
实现过程:
- 打开Flash,新建"动作脚本文件",依次建立如下.as文件,注意要把它们放在同一个目录下.源文件如下:
- //*********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;
}
} - //************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++;
}
}
}
}
} - //*************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;
}
} - //*************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;
}
}
}
}
- 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";
}
}
- 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];
}
}
//****************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;
}
}- 新建"Flash文档",命名为"push_box",并将它和以上脚本文件存在同一目录下.以下要做的就是建立要用到的电影剪辑,并将其和相应的脚本文件建立链接.
- 按"Ctrl+F8",新建一个电影剪辑,命名为"Player",在编辑状态下画一个长,宽都为40象素的小人(_stepSize=40),注意,小人的注册点放在左上脚.画完后在电影库中,右击"Player",选择"为动作脚下本导出",其它不选."标识符","As 2.0类"都为电影剪辑名"Player".要注意,大小写不能搞错,否则会出错.
- 按上述方法依次建立"Box","Target"剪辑.
- 按10建立名为"Brick"的剪辑,不过由于它不需要外部脚本文件,故"As 2.0"中不要添.
- 按10建立"Wall"剪辑,稍有不同的是,在编辑状态下,第一帧中加"stop()",第二帧中加入一个"Brick"剪辑.这样做是因为"Wall"在修建时需要用到"Brick".
- 按12建立"Manager"剪辑,不同的是需要点中“在第一帧导出”,而且第二帧加入的不是"Brick",而是"Wall","Player","Box","Target".
- 好了,一切就绪,我们可以测试一下了.在主时间轴上第一帧中中入语句:attachMovie("Manager","game1",_root.getNextHighestDepth()); game1.init(1);就可以运行第一关了.
- 至于如何建立友好的用户界面,我们只需稍花点力气就搞定了.
示例:
如果你还有任何不明白之处,可发邮件或QQ给我.xiake1860@ncepubj.edu.cn QQ:4077130