浮动区块
首先来讲一个小故事,关于浮动的方块的故事。或许你已经听说过了“移动平台”这个名字,不要迷惑,他们是一样的东西,一样有趣。
很久很久以前,在区块游戏的世界里,住者一个年轻的方块。他是一个快乐的方块。有一天,他遇到了一个英雄。英雄问他:“年轻人,为什么你不会浮动呢?”
“我不知道怎么移动……” 小方块说道。
“那真遗憾,”英雄说道,“我想要站在你上面,去以前够不到的地方。”
那一天之后,小方块就不再像以前一样开心了。
其实我们可以帮助他浮动的,看:
在我们开工写代码之前,我们还是先来考虑一下规则。
我们应该做什么?如何做?
* 浮动方块应该是云(cloud)类型的方块 (云) * 方块可以横向或纵向移动 * 英雄可以从上方落到上面 * 当英雄站到上面以后,他会随着方块运动 * 方块上的英雄不能穿过障碍物
踏上浮动的方块
英雄怎么站到运动方块上?第一个也是最简单的一个方法就是跳上去。
在上图中,英雄正处于跌落的过程中,下一步他将会碰到运动方块。我们将会把他放置到方块上去。注意,英雄必须是在运动方块的上方,而且必须是往下运动,否则他就无法站到上面。
但是,这并不是英雄上去的唯一途径。下图中,英雄站在障碍物上,没有移动。
但是方块是移动的,而且接下来就会接触到英雄,若不做任何处理,英雄就会“陷”到方块里面。所以,我们要做的就是让方块带者英雄一起往上移动。
离开运动的方块
一旦我们的英雄可以站到方块上,我们还要保证他能够以某种方式离开。首先,他可以跳开。它可以走到方块的边缘。下图画出了许多可能的情形:
党英雄站在竖直移动的方块上,而且上方有个障碍物时,他应该掉下来,否则就会被压扁。党方块水平移动,党英雄碰到障碍物,他应该被贴着障碍物放置;如果方块移开的话,英雄就会掉下去。
上图中,英雄随着方块往下移动,党他碰到障碍物的时候,他不再随着方块移动,而是停在障碍物上。而方块则继续往下移动。
准备工作
画出移动方块的影片剪辑。你可以做很多种类的移动方块,把他们放在 movingtiles 影片剪辑的不同帧,然后将剪辑连接为movingtiles
定义 movingtiles 对象:
game.MovingTilep1= function () {}; game.MovingTilep1.prototype.speed=2; game.MovingTilep1.prototype.dirx=0; game.MovingTilep1.prototype.diry=1; game.MovingTilep1.prototype.miny= 0; game.MovingTilep1.prototype.maxy=2; game.MovingTilep1.prototype.width=game.tileW/2; game.MovingTilep1.prototype.height=game.tileH/2; game.MovingTilep2= function () {}; game.MovingTilep2.prototype.speed=2; game.MovingTilep2.prototype.dirx=1; game.MovingTilep2.prototype.diry=0; game.MovingTilep2.prototype.minx= -2; game.MovingTilep2.prototype.maxx=2; game.MovingTilep2.prototype.width=game.tileW/2; game.MovingTilep2.prototype.height=game.tileH/2;
我们有两种类型的可移动方块: MovingTilep1可以竖直移动(它的diry属性为非0数值),MovingTilep2可以水平移动(它的dirx值非0)。speed属性,你一定猜到了,代表方块一次移动的像素距离。
miny/maxy/minx/maxx 属性设置了方块运动的边界。我们当然可以把边界坐标设置成绝对的数值范围,但是如果需要把方块放到别的地方的话,就要改动边界的范围了。而在这里,我们用的是相对于方块起始位置的数值。这样我们可以把方块放在任意的位置,而不用修改边界范围。需要注意的是,移动的方块不会检测碰撞,所以你应该确保他们运动时不撞到障碍物。或者你也可以允许他们穿过障碍物。你在做游戏,你就是上帝。
来看一个例子。方块起始的位置是(x=2,y=5),竖直运动,miny=-1,maxy=4。它会怎么运动呢?起始位置-miny=5+(-1)=4,所以最小可以到达的位置是(x=2,y=4),最大可以到达的位置是(x=2,y=9)。
方块起始位置的数组和敌人起始位置的数组类似:
//浮动方块数组 [方块类型, x位置, y位置] myMovingTiles = [ [0], [[1, 4, 2]], [[2, 4, 4]] ];
在地图1中,我们定义了一个浮动方块,它的类型编号是1(从MovingTile1模版创建),起始位置是(x=4,y=2)。地图2中同样有1个浮动方块。你也可以在一个地图中放置多个浮动方块。
接下来是要在buildMap函数中添加浮动方块的生成代码。在创建敌人部分后面加入:
game.movingtiles = myMovingTiles[game.currentMap]; for (var i = 0; i<game.movingtiles.length; ++i) { var name = "movingtile"+i; game[name]= new game["MovingTilep"+game.movingtiles[i][0]]; game.clip.attachMovie("movingtiles", name, 12001+i); game[name].clip=game.clip[name]; game[name].clip.gotoAndStop(game.movingtiles[i][0]); game[name].xtile = game.movingtiles[i][1]; game[name].ytile = game.movingtiles[i][2]; game[name].x = game[name].xtile *game.tileW+game.tileW/2; game[name].y = game[name].ytile *game.tileH+game.tileH/2; game[name].clip._x = game[name].x; game[name].clip._y = game[name].y; game[name].minx=game[name].minx+game[name].xtile; game[name].maxx=game[name].maxx+game[name].xtile; game[name].miny=game[name].miny+game[name].ytile; game[name].maxy=game[name].maxy+game[name].ytile; }
首先还是取得当前地图的浮动方块数组(第一句)。变量game.movingtiles保存了当前地图的浮动方块数据,包括数目和方位。然后创建新的对象,放置mc到舞台正确的位置,跳转到相应的帧。类型1的方块是第一帧,类型2的方块则是第二帧。代码的最后一部分是计算浮动方块的运动范围。虽然变量名称还是miny/maxy/minx/maxx,但是这些属性变成了确定的数字,和原先的含义(相对起始位置的坐标)已经不同了(或者说他们是绝对的坐标,使用的时候不需要再参考起始位置)。
在moveChar函数中,需要添加一行代码,用来保存y坐标:
ob.lasty=ob.y;
在moveChar函数中还需要改写移动功能的代码:
if (diry == 1) { if (ob.downleft and ob.downright and !checkMovingTiles(speed*diry)) { ob.y += speed*diry; } else { ob.jump = false; if(ob.onMovingTile){ ob.y=ob.onMovingTile.y-ob.onMovingTile.height-ob.height; }else{ ob.y = (ob.ytile+1)*game.tileH-ob.height; } } }
我们使用了checkMovingTiles函数,如果英雄将会降落在浮动方块上,这个函数会返回true。如果英雄马上就要落在浮动方块上,我们设置他的y坐标为刚好在方块上面。
英雄在浮动方块上面吗?
或许你已经从moveChar函数中增加的部分看出来了,没错,我们需要创建一个新函数,用来检测角色是不是站在浮动方块上面。checkMovingTiles函数不仅仅返回答案(是或者不是),而且还把英雄所在浮动方块的名字保存到char对象中。
function checkMovingTiles (y) { if(char.diry<>-1){ var heroymax=char.y+char.height+y; var heroxmax=char.x+char.width; var heroxmin=char.x-char.width; foundit=false; for (var i = 0; i<game.movingtiles.length; i++) { var ob=game["movingtile"+i]; var tileymax=ob.y+ob.height; var tileymin=ob.y-ob.height; var tilexmax=ob.x+ob.width; var tilexmin=ob.x-ob.width; if(char.lasty+char.height<=tileymin){ if (heroymax<=tileymax and heroymax>=tileymin) { if (heroxmax>tilexmin and heroxmax<tilexmax) { char.onMovingTile=ob; foundit=true; break; } else if (heroxmin>tilexmin and heroxmin<tilexmax) { char.onMovingTile=ob; foundit=true; break; } } } } return(foundit); } }
让我们看看发生了什么。如果角色不是往上运动(diry值不是-1),我们就计算出角色的边界。然后遍历浮动方块数组,看角色是否和当前的浮动方块接触:
带有“lasty”属性的if语句是用来确定角色的上一个位置是在浮动方块的上方,下面的两个if语句则判断角色是不是和方块有接触。如果有碰撞,那就意味着我们找到了正确的移动方块,于是onMovingTile属性就会纪录下找到的方块对象。
让他也动起来
请准备好看史上最丑陋最冗长最小气的函数!它很长,因为它要很多东西。首先,它移动所有的浮动方块,然后检查这些方块是不是需要反过来运动了,这些还不够,它还要处理英雄在浮动方块上面的动作,检查是不是应该掉下来。
function moveTiles () { for (var i = 0; i<game.movingtiles.length; i++) { var ob=game["movingtile"+i]; getMyCorners (ob.x + ob.speed*ob.dirx, ob.y + ob.speed*ob.diry, ob) if (ob.miny>ob.upY or ob.maxy<ob.downY) { ob.diry=-ob.diry; } if (ob.minx>ob.leftX or ob.maxx<ob.rightX) { ob.dirx=-ob.dirx; } ob.x = ob.x + ob.speed*ob.dirx; ob.y = ob.y + ob.speed*ob.diry; ob.xtile = Math.floor(ob.x/game.tileW); ob.ytile = Math.floor(ob.y/game.tileH); ob.clip._x = ob.x; ob.clip._y = ob.y; if(ob.diry==-1){ checkMovingTiles(0); } } //check if hero is on moving tile if(char.onMovingTile){ getMyCorners (char.x, char.y+char.onMovingTile.speed*char.onMovingTile.diry, char); if (char.onMovingTile.diry == -1) { if (char.upleft and char.upright) { char.y=char.onMovingTile.y-char.onMovingTile.height-char.height; } else { char.y = char.ytile*game.tileH+char.height; char.jumpspeed = 0; char.jump = true; char.onMovingTile=false; } } if (char.onMovingTile.diry == 1) { if (char.downleft and char.downright) { char.y=char.onMovingTile.y-char.onMovingTile.height-char.height; } else { char.onMovingTile=false; char.y = (char.ytile+1)*game.tileH-char.height; } } getMyCorners (char.x+char.onMovingTile.speed*char.onMovingTile.dirx, char.y, char); if (char.onMovingTile.dirx == -1) { if (char.downleft and char.upleft) { char.x += char.onMovingTile.speed*char.onMovingTile.dirx; } else { char.x = char.xtile*game.tileW+char.width; fall (char); } } if (char.onMovingTile.dirx == 1) { if (char.upright and char.downright) { char.x += char.onMovingTile.speed*char.onMovingTile.dirx; } else { fall (char); char.x = (char.xtile+1)*game.tileW-char.width; } } updateChar (char); } }
和上面说的一样,第一部分的代码用来移动浮动方块。遍历所有的浮动方块,把它们下一步的坐标和miny/maxy(minx/maxx)属性对照,看是否需要反过来运动。
这几行代码:if(ob.diry==-1){ checkMovingTiles(0); } 用来检查是否要载上英雄,注意满足的条件是英雄站在障碍物的边缘上不动,而且方块是朝上运动(diry是-1)。
在这行以下的函数部分:if(char.onMovingTile){ 用来处理英雄在浮动方块上的动作。当onMovingTile值不是false,意味着英雄站在某个浮动的方块上面,而且onMovingTile属性值就是所在的浮动方块对象。这里的代码和moveChar函数比较相似。我们利用getMyCorners函数计算英雄下一步的位置,如果没有碰到任何障碍物,就让英雄和方块一起运动;反之则不能把英雄移动过去。
使用函数
在detectKeys函数的开头加入这行语句,用来移动所有的浮动方块(即使英雄没有踩在它们上面):
moveTiles();
另外,当英雄起跳的时候,我们还要让他的onMovingTile属性变回false:
ob.onMovingTile=false;
下载源文件
出处:蓝色理想
责任编辑:qhwa
上一页 拾取物品 下一页 卷屏
◎进入论坛Flash专栏 版块参加讨论