Silverlight MMORPG网页游戏开发课程[一期] 第十二课:战斗系统之普通攻击

本文主要是介绍Silverlight MMORPG网页游戏开发课程[一期] 第十二课:战斗系统之普通攻击,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

引言

通常来说RPG游戏中的战斗系统按类型(AttackType)大致可划分为普通攻击和技能攻击两大类。其中较常见的普通攻击有近距离单体物理攻击、远距离单体物理攻击和远距离单体魔法攻击。本节,我们将通过为精灵控件添加一些新的事件和属性,轻松实现RPG战斗系统中的简单AI及普通攻击战斗效果。

12.1战斗系统之普通攻击(交叉参考:经典式属性设计及完美的物理攻击系统 战斗前夜之构建动态障碍物系统 人工智能(AI)之追踪者 锦上添花之魔法特效装饰 远距离单体攻击与单体魔法)

11.1中我们利用Silverlight中的命中测试来获取鼠标划过时的精灵对象,ARPG中的战斗操作大都需要通过鼠标左、右键的点击实现普通攻击和技能攻击,因此本节我们首先为游戏的LayoutRoot注册鼠标左键点击(路由)事件:

09130737_I6SS.gif 代码
        Sprite leftButtonClickSprite;  // 左键点中的精灵
         ///   <summary>
        
///  游戏中鼠标左键点击
        
///   </summary>
         void  LayoutRoot_MouseLeftButtonDown( object  sender, MouseButtonEventArgs e) {
            Point p 
=  e.GetPosition(scene);
            List
< Sprite >  hitSprites  =  HitSprite(e.GetPosition(LayoutRoot));
            
bool  IsHitSprite  =   false ;
            
for  ( int  i  =   ; i  <  hitSprites.Count; i ++ ) {
                
if  (hitSprites[i].InPhysicalRange(e.GetPosition(hitSprites[i]))) {
                    
bool  isHostile  =  hero.IsHostileTo(hitSprites[i].Camp);
                    
if  (leftButtonClickSprite  !=  hitSprites[i]) {
                        
if  (leftButtonClickSprite  !=   null ) {
                            
// 移除上一次点中精灵选中特效
                            leftButtonClickSprite.RemoveSelectedEffect();
                            
// 移除上一次点中精灵的事件
                            leftButtonClickSprite.LifeChanged  -=  UpdateTargetInfoLife;
                            leftButtonClickSprite.LifeMaxChanged 
-=  UpdateTargetInfoLife;
                        }
                        leftButtonClickSprite 
=  hitSprites[i];
                        
// 注册选中精灵更新生命值事件
                        hitSprites[i].LifeChanged  +=  UpdateTargetInfoLife;
                        hitSprites[i].LifeMaxChanged 
+=  UpdateTargetInfoLife;
                        
// 更新HUD中目标精灵资料
                        targetInfo.Update(hitSprites[i].FullName, hitSprites[i].Avatar, hitSprites[i].Level, hitSprites[i].Life, hitSprites[i].LifeMax);
                        
// 添加选中特效
                        Animation animation  =   new  Animation() { Code  =  isHostile  ?   5  :  4 , Coordinate  =  hitSprites[i].Center, Z  =   - 1  };
                        EventHandler handler 
=   null ;
                        animation.Disposed 
+=  handler  =   delegate  {
                            animation.Disposed 
-=  handler;
                            hitSprites[i].RemoveSelectedEffect();
                        };
                        hitSprites[i].AddSelectedEffect(animation);
                    }
                    
// 主角向敌对目标精灵移动
                     if  (isHostile) {
                        hero.Target 
=  hitSprites[i];
                        hero.FightDetect 
-=  sprite_FightDetect;
                        hero.FightDetect 
+=  sprite_FightDetect;
                        
if  (hero.InCircle(hero.Target.Coordinate, hero.AttackDistance)) {
                            hero.TowardTo(hero.Target);
                            hero.Attack();
                        } 
else  {
                            hero.RunTo(Scene.GetWindowCoordinate(hero.Target.Coordinate));
                        }
                    }
                    targetInfo.Visibility 
=  Visibility.Visible;
                    IsHitSprite 
=   true ;
                    
break ;
                }
            }
            
if  ( ! IsHitSprite) {
                hero.Target 
=   null ;
                hero.FightDetect 
-=  sprite_FightDetect;
                
// 主角向目标点移动
                hero.RunTo(p);
                
// 加入点击水滴
                Animation water  =   new  Animation() { Code  =   3 , Coordinate  =  p, Z  =   - 1  };
                EventHandler handler 
=   null ;
                water.Disposed 
+=  handler  =   delegate  {
                    water.Disposed 
-=  handler;
                    scene.RemoveAnimation(water);
                };
                scene.AddAnimation(water);
            }
        }

战斗存在一个前置条件,主角将要面对的精灵是否处于敌对阵营?于是我们还需为精灵添加一个描述阵营的属性Camp

09130737_I6SS.gif 代码
         ///   <summary>
        
///  获取或设置阵营
        
///   </summary>
         public  Camps Camp {  get set ; }

        
///   <summary>
        
///  阵营
        
///   </summary>
         public   enum  Camps {
            
///   <summary>
            
///   正义
            
///   </summary>
            Justice  =   ,
            
///   <summary>
            
///  中立
            
///   </summary>
            Neutrality  =   1 ,
            
///   <summary>
            
///  邪恶
            
///   </summary>
            Eval  =   2
        }

    当鼠标左键击中某个精灵对象时,通过分析主角与对方的阵营关系从而得出是否应该对其发动攻击,如果是则设置主角的攻击对象(Target)为该精灵,并向其冲去(RunTo)

主角的这些逻辑全都在鼠标左键点击事件中实现,那么如果是非主角(比如怪物类)的精灵呢?它们该如何自动(非控)的产生类似的攻击意识和行为?这就要游戏将要涉及到的AI逻辑。

接下来,我为精灵再添上了3个关于攻击这方面的重要事件:

         ///   <summary>
        
///  环境侦测
        
///   </summary>
         public   event  EventHandler Detect;

        
///   <summary>
        
///  战斗侦测
        
///   </summary>
         public   event  EventHandler FightDetect;

        
///   <summary>
        
///  普通攻击
        
///   </summary>
         public   event  EventHandler DoAttack;

    它们所触发的位置如下:

        public  Sprite() {
            
// ObjectTracker.Track(this);
             this .CacheMode  =   new  BitmapCache();
            
this .Children.Add(fullName);
            lifePanel.Children.Add(lifeBorder);
            lifeBorder.Child 
=  lifeRect;
            
this .Children.Add(lifePanel);
            
auxiliary.Interval  =  TimeSpan.FromMilliseconds( 2000 );
            auxiliary.Tick 
+=   new  EventHandler(auxiliaryTick);
            auxiliary.Start();
        }

        Frame frame;
        Frames frames;
        Dictionary
< string , Point2D >  frameOffset  =   new  Dictionary < string , Point2D > ();  // 各帧偏移
         protected   override   void  HeartTick( object  sender, EventArgs e) {
            
string  key  =   string .Format( " {0}-{1}-{2} " , ( int )State, ( int )Direction, frame.Current);
            
if  (IsResReady) {
                BodySource 
=  Global.GetWebImage( string .Format( " Sprite/{0}/{1}.png " , Code, key));
                BodyPosition 
=  frameOffset[key];
            } 
else  {
                BodySource 
=  Global.GetProjectImage( string .Format( " Model/Sprite/{0}/{1}.png " , ModelCode, key));
                BodyPosition 
=   new  Point2D( );
            }
            frame.Current
++ ;
            
if  (frame.Current  >  frame.Total) {
                
switch  (State) {
                    
case  States.Attack:
                        
if  (DoAttack  !=   null ) { DoAttack( this , e); }
                        
break ;
                    
case  States.Injure:
                    
case  States.Casting:
                        Stand();
                        
break ;
                }
                frame.Current 
=   ;
            }
            
// 进行攻击侦测
             if  (FightDetect  !=   null ) { FightDetect( this , e); }
        }

        
bool  auxiliaryTicked  =   false ; // 测试用
         void  auxiliaryTick( object  sender, EventArgs e) {
            
// 间隔环境侦测
             if  (Detect  !=   null ) { Detect( this , e); }
            auxiliaryTicked 
=   true ;
        }

且听我一一道来。

首先是Detect事件,每隔2秒触发一次(实际开发中至少1秒用处会更广,比如中毒伤血处理等)。它的作用是实现精灵每隔一段时间对周围的环境进行侦测,包括判断自身是否已处于屏幕内,主角是否处于自己的视线范围中等等;从而作出相关反应,比如:隐藏掉自己(提升性能)、巡逻(原地随机走动)和追击。

         ///   <summary>
        
///  侦测
        
///   </summary>
         void  sprite_Detect( object  sender, EventArgs e) {
            Sprite sprite 
=  sender  as  Sprite;
            
// 异步判断精灵是否处于屏幕显示区域中,是的话且无目标则进行索敌判断:在视线范围内则追击,否则警戒
             this .Dispatcher.BeginInvoke(()  =>  {
                sprite.IsVisible 
=  sprite.InScreen(hero.Coordinate);
                
if  (sprite.IsVisible  &&  sprite.Target  ==   null ) {
                    
// 目前单机版怪物的敌人只有主角
                     if  (sprite.InCircle(hero.Coordinate, sprite.SightDistance)) {
                        sprite.Target 
=  hero;
                        sprite.RunTo(Scene.GetWindowCoordinate(hero.Coordinate));
                    } 
else  {
                        sprite.GuardCenter 
=  hero.Coordinate;
                        sprite.Guard();
                    }
                }
            });
        }

当然,这些功能的实现仍然需要一些新属性的支持:

         ///   <summary>
        
///  警戒中心
        
///   </summary>
         public  Point GuardCenter {  get set ; }

        
///   <summary>
        
///  获取或设置警备距离
        
///   </summary>
         public   int  GuardDistance {  get set ; }

        
///   <summary>
        
///  获取或设置视线距离(索敌距离)
        
///   </summary>
         public   int  SightDistance {  get set ; }

        
///   <summary>
        
///  获取或设置物理攻击距离
        
///   </summary>
         public   int  AttackDistance {  get set ; }

        
///   <summary>
        
///  获取或设置施法距离
        
///   </summary>
         public   int  CastingDistance {  get set ; }

    然后是FightDetect事件,我把它放在精灵动作帧间隔里,即精灵每切换一张动作帧图片时触发一次。它在游戏中主要用作对正处于视线范围及攻击范围内的敌人进行相应的战斗处理。

         ///   <summary>
        
///  战斗侦测
        
///   </summary>
         void  sprite_FightDetect( object  sender, EventArgs e) {
            Sprite sprite 
=  sender  as  Sprite;
            
// 精灵处于屏幕中且存在目标则判断是否在攻击范围内进行攻击;否则追击;超出视线范围则停止
             if  (sprite.IsVisible  &&  sprite.Target  !=   null ) {
                
if  (sprite.InCircle(sprite.Target.Coordinate, sprite.AttackDistance)) {
                    sprite.TowardTo(sprite.Target);
                    sprite.Attack();
                } 
else   if  (sprite.InCircle(sprite.Target.Coordinate, sprite.SightDistance)) {
                    sprite.RunTo(Scene.GetWindowCoordinate(sprite.Target.Coordinate));
                } 
else  {
                    sprite.Target 
=   null ;
                    sprite.Stand();
                }
            }
        }

    最后是DoAttack事件,当精灵攻击动作播放到起效帧时触发,根据精灵普通攻击类型进行相应的处理,比如近距离单体物理攻击则直接产生伤害;远距离单体物理攻击则发射一箭支飞向目标,到达后再对目标产生伤害:

         ///   <summary>
        
///  开始普通攻击
        
///   </summary>
         void  sprite_DoAttack( object  sender, EventArgs e) {
            Sprite attacker 
=  sender  as  Sprite;
            Sprite defencer 
=  attacker.Target;
            
// 攻击起效时如果在屏幕中且目标存在则对其进行伤害
             if  (attacker.IsVisible  &&  defencer  !=   null ) {
                attacker.TowardTo(defencer);
                
switch  (attacker.AttackType) {
                    
case  AttackTypes.Close:
                        attacker.AttackToHurt(defencer);
                        
break ;
                    
case  AttackTypes.Distance:
                        Arraw arraw 
=   new  Arraw() {
                            Code 
=   ,
                            Z 
=  defencer.Z,
                            Launcher 
=  attacker,
                            Target 
=  defencer,
                        };
                        EventHandler handler 
=   null ;
                        arraw.MoveCompleted 
+=  handler  =   delegate  {
                            arraw.MoveCompleted 
-=  handler;
                            
if  (arraw.Launcher  !=   null   &&  arraw.Target  !=   null ) {
                                arraw.Launcher.AttackToHurt(arraw.Target);
                            }
                            arraw.Launcher 
=   null ;
                            arraw.Target 
=   null ;
                            scene.RemoveUIElement(arraw);
                        };
                        scene.AddUIElement(arraw);
                        arraw.Move(
new  Point(attacker.Coordinate.X  -   0.8 , attacker.Coordinate.Y  -   1.8 ),  new  Point(defencer.Coordinate.X  -   1 , defencer.Coordinate.Y  -   1 ),  50 , MoveModes.Normal);
                        
break ;
                }
            }
        }

    值得一提的是其中的箭支控件(由于暂时未做时时的碰撞检测(RPG中完全也没必要这么做),来源于网络的素材中心定位本身就不太准确,因此这里的箭支飞行大致是从身体手的部位发射出去,最后消失在被攻击者附近),该控件的呈现仅仅为一张头朝右的箭矢,根据发射者和攻击者之间的角度对其进行旋转从而实现360度全角度效果:

09130737_I6SS.gif 代码
     ///   <summary>
    
///  剪支弹药
    
///   </summary>
     public   sealed   class  Arraw : MovableObject {

        
#region  构造

        Image body 
=   new  Image() { Stretch  =  Stretch.None };
        
public  Arraw() {
            
// ObjectTracker.Track(this);
             this .IsHitTestVisible  =   false ;
            
this .CacheMode  =   new  BitmapCache();
            
this .Children.Add(body);
        }

        
#endregion

        
#region  属性

        
public   override   int  Code {
            
get  {  return   base .Code; }
            
set  { body.Source  =  Global.GetWebImage( string .Format( " Icon/{0}.png " , ( base .Code  =  value))); }
        }

        
///   <summary>
        
///  发射者
        
///   </summary>
         public  Sprite Launcher {  get set ; }

        
///   <summary>
        
///  目标精灵
        
///   </summary>
         public  Sprite Target {  get set ; }

        
#endregion

        
#region  方法

        
///   <summary>
        
///  重载坐标改变方法
        
///   </summary>
        
///   <param name="coordinate"> 游戏坐标系坐标 </param>
         protected   override   void  ChangeCoordinateTo(Point coordinate) {
            
base .ChangeCoordinateTo(Scene.GetWindowCoordinate(coordinate));
        }

        
///   <summary>
        
///  重载飞行方法
        
///   </summary>
        
///   <param name="from"></param>
        
///   <param name="to"></param>
        
///   <param name="speed"></param>
        
///   <param name="moveMode"></param>
         public   override   void  Move(Point from, Point to,  double  speed, MoveModes moveMode) {
            Point p0 
=  Scene.GetWindowCoordinate(to);
            Point p1 
=  Scene.GetWindowCoordinate(from);
            
double  angle  =  Global.GetAngle(p0.Y  -  p1.Y, p0.X  -  p1.X);
            
this .RenderTransform  =   new  RotateTransform() {
                CenterX 
=   ,
                CenterY 
=   ,
                Angle 
=  angle
            };
            
base .Move(from, to, speed, moveMode);
        }

        
#endregion

    }

Arraw继承MovableObject,游戏中一切可移动的对象都可继承自它,比如游戏中可拖动界面、特效、装饰、弹药、文字等等:

09130737_I6SS.gif 代码
     #region  枚举

    
///   <summary>
    
///  移动模式
    
///   </summary>
     public   enum  MoveModes {
        
///   <summary>
        
///  标准
        
///   </summary>
        Normal  =   ,
        
///   <summary>
        
///  带透明度渐隐效果
        
///   </summary>
        Opacity  =   1 ,
    }

    
#endregion

    
///   <summary>
    
///  可运动物体
    
///   </summary>
     public   abstract   class  MovableObject : ObjectBase {

        
#region  事件

        
public   event  EventHandler MoveCompleted; 

        
#endregion

        
#region  方法

        
///   <summary>
        
///  从一点向另一点移动
        
///   </summary>
        
///   <param name="from"> 起点 </param>
        
///   <param name="to"> 终点 </param>
        
///   <param name="speed"> 速度系数 </param>
        
///   <param name="moveMode"> 模式 </param>
         public   virtual   void  Move(Point from, Point to,  double  speed, MoveModes moveMode) {
            Duration duration 
=   new  Duration(TimeSpan.FromMilliseconds(Global.GetTwoPointDistance(from, to)  *  speed));
            Storyboard storyboard 
=   new  Storyboard();
            PointAnimation pointAnimation 
=   new  PointAnimation() {
                From 
=  from,
                To 
=  to,
                Duration 
=  duration,
            };
            Storyboard.SetTarget(pointAnimation, 
this );
            Storyboard.SetTargetProperty(pointAnimation, 
new  PropertyPath( " Coordinate " ));
            storyboard.Children.Add(pointAnimation);
            
switch  (moveMode) {
                
case  MoveModes.Normal:

                    
break ;
                
case  MoveModes.Opacity:
                    DoubleAnimation doubleAnimation 
=   new  DoubleAnimation() {
                        From 
=   1 ,
                        To 
=   ,
                        Duration 
=  duration,
                    };
                    Storyboard.SetTarget(doubleAnimation, 
this );
                    Storyboard.SetTargetProperty(doubleAnimation, 
new  PropertyPath( " Opacity " ));
                    storyboard.Children.Add(doubleAnimation);
                    
break ;
            }
            EventHandler handler 
=   null ;
            storyboard.Completed 
+=  handler  =  (s, e)  =>  {
                storyboard.Completed 
-=  handler;
                storyboard.Stop();
                storyboard 
=   null ;
                Dispose();
                
if  (MoveCompleted  !=   null ) { MoveCompleted( this , e); }
            };
            storyboard.Begin();
        }

        
#endregion

    }

综述,当以上3个事件配合上相应属性一同发挥作用时,战斗终于打响了。过程仅是绚烂的瞬间,包括我在内的所有玩家或许更关注最终产生伤害的那一刻attacker.AttackToHurt(defencer)

         ///   <summary>
        
///  普通攻击使对方造成伤害
        
///   </summary>
        
///   <param name="obj"> 对方精灵 </param>
         public   void  AttackToHurt(Sprite obj) {
            
int  damage  =   this .ATK  -  obj.DEF  <     ?    :  this .ATK  -  obj.DEF  +  Global.random.Next( - 30 30 );
            
// 各种伤害情况判断(实际不这么写,需要真实的数值公式计算)
             if  (damage  ==     ||  Global.random.Next( 100 <  obj.DEX) {
                obj.ChangeLife(
, ValueEffects.Failure);
            } 
else   if  (Global.random.Next( 100 >=   95 ) {
                obj.ChangeLife(
- damage  *   2 , ValueEffects.DoubleDecrease);
                obj.Injure();
            } 
else  {
                obj.ChangeLife(
- damage, ValueEffects.Decrease);
            }
            
// 伤害后如果对象生命为0
             if  (obj.Life  ==   ) {
                obj.ChangeLife(
, ValueEffects.Death);
                
this .Stand();
                
this .Target  =   null ;
            } 
else  {
                
// 附加被攻击特效
                 if  ( this .AttactEffect  !=   - 1 ) {
                    Animation animation 
=   new  Animation() { Code  =   this .AttactEffect, Coordinate  =  obj.Center };
                    EventHandler handler 
=   null ;
                    animation.Disposed 
+=  handler  =   delegate  {
                        animation.Disposed 
-=  handler;
                        obj.RemoveTemporaryEffect();
                    };
                    obj.AddTemporaryEffect(animation);
                }
            }
        }

    其实,真实的伤害剧本比这个要复杂百倍有余,该工作完全属于游戏数值策划师的范畴,并且大都以参数脚本的形式独立存在便于随时调试。

到此,RPG游戏的普通攻击系统简单实现告一段落,当您看见满天飞矢、战火连天的画面时,是否又一次勾起了那些封藏已久的往昔回忆?

 

最后是一些锦上添花,比如说受伤系统和动态障碍物系统。

受伤系统并不是所有RPG都具备或者说完整具备的,因为它涉及到多方面的原因和设计手法。在本节的示例游戏中,当精灵被一定几率暴击后将呈现受伤状态,此时的精灵所有动作将被打断,比如移动时失去目标而停止;攻击招式归零等。伤害系统对于规模性的群伤技能和动作感、打击感较强的ARPG类型游戏来说至关重要,常常者涉及到大量人体动作学及物理运动学等方面的相关知识,更神秘而有深度的领域等待您的参与一同去探索!

另外关于动态障碍物系统其实早在我的第一部教程中已有比较好的实现(效果完美但性能欠缺),本节中我以另外的形式进行了再一次的简单实现,不管方法如何,动态障碍物系统存在的目的仅有一个:不让精灵重叠。回合制RPG游戏似乎并不关心这方面的需求,然而却是即时战斗类型游戏不可或缺的环节之一,有了它游戏实景效果将更为贴近现实。当然,最完美的实现应该是包含坐标锁定与解锁的繁杂过程,同时很多处理都将被放上服务器,算法的好坏最终直接关系到运营成本的高低。

本课小结:每款游戏都有一个主题,一个背景,一个旋律,一个情节。成功的游戏设计大都是从众多已知的游戏特性中寻找共性,提炼出精华为己所用。战斗系统便是整个RPG游戏的精髓所在,也是游戏趣味性的重点环节,如果设计者能将更深层次的思考及优秀的策划融会贯通,使玩家得到酣畅淋漓、一气呵成之体验,实乃旷世之巨作。

本课源码:点击进入目录下载

参考资料:中游在线[WOWO世界] Silverlight C# 游戏开发:游戏开发技术

教程Demo在线演示地址http://silverfuture.cn


原文链接: http://www.cnblogs.com/alamiye010/archive/2010/11/18/1881312.html

转载于:https://my.oschina.net/chen106106/blog/43618

这篇关于Silverlight MMORPG网页游戏开发课程[一期] 第十二课:战斗系统之普通攻击的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/222238

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来