HTML5 2D平台游戏开发#11斜坡物理
在游戏中会经常遇到斜坡地形,比如众所周知的魂斗罗,角色可以在坡上移动和跳跃:
斜坡在2D游戏中很常见,处理起来也较为棘手。最初我打算用分离轴定律来实现,在建立了一个物理模型之后:
发现上坡时没什么问题,但下坡时有比较明显的弹跳,这并不是预期的结果,因为我想让物体“粘”在坡上。产生这个问题的根本原因是物体的运动分为两个阶段,
首先是水平方向的移动,最后是垂直方向的移动:
如果X轴和Y轴的速度没有一定的方式关联起来,就会产生跳跃问题。根据力的平行四边形法则,物体的运行轨迹应该像这样(以向右下坡为例):
接下来要做的工作就是计算出xspeed
和yspeed
。
为了简单起见,先将斜坡统一设置成45°,即等边直角三角形,此时只需要将Y轴速度设置为与X轴速度相同即可。
由上图可以发现,当x与y相等时,角色会贴着斜坡下降,而如果x轴的速度比y轴快,角色就会脱离斜坡,此时再加上y轴的重力加速度,将会出现上述跳跃的效果。
当然这里不是说跳跃就是错误的,有些游戏也会需要这种效果,只是在当前场景下让角色“粘”在坡上更符合需求。
任意角度的斜坡速度处理
45°斜坡只是理想情况,实际上开发者可能要面对各种角度的斜坡,这里的“各种角度”是指小于90°,因为等于90°就相当于一面墙了。现在假设角色要在斜坡上移动的距离为distance
(一般将其赋值为角色的水平速度speedX),那么其水平分量为
vx = Math.cosθ * distance;
然后令
vy = vx;
即可得出在斜坡上速度的水平和垂直分量。由于现在的水平速度是平时速度的分量,所以在斜坡上移动的速度比在平地时要慢一些。
如果不记得三角函数,可以通过下图复习一下:
上述方法都是在θ角已知的情况下展开讨论的,如果不知道θ角也没关系,它可以通过斜面的法线与垂直方向的夹角计算出来。
至此角色在下坡时跳跃的问题已经有了初步的解决方案。
现在还有一个关键问题需要解决,就是判断角色何时处于斜坡上,在斜坡上的水平移动使角色有一段时间是脱离斜坡的,必须让程序知道这个阶段的角色仍处于斜坡之上而不是离开了。
//Pseudocode
function checkCollision() {
player.onSlope = false; if(checkPlayerOnSlope()) {
player.onSlope = true;
} if(player.onSlope) {
vy = vx = Math.cosθ * distance; //计算角色在斜坡上的坐标...
}
}
为实现上面伪代码中的checkPlayerOnSlope
这个方法,需要做一些额外的准备工作。
光线投射法
光线投射法(RayCasting)是一种游戏中常见的碰撞检测手段。可以想象成一个点朝某个方向发出光线,直到光线击中或穿过待测目标。在光线投射过程中,如果记录下其穿过的Tiles,就会得到一个结果集,用这个结果集来分析判断角色所处的位置。现在假设某条光线穿过的区域如下图所示:
蓝色线段所占的区域用红色表示,但还不够精确,预期得到的结果应该像这样:
这里需要用到Bresenham画线算法(Bresenham's line algorithm)。计算机在画一条直线时,是通过像素来表现的,当像素点密集后,肉眼就看不出来了。
(图片来自wikipedia)
将该线段上所有点的坐标计算出来,观察其位于哪个Tiles内,最后就能得到线段经过的Tiles集合。
现在为角色的脚部添加3条光线:
如果其中一条经过的Tiles有斜坡,那就说明角色位于斜坡上。
斜坡物理
当角色位于斜坡上与在平地时不一样,应该忽略重力以及其它方向上的力的影响,否则会干扰其“粘”在斜坡上。角色位于斜坡上的y坐标很容易根据下图求出:
A点的y坐标为BA'。左右移动时,根据角色的x坐标即可求出对应的y坐标slopeY
,并一直令
player.y = slopeY;
直到离开斜坡。
在斜坡上忽略重力影响并不意味着角色不能进行跳跃,触发跳跃时让角色强制离地即可。
更新日志
2017/04/09 更新角色跳跃
2017/04/21 更新角色冲刺
2017/05/01 更新角色状态机
2017/05/16 更新角色攻击动画
2017/05/22 更新角色移动攻击动画
2017/05/24 更新角色跳跃攻击动画
2017/06/04 更新地图绘制
2017/06/22 更新摄像机、长距离冲刺
2017/07/01 更新指令技
2017/07/06 更新蓄力技
2017/07/12 更新wall jump
2017/10/13 更新斜坡地形
HTML5 2D平台游戏开发#11斜坡物理的更多相关文章
- HTML5 2D平台游戏开发#4状态机
在实现了<HTML5 2D平台游戏开发——角色动作篇之冲刺>之后,我发现随着角色动作的增加,代码中的逻辑判断越来越多,铺天盖地的if() else()语句实在让我捉襟见肘: 这还仅仅是角色 ...
- HTML5 2D平台游戏开发#6地图绘制
此前已经完成了一部分角色的动作,现在还缺少可以交互的地图让游戏看起来能玩.不过在开始之前应当考虑清楚使用什么类型的地图,就2D平台游戏来说,一般有两种类型的地图,Tile-based和Art-base ...
- HTML5 2D平台游戏开发#8指令技
一般在动作游戏中,玩家可以通过对输入设备输入一系列的指令让角色完成某个或多个特定的动作.以格斗游戏<拳皇>为例,键入↓↘→↘↓↙← + A or C可以触发IORI的必杀技八稚女: 通过一 ...
- HTML5 2D平台游戏开发#7Camera
在庞大的游戏世界中,玩家不能一览地图全貌,而是只能看到其中一部分,并一步步探索,这时就要用到一种技术来显示局部的地图,游戏术语称为摄像机(Camera).下面两张图中的白色矩形框表示了Camera的作 ...
- HTML5 2D平台游戏开发#5攻击
目前为止,角色除了基本的移动外还什么都不能做,于是我打算先实现角色的攻击动画.角色的普通攻击一共可以分为三个阶段: 一段斩 二段斩 三段斩 移动攻击 跳跃攻击 触发方式为角色站立时按下J(攻击)键,角 ...
- HTML5 2D平台游戏开发#10Wall Jump
这个术语不知道怎么翻译比较贴切,但并不妨碍对字面意思的理解,大概就是飞檐走壁.比如: 这是游戏<忍者龙剑传>中的场景,玩家可以通过操纵角色在墙面上移动并跳跃. 首先需要实现角色抓墙这一动作 ...
- HTML5 2D平台游戏开发#9蓄力技
在很多动作游戏中,玩家操控的角色可以施放出比普通攻击更强力的蓄力技,一般操作为按住攻击键一段时间然后松开,具体效果像下面这张图: 要实现这个操作首先要记录下按键被按住的时间,初始是0: this.sa ...
- HTML5 2D平台游戏开发#2跳跃与二段跳
在上一篇<Canvas制作时间与行为可控的sprite动画>中已经实现了角色的左右移动,本篇继续实现角色的一系列动作之一:跳跃.先来看看最终效果: 要实现跳跃,必须模拟垂直方向的速度和重力 ...
- HTML5 2D平台游戏开发#1
在Web领域通常会用到一组sprite来展示动画,这类动画从开始到结束往往不会有用户参与,即用户很少会用控制器(例如鼠标.键盘.手柄.操作杆等输入设备)进行操作.但在游戏领域,sprite动画与控制器 ...
随机推荐
- (22)C#windows打包部署
程序做好后需要打包部署后才能使用 一.创建安装项目 解决方案右键-添加-新建项目-其他项目类型-安装和部署-双击进入文件系统. 二.制作安装程序 一个完整的安装程序包括项目输出文件.内容文件.桌面快捷 ...
- Codeforces Round #109 (Div. 2) A. I_love_%username%【打擂台算法/满足当前数字在已经出现的数字的最大值和最小值之间的个数】
A. I_love_%username% time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- Python的程序结构[4] -> 函数/Function[2] -> 匿名函数
匿名函数 / Anonymous Function 匿名函数是一种不需要绑定函数名的函数 (i.e. functions that are not bound to a name).匿名函数通过 la ...
- #420 Div2 C
#420 Div2 C 题意 不断把数加入到一个栈里,取数的时候要求按照 1~n 的顺序取数,每次取数保证数一定在栈里,如果要取的数不在栈头,可以选择对栈排序一次.问最少排序几次. 分析 只要栈头的数 ...
- Out of Sorts II
问题 E: Out of Sorts II 时间限制: 1 Sec 内存限制: 128 MB提交: 68 解决: 4[提交] [状态] [讨论版] [命题人:] 题目描述 Keeping an e ...
- JAVA RandomAccessFile writeBytes
writeBytes public final void writeBytes(String s) throws IOException 按字节序列将该字符串写入该文件.该字符串中的每个字符均按顺序写 ...
- Linux下安装PHP的GD支持库
Linux下安装PHP的GD支持库 1.安装 zlib wget ftp://ftp.sunfreeware.com/pub/freeware/SOURCES/zlib-1.2.3.tar.gz ...
- Ubuntu 16.04 -- 同时配置Nginx(转发)和frp(内网映射)和HTTPS(ca加密) - 端口转发
Ubuntu16.04下: sudo apt -get nginx 用这条命令安装完nginx之后, nginx在该目录下: 然后配置nginx: 如下: 红圈圈住的地方多写几个可以做负载均衡. 端口 ...
- samba 服务实现在windows共享文件
1. 什么是samba Samba服务类似于windows上的共享功能,可以实现在Linux上共享文件,windows上访问,当然在Linux上也可以访问到. 是一种在局域网上共享文件和打印机的一种通 ...
- selfshadow
realtime rendering v3 page 351 Moire pattern sruface acne artifacts ----------------------- 用 setsta ...