简介
这个游戏是我学习eloquent javascript中的案例修改的,游戏是一个横板过关小游戏,通过js的函数封装实现的,在原来的基础上,我添加了兔子的和胡萝卜的主题,本来想着为操作添加移动帧,但是不知道为什么没有成功,调试了几个小时,放弃了,所以就只用现在的样子了,只有贴图。。。。下面是具体的一些函数解释:
函数解释
静态地图,向量函数,接受的两个参数作为横坐标和纵坐标,两个方法,一个相加,一个相乘,
添加映射,玩家,墙壁,岩浆,
玩家函数,接受一个向量函数,定义了初始位置,大小,速度,都是向量,
岩浆函数,接受一个向量,一个字符串参数,初始位置,大小,进行判断,三个种类岩浆,给三个不同的方向
金币函数,接受向量,作为初始位置,初始大小,给了一个随机数,
关卡函数,接收地图数组,初始化宽度为第一个元素的长度,高度为数组的长度,初始化了一个grid,一个actors数组
首先遍历y也就是行,定义line内容为数组第一行,接下来遍历列,ch代表每一个字符串,然后用之前的映射判断类型,如果存在就给actors数组添加进去,里面的元素包含一个位置,一个字符,然后push类型到gridline,这代表行,循环结束,再push到grid里面,grid是一个二维数组,然后给player设置,从actors里面找到唯一一个player,设置关卡状态为空,
元素函数,两个参数,一个类名,一个标签名
DOM展示函数,两个参数,一个作为父元素,一个是关卡,wrap是给父元素下面创建了一个div.game,然后给game新建子元素调用了一个函数drawBackground,调用了drawFrame
drawBackground函数,新建table元素作为背景,宽高设置为地图数组大小*15px,遍历关卡,添加tr,设置大小,每一行为tr,每一列为td,
drawFrame函数,首先判断有没有玩家,有,就移除,没有要新建一个,调用了drawActors函数,设置类名了,然后调用了scrollPlayerIntoView,
scrollPlayerIntoView函数,设置宽高,间距,
DOM的clear函数,通过父节点清除当前元素
level的obstacleAt函数,接受两个参数:pos(表示障碍物的位置)和size(表示障碍物的大小)。函数通过枚举障碍物所在的格子,并在Level对象的grid数组中查找是否存在任何类型的障碍物。如果障碍物存在,则返回障碍物的类型(例如”wall”或”lava”)。如果障碍物不存在,则返回null。
actorAt函数,它接受一个参数:actor,表示需要检测的演员。函数通过遍历Level对象的actors数组,并检查给定的actor是否与其他任何演员发生碰撞。如果发生碰撞,则返回另一个演员;如果没有发生碰撞,则返回null。
animate函数,
它接受两个参数:step(表示动画的时间步长)和keys(表示游戏中当前按下的按键)。函数首先检查游戏状态是否正在运行(如果不是,则将finishDelay减少相应的值)。
然后,函数将动画时间步长分解成若干个小的步长,并对每个演员(即游戏对象)调用act()方法,以更新演员的位置和状态。
岩浆act函数,
它接受两个参数:step(表示模拟的步骤)和level(表示游戏的等级)。
函数通过计算当前位置加上速度乘以步长,得到熔岩在下一个步骤中的新位置。然后,它使用level.obstacleAt方法检查熔岩是否与其他任何障碍物相撞。如果没有,则将熔岩的位置更新为新位置。否则,如果Lava对象有repeatPos属性,则将熔岩的位置更新为repeatPos。如果没有,则将熔岩的速度乘以-1。
金币act函数,
在该方法中,硬币对象的摆动属性被增加了步长乘以wobbleSpeed。然后,wobblePos变量是通过取摆动属性的正弦值并乘以wobbleDist来计算的。
最后,硬币对象的pos属性被更新为等于该对象的basePos属性加上一个新的Vector对象,x值等于0,y值等于wobblePos。
这样就创建了一个动画,硬币看起来在上下摆动,摆动的幅度由wobbleDist决定,摆动的速度由wobbleSpeed决定。
玩家移动x函数,
接收三个参数:步长、级别和键。
然后,如果左键被按下(如keys.left属性所示),speed.x属性会被playerXSpeed减少。如果右键被按下(如keys.right属性所示),speed.x属性会被playerXSpeed增加。
一个新的矢量对象被创建,x等于speed.x乘以步骤,y等于0,代表玩家沿x轴的运动。然后,一个newPos变量被计算出来,将这个运动加入到播放器对象的pos属性中。
然后用newPos和玩家的大小作为参数调用关卡对象的obstacleAt方法。如果返回一个障碍物,关卡对象的playerTouched方法会被调用,并以障碍物作为参数。否则,播放器对象的pos属性被更新为等于newPos,表明播放器已经沿x轴移动。
玩家移动y函数,
玩家的垂直速度this.speed.y首先被重力影响而增加(步长*重力)。然后根据玩家的垂直速度和当前位置计算出一个新的位置newPos。然后,该函数使用level.obstacleAt(newPos, this.size)检查在新位置是否有障碍物。
如果有障碍物,该函数会调用level.playerTouched(obstacle)来处理碰撞,如果向上箭头键被按下并且玩家的速度大于0,玩家的速度会被设置为-jumpSpeed以实现跳跃。否则,玩家的速度被设置为零,以停止向上的运动。
如果没有障碍物,玩家的位置会被更新到新的位置。
玩家act函数,
在 “act” 方法中,它首先在 “X” 和 “Y” 方向上调用 “moveX” 和 “moveY” 方法,分别处理水平和垂直方向的移动。 然后,它使用 “level.actorAt” 方法检查是否有其他演员存在于当前位置。 如果存在,则调用 “level.playerTouched”,告诉游戏级别有一个演员被碰到了。
如果游戏的状态是 “lost”,那么 “Player” 将进行失败动画,即,沿着 “Y” 轴向下移动,并减小其高度。
关卡的playerTouched函数,
该函数接收两个参数:type 和 actor,其中 type 表示玩家与元素相接触时的元素的类型,actor 表示这个元素的对象。
如果玩家与类型为 “lava” 的元素相接触,并且当前游戏状态为 null,则将游戏状态设置为 “lost” 并设置 finishDelay 为 1。
如果玩家与类型为 “coin” 的元素相接触,则从 actors 数组中移除该元素,并判断 actors 数组是否仍然存在元素类型为 “coin”,如果不存在则将游戏状态设置为 “won” 并设置 finishDelay 为 1。
键盘事件,它创建一个对象 “pressed”,该对象将存储键盘上按下/放开的状态。该函数通过为键盘上的 “keydown” 和 “keyup” 事件分别设置事件处理程序来跟踪键盘状态。事件处理程序检查触发该事件的按键的键码,如果键码在 “codes” 对象中,则确定该按键是否被按下,并将该信息存储在 “pressed” 对象中。
runanimate函数,这个函数通过连续调用frameFunc并传递给它自上一帧起的时间步长(以秒为单位)来运行一个动画。该动画是通过 requestAnimationFrame 函数实现的,该函数要求浏览器在下一次重绘之前调用一个函数来更新动画。 runAnimation 使用 requestAnimationFrame 来调用 frame,该函数计算时间步长,并用时间步长来调用 frameFunc。当framFunc返回false时,该函数返回。
函数runLevel,它接收了一个关卡对象、一个显示构造器和一个回调函数andThen。它创建一个新的显示对象,并使用runAnimation函数启动一个动画循环。在动画循环中,它为关卡制作动画,绘制显示器,并检查关卡是否完成。如果关卡完成了,它将清除显示,并以关卡的状态调用andThen回调函数。
开始游戏,
这个函数用于运行一个由多个关卡组成的游戏。它需要两个参数,计划和显示,其中。
plans是一个字符串数组,代表游戏中每个关卡的计划。
Display是一个构造函数,为游戏创建一个显示对象的实例,负责在屏幕上渲染关卡。
该函数定义了一个内部函数startLevel,它接受一个关卡编号n作为参数。这个函数使用plan[n]创建一个新的关卡对象,并将其与Display构造函数一起传递给runLevel函数。
runLevel函数启动动画循环并绘制帧,直到关卡完成。当关卡完成时,runLevel函数用关卡的状态调用传递给它的回调函数。
如果状态是 “丢失”,则当前关卡重新开始。如果当前关卡不是游戏中的最后一个关卡,则通过调用startLevel的n+1开始下一个关卡。如果当前关卡是最后一关,该函数会向玩家显示一个 “你赢了!”的提示。
最后,该函数以游戏的第一关n=1调用startLevel。
试玩地址:http://jingqun.top/rabbit/