使用Angular9和TypeScript开发RPG游戏的方法


Posted in Javascript onMarch 25, 2020

RPG系统构造

通过对于斗罗大陆小说的游戏化过程,熟悉Angular的结构以及使用TypeScript的面向对象开发方法。

项目地址

人物

和其他RPG游戏类似,游戏里面的人物角色大致有这样的一些属性:生命值,魔法值(魂力),攻击力,防御力,速度。RPG游戏中的角色随着等级的提高,这些属性都会提升,属性提升的快慢则取决于资质,同时,由于在实际战斗中,会出现各种增益和光环效果,这些值都是动态变化的,所以这里将这些属性都设置了Base和Real两套数据。

Base属性是指人物的初始属性,是一种固有属性,在整个游戏开始的时候就固定下来的。然后每个人物根据不同的资质,有一个成长值,例如SSR的角色,成长值可以是1.5,普通角色是1。这个成长值关系到每提升一个等级,角色属性的增加值,代码大致如下:

/**经过增益之后的生命最大值 */
 get RealMaxHP(): number {
 var R = this.BaseMaxHP + (this.LV - 1) * this.MaxHPUpPerLv * this.GrowthFactor;
 ...
 ...
 ...
 return Math.round(R);
 }

这里的 MaxHPUpPerLv 表示每个等级的最大生命值提升数值,GrowthFactor则表示成长值。

注意:这里使用了TypeScript的get属性,也就是只读/计算属性来处理Real系的属性,这些属性都是实时计算出来的!

在小说里面,经常可以看到3成功力的角色,为了表示这种情况,代码里面还设定了一个Factor变量,通过这个变量可以设定整体的缩放比例。这个值默认为1,表示不缩放。

/**经过增益之后的生命最大值 */
 get RealMaxHP(): number {
 var R = this.BaseMaxHP + (this.LV - 1) * this.MaxHPUpPerLv * this.GrowthFactor;
 R = R * this.Factor;
 ...
 ...
 ...
 return Math.round(R);
 }

由于乘法计算会出现小数点,这里使用了Math.round对结果进行取整。

技能

技能是一个游戏的战斗核心,所有技能本质上都是为了改变角色状态。如果要具体细分大致可以分为

  • 攻击类:对于指定角色产生伤害
  • 回复类:对于指定角色,回复生命值和魔法值
  • 状态改变类:这里其实包含了Buffer和状态变化两种情况,Buffer类大多是被动技能,游戏中只要某个角色在战场上就获得,并且效果是持续性的。状态变化则一般必须主动施放技能才行,而且持续时间也是有限制的。

同时技能设计的时候,还需要设定使用的方向,既这个技能是对于我方使用,还是敌方使用,还是无差别使用。另外这个技能的对象是某个对象,还是群体。

/**技能类型 */
export enum enmSkillType {
 /**攻击 */
 Attact,
 /**治疗 */
 Heal,
 /**光环和状态 */
 Buffer
}

/**技能范围 */
export enum enmRange {
 Self, //自己
 PickOne, //选择一个人
 RandomOne, //随机选择一个人
 FrontAll, //前排所有人
 BackAll, //后排所有人
 EveryOne, //战场所有人
}

/**只能方向 */
export enum enmDirect {
 MyTeam, //本方
 Enemy, //敌方
 All, //全体
}

一般使用枚举来编写这样相对固定,项目较少的列表

技能的设计,这里使用了OOP的继承来实现,技能的基类定义了一些共通的属性和抽象方法。设计的时候还考虑到以下几种特殊情况

  • 每一种具体技能必须要实现一个执行(施放)方法:Excute,这里使用抽象函数,来强制子类型必须要实现这个方法
  • 对于复杂技能,需要有一个自定义的执行方法:CustomeExcute,同时通过返回值来告诉系统是不是该技能有自定义执行方法。则跳过固有的Excute方法。
  • 对于有些技能可能要同时实现两种效果,这里增加了AddtionSkill变量
/** 技能 */
export abstract class SkillInfo {
 Name: string;
 Order: number; //第N魂技
 SkillType: enmSkillType;
 Range: enmRange;
 Direct: enmDirect;
 Description: string;
 Source: string;
 get MpUsage(): number {
 return Math.pow(2, this.Order);
 }
 /**武魂融合技的融合者列表 */
 Combine: string[];
 abstract Excute(c: character, fs: FightStatus): void;
 /**自定义执行方法 */
 CustomeExcute(c: character, fs: FightStatus): boolean {
 return false;
 }
 //攻击并中毒这样的两个效果叠加的技能
 AddtionSkill: SkillInfo = undefined;
}

export class AttactSkillInfo extends SkillInfo {
 SkillType = enmSkillType.Attact;
 Harm: number;
 Excute(c: character, fs: FightStatus) {
 //如果自定义方法被执行,则跳过后续代码
 if (this.CustomeExcute(c, fs)) return;
 let factor = fs.currentActionCharater.LV / 100;
 c.HP -= Math.round(this.Harm * factor);
 if (c.HP <= 0) c.HP = 0;
 //如果需要产生其他效果
 if (this.AddtionSkill !== undefined) this.AddtionSkill.Excute(c, fs);
 }
}

undefined来检测是否拥有对象

剧情

剧情暂时使用传统的列表在当前位置指针方式来制作

export const FightPrefix = "[FightScene]";
export const ChangeScenePrefix = "[ChangeScene]";
export const Scene0000: SceneInfo = {
 Title: "引子 穿越的唐家三少",
 Background: "唐门",
 Lines: [
 "唐门唐三@我知道,偷入内门,偷学本门绝学罪不可恕,门规所不容。但唐三可以对天发誓,绝未将偷学到的任何一点本门绝学泄露与外界。",
 FightPrefix + "Battle0001",
 "唐门唐三@我说这些,并不是希望得到长老们的宽容,只是想告诉长老们,唐三从未忘本。以前没有,以后也没有。",
 "唐门唐三@唐三的一切都是唐门给的,不论是生命还是所拥有的能力,都是唐门所赋予,不论什么时候,唐三生是唐门的人,死是唐门的鬼,",
 "唐门唐三@我知道,长老们是不会允许我一个触犯门规的外门弟子尸体留在唐门的,既然如此,就让我骨化于这巴蜀自然之中吧。",
 "唐门长老@玄天宝录,你竟然连玄天宝录中本门最高内功也学了?",
 "唐门唐三@赤裸而来,赤裸而去,佛怒唐莲算是唐三最后留给本门的礼物。",
 "唐门唐三@现在,除了我这个人以外,我再没有带走唐门任何东西,秘籍都在我房间门内第一块砖下。唐三现在就将一切都还给唐门。",
 "唐门唐三@哈哈哈哈哈哈哈……。",
 "唐门长老@等一下。",
 "唐门唐三@(云雾很浓,带着阵阵湿气,带走了阳光,也带走了那将一生贡献给了唐门和暗器的唐三。)",
 ChangeScenePrefix + "Scene0001"
 ]
};

这里使用 FightPrefix表示进入战斗,ChangeScenePrefix表示场景转换。对话列表则使用@符号将角色和台词进行区分。

使用Angular9和TypeScript开发RPG游戏的方法

总结

到此这篇关于使用Angular9和TypeScript开发RPG游戏的文章就介绍到这了,更多相关Angular9和TypeScript开发RPG游戏内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
JavaScript 命名空间 使用介绍
Aug 29 Javascript
AngularJS语法详解(续)
Jan 23 Javascript
JavaScript使用slice函数获取数组部分元素的方法
Apr 06 Javascript
Svg.js实例教程及使用手册详解(一)
May 16 Javascript
angularjs中回车键触发某一事件的方法
Apr 24 Javascript
Easyui Datagrid自定义按钮列(最后面的操作列)
Jul 13 Javascript
vue.js数据绑定的方法(单向、双向和一次性绑定)
Jul 13 Javascript
Node.js学习之查询字符串解析querystring详解
Sep 28 Javascript
vue中多路由表头吸顶实现的几种布局方式
Apr 12 Javascript
解决mui框架中switch开关通过js控制开或者关状态时小圆点不动的问题
Sep 03 Javascript
微信小程序获取用户信息及手机号(后端TP5.0)
Sep 12 Javascript
JS异步宏队列微队列原理详解
Sep 09 Javascript
javascript+css实现进度条效果
Mar 25 #Javascript
JS实现可控制的进度条
Mar 25 #Javascript
js实现简单进度条效果
Mar 25 #Javascript
JavaScript实现简单进度条效果
Mar 25 #Javascript
JavaScript实现随机点名程序
Mar 25 #Javascript
微信小程序分享小程序码的生成(带参数)以及参数的获取
Mar 25 #Javascript
JS实现网页时钟特效
Mar 25 #Javascript
You might like
图解上海144收音机
2021/03/02 无线电
PHP新手上路(三)
2006/10/09 PHP
Discuz 5.0 中读取纯真IP数据库函数分析
2007/03/16 PHP
php &amp;&amp; 逻辑与运算符使用说明
2010/03/04 PHP
php mail to 配置详解
2014/01/16 PHP
mysql alter table命令修改表结构实例详解
2016/09/24 PHP
laravel 框架结合关联查询 when()用法分析
2019/11/22 PHP
XML+XSL 与 HTML 两种方案的结合
2007/04/22 Javascript
jquery 图片截取工具jquery.imagecropper.js
2010/04/09 Javascript
document.getElementById的简写方式(获取id对象的简略写法)
2010/09/10 Javascript
JavaScript中一个奇葩的IE浏览器判断方法
2014/04/16 Javascript
js识别不同浏览器基于userAgent做判断
2014/07/29 Javascript
js实现当复选框选择匿名登录时隐藏登录框效果
2015/08/14 Javascript
AngularJS指令用法详解
2016/11/02 Javascript
jQueryMobile之窗体长内容的缺陷与解决方法实例分析
2017/09/20 jQuery
vue2 全局变量的设置方法
2018/03/09 Javascript
html2canvas属性和使用方法以及如何使用html2canvas将HTML内容写入Canvas生成图片
2020/01/12 Javascript
JavaScript语法约定和程序调试原理解析
2020/11/03 Javascript
浅谈Python中copy()方法的使用
2015/05/21 Python
python json.loads兼容单引号数据的方法
2018/12/19 Python
详解用pyecharts Geo实现动态数据热力图城市找不到问题解决
2019/06/26 Python
Python OpenCV实现鼠标画框效果
2020/08/19 Python
如何解决django-celery启动后迅速关闭
2019/10/16 Python
详解Python中import机制
2020/09/11 Python
下面这个程序执行后会有什么错误或者效果
2014/11/03 面试题
竞选生活委员演讲稿
2014/04/28 职场文书
创意婚礼策划方案
2014/05/18 职场文书
汽车技术服务与贸易专业求职信
2014/07/20 职场文书
户籍证明模板
2014/09/28 职场文书
2015暑假实习报告范文
2015/07/13 职场文书
如何书写邀请函?
2019/06/24 职场文书
超详细Python解释器新手安装教程
2021/05/10 Python
Python爬虫:从m3u8文件里提取小视频的正确操作
2021/05/14 Python
Java日常练习题,每天进步一点点(38)
2021/07/26 Java/Android
Python自动化工具之实现Excel转Markdown表格
2022/04/08 Python
Golang 对es的操作实例
2022/04/20 Golang