小可耐
2023/04/08阅读:32主题:默认主题
canvas实现二娃翠花回家之路小游戏
Canvas是HTML5中的一个非常有用的技术,它可以用于实现各种图形化效果。本文将介绍使用Canvas实现的小游戏——“二娃翠花回家之路”。这个小游戏非常有趣,玩家需要通过绘制角色的行走路线来控制他们的行动,并避免他们相撞。
一、玩法介绍
-
玩家需要通过绘制二娃和翠花的行走路线,来控制他们的行动。 -
二娃和翠花需要分别回到各自的房子才能过关。 -
玩家需要避免二娃和翠花的行走的路上发生碰撞,否则游戏失败。 -
玩家可以使用“开始”按钮开始游戏,使用“重置”按钮重新开始游戏。
二、预览效果
体验链接:码上掘金-二娃翠花回家之路
三、开发难点
在实现“二娃翠花回家之路”小游戏的过程中,我遇到了如下几个技术难点:如何绘制路径不被页面刷新影响、如何计算两条路线交叉点最相近坐标距离、如何判断碰撞、如何计算人物的移动速度和步长。
-
绘制路线:在Canvas中,通过监听鼠标事件获取鼠标的坐标,并根据鼠标的移动轨迹来绘制路径。在绘制路线时需要保存路径的坐标,以便于后续的操作。需要考虑多个角色之间的交互,页面刷新函数调用时机影响着路径的绘制。
-
计算距离:需要计算二娃和翠花之间的距离,以及二娃和翠花与路线之间的距离。距离的计算需要使用勾股定理: 。需要注意单位的转换和精度的控制。
-
判断碰撞:需要在角色行走时,判断角色与另一个角色的距离是否小于一定的阈值。如果小于阈值,则需要根据一定的几率避免碰撞,或者直接暂停游戏并提示失败。需要考虑多个角色之间的相互作用。
-
人物移动速度和步长计算:需要计算人物与目标点之间的距离,以及人物的速度,计算出人物的移动步长。需要注意人物在路径交叉点位置碰撞的问题。这里我的解决方案是:计算两条路径的最近的两个坐标(因为交叉点不一定存在坐标,这是canvas绘制线条存在的可能性),然后拿到这两个坐标,找出原路径起点到该坐标的路径保存起来,再计算路径长度,得到长度用公式 的到速度v。
三、核心实现步骤
1、创建画布和按键元素
使用HTML和JavaScript来创建了一个画布和两个按键元素。首先创建了一个HTML文件,然后在其中添加了一个画布和两个按键。然后使用JavaScript来获取画布和按键元素,并设置了它们的属性和事件监听器。最后为画布创建了一个绘图环境,并在画布上绘制了两个人物和他们的家。代码实现在本文第四部分。
2、创建人物类
创建一个人物类character
,并在其中实现绘制角色draw()
、绘制家drawHouse()
、计算路径总长度calculatePathLength(def_path)
这里def_path
是为了后面找到两条路线交叉点最相近坐标到各自路线起点的路线备用的。计算两个坐标的距离distance(x1,y1,x2,y2)
、人物移动move()
等方法。通过这些方法,我们可以实现人物的移动和路径的划分。在实现路径划分时,我们可以通过计算路径总长度,将路径划分成若干个点,使角色在这些点之间移动。代码实现在本文第四部分。
3、创建两个人物实例
创建两个人物实例,并设置它们的属性和方法。我们将为每个人物实例设置起点、终点和当前位置,姓名和颜色属性。在移动时判断碰撞。
4、监听鼠标事件
在 Canvas 元素上监听鼠标事件,并根据鼠标的移动轨迹来绘制路径。我们将使用鼠标事件监听器来获取鼠标的坐标,并使用 Canvas API 来绘制路径。在绘制路线时需要保存路径的坐标,以便于后续的操作。
5、绘制路径
根据绘制好的路径,将路径按照一定的长度划分成若干个点。这些点可以作为人物移动的目标位置。然后,我们可以在每个点上计算出人物应该移动的目标位置,从而实现人物的移动。 在 Canvas 中,可以使用 moveTo
和 lineTo
方法来绘制路径。使用 stroke
方法来绘制路径。可以设定 lineWidth
和 strokeStyle
属性来设置路径的颜色和宽度。
算法部分,可以使用距离阈值来判断两个点之间的距离是否超过了阈值。如果超过了阈值,我们就将路径划分成两部分,分别计算出每个部分的长度。然后,选择较短的路径作为人物移动的路径。这样可以避免人物走过太多的弯路,从而增加游戏的流畅度。
//核心部分
//......
//......
if (var_distance > DISTANCE_THRESHOLD) {
this.x += dx / var_distance * speed;
this.y += dy / var_distance * speed;
} else {
this.x = target.x;
this.y = target.y;
this.path.shift();
//......
//......
}
6、判断碰撞
在角色行走时,判断角色与另一个角色的距离是否小于一定的阈值。如果小于阈值,则需要根据一定的几率避免碰撞,或者直接暂停游戏并提示失败。需要考虑多个角色之间的相互作用。
//核心部分
//......
if (this.path.length > 0 && this.distance(target.x, target.y, this === A ? B.x : A.x, this === A ? B.y : A.y) < COLLISION_THRESHOLD) {
const avoidCollision = Math.random() < COLLISION_AVOIDANCE_RATE; // 以一定的几率避免碰撞
if (avoidCollision) {
this.path.splice(0, 1); // 直接移动到下个点位
} else {
gameStatus = GAME_PAUSE_STATUS;
alert(`${this === A ? A.uname : B.uname} 碰到了对方,游戏失败`);
}
}
7、开始和重置游戏
实现开始和重置游戏的功能,包括重置路径、重置人物位置等。当游戏开始时,需要计算两个人物最短的路径,并将其保存到对应的路径数组中。当游戏结束时,将人物位置重置,并清空路径数组和绘制的路径。
//重置游戏
function resetGame() {
//逻辑:对人物和画布的一些参数复原
//.....
}
//开始游戏
function startGame() {
update();
if (!A.path.length || !B.path.length) {
alert('请先绘制人物回家路线');
return;
}
// 人物移动逻辑
//.....
}
8、实现动画效果
动画效果的实现主要是通过 requestAnimationFrame
方法来实现的。requestAnimationFrame
是一个用来优化动画效果的方法,可以让动画更流畅自然。具体地,requestAnimationFrame
方法会在下一帧动画之前调用一个回调函数,以便于更新动画效果。在这个回调函数中,可以实现人物的移动、路径的绘制等等,从而达到动画效果。
动画效果的实现主要在人物类Character
中。每个人物都有自己的动画状态和动画参数,包括位置、速度、目标位置等等。在每一帧的动画中,都会根据当前位置和目标位置之间的距离来计算移动的距离和速度,并且不断更新人物的位置和状态。这个过程中,使用了一些基本的数学计算,比如计算两点之间的距离、计算两点之间的角度等等。
四、完整的代码实现
考虑到文章篇幅过大,可以去这个链接查看完整代码哈:
https://juejin.cn/post/72192376664859279973
下面是实现该游戏的完整代码,这里着重强调几个关键函数,在代码中找到对应的注释
,这跟我在上面文章第二部分划重点的提问有关哦!。
主要的涉及的逻辑是,每个人物类有一个属性total_distance
用于存储距离,当用户点击开始回家按钮后,在startGame
方法里会计算两个人物回家路径最近的两个坐标点,并获得这两个坐标所在路径到所在路径起点的路径坐标数组,然后计算该新路径的长度保存到total_distance
中,在人物移动方法move()
中会计算人物移动速度和人物移动步长。
五、写在最后
Canvas开发游戏是一项充满趣味性和挑战性的任务。使用Canvas可以实现各种各样的游戏效果和交互方式,例如动画、碰撞检测、路径计算等等。通过开发游戏,可以锻炼我们自己的编程能力和解决问题的能力,提高自己的代码质量和效率。
在开发过程中,常常需要考虑游戏的用户体验和界面设计。例如,我们可以为游戏添加音效和动画效果,以增加游戏的趣味性和互动性。还可以为游戏添加计分板和排行榜,以便于玩家比较成绩和分享游戏。
作者介绍