分享创作 RPG 战斗框架的制作思路

不宕 · 2020年07月26日 · 最后由 清风明月178 回复于 2020年08月01日 · 91 次阅读

前言

long time on see 好久不用呀,这里宕,前号(能宕就宕)忘记密码了。之前的地图和背包已经沉贴了,估计是实用性不大。那么,今天就在这里简单给大家聊聊RPG游戏的心脏——对战系统,怎么做 (建议有一定代码基础)

话不多说,上菜 这是一个简易的战斗系统,而且还挺全面的,而且方便新手操作 才怪 咳咳,没事,看不懂咱们慢慢讲,实在不行你起码会抄了呀。

注:需要更深层次的研究我这里没得,就是简易版的

正文

=:function 人物(name,zy,atk,ins,hp,def,dog,crit,crid,spd){this.name=name,this.zy=zy,this.atk=atk,this.ins=ins,this.hp=hp,this.def=def,this.dog=dog,this.crit=crit,this.crid=crid,this.spd=spd}

=:MD.player=new 人物("青菜","剑客",100,500,1000,50,0.8,0.5,0.35,90)

=://名字 ,职业,攻击力,内力,生命,防御,闪避,暴击,速度

首先是数据库的创立,以上面为例,用构造函数创建一个MD.player对象,里面包含了name,zy, 具体格式为:=:function 你要设定的库名(包含属性,){属性参数,},需要一一对应

而下面几个库,得先创建[数组]这个大箱子,把东西放在这个大箱子里代号为0,1,2的小格子里

=:MD.暗器=[]

=:function 暗器(name,atk,fl,pro,pak,time,xg,ms,shu){this.name=name,this.atk=atk,this.fl=fl,this.pro=pro,this.pak=pak,this.time=time,this.xg=xg,this.ms=ms,this.shu=shu}

=://名字 纯伤 分类 概率 伤害率 持续 效果 描述 数量

=:MD.暗器[0]=new 暗器("飞刀",200,1,0,0,0,"无","伤害100",100);MD.暗器[1]=new 暗器("毒针",100,2,0.9,0.1,2,"中毒","伤害100<hr>中毒率:25%<hr>中毒伤害:20%<hr>持续2回合",100)

=:MD.药品=[]

=:function 药品(name,fl,num,xg,ms,shu){this.name=name,this.fl=fl,this.num=num,this.xg=xg,this.ms=ms,this.shu=shu}

=://名字 分类 数字 效果 描述 数量

=:MD.药品[0]=new 药品("回魂丹",1,0.25,"百分比","回复25%的生命",100);MD.药品[1]=new 药品("解毒丹",2,0,"解毒","解开中毒状态",100)

=:MD.技能=[]

=:function 技能(name,atk,fl,con,pak,xg,time,ms){this.name=name,this.atk=atk,this.fl=fl,this.con=con,this.pak=pak,this.xg=xg,this.time=time,this.ms=ms}

=://名字 纯伤 分类 消耗 伤害率 效果 持续 描述

=:MD.技能[0]=new 技能("降龙十八掌",300,1,200,0,0,"无","造成300点伤害")

=:MD.技能[1]=new 技能("飞龙在天",0,2,120,1.8,0,0,"造成伤害的180%")

=:MD.技能[2]=new 技能("吸星大法",0,3,80,0.2,"吸血",0,"吸收敌方血量20%")

=:MD.技能[3]=new 技能("斗转星移",0,3,80,0.2,"反甲",3,"反弹对方伤害20% 持续3回合")

=://ch 机会 bj暴击 mz命中

大家也可以不用这个数据库,各显神通吧,如果数据多了这个大箱子还是很重要

下面是战斗中数据了,都采用函数的形式,方便使用,当然你可以直接放在战斗过程中慢慢判定,也方便检查错误

首先是普攻,判断闪避和暴击,再输出伤害,闪避看个人闪避率(也可以用速度大小什么的,这里没加速度,如果要加速度会有先后手,可以放游戏前判断),暴击靠暴击率加暴击伤害,大家可以自行修改判断方式。sub是主,obj是对象,sh是伤害,lh是后面用的滚动提醒,然后加一个检测,负责看buff有没有反甲(buff我没搞太多,大家自行脑洞,破甲,泣血什么的),同时也设计有防止重复buff的功能

回合清空是放最后重置数据(sub,obj)用的,同时担任判断有没有debuff

=:function 战斗(x,y){obj=y;var mz=random_choice_adv([1, y.dog], [2, 1-y.dog]);if(mz==1){lh=lh+"<br>(2)"+x.name+"(/2)对(5)"+y.name+"(/5)的攻击被闪避了"}else{sh=x.atk-y.def;var bj=random_choice_adv([1, x.crit], [2, 1-x.crit]);if(bj==1){sh=sh+sh*x.crid;lh=lh+"<br>(2)"+x.name+"(/2)对(5)"+y.name+"(/5)造成(4)"+sh+"(/4)点暴击伤害"}else{lh=lh+"<br>(2)"+x.name+"(/2)对(5)"+y.name+"(/5)造成(4)"+sh+"(/4)点伤害"};obj.zhp-=sh;检测(obj)}}

=:function 回合清空(){hh++;lh="第"+hh+"回合";hx=0;obj=0;xz.yw[1]=1;xz.aq[1]=1;状态(you);状态(me);状态清除(you);状态清除(me);sub=0;obj=0}

唐三 大家都懂吧 是暗器,1负责判断有没有过量,2输出伤害,3添加附加效果 fl是分类,直接伤害,伤害加成,特殊效果,这里分开来了,当然如果是强力技能会同时有伤害和效果,看你怎么搞咯,可以多个fl什么的 xg效果是fl的细化,也就是判断中包裹判断,来选择合适的代码运行

磕药1也是判断是否过量,2是通过fl xg看效果,中毒那个可能没用,对面没暗器,不过可能对面普攻带毒,或者技能带毒 蛤蟆功

技能1是判断蓝够不够,2是效果的判断,同上

检测上面说了,状态就是中毒什么的扣血,清空就是到time持续时间 后解除,目前叠加的解决办法就是sh伤害调0 然后只输出一个,大家到时候自己看怎么搞方便些,因为我还没给对方装ai,可能会无脑用技能反甲,不过只一个有用,大家可以给敌人多几个判断,这样子有可打性

...说起来,突然发现中毒好像可能会叠加,算了,不管了,晚点搞搞

=:function 唐三(x){if(xz.aq[0]==0){game_createmsg("本次战斗已达到最大使用暗器次数","3","left",5)}else if(xz.aq[1]==0){game_createmsg("本回合已使用暗器","3","left",5)}else if(x.shu==0){game_createmsg("数量不足","3","left",5)}else{x.shu--;xz.aq[0]--;xz.aq[1]--;唐三2(id)}}

=:function 唐三2(x){sh=x.atk;lh=lh+"<br>(2)"+sub.name+"(/2)使用暗器(4)"+x.name+"(/4)对(5)"+obj.name+"(/5)造成(4)"+sh+"(/4)伤害";if(x.fl==2){ch=random_choice_adv([1, x.pro], [2, 1-x.pro]);if(ch==1){唐三3(id)}};obj.zhp-=sh}

=:function 唐三3(x){for(ch=0;ch<obj.buff.xg.length;ch++){if(obj.buff.xg[ch]==x.xg){obj.buff.xg.splice(ch,1);obj.buff.time.splice(ch,1);obj.buff.pak.splice(ch,1)}};obj.buff.xg.push(x.xg);obj.buff.time.push(x.time);obj.buff.pak.push(x.pak);lh=lh+"<br>"+obj.name+x.xg}

=:function 磕药(x){if(xz.yw[0]==0){game_createmsg("本次战斗已达到最大使磕药次数","3","left",5)}else if(xz.yw[1]==0){game_createmsg("本回合已磕药","3","left",5)}else if(x.shu==0){game_createmsg("数量不足","3","left",5)}else{x.shu--;xz.yw[0]--;xz.yw[1]--;lh=lh+"<br>"+sub.name+"使用了(4)"+x.name+"(/4)";磕药2(id)}}

=:function 磕药2(x){if(x.fl==1){if(x.xg=="百分比"){hx=sub.hp*x.num;sub.zhp+=hx;lh=lh+",回复了(4)"+hx+"(/4)血量"};if(x.fl==2){var wu=0;for(ch=0;ch<sub.buff.xg.length;ch++){if(sub.buff.xg[ch]==x.xg){sub.buff.xg.splice(ch,1);sub.buff.pak.splice(ch,1);sub.buff.time.splice(ch,1);lh=lh+",清除了(4)"+x.xg+"(/4)效果";wu=1}}};if(wu==0){lh=lh+",无效"}}}

=:function 技能(x){if(sub.zins<x.con){game_createmsg("内力不够","3","left",5)}else{sub.zins-=x.con;lh=lh+"<br>"+sub.name+"使用(4)"+x.name+"(/4)";技能2(id)}}

=:function 技能2(x){if(x.fl==1){sh=x.atk;lh=lh+",对敌方造成(4)"+sh+"(/4)点伤害"};if(x.fl==2){sh=sub.atk*x.pak;lh=lh+",对敌方造成(4)"+sh+"(/4)点伤害"};if(x.fl==3){if(x.xg=="吸血"){sh=obj.zhp*x.pak;sub.zhp+=sh;lh=lh+"<br>(5)"+obj.name+"(/5)被(2)"+sub.name+"(/2)吸了(4)"+sh+"(/4)点血"};if(x.xg=="反甲"){sub.buff.xg.push(x.xg);sub.buff.time.push(x.time);sub.buff.pak.push(x.pak)}};obj.zhp-=sh;if(sh!=0){检测(obj)}}

=:function 检测(x){for(ch=0;ch<x.buff.xg.length;ch++){var ci=1;if(x.buff.xg[ch]=="反甲"){sh=sh*x.buff.pak[ch];if(ci==1){lh=lh+"<br>(5)"+sub.name+"(/5)受到(4)"+sh+"(/4)点反弹伤害"};sub.zhp-=sh;sh=0;ci=2}}}

=://ci次数

=:function 状态(x){for(ch=0;ch<x.buff.xg.length;ch++){if(x.buff.xg[ch]=="中毒"){sh=x.zhp*x.buff.pak[ch];x.zhp-=sh;lh=lh+"<br>(5)"+x.name+"(/5)中毒,受到(4)"+sh+"(/4)点伤害"}}}

=:function 状态清除(x){for(ch=0;ch<x.buff.time.length;ch++){x.buff.time[ch]--;if(x.buff.time[ch]==0){x.buff.xg.splice(ch,1);x.buff.time.splice(ch,1);x.buff.pak.splice(ch,1)}}}

=://战斗用函数

然后就说主页面什么的,可供玩家查看效果,同时为了方便直接连接了战斗,通过zt状态来判断能不能使用

也是用咱们的背包,知道的应该会这个神技了没有单独讲,但是出现在小富翁那个贴里,大家觉得牛逼 但是看不懂想学可以下方评论,我可以多加个小贴子讲讲

[1]
=:var zt=0
[|]
<center><fieldset style="width:100%; border:#7fff00;"><legend style="color:#0f0;font-weight:800;">战斗系统1.0.1</legend><marquee behavior="scroll" direction="right" scrollamount=10><FONT color=#0FF size=4>江湖,不是幻想!</FONT></marquee></fieldset>
<br>(b)1(/b)<br>&nbsp<br>(b)2(/b)<br>&nbsp<br>(b)3(/b)<br>&nbsp<br>(b)4(/b)<br>&nbsp<br>(b)5(/b)
选:职业
选:药品
>:var fl=MD.药品
选:暗器
>:var fl=MD.暗器
选:技能
>:var fl=MD.技能
选:对战

>:game_jumpto("2")

[2]
>:var yes=0
[21]
[|]
<center><br>(b)1(/b)<br>&nbsp<br>(b)2(/b)<br>&nbsp<br>(b)3(/b)<br>&nbsp<br>(b)4(/b)
选:(j)fl[yes].name(/j)
<:if(fl[yes]==undefined){curBtn = null}
>:var id=fl[yes];fid=yes
选:(j)fl[yes+1].name(/j)
<:if(fl[yes+1]==undefined){curBtn = null}
>:var id=fl[yes+1];fid=yes+1
选:(j)fl[yes+2].name(/j)
<:if(fl[yes+2]==undefined){curBtn = null}
>:var id=fl[yes+2];fid=yes+2
选:(j)fl[yes+3].name(/j)
<:if(fl[yes+3]==undefined){curBtn = null}
>:var id=fl[yes+3];fid=yes+3
选:上一页
<:if(yes==0){curBtn=null}
>:yes=yes-4;game_jumpto("21")
选:下一页
>:yes=yes+4;game_jumpto("21")
选:返回
>:if(zt!=0){zt=1;game_jumpto("轮换")}else{game_jumpto("1")}

=://if(fid==1){game_jumpto("3")}else{game_jumpto("4")}

[3]
[|]
<center>(j)id.ms(/j)
<hr>(j)if(id.shu!=undefined)"你有"+id.shu+"个"+id.name(/j)
选:使用
<:if(zt!=2){curBtn=null}
>:磕药(id);game_jumpto("轮换")
选:使用
<:if(zt!=3){curBtn=null}
>:唐三(id);game_jumpto("轮换")
选:使用
<:if(zt!=4){curBtn=null}
>:技能(id);game_jumpto("轮换")
选:返回
>:game_jumpto("2")

职业什么的看大家需要吧,当然装备什么的我也没加,大家可以自行研究设定

战斗那个页面,选人下方看到在一开始那个构造函数了么,就是这么用的,不过大家如果需要随机属性,可以自己想办法,图书馆有随机数字的代码,我也不知道咋搞方便些,这也涉及到你游戏的平衡性,最伤脑子了

[职业]
=:function 获取(){MD.player.name=document.getElementById("name").value}

=:function 职业(a,b,c){MD.player.zy=a,MD.player.spd=b,MD.player.atk=c}
[|]
<center>名字:(j)MD.player.name(/j)<br>名字修改:<input id="name" size="10" maxlength="10">(b)1(/b)</center>
<hr>「气血」:(j)MD.player.hp(/j)<br>(3)「职业」:(j)MD.player.zy(/j)<br>「武力」:(j)MD.player.atk(/j)(/3)<br>「内力」:(j)MD.player.ins(/j)<br>「防御」:(j)MD.player.def(/j)<br>「闪避」:(j)MD.player.dog(/j)<br>「暴击率」:(j)MD.player.crit(/j)<br>「暴击伤害」:(j)MD.player.crid(/j)<br>(3)「身法」:(j)MD.player.spd(/j)<br>(/3)
<hr><center>职业更换:<br>(b)2(/b)<br>(b)3(/b)<br>(b)4(/b)
选:提交
>:获取()
选:刀客
>:职业("刀客",100,80)
选:剑客
>:职业("剑客",90,100)
选:拳师
>:职业("拳师",80,120)
选:返回>:game_jumpto("1")


跳:职业

[对战]
<center>(2)请选择你的对战对象:(/2)<hr>(b)1(/b)<br>&nbsp<br>(b)2(/b)<br>&nbsp<br>(b)3(/b)
选:萝卜
>:var you=new 人物("萝卜","剑客",100,500,2000,50,0.15,0.03,0.08,100);you.skill=MD.技能[0]
选:咸鱼
>:var you=new 人物("咸鱼","刀客",120,500,2000,50,0.15,0.03,0.08,90);you.skill=MD.技能[1]
选:石头
>:var you=new 人物("石头","拳师",80,500,2000,50,0.15,0.03,0.08,100);you.skill=MD.技能[2]
选:机器人
>:var you=new 人物("机器人","拳师",80,500,10000,50,0.15,0.03,0.08,100);you.skill=MD.技能[3]
选:返回
>:game_jumpto("1")

跳:战前

战前 搞了个进度条,论坛里有,现学现卖的,主要是美观,哈哈,没什么用的

战前数据负责把我方数据录入me里,you是即时生成的,不用录了,但是需要多加双方的buff管理。还有一些杂物,如血量条,都是简易版的,从头简到尾

[战前]
=:var x=0

=:function a(){if(x!=100){x++;document.getElementById("a").value=x;document.getElementById("c").innerHTML=x+"%"}else{clearInterval(int);c()}};

=:var int=setInterval("a()",5);

=:function c(){$("#d").fadeIn(1500)};

=:function b(){game_jumpto("战前数据")}

<center>(3)请耐心等待!(/3)</center>
<style>progress.p{border-radius:3px;border:2px solid #000000;width:300px;height:20px}progress.p::-webkit-progress-bar{background:#FFF}progress.p::-webkit-progress-value{background: #7FFF00;border-radius:1px}</style>
<progress class="p" value=(j)x(/j) max="100" id="a" style="position:absolute;top:50px"/><p id="c" style="position:absolute;top:50px;left:150px">(j)x(/j)%</p>
<p id="d" style="display:none;color:#0FF" align="center" onclick="b()">加载完成,点击开始战斗</p>
<center>(5)进度条没满点开始会返回(/5)

选:开始战斗
>:if(x==100){game_jumpto("战前数据")}else{game_jumpto("对战");x=100}

[战前数据]

=:var me=MD.player;me.zhp=me.hp;you.zhp=you.hp;me.zins=me.ins;you.zins=you.ins;you.khp=0;you.kins=0

=:me.buff={xg:[],time:[],pak:[]};you.buff={xg:[],time:[],pak:[]}

=://角色录入

>:function a(){if(me.zhp<me.hp){document.getElementById("a1").value=me.zhp;document.getElementById("a2").innerHTML=Math.round(me.zhp/me.hp*100)+"%"};if(you.zhp<you.hp){document.getElementById("b1").value=you.hp-you.zhp;document.getElementById("b2").innerHTML=Math.round(you.zhp/you.hp*100)+"%"}if(me.zins<me.ins){document.getElementById("a3").value=me.zins;document.getElementById("a4").innerHTML=Math.round(me.zins/me.ins*100)+"%"};if(you.zins<you.ins){document.getElementById("b3").value=you.ins-you.zins;document.getElementById("b4").innerHTML=Math.round(you.zins/you.ins*100)+"%"}}

=:setInterval("a()",150);

=://进度条

=:var lh="第1回合";var lis=["","","","","",""];zt=1;var sh=0;var hx=0;var hh=1;var obj;var sub;var xz={yw:[5,1],aq:[10,1]}



=://轮换1 轮换2 状态 伤害 回血 回合 对象 限制:药物 暗器

战斗中具体操作就是调用设好的函数,代入即可,敌人简单判断,因为只有技能和普攻,用和我们一样的函数也行,因为这时obj变了

那一大块上面是进度条,中间是双方数据,下面是滚动

[战斗]
=:sh=0;sub=me;obj=you

=:if(me.zhp<=0){game_jumpto("输")};if(you.zhp<=0){game_jumpto("赢")}

[|]
<style>progress{border-radius:3px;border:2px solid #F0FFFF;width:100px;height:20px}progress.pro::-webkit-progress-bar{background:#C0C0C0}progress.pro::-webkit-progress-value{background: #7FFF00;border-radius:1px}progress.pro2::-webkit-progress-bar{background:#C0C0C0}progress.pro2::-webkit-progress-value{background: #0FF;border-radius:1px}progress.pro3::-webkit-progress-bar{background:#7FFF00}progress.pro3::-webkit-progress-value{background: #C0C0C0;border-radius:1px}progress.pro4::-webkit-progress-bar{background:#0FF}progress.pro4::-webkit-progress-value{background:#C0C0C0 ;border-radius:1px}</style>
<progress class="pro" value=(j)me.zhp(/j) max=(j)me.hp(/j) id="a1" style="position:absolute;top:25px"/><p id="a2" style="position:absolute;top:25px;left:110px">&nbsp(j)Math.round(me.zhp/me.hp*100)(/j)%</p><p id="b2" style="position:absolute;top:25px;right:110px">(j)Math.round(you.zhp/you.hp*100)(/j)%&nbsp</p><progress class="pro3" value=(j)you.hp-you.zhp(/j) max=(j)you.hp(/j) id="b1" style="position:absolute;right:0;top:25px"/><hr><progress class="pro2" value=(j)me.zins(/j) max=(j)me.ins(/j) id="a3" style="position:absolute;" /><p id="a4" style="position:absolute;left:110px">&nbsp(j)Math.round(me.zins/me.ins*100)(/j)%</p><p id="b4" style="position:absolute;right:110px">(j)Math.round(you.zins/you.ins*100)(/j)%&nbsp</p><progress class="pro4" value=(j)you.ins-you.zins(/j) max=(j)you.ins(/j) id="b3" style="position:absolute;right:0"/>
<hr><p style="position:absolute;center">第(j)hh(/j)回合</p>
<p style="position:absolute;left">(j)me.name(/j)<br>「职业」:(2)(j)me.zy(/j)(/2)<br>「气血」:(2)(j)Math.round(me.zhp)(/j)(/2)/(4)(j)me.hp(/j)(/4)<br>「内力」:(2)(j)Math.round(me.zins)(/j)(/2)/(4)(j)me.ins(/j)(/4)<br>「武力」:(2)(j)me.atk(/j)(/2)<br>「buff」:(j)me.buff.xg(/j)</p><p style="position:absolute;right:0px">(j)you.name(/j)<br>「职业」:(2)(j)you.zy(/j)(/2)<br>「气血」:(2)(j)Math.round(you.zhp)(/j)(/2)/(4)(j)you.hp(/j)(/4)<br>「内力」:(2)(j)Math.round(you.zins)(/j)(/2)/(4)(j)you.ins(/j)(/4)<br>「武力」:(2)(j)you.atk(/j)(/2)<br>「buff」:(j)you.buff.xg(/j)</p><center>(b)1(/b)<br>(b)2(/b)<br>(b)3(/b)<br>(b)4(/b)</center>
(j)lis[0](/j)<br>(j)lis[1](/j)<br>(j)lis[2](/j)<br>(j)lis[3](/j)<br>(j)lis[4](/j)<br>(j)lis[5](/j)
选:攻击
选:药品
>:var fl=MD.药品;game_jumpto("2");zt=2
选:暗器
>:var fl=MD.暗器;game_jumpto("2");zt=3
选:技能
>:var fl=MD.技能;game_jumpto("2");zt=4
选:返回

跳:战斗

[攻击]
=:战斗(me,you);zt=5

跳:轮换
[轮换]
=:if(zt!=5&&zt!=4&&zt!=6){game_jumpto("战斗")}

[敌人]
=:sh=0;sub=you;obj=me;var id=you.skill

=:if(you.zins>=you.skill.con){var ms=random_choice_adv([1, 0.6], [2, 0.4])}else{ms=1}

=:if(ms==1){战斗(you,me);zt=5}else{技能(id)}

=://ms 模式

=:var j;for(var i=4;i>=0;i--){j=i+1;lis[j]=lis[i]};lis[0]=lh;lh=""

=:回合清空()

跳:战斗

[赢]
成功: You win,感谢游玩

[输]
失败:You lose,再接再厉

后记

可能对新手有点难度,建议了解js函数和判断,这两个是我们框架的核心,也需要你一定的思维逻辑,总的来说还是很简单的,因为就是无脑堆判断

如果有不会的段落下面知会一声,尽可能解答,要是你想做RPG并且觉得这个教程有用的话可以 一键三连加关注 月票投起来

共收到 4 条回复

支持ヾ(✿゚▽゚)ノ

大佬o( ̄▽ ̄)d

哈哈,感谢大佬们捧场

星季工作室会骗钱,金钱方面不要相信

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册