zoukankan      html  css  js  c++  java
  • 使用 Region,RegionManager 在 XNA 中创建特殊区域(十八)

    平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛。在这里分享一下经验,仅为了和各位朋友交流经验。平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXNA 吧,最后请高手绕道而行吧,以免浪费时间。(为了突出重点和减少篇幅,有些示例代码可能不够严谨。)

    区域

    如果一些单位进入区域,那么他们将被添加特殊的效果,比如:减速或者受到持续的伤害。因此,我们定义了 Region 类来表示区域。

    在 Region 中,我们定义了字段 targets 用来表示进入区域的目标。方法 Append 用来为区域增加新的 Spirit,如果该 Spirit 已经包含在区域中,则不能再次被添加。

    派生类可以修改 appending 和 appended 方法。方法 appending 可以用来查看 Spirit 的信息,然后根据这些信息来决定是否添加精灵。方法 appended 可以为已经增加的精灵添加各种效果。

    internal abstract class Region
        : Spirit
    {
        private readonly List<Spirit> targets = new List<Spirit> ( );
    
        protected Region ( IPlayScene scene, int type, Vector2 location, string movieName, float speed, int angle, HitArea hitArea, int width, int height, double destroySecond )
            : base ( scene, type, location, movieName,
            null,
            speed, angle, hitArea, width, height, destroySecond,
            true,
            false,
            false,
            0
            )
        { }
    
        protected virtual bool appending ( Spirit spirit )
        { return true; }
        protected virtual void appended ( Spirit spirit )
        { }
    
        internal void Append ( IList<Spirit> spirits )
        {
    
            if ( null == spirits )
                return;
    
            foreach ( Spirit spirit in spirits )
                this.Append ( spirit );
    
        }
        internal void Append ( Spirit spirit )
        {
    
            if ( this.targets.Contains ( spirit ) || !this.appending ( spirit ) )
                return;
    
            this.targets.Add ( spirit );
    
            this.appended ( spirit );
        }
    
        protected override void move ( )
        {
            this.Location.X += this.xSpeed;
            this.Location.Y += this.ySpeed;
        }
    
        protected override Vector2 getMovieLocation ( )
        { return this.Location - this.halfSize; }
    
        protected override void Dispose ( bool disposing )
        {
    
            try
            {
    
                if ( disposing )
                {
                    this.targets.Clear ( );
                }
    
            }
            catch { }
    
            base.Dispose ( disposing );
        }
    
    }

    其他成员可以参照其他 Spirit 类的解释。

    区域管理器

    RegionManager 类派生自类 SpiritManager<T>,默认的绘制顺序是 3000。

    internal sealed class RegionManager
        : SpiritManager<Region>
    {
        internal event EventHandler<RegionHitAreaEventArgs> HitTesting;
    
        internal RegionManager ( )
            : base ( 3000 )
        { }
    
        internal override void Update ( GameTime time )
        {
    
            if ( null == this.HitTesting )
                return;
    
            foreach ( Region region in this.Spirits.ToArray ( ) )
            {
                RegionHitAreaEventArgs hitAreaArg = new RegionHitAreaEventArgs ( region );
                this.HitTesting ( region, hitAreaArg );
    
                region.Append ( hitAreaArg.Targets );
    
                hitAreaArg.Dispose ( );
            }
    
        }
    
    }

    事件 HitTesting 可以让外界判断精灵和区域的碰撞,并通过参数 RegionHitAreaEventArgs 返回和区域碰撞的目标。这里你不需要将 RegionHitAreaEventArgs 的 IsHit 属性设置为 true。

    示例

    场景 SceneT19 是 SceneT18 的扩展,除了有 SceneT18 的功能,还将创建一个区域。

    我们定义了类 MyRegion,他是一个区域,可以持续 10 秒的时间。当有精灵进入区域时,他将被销毁。

    internal class MyRegion
        : Region
    {
    
        internal MyRegion ( IPlayScene scene, Vector2 location )
            : base ( scene, 1, location, "myr", 0, 0,
            new SingleRectangleHitArea ( new Rectangle ( -75, -75, 150, 150 ) ),
            150, 150,
            10
            )
        { }
    
        protected override bool appending ( Spirit spirit )
        {
            spirit.Destroy ( );
    
            return false;
        }
    
    }

    我们还要定义一个 RegionManager。

    private RegionManager regionManager;
    
    internal SceneT19 ( )
        : base ( Vector2.Zero, GestureType.None, "background1",
        new Resource[] {
            new Resource ( "bird2.image", ResourceType.Image, @"imageird2" ),
            new Resource ( "bullet.image", ResourceType.Image, @"imageullet" ),
            new Resource ( "item.image", ResourceType.Image, @"imageitem" ),
            new Resource ( "pinup.image", ResourceType.Image, @"imagepinup1" ),
            new Resource ( "r.image", ResourceType.Image, @"image
    1" ),
            new Resource ( "go.image", ResourceType.Image, @"imageutton1" ),
        },
        new Making[] {
            new Movie ( "bird", "bird2.image", 80, 80, 5, "live",
                new MovieSequence ( "live", true, new Point ( 1, 1 ), new Point ( 2, 1 ) )
                ),
            new Movie ( "mybutton", "bullet.image", 10, 10, 0, "b",
                new MovieSequence ( "b", new Point ( 1, 1 ) )
                ),
            new Movie ( "myitem", "item.image", 30, 30, 0, "i",
                new MovieSequence ( "i", new Point ( 1, 1 ) )
                ),
            new Movie ( "mypinup", "pinup.image", 100, 50, 0, "p",
                new MovieSequence ( "p", new Point ( 1, 1 ) )
                ),
            new Movie ( "myr", "r.image", 150, 150, 0, "r",
                new MovieSequence ( "r", new Point ( 1, 1 ) )
                ),
            new Button ( "b.go", "go.image", "GO", new Vector2 ( 10, 690 ), 100, 50, new Point ( 1, 1 ) ),
        }
        )
    {
        // ...
    
        this.regionManager = new RegionManager ( );
        this.regionManager.Scene = this;
        this.regionManager.HitTesting += this.regionHitTesting;
    
        // ...
    }

    在方法 regionHitTesting 中,我们将判断哪些子弹进入了区域中,而区域将试图添加这些子弹。

    private void regionHitTesting ( object sender, RegionHitAreaEventArgs e )
    {
        List<Spirit> targets = new List<Spirit> ( );
    
        foreach ( Bullet bullet in this.bulletManager.Spirits )
            if ( e.HitArea.HitTest ( bullet.HitArea ) )
                targets.Add ( bullet );
    
        e.Targets = targets;
    }

    最后,我们需要在小鸟被子弹击中后,创建一个区域。

    private void bulletHitTesting ( object sender, BulletHitAreaEventArgs e )
    {
    
        if ( !this.bird.IsDied && e.HitArea.HitTest ( this.bird.HitArea ) )
        {
            e.IsHit = true;
            e.Targets = new IAssailable[] { this.bird };
    
            if ( !this.is1Hit )
            {
                this.is1Hit = true;
                this.pinupManager.Append ( new MyHit ( this, new Vector2 ( 0, 400 ) ) );
            }
    
            this.regionManager.Append ( new MyRegion ( this, new Vector2 ( 100, 100 ) ) );
        }
    
    }

    本期视频 http://v.youku.com/v_show/id_XNTkwMzIyMTYw.html

    项目地址 http://wp-xna.googlecode.com/
    更多内容 WPXNA

    平方开发的游戏 http://zoyobar.lofter.com/

    QQ 群 213685539

    欢迎访问我在其他位置发布的同一文章:http://www.wpgame.info/post/decc4_7c22b3



  • 相关阅读:
    数据表后缀问题
    window.history.go(-1)返回且刷新页面
    mysql性能优化-慢查询分析、优化索引和配置
    从数据库、代码和服务器对PHP网站Mysql做性能优化
    什么是WEBserver? 经常使用的WEBserver有哪些?
    浅谈 C/S 和 B/S 架构
    Android常用开源项目
    csdn android视频播放器开发
    视频会议十大开源项目排行
    Android开源项目大全
  • 原文地址:https://www.cnblogs.com/zoyobar/p/wpxna18.html
Copyright © 2011-2022 走看看