FormAstar.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. using CommonAI.RTS;
  2. using CommonLang.Vector;
  3. using CommonAI.RTS.Manhattan;
  4. using CommonAI.Zone;
  5. using CommonAI.Zone.ZoneEditor;
  6. using CommonLang;
  7. using GameEditorPlugin.Win32;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.ComponentModel;
  11. using System.Data;
  12. using System.Diagnostics;
  13. using System.Drawing;
  14. using System.IO;
  15. using System.Linq;
  16. using System.Text;
  17. using System.Windows.Forms;
  18. using CommonAI.Zone.Helper;
  19. using CommonLang.Property;
  20. namespace GameEditorPlugin.Tools
  21. {
  22. public partial class FormAstar : Form
  23. {
  24. private AStarTerrain display;
  25. private Vector2 mPathBegin;
  26. public static Vector2 pic_lastMouesPos = new Vector2(0, 0);
  27. private string mScenePath;
  28. public FormAstar(string scene_path = null, TerrainDefinitionMap define = null, SceneData zone = null)
  29. {
  30. InitializeComponent();
  31. this.mScenePath = scene_path;
  32. this.display = new AStarTerrain(define);
  33. try
  34. {
  35. display.RandomSeed = DateTime.Now.Millisecond;
  36. display.Reset(zone);
  37. }
  38. catch (Exception err)
  39. {
  40. MessageBox.Show(err.Message);
  41. }
  42. }
  43. private void FormAstar_Load(object sender, EventArgs e)
  44. {
  45. this.displayTerrainPanel1.Display = display;
  46. this.display.PathFinder.SpaceDivEnableDistance = (int)num_EnableSpaceDivDistance.Value;
  47. this.display.PathFinder.SpaceOptimizePathLimitDistance = (int)num_OptimizePathLimit.Value;
  48. this.display.SetSpaceDiv((int)num_SpaceDivDistance.Value);
  49. this.display.GenShowItems(toolStripDropDownButton3);
  50. }
  51. private void resetToolStripMenuItem_Click(object sender, EventArgs e)
  52. {
  53. display.Reset();
  54. }
  55. private void btn_LoadScene_Click(object sender, EventArgs e)
  56. {
  57. OpenFileDialog fd = new OpenFileDialog();
  58. if (mScenePath != null)
  59. {
  60. fd.InitialDirectory = mScenePath;
  61. }
  62. if (fd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
  63. {
  64. try
  65. {
  66. string text = File.ReadAllText(fd.FileName);
  67. SceneData sd = EditorTemplates.DataFromXML<SceneData>(text);
  68. display.Reset(sd);
  69. }
  70. catch (Exception err)
  71. {
  72. MessageBox.Show(err.Message);
  73. }
  74. }
  75. }
  76. private void btn_FillTerrain_Click(object sender, EventArgs e)
  77. {
  78. btn_CleanTerrain.Checked = false;
  79. }
  80. private void btn_CleanTerrain_Click(object sender, EventArgs e)
  81. {
  82. btn_FillTerrain.Checked = false;
  83. }
  84. private void num_SpaceDivDistance_ValueChanged(object sender, EventArgs e)
  85. {
  86. this.display.SetSpaceDiv((int)num_SpaceDivDistance.Value);
  87. }
  88. private void num_EnableSpaceDivDistance_ValueChanged(object sender, EventArgs e)
  89. {
  90. this.display.PathFinder.SpaceDivEnableDistance = (int)num_EnableSpaceDivDistance.Value;
  91. }
  92. private void num_OptimizePathLimit_ValueChanged(object sender, EventArgs e)
  93. {
  94. this.display.PathFinder.SpaceOptimizePathLimitDistance = (int)num_OptimizePathLimit.Value;
  95. }
  96. private void displayTerrainPanel1_PictureBoxMouseDown(object sender, MouseEventArgs e)
  97. {
  98. float wx = display.screenToWorldX(e.X);
  99. float wy = display.screenToWorldY(e.Y);
  100. pic_lastMouesPos.SetX(wx);
  101. pic_lastMouesPos.SetY(wy);
  102. if (btn_FillTerrain.Checked || btn_CleanTerrain.Checked)
  103. {
  104. display.ShowPoint = true;
  105. int size = int.Parse(com_FillTerrainSize.Text);
  106. display.SetPointer(wx, wy, size);
  107. if (e.Button == System.Windows.Forms.MouseButtons.Left)
  108. {
  109. display.FillTerrain(btn_FillTerrain.Checked);
  110. }
  111. }
  112. else if (mPathBegin == null)
  113. {
  114. if (e.Button == System.Windows.Forms.MouseButtons.Left)
  115. {
  116. mPathBegin = new Vector2(e.X, e.Y);
  117. display.BeginFindPath(wx, wy);
  118. }
  119. }
  120. else if (!btn_FreeMove.Checked)
  121. {
  122. if (e.Button == System.Windows.Forms.MouseButtons.Left)
  123. {
  124. mPathBegin = null;
  125. display.EndFindPath(wx, wy, btn_Optimize.Checked);
  126. }
  127. }
  128. }
  129. private void displayTerrainPanel1_PictureBoxMouseMove(object sender, MouseEventArgs e)
  130. {
  131. float wx = display.screenToWorldX(e.X);
  132. float wy = display.screenToWorldY(e.Y);
  133. pic_lastMouesPos.SetX(wx);
  134. pic_lastMouesPos.SetY(wy);
  135. display.ShowPoint = false;
  136. if (btn_FillTerrain.Checked || btn_CleanTerrain.Checked)
  137. {
  138. display.ShowPoint = true;
  139. int size = int.Parse(com_FillTerrainSize.Text);
  140. display.SetPointer(wx, wy, size);
  141. if (e.Button == System.Windows.Forms.MouseButtons.Left)
  142. {
  143. display.FillTerrain(btn_FillTerrain.Checked);
  144. }
  145. }
  146. else if (btn_FreeMove.Checked)
  147. {
  148. if (e.Button == System.Windows.Forms.MouseButtons.Left)
  149. {
  150. if (mPathBegin != null)
  151. {
  152. display.EndFindPath(wx, wy, btn_Optimize.Checked);
  153. }
  154. }
  155. }
  156. }
  157. private void displayTerrainPanel1_PictureBoxMouseUp(object sender, MouseEventArgs e)
  158. {
  159. float wx = display.screenToWorldX(e.X);
  160. float wy = display.screenToWorldY(e.Y);
  161. if (btn_FillTerrain.Checked)
  162. {
  163. }
  164. else if (btn_FreeMove.Checked)
  165. {
  166. if (e.Button == System.Windows.Forms.MouseButtons.Left)
  167. {
  168. if (mPathBegin != null)
  169. {
  170. mPathBegin = null;
  171. display.EndFindPath(wx, wy, btn_Optimize.Checked);
  172. }
  173. }
  174. }
  175. }
  176. class AStarTerrain : DisplayManhattanTerrain
  177. {
  178. [Desc("显示点", "show")]
  179. public bool ShowPoint = true;
  180. private const int BLOCK_VALUE = (int)0x7F00FF00;
  181. private int random_seed_index = 1;
  182. private ZoneInfo zone_data;
  183. private TerrainDefinitionMap define;
  184. private AstarManhattan path_finder;
  185. private AstarManhattan.MWayPoint current_path;
  186. private Vector2 path_begin;
  187. private Vector2 path_end;
  188. private long last_pathfind_tick = 0;
  189. private long last_touchmap_tick = 0;
  190. private Vector2 point_pos = new Vector2();
  191. private int point_size = 1;
  192. public override AstarManhattan PathFinder
  193. {
  194. get { return path_finder; }
  195. }
  196. public override int SpaceDivSize
  197. {
  198. get { return path_finder.SpaceDivSize; }
  199. }
  200. public int RandomSeed
  201. {
  202. get { return random_seed_index; }
  203. set { random_seed_index = value; }
  204. }
  205. public AStarTerrain(TerrainDefinitionMap define)
  206. {
  207. this.define = define;
  208. this.ShowSpaceDiv = true;
  209. this.ShowTerrainMesh = true;
  210. }
  211. public void SetSpaceDiv(int value)
  212. {
  213. if (zone_data != null)
  214. {
  215. if (path_finder == null || path_finder.SpaceDivSize != value)
  216. {
  217. this.path_finder = new AstarManhattan(this.zone_data.TemplateID, new EditorZoneManhattanMap(zone_data, define), true, value);
  218. }
  219. }
  220. }
  221. public void Reset(SceneData sd = null)
  222. {
  223. if (sd == null)
  224. {
  225. Random random = new Random(random_seed_index);
  226. random_seed_index++;
  227. this.zone_data = new ZoneInfo(random.Next(50, 200), random.Next(50, 200), 32, 32);
  228. for (int x = 0; x < zone_data.XCount; x++)
  229. {
  230. for (int y = 0; y < zone_data.YCount; y++)
  231. {
  232. zone_data.TerrainMatrix[x, y] = CUtils.RandomPercent(random, 85) ? 0 : BLOCK_VALUE;
  233. }
  234. }
  235. this.InitTerrain(zone_data);
  236. }
  237. else
  238. {
  239. zone_data = (ZoneInfo)sd.ZoneData.Clone();
  240. // zone_data.mGridCellW = sd.;
  241. // zone_data.mGridCellH = 32;
  242. this.InitTerrain(zone_data);
  243. }
  244. }
  245. public override void Dispose()
  246. {
  247. }
  248. //--------------------------------------------------------------------------------------
  249. protected override void InitTerrain(ZoneInfo zone)
  250. {
  251. base.InitTerrain(zone);
  252. if (path_finder != null)
  253. {
  254. path_finder.Dispose();
  255. }
  256. this.path_finder = new AstarManhattan(zone.TemplateID, new EditorZoneManhattanMap(zone, define), true, 8);
  257. }
  258. internal void SetPointer(float sx, float sy, int r)
  259. {
  260. point_pos.SetX(sx);
  261. point_pos.SetY(sy);
  262. point_size = r;
  263. }
  264. internal void BeginFindPath(float sx, float sy)
  265. {
  266. path_begin = new Vector2(sx, sy);
  267. path_end = null;
  268. current_path = null;
  269. }
  270. internal void EndFindPath(float dx, float dy, bool optimize)
  271. {
  272. path_end = new Vector2(dx, dy);
  273. {
  274. var sw = Stopwatch.StartNew();
  275. path_finder.findPath(path_begin.X, path_begin.Y, dx, dy, out current_path, optimize);
  276. sw.Stop();
  277. last_pathfind_tick = sw.ElapsedTicks;
  278. }
  279. }
  280. internal void FillTerrain(bool block)
  281. {
  282. int bx, by;
  283. path_finder.PosToBlock(point_pos.X, point_pos.Y, out bx, out by);
  284. path_finder.FillTerrainByBlock(
  285. (bx - point_size / 2),
  286. (by - point_size / 2),
  287. (point_size),
  288. (point_size),
  289. block ? BLOCK_VALUE : 0);
  290. }
  291. //--------------------------------------------------------------------------------------
  292. #region Render
  293. private Pen path_pen = new Pen(Color.Red);
  294. private SolidBrush path_brush = new SolidBrush(Color.FromArgb(0x80, Color.Gray));
  295. private Pen pen_point = new Pen(Color.FromArgb(0xA0, 0xff, 0xff, 0xff));
  296. private Pen pen_begin = new Pen(Color.FromArgb(0xFF, 0, 0xff, 0));
  297. private Pen pen_space_div = new Pen(Color.FromArgb(0x20, 0xff, 0xff, 0xff));
  298. private Pen pen_space_div_next = new Pen(Color.FromArgb(0x20, 0xff, 0xff, 0xff));
  299. //private Brush brush_mesh = new SolidBrush(Color.FromArgb(0x80, 0xff, 0xff, 0xff));
  300. private Pen pen_path_begin = new Pen(Color.FromArgb(0x10, 0xFF, 0xFF, 0xFF));
  301. private Pen pen_ray = new Pen(Color.Yellow);
  302. public override void render(Graphics g)
  303. {
  304. pen_point.Width =
  305. pen_space_div_next.Width =
  306. pen_space_div.Width =
  307. pen_begin.Width =
  308. path_pen.Width =
  309. pen_path_begin.Width =
  310. pen_ray.Width =
  311. 1 / getCameraScale();
  312. base.render(g);
  313. }
  314. protected override void renderTerrain(Graphics g, RectangleF rect)
  315. {
  316. base.renderTerrain(g, rect);
  317. if (ShowPoint)
  318. {
  319. int bx, by;
  320. path_finder.PosToBlock(point_pos.X, point_pos.Y, out bx, out by);
  321. g.DrawRectangle(pen_point,
  322. (bx - point_size / 2) * base.CellW,
  323. (by - point_size / 2) * base.CellH,
  324. (point_size) * base.CellW,
  325. (point_size) * base.CellH);
  326. }
  327. }
  328. protected override void renderCell(Graphics g, int bx, int by, int flag)
  329. {
  330. base.renderCell(g, bx, by, flag);
  331. if (ShowSpaceDiv && path_finder != null && path_finder.SpaceDivSize > 0)
  332. {
  333. if (bx % path_finder.SpaceDivSize == 0 && by % path_finder.SpaceDivSize == 0)
  334. {
  335. int cx = bx / path_finder.SpaceDivSize;
  336. int cy = by / path_finder.SpaceDivSize;
  337. var sn = path_finder.GetSpaceMapNode(cx, cy);
  338. if (sn != null && sn.AnchorNode != null)
  339. {
  340. g.DrawRectangle(pen_space_div,
  341. sn.AnchorNode.BX * CellW,
  342. sn.AnchorNode.BY * CellH,
  343. CellW,
  344. CellH);
  345. foreach (var next in sn.NextsSpaceNode)
  346. {
  347. var link = sn.GetNextLink(next);
  348. if (link != null)
  349. {
  350. renderPath(g, new Vector2(sn.AnchorNode.PosX, sn.AnchorNode.PosY), link, pen_space_div_next, pen_space_div_next);
  351. }
  352. }
  353. }
  354. }
  355. }
  356. }
  357. protected override void renderMeshCell(Graphics g, AstarManhattan.MMapNode tn)
  358. {
  359. //if (tn.Mesh != null)
  360. {
  361. //g.FillRectangle(brush_mesh, tn.BX * CellW, tn.BY * CellH, CellW, CellH);
  362. base.renderMeshCell(g, tn);
  363. }
  364. }
  365. protected void renderPath(Graphics g, Vector2 path_begin, AstarManhattan.MWayPoint path, Pen pen_line, Pen pen_begin = null, Brush pen_brush = null)
  366. {
  367. if (path_begin != null && pen_begin != null)
  368. {
  369. g.DrawLine(pen_begin, path_begin.X, path_begin.Y, path.PosX, path.PosY);
  370. }
  371. if (path != null)
  372. {
  373. foreach (AstarManhattan.MWayPoint wp in path)
  374. {
  375. if (pen_brush != null)
  376. {
  377. g.FillRectangle(pen_brush, wp.BX * CellW, wp.BY * CellH, CellW, CellH);
  378. }
  379. if (wp.Next != null)
  380. {
  381. g.DrawLine(pen_line, wp.PosX, wp.PosY, wp.Next.PosX, wp.Next.PosY);
  382. }
  383. }
  384. }
  385. }
  386. protected override void renderObjects(Graphics g, RectangleF worldBounds)
  387. {
  388. if (path_begin != null)
  389. {
  390. g.DrawArc(path_pen, path_begin.X - 1, path_begin.Y - 1, 2, 2, 0, 360);
  391. }
  392. if (path_end != null)
  393. {
  394. g.DrawArc(path_pen, path_end.X - 1, path_end.Y - 1, 2, 2, 0, 360);
  395. }
  396. if (path_begin != null && path_end != null)
  397. {
  398. g.DrawLine(pen_path_begin, path_begin.X, path_begin.Y, path_end.X, path_end.Y);
  399. float tx, ty, td;
  400. Stopwatch watch = new Stopwatch();
  401. watch.Start();
  402. bool ret = (path_finder.GetLineTouchPoint(path_begin.X, path_begin.Y, path_end.X, path_end.Y, out tx, out ty, out td));
  403. watch.Stop();
  404. last_touchmap_tick = watch.ElapsedTicks;
  405. if (ret)
  406. {
  407. g.DrawLine(pen_ray, path_begin.X, path_begin.Y, tx, ty);
  408. g.DrawArc(pen_ray, tx - 1, ty - 1, 2, 2, 0, 360);
  409. }
  410. else
  411. {
  412. g.DrawLine(pen_ray, path_begin.X, path_begin.Y, path_end.X, path_end.Y);
  413. g.DrawArc(pen_ray, path_end.X - 1, path_end.Y - 1, 2, 2, 0, 360);
  414. }
  415. }
  416. if (current_path != null)
  417. {
  418. renderPath(g, path_begin, current_path, path_pen, pen_begin, path_brush);
  419. }
  420. }
  421. protected override void renderSpaceDiv(Graphics g, RectangleF rect)
  422. {
  423. base.renderSpaceDiv(g, rect);
  424. }
  425. protected override void renderScreen(Graphics g, RectangleF worldBounds)
  426. {
  427. g.DrawString(
  428. string.Format(" mnodes={0}/{1} mesh={2} wps={3} pathfind={4}(t) touchmap={5}(t), Mouse=({6},{7})",
  429. AstarManhattan.MMapNode.ActiveObjectCount,
  430. (PathFinder != null ? (PathFinder.MMap.XCount * PathFinder.MMap.YCount) : 0),
  431. AstarManhattan.MMapNode.BlockMesh.ActiveObjectCount,
  432. AstarManhattan.MWayPoint.ActiveObjectCount,
  433. last_pathfind_tick,
  434. last_touchmap_tick,
  435. pic_lastMouesPos.X,
  436. pic_lastMouesPos.Y
  437. ),
  438. Control.DefaultFont, new SolidBrush(Color.White), 10, 10);
  439. }
  440. #endregion
  441. }
  442. private void gCToolStripMenuItem_Click(object sender, EventArgs e)
  443. {
  444. GC.Collect();
  445. }
  446. }
  447. }