跳跃
开始之前,我们先把视角从俯视改成侧视,这样英雄才可以跳跃。就像下面的这个,按左右键英雄移动,按空格键跳跃:
跳跃基础
跳跃意味着上升,上升在Flash中意味着_y属性的减少。所以我们需要计算这样的式子: 新的坐标=现在的坐标-上升速度
如果只计算一次,坐标只改变一次,英雄很快就停止了。因此我们需要持续不断的计算新坐标。而且,我们还应该改变速度的值,否则英雄就在空中下不来了。 下落和上升一样,只不过速度值前面加个负号而已。
为了改变速度,我们定义一个新的变量:重力加速度。重力把英雄拉向地面,学过物理吧?重力加速度并不直接改变坐标,他改变的是速度: 速度=速度+加速度
这就是Flash中的表示方法,=可不是表示左右相等,是把右边计算的结果赋给”速度”变量。这个式子也是需要不停计算的,以便保持连贯的运动。你可以改变重力的值,较小的值意味着在空中的时间更长,较大的值很快就会把英雄“拉”下来。 从另外的角度看,重力也意味着跳跃能力,我们可以给不同的对象赋以不同的“重力”属性,这样他们跳得就不至于一样高。
让我们来看一个例子。比如刚开始的速度是-10,重力是2。 那么开始的时候,英雄将会上移10象素,然后速度降低到8; 接着英雄上移8象素,然后速度又变成了6…… 如此往复,直到速度等于0的时候,英雄不再上升了。 接着速度成了2,英雄开始下降2象素; 下一步又下降4象素、6象素、8象素……直到落地。
落地后,跳跃自然也应该结束了。但是要是英雄在跳跃过程中顶到障碍物怎么办? 很简单,我们把速度强行改成0就行了,然后英雄就会落下来。
【注意】在区块游戏开发中,不要让速度值超过方块的高度。过大的速度会导致碰撞检测跳过某个方块,导致英雄“穿过”障碍物。或许有些魔法师可以穿过障碍物,但是在普通的区块游戏中,这是个bug。
跳跃并不影响水平方向的运动,在空中我们还可以用方向键控制英雄的水平运动。我们需要做的是,在左移或右移后,判断英雄脚下是不是还有东西,如果是空的,跳跃就开始了(这时候初始速度是0,英雄直接下落)。
会跳的英雄
我们给英雄再添加一些属性: char = {xtile:2, ytile:1, speed:4, jumpstart:-18, gravity:2, jump:false}; speed属性是水平移动速度,jumpstart是跳跃的初始速度, granvity是重力值,jump属性用来表示英雄是不是在跳跃过程中。
下面加一句as到buildMap函数中: char.y = ((char.ytile + 1) * game.tileW) - char.height;
因为我们的视图是侧视的,英雄刚开始的位置可能是“漂”在空中的,我们应该让他站到地面上来。
changeMap函数和getMyCorners函数不需要任何变动。
腾空的感觉
我们先来改造detectKey函数,删除上下键检测,添加空格键检测:
function detectKeys() { var ob = _root.char; var keyPressed = false; if (Key.isDown(Key.SPACE) and !ob.jump) { ob.jump = true; ob.jumpspeed = ob.jumpstart; } if (Key.isDown(Key.RIGHT)) { keyPressed = _root.moveChar(ob, 1, 0); } else if (Key.isDown(Key.LEFT)) { keyPressed = _root.moveChar(ob, -1, 0); } if (ob.jump) { keyPressed = _root.jump(ob); } if (!keyPressed) { ob.clip.char.gotoAndStop(1); } else { ob.clip.char.play(); } }
注意看我们怎么避免跳跃过程中空格键触发新的跳跃(听起来很拗口,哈哈),实际上就是当处于跳跃中时,忽略空格键。如果按了空格键,而且英雄没有处于跳跃过程,那就开始跳吧,把jump属性改成true,把jumpspeed改成speedstart属性值。
看一下,在左右方向键的检测语句后面,我们添加了几句。 if (ob.jump) { keyPressed = _root.jump(ob); }
如果jump属性为true(正在跳),那么执行jump函数。只要jump属性为true,jump函数就会不断地被执行,直到jump属性变成了false。这个函数可以在空格键松开后仍然执行,只要jump属性为true。
Jump函数所做的只是改变jumpspeed的值,给他加上重力值。同时做一些处理防止速度值过大,让jumpspeed不会超过方块高度。最后调用moveChar函数移动角色。
function jump (ob) { ob.jumpspeed = ob.jumpspeed + ob.gravity; if (ob.jumpspeed > game.tileH) { ob.jumpspeed = game.tileH; } if (ob.jumpspeed < 0) { moveChar(ob, 0, -1, -1); } else if (ob.jumpspeed > 0) { moveChar(ob, 0, 1, 1); } return (true); }
我们还需要改一下moveChar函数,因为加入了跳跃过程,跳跃时的速度jumpspeed和水平移动的速度speed是不同的:
function moveChar(ob, dirx, diry, jump) { if (Math.abs(jump) == 1) { speed = ob.jumpspeed * jump; } else { speed = ob.speed; } ...
jump参数是从上面的jump函数中传递过来的,它的取值不是1就是-1。如果jump的绝对值(Math.abs)是1,移动的距离就是jumpspeed*jump,否则就是speed属性。
如果这一步移动结束后,角色的顶到了障碍物,就要把jumpspeed值改成0: ob.y = ob.ytile * game.tileH + ob.height; ob.jumpspeed = 0;
如果这一步移动结束后,角色站到了地面上,跳跃就该结束了: ob.y = (ob.ytile + 1) * game.tileH - ob.height; ob.jump = false;
在左右移动后,我们还要看看角色是不是还站在平台上,如果不是,就应该落下来: ob.x += speed * dirx; fall (ob);
所以,我们还需要一个fall函数: function fall (ob) { if (!ob.jump) { getMyCorners (ob.x, ob.y + 1, ob); if (ob.downleft and ob.downright) { ob.jumpspeed = 0; ob.jump = true; } } }
如果角色已经处于跳跃过程中,这个函数就没有必要运行了,它是用来检测“踩空”的情况的,只有当角色站着(!ob.jump)的时候才有用。这时候我们调用getMycorners函数,如果角色下方的两个方块都是可通行的,那就应该落下来了, 起始速度是0,然后把jump属性改成true。
下载源文件
出处:蓝色理想
责任编辑:qhwa
上一页 芝麻开门-地图切换 下一页 腾云驾雾
◎进入论坛Flash专栏版块参加讨论
|