GameWorldObject.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Drawing;
  6. using System.Drawing.Drawing2D;
  7. using CommonAI.RTS;
  8. using CommonAI.Zone;
  9. using CommonAI.Zone.Instance;
  10. namespace CommonTest
  11. {
  12. /// <summary>
  13. /// 基础对象
  14. /// </summary>
  15. public abstract class GameObject
  16. {
  17. readonly public Vector2 pos = new Vector2();
  18. public float pos_z;
  19. public float direction;
  20. private GameWorld world;
  21. private int id;
  22. public GameObject(GameWorld wd, int id)
  23. {
  24. this.world = wd;
  25. this.id = id;
  26. }
  27. public int ID { get { return id; } }
  28. public GameWorld Parent { get { return world; } }
  29. abstract public RectangleF Bounds { get; }
  30. abstract public void doEvent(ObjectEvent e);
  31. abstract public void update();
  32. abstract public void render(Graphics g);
  33. internal void syncPos(float x, float y, float d)
  34. {
  35. this.pos.x = x;
  36. this.pos.y = y;
  37. this.direction = d;
  38. }
  39. }
  40. //-----------------------------------------------------------------------------------------------
  41. /// <summary>
  42. /// 显示对象
  43. /// </summary>
  44. abstract public class GameUnit : GameObject
  45. {
  46. public enum UnitStateType
  47. {
  48. IDLE = 0,
  49. MOVE,
  50. ACTION,
  51. DAMAGE,
  52. LIMITED,
  53. DEAD,
  54. }
  55. private UnitInfo info;
  56. private UnitStateType state = UnitStateType.IDLE;
  57. // Move
  58. private Vector2 targetPos = null;
  59. // Status
  60. private int mHP;
  61. private int mFreezeTimeHit;
  62. private int mFreezeTimeAtk;
  63. Pen[] pens = new Pen[]
  64. {
  65. new Pen(Color.LightBlue),
  66. new Pen(Color.Red),
  67. new Pen(Color.Green),
  68. new Pen(Color.Magenta),
  69. };
  70. public GameUnit(GameWorld wd, UnitInfo info, int id)
  71. : base(wd, id)
  72. {
  73. this.info = info;
  74. this.pen = pens[info.force];
  75. this.mHP = info.HealthPoint;
  76. foreach (int skillID in info.skills)
  77. {
  78. SkillTemplate st = TemplateManager.getInstance().getSkill(skillID);
  79. if (st != null && !mSkillStatus.ContainsKey(skillID))
  80. {
  81. mSkillStatus.Add(skillID, new SkillState(st));
  82. }
  83. }
  84. }
  85. public UnitInfo Info { get { return info; } }
  86. public float Speed { get { return info.moveSpeed; } }
  87. public UnitStateType State
  88. {
  89. get { return state; }
  90. set { this.state = value; }
  91. }
  92. override public RectangleF Bounds
  93. {
  94. get
  95. {
  96. return new RectangleF(
  97. pos.x - info.bodySize,
  98. pos.y - info.bodySize,
  99. info.bodySize * 2,
  100. info.bodySize * 2);
  101. }
  102. }
  103. //--------------------------------------------------------------------------------------------
  104. #region Render
  105. private Pen pen;
  106. private Pen pen_attack = new Pen(Color.FromArgb(0x80, 0xff, 0x00, 0x00));
  107. private Pen pen_guard = new Pen(Color.FromArgb(0x80, 0xff, 0xff, 0x00));
  108. private Pen pen_path = new Pen(Color.FromArgb(0xff, 0x80, 0xff, 0x80));
  109. private Pen pen_hit = new Pen(Color.FromArgb(0xff, 0xff, 0xff, 0xff));
  110. private Brush brush = new SolidBrush(Color.FromArgb(0x80, 0x80, 0x80, 0x80));
  111. private Brush brush_hp = new SolidBrush(Color.FromArgb(0xff, 0, 0xff, 0));
  112. private Brush brush_black = new SolidBrush(Color.FromArgb(0xff, 0, 0, 0));
  113. private Brush brush_attack = new SolidBrush(Color.FromArgb(0x80, 0xff, 0x00, 0x00));
  114. override public void render(Graphics g)
  115. {
  116. if (mFreezeTimeHit > 0)
  117. {
  118. g.TranslateTransform((float)Math.Cos(mFreezeTimeHit * Math.PI / 2) * 2, 0);
  119. }
  120. if (state == UnitStateType.DAMAGE || mFreezeTimeHit > 0)
  121. {
  122. g.FillPie(brush_attack, -info.bodySize, -info.bodySize, info.bodySize * 2, info.bodySize * 2, 0, 360);
  123. }
  124. else if (state == UnitStateType.ACTION)
  125. {
  126. g.FillPie(brush, -info.bodySize, -info.bodySize, info.bodySize * 2, info.bodySize * 2, 0, 360);
  127. }
  128. // render body
  129. g.DrawArc(pen, -info.bodySize, -info.bodySize, info.bodySize * 2, info.bodySize * 2, 0, 360);
  130. // render direction
  131. renderDirection(g, pen, direction, info.bodySize);
  132. // render attack angle
  133. //renderRange(g, pen_attack, direction, info.attackRange, info.attackAngle);
  134. // render guard angle
  135. //g.DrawArc(pen_guard, -info.guardRange, -info.guardRange, info.guardRange * 2, info.guardRange * 2, 0, 360);
  136. if (mFreezeTimeAtk > 0)
  137. {
  138. // fillRange(g, brush_attack, direction, info.attackRange, info.attackAngle);
  139. }
  140. if (targetPos != null && info.type == UnitInfo.UnitType.TYPE_PLAYER)
  141. {
  142. g.DrawLine(pen_path, 0, 0, targetPos.x - pos.x, targetPos.y - pos.y);
  143. }
  144. renderHP(g);
  145. //g.DrawString("123", GameWorld.global_font, new SolidBrush(Color.White), 0, 0, StringFormat.GenericDefault);
  146. }
  147. private void renderHP(Graphics g)
  148. {
  149. float sx = -info.bodySize-2;
  150. float sy = -info.bodySize-8;
  151. float sw = info.bodySize*2+4;
  152. float sh = 6;
  153. g.FillRectangle(brush_black, sx, sy, sw, sh);
  154. g.FillRectangle(brush_hp, sx + 1, sy + 1, (sw - 2) * mHP / info.HealthPoint, sh - 2);
  155. }
  156. private void renderDirection(Graphics g, Pen pen, float direction, float range)
  157. {
  158. g.DrawLine(pen, 0, 0,
  159. (float)Math.Cos(direction) * range,
  160. (float)Math.Sin(direction) * range);
  161. }
  162. private void renderRange(Graphics g, Pen pen, float direction, float range, float angle)
  163. {
  164. float startRadians = direction - angle / 2;
  165. float endRadians = direction + angle / 2;
  166. g.DrawArc(pen,
  167. -range,
  168. -range,
  169. range * 2,
  170. range * 2,
  171. RTSMath.RadiansToDegrees(startRadians),
  172. RTSMath.RadiansToDegrees(angle));
  173. g.DrawLine(pen, 0, 0,
  174. (float)Math.Cos(startRadians) * range,
  175. (float)Math.Sin(startRadians) * range);
  176. g.DrawLine(pen, 0, 0,
  177. (float)Math.Cos(endRadians) * range,
  178. (float)Math.Sin(endRadians) * range);
  179. }
  180. private void fillRange(Graphics g, Brush pen, float direction, float range, float angle)
  181. {
  182. float startRadians = direction - angle / 2;
  183. float endRadians = direction + angle / 2;
  184. g.FillPie(pen,
  185. -range,
  186. -range,
  187. range * 2,
  188. range * 2,
  189. RTSMath.RadiansToDegrees(startRadians),
  190. RTSMath.RadiansToDegrees(angle));
  191. }
  192. #endregion
  193. //--------------------------------------------------------------------------------------------
  194. override public void doEvent(ObjectEvent e)
  195. {
  196. if (e is UnitIdleEvent)
  197. {
  198. this.State = UnitStateType.IDLE;
  199. //Parent.showLog("UnitIdleEvent", pos.x, pos.y);
  200. }
  201. else if (e is UnitMoveEvent)
  202. {
  203. UnitMoveEvent me = (UnitMoveEvent)e;
  204. this.State = UnitStateType.MOVE;
  205. this.targetPos = new Vector2(me.x, me.y);
  206. }
  207. else if (e is UnitSlipEvent)
  208. {
  209. UnitSlipEvent me = e as UnitSlipEvent;
  210. this.targetPos = null;
  211. }
  212. else if (e is UnitFollowEvent)
  213. {
  214. UnitFollowEvent me = (UnitFollowEvent)e;
  215. this.State = UnitStateType.MOVE;
  216. }
  217. else if (e is UnitLaunchSkillEvent)
  218. {
  219. UnitLaunchSkillEvent me = (UnitLaunchSkillEvent)e;
  220. SkillState ss;
  221. if (mSkillStatus.TryGetValue(me.skill_id, out ss))
  222. {
  223. ss.launch();
  224. }
  225. }
  226. else if (e is UnitActionkEvent)
  227. {
  228. UnitActionkEvent me = (UnitActionkEvent)e;
  229. this.State = UnitStateType.ACTION;
  230. }
  231. else if (e is UnitAttackEvent)
  232. {
  233. UnitAttackEvent me = (UnitAttackEvent)e;
  234. this.mFreezeTimeAtk = me.freeze_time;
  235. }
  236. else if (e is UnitHitEvent)
  237. {
  238. UnitHitEvent me = (UnitHitEvent)e;
  239. if (me.damage)
  240. {
  241. this.State = UnitStateType.DAMAGE;
  242. }
  243. this.mFreezeTimeHit = me.freeze_time;
  244. this.mHP -= me.hp;
  245. this.mHP = Math.Max(0, mHP);
  246. Parent.showLog("" + me.hp, pos.x, pos.y);
  247. }
  248. else if (e is UnitDeadEvent)
  249. {
  250. UnitDeadEvent me = (UnitDeadEvent)e;
  251. this.State = UnitStateType.DEAD;
  252. Parent.showLog("UnitDeadEvent", pos.x, pos.y);
  253. }
  254. }
  255. override public void update()
  256. {
  257. if (mFreezeTimeAtk > 0)
  258. {
  259. mFreezeTimeAtk--;
  260. }
  261. if (mFreezeTimeHit > 0)
  262. {
  263. mFreezeTimeHit--;
  264. }
  265. switch (state)
  266. {
  267. case UnitStateType.IDLE:
  268. break;
  269. case UnitStateType.MOVE:
  270. break;
  271. case UnitStateType.DAMAGE:
  272. break;
  273. case UnitStateType.ACTION:
  274. break;
  275. default:
  276. break;
  277. }
  278. foreach (SkillState ss in mSkillStatus.Values)
  279. {
  280. ss.update();
  281. }
  282. }
  283. //-----------------------------------------------------------------------------------------------
  284. #region SkillState
  285. // Skills
  286. private IDictionary<int, SkillState> mSkillStatus = new SortedDictionary<int, SkillState>();
  287. public class SkillState
  288. {
  289. readonly public SkillTemplate Data;
  290. private int cool_down_time;
  291. public SkillState(SkillTemplate data)
  292. {
  293. this.Data = data;
  294. }
  295. internal void launch()
  296. {
  297. this.cool_down_time = Data.cool_down;
  298. }
  299. internal void update()
  300. {
  301. if (cool_down_time > 0)
  302. {
  303. cool_down_time--;
  304. }
  305. }
  306. public float getCDPercent()
  307. {
  308. if (Data.cool_down == 0)
  309. {
  310. return 0;
  311. }
  312. return (cool_down_time / (float)Data.cool_down);
  313. }
  314. public bool isCD()
  315. {
  316. return cool_down_time > 0;
  317. }
  318. }
  319. public ICollection<SkillState> getSkillStatus()
  320. {
  321. return new List<SkillState>(mSkillStatus.Values);
  322. }
  323. #endregion
  324. }
  325. //-----------------------------------------------------------------------------------------------
  326. public class GameUnitActor : GameUnit
  327. {
  328. public GameUnitActor(GameWorld wd, UnitInfo info, int id)
  329. : base(wd, info, id)
  330. {
  331. }
  332. }
  333. public class GameUnitNpc : GameUnit
  334. {
  335. public GameUnitNpc(GameWorld wd, UnitInfo info, int id)
  336. : base(wd, info, id)
  337. {
  338. }
  339. }
  340. //-----------------------------------------------------------------------------------------------
  341. public class GameSpellObject : GameObject
  342. {
  343. private SpellTemplate info;
  344. private Pen pen = new Pen(Color.FromArgb(0xff, 0xff, 0xff, 0x00));
  345. private float size;
  346. public GameSpellObject(GameWorld wd, SpellTemplate sp, int id, GameUnit launcher, GameUnit target)
  347. : base(wd, id)
  348. {
  349. this.info = sp;
  350. this.size = info.bodySize;
  351. }
  352. override public RectangleF Bounds
  353. {
  354. get
  355. {
  356. return new RectangleF(
  357. pos.x - info.bodySize,
  358. pos.y - info.bodySize,
  359. info.bodySize * 2,
  360. info.bodySize * 2);
  361. }
  362. }
  363. public override void doEvent(ObjectEvent e)
  364. {
  365. }
  366. public override void update()
  367. {
  368. if (info.motionType == SpellTemplate.MotionType.AOE)
  369. {
  370. size += info.motionSpeed;
  371. }
  372. }
  373. public override void render(Graphics g)
  374. {
  375. if (info.motionType == SpellTemplate.MotionType.Laser)
  376. {
  377. g.DrawLine(pen, 0, 0,
  378. (float)Math.Cos(direction) * info.bodySize,
  379. (float)Math.Sin(direction) * info.bodySize);
  380. }
  381. else
  382. {
  383. // render body
  384. g.DrawArc(pen, -size, -size, size * 2, size * 2, 0, 360);
  385. g.DrawLine(pen, 0, 0,
  386. (float)Math.Cos(direction) * info.bodySize,
  387. (float)Math.Sin(direction) * info.bodySize);
  388. }
  389. }
  390. }
  391. //-----------------------------------------------------------------------------------------------
  392. }