横板闯关游戏中的角色移动
前言
在很多2D游戏中,都会涉及到角色移动,跳跃等操作,最典型的就是横板闯关游戏。例如经典的魂斗罗、三国战纪等。这两款游戏在地图移动和角色行走的方式中唯一的不同就是魂斗罗是没有纵深的那种。
看似简单,其实涉及了地图,摄像机移动,数学和物理的一些内容。
本片内容先介绍一下移动组件的定义,稍后的文章会一点点讲解地图、自定义摄像机等,最终应用到游戏中,做成一个完整的demo。
坐标系
首先不得不说的一点,所有的移动都是依托坐标系的。我们这里的坐标系是以左下角为原点,横向向右为x正方向,纵向向上为y正方向,朝向屏幕的方向为z正方向,也就是unity使用的左手坐标系。而cocoscreator使用的是右手坐标系,但是这个转换是比较简单的。
移动组件的定义
首先列举一下移动中都需要支持哪些功能
- 上下移动: 对于不可以上下移动的游戏来说,z方向的速度始终为0即可。
- 左右移动:x坐标的变化。
- 支持两个方向同时移动:当同时按下前上键时应该可以向左前方移动。
- 移动速度定义:当某个方向有速度时,才会向某个方向移动,站立状态下,所有方向速度均为0.
- 弹力:这个是为了模拟球的落地弹起,实现并不要求那么严格的。
- 摩擦力: 这个是为了模拟逐渐停止的效果。实现并不要求那么严格。
- 是否受重力影响: 对于一些不受重力影响的物理,可以不做重力计算
- 是否启用: 只有启用以后才会进行移动计算。
- 在游戏地图中的坐标:记录角色当前在地图中的位置。
import { DIR } from "../../cfw/tools/Define";
import PhysicalManager from "./PhysicalManager";
const { ccclass, property } = cc._decorator;
@ccclass
export default class MoveSystem extends cc.Component {
@property({ displayName: '是否受重力' })
g: Boolean = true;
@property({ displayName: '是否启用' })
enable: Boolean = true;
@property({ displayName: '速度' })
speed: cc.Vec3 = cc.v3(0, 0, 0)
// 弹力
@property({ type: cc.Float, displayName: '弹力' })
elasticity: number = 0;
//摩擦力
@property({ type: cc.Float, displayName: '摩擦力' })
frictional: number = 1;
@property({ type: cc.Float, displayName: '跳跃高度' })
jumpHigh: number = 350;
//左右移动方向
protected moveXDir: DIR = DIR.RIGHT;
//上下移动方向
protected moveZDir: DIR = DIR.UP;
//角色在地图中的位置
protected position: cc.Vec3 = cc.v3(0, 0, 0)
start() {
if (this.enable) {
this.setEnable(true)
}
}
onDestroy() {
if (this.enable) {
this.setEnable(false)
}
}
setEnable(f: boolean) {
this.enable = f;
cc.log('MoveSystem setEnable f ', f)
if (this.enable) {
PhysicalManager.instance().add(this)
} else {
PhysicalManager.instance().remove(this)
}
}
isEnable() {
return this.enable;
}
setMoveXDir(d: DIR) {
this.moveXDir = d;
}
getMoveXDir() {
return this.moveXDir;
}
setMoveZDir(d: DIR) {
this.moveZDir = d;
}
getMoveZDir() {
return this.moveZDir;
}
getFrictional() {
return this.frictional;
}
setGrictional(n: number) {
this.frictional = n;
}
setElasticity(n: number) {
this.elasticity = n;
}
getElasticity() {
return this.elasticity;
}
isG() {
return this.g
}
setG(f: boolean) {
this.g = f;
}
getJumpHigh() {
return this.jumpHigh;
}
setJumpHight(h: number) {
this.jumpHigh = h;
}
addJumpHigh(h: number) {
this.jumpHigh += h;
}
isJumping() {
return this.speed.y != 0;
}
setX(x: number) {
this.position.x = x;
}
setY(y: number) {
this.position.y = y;
}
getZ() {
return this.position.z;
}
setZ(z: number) {
this.position.z = z;
this.node.zIndex = -z
}
getX() {
return this.position.x;
}
getY() {
return this.position.y;
}
getSpeedX() {
return this.speed.x;
}
setSpeedX(s: number) {
this.speed.x = s;
}
setSpeedY(spy: number) {
this.speed.y = spy;
}
getSpeedY() {
return this.speed.y
}
setSpeedZ(z: number) {
this.speed.z = z;
}
getSpeedZ() {
return this.speed.z;
}
}
结语
对于移动的需求可能不止如此,但是在我以往的开发过程中,有这些已经可以应付大多数游戏的需求了。代码仅供参考,欢迎留言探讨。
欢迎关注我的个人GZH<微笑游戏>
欢迎扫码关注公众号《微笑游戏》,浏览更多内容。