基於C#彈幕類射擊遊戲的實現——(二)渲染
阿新 • • 發佈:2019-01-29
這個遊戲打算是用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()