中間實在忙啊,隔了幾天,終於有點時間,原本覺得寫博客很簡單,不過如今感受怎麼把意思表達清楚真是件難事啊,因此,寫的很差,園友們不要介意啊。git
話說,上回我打算開發遊戲,考慮了4種技術,後來我發現不管哪一種技術應該是都能實現,區別大概就是性能以及佔用的資源吧,因此,我後來實現用的是wpf。當時在網上搜索了一下,發現曾經有人寫過,也在國外的網站上找到了部分代碼,因此就這麼拼拼湊湊就把效果跑起來了。緩存
下面先上個效果圖吧,算是這幾天的一個成果。ide
我這個是徹底模仿《傳奇》,屏幕所能容納的物件數量是17*17,因此我在每個格子上放置一格人物,並讓這我的物進行運動,個人預想是,若是全屏幕人物運動的狀況下還能達到10FPS,那麼理論上實現《傳奇》這樣的遊戲應該是可行的。性能
下面是個人代碼部分,要說實現上面這個效果,不算簡單也不算難,主要應該是一些思想。個人項目名字叫作LightDarkLegend.網站
典型的WPF項目,App.xaml是wpf默認的啓動頁,MainWindow.xaml是遊戲的登陸器頁面,GameBox.xaml是遊戲運行的頁面,結構上來講仍是很是簡單的。this
其實最主要的核心就是這個MyDraw,也就是自定義的繪製控件。MyDraw的主要邏輯就是處理傳入的人物、魔法、怪物、地圖等參數,與原始數據進行比較,假如發現數據不一樣,則觸發繪製,最終有自定義控件的OnRender方法呈現圖像。spa
核心代碼MyMap類code
public class MyMap : INotifyPropertyChanged { private long x; public long X { get { return this.x; } set { if (this.x != value) { this.x = value; this.OnPropertyChanged("X"); } } } private long y; public long Y { get { return this.y; } set { if (this.y != value) { this.y = value; this.OnPropertyChanged("Y"); } } } private long moveX; private long moveY; public long MoveX { get => moveX; set => moveX = value; } public long MoveY { get => moveY; set => moveY = value; } private Map map; public Map Map { get { return this.map; } set { if (this.map != value) { this.map = value; this.OnPropertyChanged("Map"); } } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } }
MyDraw類orm
public class MyDraw : FrameworkElement { public WriteableBitmap mapBitMap; public WriteableBitmap magicBitMap; public WriteableBitmap monsterBitMap; public WriteableBitmap personBitMap; public WriteableBitmap itemBitMap; public WriteableBitmap controlBoxBitMap; public static int pixelWidth = 2040; //(int)myMap.Map.width; public static int pixelHeight = 1530; // (int)myMap.Map.height; public static int xGezi = 120;//一個磚塊佔用像素x public static int yGezi = 90;//一個磚塊佔用像素y public static int moveWidth = pixelWidth / xGezi;//人物x座標移動格子數一屏幕 public static int moveHeight = pixelHeight / yGezi;//人物y座標移動格子數一屏幕 public bool isLoadObject = false;//是否不進行繪製,進行元素加載。 #region 個人地圖 public static readonly DependencyProperty myMapProperty = DependencyProperty.Register("map", typeof(MyMap), typeof(MyDraw), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None, OnMyMapPropertyChanged)); private static void OnMyMapPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { MyDraw draw = (MyDraw)d; MyMap myMap = (MyMap)e.NewValue; MyMap oldMap = (MyMap)e.OldValue; if (myMap != null && myMap.Map != null) { if (oldMap != null && myMap.Map.id != oldMap.Map.id) { //LoadAllObject();//載入全部當前地圖相關元素(地磚元素,建築物,怪物圖片) } //從新繪圖 if (oldMap != null && oldMap.X == myMap.X && oldMap.Y == myMap.Y)//僅僅移動 { draw.MoveMap((int)myMap.MoveX, (int)myMap.MoveY); return; } draw.DrawMap(); } } public MyMap myMap { get { return (MyMap)GetValue(myMapProperty); } set { SetValue(myMapProperty, value); } } Image GetImage(int x, int y) { int index = x * (int)myMap.Map.width + y; return myMap.Map.layouts[0].metros[index].img; } void DrawMap() { int x = (int)myMap.X;//人物x座標 int y = (int)myMap.Y;//人物y座標 //須要根據人物所在座標,取得地圖的點陣數據 int moveMinX = x - moveWidth / 2-1; int moveMaxX = x + moveWidth / 2 + 2; int moveMinY = y - moveHeight / 2-1; int moveMaxY = y + moveHeight / 2 + 2; mapBitMap.Lock(); //雙重緩存 using (Bitmap backBufferBitmap = new Bitmap(pixelWidth, pixelHeight, mapBitMap.BackBufferStride, System.Drawing.Imaging.PixelFormat.Format32bppPArgb, mapBitMap.BackBuffer)) { using (Graphics backBufferGraphics = Graphics.FromImage(backBufferBitmap)) { backBufferGraphics.Clear(System.Drawing.Color.Black); DateTime de = DateTime.Now; //繪製地表 int drawX = -1; for (int i = moveMinX; i < moveMaxX; i++)//得到數據進行繪製 { int drawY = -1; for (int j = moveMinY; j < moveMaxY; j++) { if (i < 0 || j < 0) { //超出地圖範圍,以空元素代替 //不進行繪製 } else { backBufferGraphics.DrawImage(GetImage(i, j), drawX * xGezi, drawY * yGezi); } drawY += 1; } drawX += 1; } backBufferGraphics.Flush(); DateTime de2 = DateTime.Now; TimeSpan dm = de2 - de; } } //結束繪製 mapBitMap.AddDirtyRect(new Int32Rect(0, 0, pixelWidth, pixelHeight)); mapBitMap.Unlock(); } #endregion public MyDraw() { if (mapBitMap == null || (mapBitMap != null && (mapBitMap.PixelWidth != pixelWidth || mapBitMap.PixelHeight != pixelHeight))) { mapBitMap = new WriteableBitmap(pixelWidth, pixelHeight, 96, 96, PixelFormats.Pbgra32, null); } } protected override void OnRender(DrawingContext drawingContext) { drawingContext.DrawImage(mapBitMap, new Rect(0, 0, RenderSize.Width, RenderSize.Height)); } }
發現,粘貼代碼確實比較麻煩,尤爲是代碼量很是大的時候,看來下次我得考慮使用git或者本身部署一套代碼系統,但願能更方便一點。另外我發現本身日常得我基本上都是別人問我問題我答得頭頭是道,真要讓我本身寫文章還真是一大挑戰啊,你們有什麼好得思路都歡迎評論。blog