GDE-silverlight是我和几个朋友准备在silverlight上开发一款金庸群侠传X版的游戏引擎部分。
之前一直没鼓起干劲搞,这个周末终于得空,把silverlight的几个基本功能自己动手实验了一下。基本弄明白了,准备开始鼓起干劲把GDE-silverlight完成!
感觉silverlight的UI开发还是比之前HGE好多了……之前那个呼呼累啊,梦魇~
非常简单的测试了以下几点
1. 图片加载
2. 之前部分C++代码逻辑上的移植(如寻找移动、攻击区域)
3. 地图单元格绘制
4. 动画(左上角那个爆炸是个动画。。)
5. 复用QXENGINE提供的A*寻路算法,如下图红色部分所示(它这个可以斜着寻路。。到时候需要根据具体要求改)
6. 动态加载控件(如右下的对话框)
7. 加载XML数据(可作为游戏脚本及配置文件)
接下来就是准备开始着手开始写我们的游戏引擎了。
附上代码
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Media.Imaging; using System.Windows.Threading; using QXGame_Silverlight3.AStar; using System.Xml.Linq; namespace BattleTest { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); //加载背景图片测试 DrawBackImage(); //寻路测试 FindMoveZone(4, 5, 3); //地图单元格 DrawMapBack(); //静态图片测试 DrawElementPic("/pic/MM.png",4, 5); DrawElementPic("/pic/rolebig1.png",3, 2); DrawElementPic("/pic/2.png", 7, 7); //动画测试 DrawAnimation(2, 2); //寻路 FindPath(3, 3, 1, 8); //动态加载控件 LoadUserControl(); //加载XML数据 LoadXMLData(); } //加载图片 public static BitmapSource GetImage(string address) { return new BitmapImage(new Uri(string.Format(@"{0}", address), UriKind.Relative)); } //绘制地图单元格 public void DrawMapBack() { for (int i = 0; i < MAP_SIZE_X; ++i) for (int j = 0; j < MAP_SIZE_Y; ++j) { DrawMapBlock(i,j); } } //加载背景图片 private void DrawBackImage() { Brush brush_instance = new ImageBrush { ImageSource = GetImage("/pic/battle_back.jpg") }; Carrier.Background = brush_instance; } //搜索角色移动范围 bool[,] m_MoveZoneResult; static int[] dx = new int[4] { 0,1,0,-1 }; static int[] dy = new int[4] { 1,0,-1,0 }; private void FindMoveZone(int x, int y, int move_ability) { m_MoveZoneResult = new bool[MAP_SIZE_X, MAP_SIZE_Y]; MoveZoneSearch(x, y, move_ability); } private void MoveZoneSearch(int x, int y, int v) { int tmpx,tmpy; m_MoveZoneResult[x, y] = true; if( v == 0) return; for( int i=0;i<4;i++ ) { tmpx = x + dx[i]; tmpy = y + dy[i]; if( Visitable( tmpx ,tmpy ) ) MoveZoneSearch(tmpx, tmpy, v - 1); } } private bool Visitable(int x,int y) { return true; } //绘制地图单元格 public void DrawMapBlock(int x, int y) { Rectangle rect = new Rectangle(); if (m_MoveZoneResult[x, y]) rect.Fill = new SolidColorBrush(Colors.Green); else rect.Fill = new SolidColorBrush(Colors.Yellow); rect.Opacity = 0.3;//透明度 //rect.Stroke = new SolidColorBrush(Colors.Black); rect.Width = block_size; rect.Height = block_size; rect.RadiusX = block_radius; rect.RadiusY = block_radius; Carrier.Children.Add(rect); Canvas.SetLeft(rect, Transfer_X(x)); Canvas.SetTop(rect, Transfer_Y(y)); } //绘制元素(方块) public void DrawElement(int x, int y) { Rectangle rect = new Rectangle(); rect.Fill = new SolidColorBrush(Colors.Red); rect.Width = block_size; rect.Height = element_height; rect.RadiusX = block_radius; rect.RadiusY = block_radius; Carrier.Children.Add(rect); Canvas.SetLeft(rect, Transfer_X(x)); Canvas.SetTop(rect, Transfer_Y_Element(y)); } //绘制图片元素 public void DrawElementPic(string image,int x, int y) { Image SpiritInstance = new Image() { Source = GetImage(image) }; SpiritInstance.Width = block_size; SpiritInstance.Height = element_height; Carrier.Children.Add(SpiritInstance); Canvas.SetLeft(SpiritInstance, Transfer_X(x)); Canvas.SetTop(SpiritInstance, Transfer_Y_Element(y)); } //坐标系转换 public int Transfer_X(int x) { return (block_size + block_blank) * x; } public int Transfer_Y(int y) { return y_offset + (block_size + block_blank) * y; } //人物元素纵坐标转换 public int Transfer_Y_Element(int y) { return y_offset + (block_size + block_blank) * y - (element_height - block_size); } //动画 int count = 0; Image Animation; public void DrawAnimation(int x, int y) { Animation = new Image(); Animation.Width = 150; Animation.Height = 150; Carrier.Children.Add(Animation); DispatcherTimer dispatcherTimer = new DispatcherTimer(); dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick); dispatcherTimer.Interval = TimeSpan.FromMilliseconds(150); dispatcherTimer.Start(); } private void dispatcherTimer_Tick(object sender, EventArgs e) { Animation.Source = GetImage("/magic/0-" + count + ".png"); count++; if (count > 9) count = 0; } private IPathFinder PathFinder = null; private byte[,] Matrix = new byte[16, 16];//只能是2的次方……QX ENGINE的问题估计是。。 //寻路 public void FindPath(int start_x, int start_y, int end_x, int end_y) { Point Start = new Point(start_x, start_y); Point End = new Point(end_x, end_y); for (int i = 0; i < 16; i++) for (int j = 0; j < 16; j++) Matrix[i,j] = 1;//假设没有障碍物 //使用QXEngine提供的A*算法,此处可以斜方向寻路,到时候需要改…… PathFinder = new PathFinderFast(Matrix) { HeavyDiagonals = false, HeuristicEstimate = 2, SearchLimit = 2000 }; List<PathFinderNode> path = PathFinder.FindPath(Start, End); if (path == null) MessageBox.Show("没有路径"); else { for (int i = 0; i < path.Count; i++) { Rectangle rect = new Rectangle(); rect.Fill = new SolidColorBrush(Colors.Red); rect.Width = block_size; rect.Height = block_size; rect.Opacity = 0.3;//透明度 Carrier.Children.Add(rect); Canvas.SetLeft(rect, Transfer_X(path[i].X)); Canvas.SetTop(rect, Transfer_Y(path[i].Y)); } } } //加载用户控件 public void LoadUserControl() { SilverlightControl1 test = new SilverlightControl1(); Carrier.Children.Add(test); test.Opacity = 0.5; Canvas.SetLeft(test, 400); Canvas.SetTop(test, 200); } //加载XML数据 public void LoadXMLData() { XElement mapdata = GetTreeNode(XElement.Load("XMLFile1.xml"), "Map", "Name", "大地图"); string value = mapdata.Attribute("Value").Value; MessageBox.Show(value); } public static XElement GetTreeNode(XElement XML, string newroot, string attribute, string value) { return XML.DescendantsAndSelf(newroot).Single(X => X.Attribute(attribute).Value == value); } //常数 private static int element_height = 80; private static int block_radius = 5; private static int block_size = 50; private static int y_offset = 30; private static int block_blank = 2; private static int MAP_SIZE_X = 10; private static int MAP_SIZE_Y = 10; } }