您的位置:首页 > 编程语言 > C#

基于C#弹幕类射击游戏的实现——(二)渲染

2013-12-17 17:51 686 查看
这个游戏打算是用C#+GDI做~所以渲染效率上还是要进行一些考虑的

这里对传统的GDI+封装了下,通过批处理来提高一些效率



首先给出的是渲染接口的定义,方面以后更换高性能的渲染器(当然很遥远)

/// <summary>
    /// 渲染器接口
    /// </summary>
    public interface IRenderHandler
    {
    	void Clear(Color backgroundColor);
    	void DrawLine(int x1, int y1, int x2, int y2, Color color);
        void DrawBox(int x, int y, int width, int height, Color color, bool fill);
        void DrawImage(int destX, int destY, int destWidth, int destHeight, Bitmap source, int sourceX, int sourceY, int sourceWidth, int sourceHeight);
        
        object GetSurface();
    }


这是实现一个渲染器需要实现的接口,大体上就这么多

然后是用GDI实现的一个渲染器

/// <summary>
    /// GDI渲染器
    /// </summary>
    public class GDIRender : IRenderHandler
    {
    	private Bitmap mSurface;
    	private Graphics mG;
    	
    	public GDIRender(int width, int height)
    	{
    		mSurface = new Bitmap(width, height);
    		mG = Graphics.FromImage(mSurface);
    	}
    	
    	public void Clear(Color backgroundColor)
    	{
    		mG.Clear(backgroundColor);
    	}
    	
    	public void DrawLine(int x1, int y1, int x2, int y2, Color color)
        {
            mG.DrawLine(new Pen(color), x1, y1, x2, y2);
        }

        public void DrawBox(int x, int y, int width, int height, Color color, bool fill)
        {
            if (fill == true)
            {
                mG.FillRectangle(new SolidBrush(color), new Rectangle(x - width / 2, y - height / 2, width, height));
            }
            else
            {
                mG.DrawRectangle(new Pen(color), new Rectangle(x - width / 2, y - height / 2, width, height));
            }
        }

        public void DrawImage(int destX, int destY, int destWidth, int destHeight, Bitmap source, int sourceX, int sourceY, int sourceWidth, int sourceHeight)
        {
            mG.DrawImage(source,
                new Rectangle(destX - destWidth / 2, destY - destHeight / 2, destWidth, destHeight),
                new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
                GraphicsUnit.Pixel);
        }
        
        public object GetSurface()
        {
        	return mSurface;
        }
    }


有了这个东西,我们就可以在屏幕上画东西了。。。

慢着,上面说的批处理呢?别急,马上来

下面实现的是一个图形设备,封装了一下渲染器

/// <summary>
    /// 图形设备
    /// </summary>
    public class GraphicDevice
    {
    	public IRenderHandler RenderHandler;
    	
        private int mRenderStatus; // 渲染器的状态(0:Normal 1:Begin)
        
        private int mWidth;
        private int mHeight;
        private Color mBackgroundColor;

        public object Surface
        {
            get
            {
            	return RenderHandler.GetSurface();
            }
        }

        private List<RenderObject> mRenderObjects;

        public event RenderOverHandler RenderOver;

        public GraphicDevice(int width, int height, Color backColor)
        {
        	this.RenderHandler = new GDIRender(width, height);
        	
            this.mWidth = width;
            this.mHeight = height;
            this.mBackgroundColor = backColor;

            this.mRenderObjects = new List<RenderObject>();

            this.RenderOver = null;
        }

        public void Begin()
        {
            if (mRenderStatus != 0)
            {
                throw new Exception("上一次调用Begin()后未调用End()");
            }

            mRenderStatus = 1;
            mRenderObjects.Clear();
            
            RenderHandler.Clear(mBackgroundColor);
        }

        public void End()
        {
            if (mRenderStatus != 1)
            {
                throw new Exception("调用End()之前必须调用Begin()");
            }

            mRenderStatus = 0;
            mRenderObjects.Sort(DepthComparer);

            int len = mRenderObjects.Count;
            for (int i = 0; i < len; i++)
            {
                mRenderObjects[i].Render(RenderHandler);
            }

            if (RenderOver != null)
            {
                RenderOver(this);
            }
        }

        public void RenderObject(RenderObject obj)
        {
            mRenderObjects.Add(obj);
        }

        private int DepthComparer(RenderObject obj1, RenderObject obj2)
        {
            if (obj1.Depth < obj2.Depth)
            {
                return -1;
            }
            else if (obj1.Depth > obj2.Depth)
            {
                return 1;
            }
            return 0;
        }
    }


在Begin的时候清空需要渲染的东西,在End的时候进行批处理绘制。

绘制的对象是一个叫做RenderObject的类,这个类是基础渲染图元,也就是Line,Image之类的基类了

/// <summary>
    /// 渲染目标基类
    /// </summary>
    public class RenderObject
    {
        /// <summary>
        /// 渲染深度(0-100越大越靠前)
        /// </summary>
        public int Depth;

        public RenderObject()
        {
            Depth = 0;
        }

        public virtual void Render(IRenderHandler renderHandler)
        {
        }
    }


然后接下来给出几种具体实现

public class RenderLine : RenderObject
    {
        public int X1;
        public int Y1;
        public int X2;
        public int Y2;
        public Color Color;

        public RenderLine(int x1, int y1, int x2, int y2, Color color, int depth = 100)
            : base()
        {
            this.Depth = depth;
            this.X1 = x1;
            this.Y1 = y1;
            this.X2 = x2;
            this.Y2 = y2;
            this.Color = color;
        }

		public override void Render(IRenderHandler renderHandler)
        {
        	renderHandler.DrawLine(X1, Y1, X2, Y2, Color);
        }
    }




public class RenderBox : RenderObject
    {
        public int X;
        public int Y;
        public int Width;
        public int Height;
        public Color Color;
        public bool Fill;

        public RenderBox(int x, int y, int width, int height, Color color, bool fill, int depth = 100)
        {
            this.Depth = depth;
            this.X = x;
            this.Y = y;
            this.Width = width;
            this.Height = height;
            this.Color = color;
            this.Fill = fill;
        }

        public override void Render(IRenderHandler renderHandler)
        {
        	renderHandler.DrawBox(X, Y, Width, Height, Color, Fill);
        }
    }


其余的类似~~

好了,有了这些东西,我们才真正的开始在屏幕上绘制东西了,大概流程是这样



GraphiceDevice.Begin()

...

GraphiceDevice.RenderObject(obj);

...

GraphiceDevice.End()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: