使用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 相关文章推荐
两个DIV等高的JS的实现代码
Dec 23 Javascript
js操纵跨frame的三级联动select下拉选项实例介绍
May 19 Javascript
JS实现在状态栏显示打字效果完整实例
Nov 02 Javascript
javascript每日必学之循环
Feb 19 Javascript
关于Vue.js一些问题和思考学习笔记(1)
Dec 02 Javascript
jQuery、zepto、js常用小技巧
Feb 12 Javascript
微信小程序视图template模板引用的实例详解
Sep 20 Javascript
深入浅析Vue.js中 computed和methods不同机制
Mar 22 Javascript
Node.js命令行/批处理中如何更改Linux用户密码浅析
Jul 22 Javascript
原生JS+HTML5实现的可调节写字板功能示例
Aug 30 Javascript
Vue.set() this.$set()引发的视图更新思考及注意事项
Aug 30 Javascript
vue单元格多列合并的实现
Nov 26 Vue.js
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
刚才在简化php的库,结果发现很多东西
2006/12/31 PHP
php中session_unset与session_destroy的区别分析
2011/06/16 PHP
浅析使用Turck-mmcache编译来加速、优化PHP代码
2013/06/20 PHP
php预定义变量使用帮助(带实例)
2013/10/30 PHP
CodeIgniter中实现泛域名解析
2014/07/19 PHP
叫你如何修改Nginx与PHP的文件上传大小限制
2014/09/10 PHP
PHP超牛逼无限极分类生成树方法
2015/05/11 PHP
PHP面向对象详解(三)
2015/12/07 PHP
BOOM vs RR BO5 第二场 2.14
2021/03/10 DOTA
javascript Array.sort() 跨浏览器下需要考虑的问题
2009/12/07 Javascript
jquery中动态效果小结
2010/12/16 Javascript
浅谈javascript的原型继承
2012/07/25 Javascript
js判断iframe内的网页是否滚动到底部触发事件
2014/03/18 Javascript
JS实现网页滚动条感应鼠标变色的方法
2015/02/26 Javascript
轻松搞定jQuery.noConflict()
2016/02/15 Javascript
DOM 事件的深入浅出(一)
2016/12/05 Javascript
Webpack常见静态资源处理-模块加载器(Loaders)+ExtractTextPlugin插件
2017/06/29 Javascript
js实现水平滚动菜单导航
2017/07/21 Javascript
[js高手之路]单例模式实现模态框的示例
2017/09/01 Javascript
[06:01]刀塔次级联赛top10第一期
2014/11/07 DOTA
python3 面向对象__类的内置属性与方法的实例代码
2018/11/09 Python
Python爬取知乎图片代码实现解析
2019/09/17 Python
python并发爬虫实用工具tomorrow实用解析
2019/09/25 Python
使用Pycharm分段执行代码
2020/04/15 Python
python+adb+monkey实现Rom稳定性测试详解
2020/04/23 Python
pycharm 关闭search everywhere的解决操作
2021/01/15 Python
阿玛瑞酒店中文官方网站:Amari.com
2018/02/13 全球购物
焊接专业毕业生求职信
2013/10/01 职场文书
高中的职业生涯规划书
2013/12/28 职场文书
中医临床专业自我鉴定范文
2014/01/15 职场文书
作弊检讨书
2015/01/27 职场文书
大学生敬老院活动总结
2015/05/07 职场文书
四风之害观后感
2015/06/09 职场文书
消防宣传语大全
2015/07/13 职场文书
初中生活随笔
2015/08/15 职场文书
javascript的setTimeout()使用方法总结
2021/11/20 Javascript