|
不是表示左右相等,是把右边计算的结果赋给”速度”变量。这个式子也是需要不停计算的,以便保持连贯的运动。你可以改变重力的值,较小的值意味着在空中的时间更长,较大的值很快就会把英雄“拉”下来。 从另外的角度看,重力也意味着跳跃能力,我们可以给不同的对象赋以不同的“重力”属性,这样他们跳得就不至于一样高。
让我们来看一个例子。比如刚开始的速度是-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。
下载源文件
腾云驾雾
到目前为止,我们已经做出了阻止英雄通过墙的效果。很有趣,不是吗?许多游戏还有一类叫做“云”的方块,角色门可以左右穿行他们,甚至可以从下面跳上去, 但是当下落的时候,他们确是不可通行的,英雄会停在上面。看这个例子:
|