博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Silverlight 2.5D RPG游戏“.NET技术”技巧与特效处理:(十二)魔法系统
阅读量:5718 次
发布时间:2019-06-18

本文共 6961 字,大约阅读时间需要 23 分钟。

  :伴着与XNA合体后的Silverlight 5 强势发布,一波Silverlight网游研发海啸即将席卷全球! 

  多磨的好事依旧让人激动,于是一不小心写下10款全新的魔法效果旨在祝贺。今天的教程不会让你失望,没错,又是一场超豪华魔法盛宴!接下来您将看到的是本教程ARPG Demo战斗实景,一切灵感与临摹均来源于近期即将内测的2.5D大作《》(以下左边为倩女幽魂实景,右边为Demo对应实景)。野蛮冲撞之幻象刺杀!自适配地形之雷电风行!完美冰冻之暴风狂雪!环形突击之圆月斩!随机多段连环突刺~毒化!自定义波浪发散之烈火轰炸!连续多段灼烧之陨石坠落!扇形范围之石化穿梭箭! 

  在线演示Demo地址:

  那么回溯到本节的主题:魔法系统是如何创建的呢?首先,我们可以将魔法和技能看做同一系统;魔法的原理与AI系统类似,从简单切入主要划分为“规则”与“使用”两个部分。“规则”包括魔法的基础性质/属性(等级、施放条件、抵抗条件、威力、附加效果、特效、物理引擎、粒子系统等等),魔法的分类(以元素为基础,日系的如气、水、火、土、光明、黑暗;中式的金、木、水、火、土,相生相克。以作用为根据,BuffDeBuff、召唤、复制、魔幻等等),以及魔法的炼化(金钱/经验/使用次数升级;装备加成;组合拆分等等)。而“使用”则面向所有不同类型的魔法从触发开始到完成所有伤害这整个流程。

  规则这部分属于策划的范畴我们暂且放它一边,本节的重点是向大家讲解Silverlight MMORPG中魔法施放的整个流程。

  首先是触发,主角施法过程通常由玩家操作鼠标右键或通过键盘的快捷键触发:

 
///
<summary>
///
游戏中鼠标右键按下
///
</summary>
void
LayoutRoot_MouseRightButtonDown(
object
sender, MouseButtonEventArgs e) {
e.Handled
=
true
;
Point p
=
e.GetPosition(space);
leader.Target
=
null
;
leader.TurnTowardsTo(p);
leader.Casting(
new
MagicArgs() {
Code
=
Convert.ToInt32(((ComboBoxItem)comboBox39.SelectedItem).Tag),
Level
=
Convert.ToInt32(((ComboBoxItem)comboBox38.SelectedItem).Tag),
SpaceLayer
=
leader.SpaceLayer,
Scale
=
leader.Scale,
Position
=
leader.Position,
Destination
=
p,
});
}
而非控角色则通常由
AI引导触发:
 
///
<summary>
///
角色行为执行
///
</summary>
void
role_ActionDecide(
object
sender, EventArgs e) {
RoleBase attacker
=
sender
as
RoleBase;
RoleBase target
=
attacker.Target;
if
(attacker.IsHostileTo(target)
&&
attacker.IsVisible) {
//
怯懦行为简单表现为不主动追击,发现被攻击时立刻逃跑
if
(target.ActionAI
==
ActionAIs.Cowardice) {
target.Target
上海企业网站设计与制作le="color: #000000;">=
null
;
target.MoveTo(
new
Point(ObjectBase.RandomSeed.Next((
int
)(target.Position.X
-
target.SightRange), (
int
)(target.Position.X
+
target.SightRange)), ObjectBase.RandomSeed.Next((
int
)(target.Position.Y
-
target.SightRange), (
int
)(target.Position.Y
+
target.SightRange))));
}
if
(target.InCircle(attacker.Position, attacker.AttackRange)) {
attacker.TurnTowardsTo(target.Position);
#region
测试用,一定机会释放魔法/技能
if
(attacker.Action
==
Actions.Casting) {
return
; }
if
(ObjectBase.RandomSeed.Next(
100
)
<
(
int
)slider13.Value) {
......
attacker.Casting(
new
MagicArgs() {
Code
=
code,
Level
=
ObjectBase.RandomSeed.Next(
1
,
4
),
SpaceLayer
=
attacker.SpaceLayer,
Scale
=
attacker.Scale,
Position
=
attacker.Position,
Destination
=
target.Position,
});
}
else
{
attacker.Attack();
}
#endregion
......
}
else
if
(target.InCircle(attacker.Position, attacker.SightRange)
||
attacker.ActionAI
==
ActionAIs.Persistent) {
//
固执行为简单表现为抓住一个目标一直追击,直至自己或目标死亡为止
attacker.MoveTo(
new
Point(ObjectBase.RandomSeed.Next((
int
)(target.Position.X
-
attacker.AttackRange), (
int
)(target.Position.X
+
attacker.AttackRange)), ObjectBase.RandomSeed.Next((
int
)(target.Position.Y
-
attacker.AttackRange), (
int
)(target.Position.Y
+
attacker.AttackRange))));
}
else
{
attacker.Target
=
null
;
attacker.Stop();
}
}
}

  接下来是动作播放,角色控件内部播放施法动作,无论是2D还是3D模型,当播放到“放出”关键帧时解析魔法配置并触发DoCasting事件:

 
//
不同动作处理
switch
(Action) {
case
Actions.Attack:
if
(frame.Current
==
frames.AttackEffect) {
if
(DoAttack
!=
null
) { DoAttack(
this
, e); }
}
break
;
case
Actions.Casting:
if
(frame.Current
==
frames.AttackEffect) {
if
(DoCasting
!=
null
) {
//
解析等级魔法具体参数
XElement info
=
Infos[
"
Magic
"
].DescendantsAndSelf(
"
Magics
"
).Elements().Single(X
=>
X.Attribute(
"
Code
"
).Value
==
magicArgs.Code.ToString());
magicArgs.AnimationCode
=
(
int
)(info.Attribute(
"
AnimationCode
"
));
magicArgs.MagicType
=
(MagicTypes)(
int
)info.Attribute(
"
MagicType
"
);
magicArgs.MagicLayer
=
(MagicLayers)(
int
)info.Attribute(
"
MagicLayer
"
);
magicArgs.MagicPosition
=
(MagicPositions)(
int
)info.Attribute(
"
MagicPosition
"
);
magicArgs.AdditionalEffect
=
(AdditionalEffects)(
int
)info.Attribute(
"
AdditionalEffect
"
);
magicArgs.SpecialEffect
=
(SpecialEffects)(
int
)info.Attribute(
"
SpecialEffect
"
);
XElement levelInfo
=
info.Element(
"
Levels
"
).Elements().Single(X
=>
X.Attribute(
"
ID
"
).Value
==
magicArgs.Level.ToString());
magicArgs.DamageMin
=
(
int
)(levelInfo.Attribute(
"
DamageMin
"
));
magicArgs.DamageMax
=
(
int
)(levelInfo.Attribute(
"
DamageMax
"
));
magicArgs.Radius
=
(
int
)(levelInfo.Attribute(
"
Radius
"
));
magicArgs.Number
=
(
int
)(levelInfo.Attribute(
"
Number
"
));
DoCasting(
this
,
new
DoCastingEventArgs() { MagicArgs
=
magicArgs });
}
}
break
;
}

  在角色所注册的DoCasting事件中通过反射来创建魔法实例并运行重写MagicBaseRun方法:

 
//
角色开始技能/魔法攻击
void
role_DoCasting(
object
sender, DoCastingEventArgs e) {
RoleBase caster
=
sender
as
RoleBase;
//
通过反射来加载并实例化各类型魔法
Assembly assembly
=
Assembly.Load(
"
Components,Version=1.0.0.0
"
);
MagicBase magic
=
assembly.CreateInstance(
string
.Format(
"
Components.Magic.{0}
"
, e.MagicArgs.MagicType.ToString()))
as
MagicBase;
magic.Run(caster, space, e.MagicArgs);
}

  依据魔法参数中的魔法类型,选择相应的具体魔法类执行具体逻辑,比如魔法实体及子魔法实体的创建、移动、特效显示、伤害处理等等,以一个圆形范围的群攻魔法为例,其逻辑组成代码如下: 

 
namespace
Components.Magic {
///
<summary>
///
圆形范围魔法
///
</summary>
public
sealed
class
CircleMagic : MagicBase {
public
override
void
Run(RoleBase caster, Space space, MagicArgs args) {
args.Position
=
args.MagicPosition
==
MagicPositions.Position
?
args.Position : args.Destination;
Point p
=
space.Terrain.GetCoordinateFromPosition(args.Position);
if
(space.Terrain.InEffectiveRange(p)) {
if
((args.SpaceLayer
==
SpaceLayers.Ground
&&
space.Terrain.Matrix[(
int
)p.X, (
int
)p.Y]
!=
0
)
||
args.SpaceLayer
==
SpaceLayers.Sky) {
AnimationBase magic
=
new
AnimationBase() { Code
=
args.AnimationCode, SpaceLayer
=
args.SpaceLayer, Position
=
args.Position, Z
=
args.MagicLayer
==
MagicLayers.Ground
?
-
1
: (
int
)args.Position.Y };
EventHandler handler
=
null
;
magic.Disposed
+=
handler
=
delegate
{
magic.Disposed
-=
handler;
space.RemoveAnimation(magic);
};
space.AddAnimation(magic);
}
}
//
space.Wave(args.Position);
for
(
int
i
=
space.AllRoles().Count
-
1
; i
>=
0
; i
--
) {
RoleBase target
=
space.AllRoles()[i];
if
(caster.IsHostileTo(target)
&&
target.InCircle(args.Position, args.Radius
*
args.Scale)) {
Targets.Add(target);
}
}
//
对精灵表中所有精灵进行魔法/技能伤害
foreach
(RoleBase role
in
Targets) {
caster.CastingToHurt(role, args);
}
Targets.Clear();
}
}
}

   一款网游能够吸引玩家的几大模块不外乎魔法、装备与探索;随着个人电脑性能跨越式飙升,当下网游更青睐以画面取悦玩家;没错,确实是屡试不爽。而魔法又是网游画面与体验的形象代言。可见,在网游开发中如能把握住魔法工序的每道细节,比如魔法与障碍的碰撞检测、动态运动轨迹、自适应及随机性、分帧处理架构、修饰及特效的组合布局等等,那么你的团队打造出一款世界顶级的网游必定指日可待,还在垂涎魔兽世界而望其项背吗?你也能做到的!

  再返回本文的开头,或许你会说这样的画面哪能和倩女幽魂Online比呀?

  请记住了,我们只是Silverlight Game Engine Developer,你懂的。Silverlight 5 目前已完美集成了XNA3D API,我相信如果您拥有一只美工水准堪称媲美雷火工作室的美术团队,使用Silverlight 5绝对能够研发出与之一拼的极品网游,甚至超越。

  。没错,轻量化的网游正需要像Silverlight这样高研发效率、高性能、完全动态布局的RIA来实现;Silverlight 2.5D/3D网游时代已扬帆起航,所有的一切都是从零开始,完全自主的知识产权,完全自主研发的核心引擎、辅助工具,高度可维护性与拓展性,零外部依赖;俗话说的好:拽在自己手中的东西才最踏实,而Silverlight让我们开发者从心记忆着每个工序流程,没错,一切都属于你。我们可以面朝世界昂首呐喊:Silverlight 网游,中国造!

  这才是我们国人的骄傲!

  兵法曰:兵贵神速。不需要“十年一剑”,一年足矣。缔造的神话只有伴着酸甜苦辣走来的我们深刻体会。今日,当3D页游领域依旧仿若白纸一张时,我相信谁都迫切渴望通过最短的时间攻占世界前沿技术之巅峰!

  Silverlight 5 正预言着这么一个奇迹:中国的网游将在世界重新崛起,变革便在今朝!

  本节源码请到中下载

  在线演示地址:

转载于:https://www.cnblogs.com/waw/archive/2011/10/13/2210667.html

你可能感兴趣的文章
时间助理 时之助
查看>>
nginx快速安装
查看>>
自定义转场动画
查看>>
英国征召前黑客组建“网络兵团”
查看>>
Silverlight 2.5D RPG游戏“.NET技术”技巧与特效处理:(十二)魔法系统
查看>>
[NPM] Run npm scripts in series
查看>>
vs2013修改书签(vs书签文件位置)
查看>>
BZOJ 1923: [Sdoi2010]外星千足虫 [高斯消元XOR]
查看>>
C语言学习笔记
查看>>
PHP 命令行模式实战之cli+mysql 模拟队列批量发送邮件(在Linux环境下PHP 异步执行脚本发送事件通知消息实际案例)...
查看>>
几种进程间的通信方式
查看>>
PS 如何使用液化工具给人物减肥
查看>>
cvc-complex-type.2.4.c: The matching wildcard...
查看>>
android 读取json数据(遍历JSONObject和JSONArray)
查看>>
pyjamas build AJAX apps in Python (like Google did for Java)
查看>>
<JavaScript语言精粹>-读书笔记(一)
查看>>
NPM教程
查看>>
Java学习笔记(40)——Java集合12之fail-fast
查看>>
Centos 配置IP的方式
查看>>
Go 的吉祥物,萌不萌
查看>>