Silverlight C# 游戏开发:面向对象在游戏中的实例(二)

本文通过实例展示了如何使用面向对象方法在游戏开发中实现物体管理和逻辑处理,阐述了其简化代码、提高效率的优势。通过创建类结构,实现了不同物体(如云、食物、螺丝钉)的统一处理,简化了碰撞检测和移动逻辑,同时提供了实例代码和最终文件状态展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    本系列所有代码都是使用Microsoft Visual Studio 2008开发,为基于Silverlight的游戏开发技术,如果您看完之后觉得不错,回复顶一下,万分感激:)

    在上一次,介绍了面向对象在怪物上的应用,比较简单的代码完成了多重怪物的不同逻辑,然而并不是非常明显的使用了面向对象,因为数量较小,这次我们搞一个对象数目繁多的应用,来证明面向对象在游戏开发中是多么的好用。还是老规矩,仍然提供一个实例。代码在这里下载
    是否还记得,这个系列中的《Flyer》小游戏,那个系列为了更好的介绍Silverlight的基础知识没有使用面向对象方法,所有的对象都是独立编程,因此我们发现所有的基础对象都有这么一段代码。
        public double Speed = 4;
        public double X
        {
            get { return Canvas.GetLeft(this); }
            set { Canvas.SetLeft(this, value); }
        }
        public double Y
        {
            get { return Canvas.GetTop(this); }
            set { Canvas.SetTop(this, value); }
        }
        public Rect MyRect
        {
            get
            {
                return new Rect(X, Y, _rectangle.Width, _rectangle.Height);
            }
         }
    恐怕非常的不爽,先不说维护起来麻烦,就是来回的复制粘贴也够费劲的,以后要是增加了各种各样的物体,这个工作就够手疼的,但是我们在面向对象的面前就省去了很多力气,然而……这个世界没有公平的事情,手不疼了,脑袋就要疼了,嘿嘿,具体为什么,下面就知道。
我们的目的是,用面向对象实现之前《Flyer》的功能,为了更好的说明,这个游戏就不写太多的逻辑代码,有兴趣的朋友自行研究:)
建立工程……(请参阅其他文章)
    为了更加方便快速的完成,这次我们用上Blend,请参照下图设置:

 

    然后加入之前的图片,这次的图片没有做动画,一切从简,否则复杂的代码不利于大家读代码。


    这个时候,我们开始研究如何创造类的结构,使用面向对象的方法来完成这个项目,这需要编程人员的经验以及基础的共同作用,所以,在写之前先要想好,经过思考,我们发现很多可以抽象出来的东西,咱们画了一个类结构图:

ClassBaseRole 类从 Canvas 继承,完成所有的图形方面的事情,并且将坐标 XY 直观化,提供初始化接口。
ClassActivityRole
类更加高级了一点,它可以做一些行为,提供检测还有移动等方法。
ClassSolid
类是不需要操作的物体集合。
ClassFlyer
ClassSolid 有本质的不同, ClassSolid 只需要向上移动就行,但是 Flyer 却不行,它需要键盘的控制,所以,作为 ClassSolid 的子类不合适,所以我们将 ClassActivityRole 作为父类。
ClassCloud
ClassFood 、、 ClassScrew ClassSolid 继承获得了有用的部分,而且告诉大家,我是一个 Solid ,但是他们之间不同的是三种完全不同的作用, Cloud 什么都不做只是向上飘, Food 在碰撞的时候会加血, Screw 则是损血,这是完全不同的三种逻辑,这个部分和上一个篇里打怪物的情况几乎一样,所以可以使用同一的碰撞逻辑(这部分的代码未实现,如要请参考其他篇)
    那么下面就是 Coding 的时间,我在这里给出部分代码,详细的请下载源文件
    public class ClassBaseRole : Canvas
    {
        public Image ResImage = new Image();
        public ClassBaseRole()
        {
            this.Children.Add(ResImage);
            InitializtionRole();
        }
        public virtual void InitializtionRole()
        {
        }
        /// <summary>
        ///
移动速度
        /// </summary>
        public double Speed = 1;
        /// <summary>
        ///
修改或获取X坐标
        /// </summary>
        public double X
        {
            get { return Canvas.GetLeft(this); }
            set { Canvas.SetLeft(this, value); }
        }
        /// <summary>
        ///
修改或获取Y坐标
        /// </summary>
        public double Y
        {
            get { return Canvas.GetTop(this); }
            set { Canvas.SetTop(this, value); }
        }
    }
         public class ClassActivityRole : ClassBaseRole
    {
        public ClassActivityRole()
        {
            MyRectangle = new Rectangle() { Width = 32, Height = 32, Stroke = new SolidColorBrush(Colors.Red) };
            this.Children.Add(MyRectangle);
        }       
        protected Rectangle MyRectangle;
        /// <summary>
        ///
取得自身的碰撞区域
        /// </summary>
        public Rect MyRect
        {
            get
            {
                return new Rect(X, Y, MyRectangle.Width, MyRectangle.Height);
            }
        }
        /// <summary>
        ///
碰撞测试
        /// </summary>
        /// <param name="objective">
目标物体 </param>
        /// <returns></returns>
        public bool CollidedTest(ClassActivityRole objective)
        {
            Rect rt = objective.MyRect;
            rt.Intersect(this.MyRect);
            if (!double.IsInfinity(rt.Height) && !double.IsInfinity(rt.Width))           
                return true;           
            else
                return false;
        }
        public virtual void DownWard()
        {
            Y += base.Speed;
        }
       public virtual void UpWard()
        {
            Y -= base.Speed;
        }
        public virtual void RightWard()
        {
            X += base.Speed;
        }
        public virtual void LeftWard()
        {
            X -= base.Speed;
        }
        public virtual void LoopLogic()
        {
        }
    }
         后面还有更多,在这里不一一列举,直接看效果:
    

    另外,我们可以最后的完成的文件情况:
  

         写的类很少,并且去掉了这个 Group 那个 Group ,并且每个类的代码很少,没有超过 50 行,最少的就 5 行代码,这是为什么呢,因为我们用了面向对象,现在将主页面写成这样:
        
public partial class MainPage : UserControl
    {
        public static Random random = new Random((int)DateTime.Now.Ticks);
        public static double ScreenWidth = 400;
        public static double ScreenHeight = 400;
        public ClassFlyer Hero = new ClassFlyer();
        public MainPage()
        {
            InitializeComponent();
            for (int i = 0; i < 20; i++)
            {
                Sky.Children.Add(new ClassCloud());
                Sky.Children.Add(new ClassFood());
                Sky.Children.Add(new ClassScrew());
            }
            Sky.Children.Add(Hero);
            DispatcherTimer GameLoop = new DispatcherTimer();
            GameLoop.Interval = TimeSpan.FromMilliseconds(40);
            GameLoop.Tick += new EventHandler(GameLoop_Tick);
            GameLoop.Start();

            base.KeyDown += new KeyEventHandler(MainPage_KeyDown);
            base.KeyUp += new KeyEventHandler(MainPage_KeyUp);
        }

        void MainPage_KeyUp(object sender, KeyEventArgs e)
        {
            Hero.FylerState = EmFlyerState.
正常;
        }

        void MainPage_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.Up:
                    Hero.FylerState = EmFlyerState.向上;
                    break;
                case Key.Down:
                    Hero.FylerState = EmFlyerState.向下;
                    break;
                case Key.Left:
                    Hero.FylerState = EmFlyerState.向左;
                    break;
                case Key.Right:
                    Hero.FylerState = EmFlyerState.向右;
                    break;
            }
        }
        void GameLoop_Tick(object sender, EventArgs e)
        {           
            foreach (var item in Sky.Children)
            {
                if (item is ClassActivityRole)
                {
                    ClassActivityRole temp = (item as ClassActivityRole);
                    temp.LoopLogic();
                    if (temp.Y <= -32)
                    {
                        temp.InitializtionRole();
                    }
                    else
                    {
                        if (temp.CollidedTest(Hero) && !(temp is ClassCloud))
                        {
                            temp.InitializtionRole();
                        }
                    }
                }
            }
        }
    }

        
综述,我们从这个例子中,可以看到有关于多重的类别对象在整体管理时候的应用,在做整体的游戏管理时候,只需要调用基本对象,基本类的方法会直接调用继承下来的类,比如说 LoopLogic ,对于不同的对象 Solid Flyer Cloud Food 处理不同的逻辑,在 CollidedTest 中更加明显,只需要传入基类即可,不需要做单独的判定条件。
        
本代码中没有做损血和加血,主要是为了更加直观,损血和加血只需要写在碰撞检测里就可以,也不需要做太多的代码,甚至碰撞检测可以写在自身的逻辑中,而不需要每次都调用迭代器做判定
        
它在实际开发中非常重要,它能很好的简化代码,让结构更加清晰,而且修改起来非常容易,即便是增加功能也是非常简单的事情,比如我们搞一个横着飞的火球,只需要简单继承,修改一下飞行轨迹即可,可能在其他方面的应用更加广泛和舒适,欢迎共同探讨,各位高手可能有更加面向对象的例子,我也想好好学习啊:)

获取 Microsoft Silverlight

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值