using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Drawing.Drawing2D; using CommonAI.RTS; using CommonAI.Zone; using CommonAI.Zone.Instance; namespace CommonTest { /// /// 基础对象 /// public abstract class GameObject { readonly public Vector2 pos = new Vector2(); public float pos_z; public float direction; private GameWorld world; private int id; public GameObject(GameWorld wd, int id) { this.world = wd; this.id = id; } public int ID { get { return id; } } public GameWorld Parent { get { return world; } } abstract public RectangleF Bounds { get; } abstract public void doEvent(ObjectEvent e); abstract public void update(); abstract public void render(Graphics g); internal void syncPos(float x, float y, float d) { this.pos.x = x; this.pos.y = y; this.direction = d; } } //----------------------------------------------------------------------------------------------- /// /// 显示对象 /// abstract public class GameUnit : GameObject { public enum UnitStateType { IDLE = 0, MOVE, ACTION, DAMAGE, LIMITED, DEAD, } private UnitInfo info; private UnitStateType state = UnitStateType.IDLE; // Move private Vector2 targetPos = null; // Status private int mHP; private int mFreezeTimeHit; private int mFreezeTimeAtk; Pen[] pens = new Pen[] { new Pen(Color.LightBlue), new Pen(Color.Red), new Pen(Color.Green), new Pen(Color.Magenta), }; public GameUnit(GameWorld wd, UnitInfo info, int id) : base(wd, id) { this.info = info; this.pen = pens[info.force]; this.mHP = info.HealthPoint; foreach (int skillID in info.skills) { SkillTemplate st = TemplateManager.getInstance().getSkill(skillID); if (st != null && !mSkillStatus.ContainsKey(skillID)) { mSkillStatus.Add(skillID, new SkillState(st)); } } } public UnitInfo Info { get { return info; } } public float Speed { get { return info.moveSpeed; } } public UnitStateType State { get { return state; } set { this.state = value; } } override public RectangleF Bounds { get { return new RectangleF( pos.x - info.bodySize, pos.y - info.bodySize, info.bodySize * 2, info.bodySize * 2); } } //-------------------------------------------------------------------------------------------- #region Render private Pen pen; private Pen pen_attack = new Pen(Color.FromArgb(0x80, 0xff, 0x00, 0x00)); private Pen pen_guard = new Pen(Color.FromArgb(0x80, 0xff, 0xff, 0x00)); private Pen pen_path = new Pen(Color.FromArgb(0xff, 0x80, 0xff, 0x80)); private Pen pen_hit = new Pen(Color.FromArgb(0xff, 0xff, 0xff, 0xff)); private Brush brush = new SolidBrush(Color.FromArgb(0x80, 0x80, 0x80, 0x80)); private Brush brush_hp = new SolidBrush(Color.FromArgb(0xff, 0, 0xff, 0)); private Brush brush_black = new SolidBrush(Color.FromArgb(0xff, 0, 0, 0)); private Brush brush_attack = new SolidBrush(Color.FromArgb(0x80, 0xff, 0x00, 0x00)); override public void render(Graphics g) { if (mFreezeTimeHit > 0) { g.TranslateTransform((float)Math.Cos(mFreezeTimeHit * Math.PI / 2) * 2, 0); } if (state == UnitStateType.DAMAGE || mFreezeTimeHit > 0) { g.FillPie(brush_attack, -info.bodySize, -info.bodySize, info.bodySize * 2, info.bodySize * 2, 0, 360); } else if (state == UnitStateType.ACTION) { g.FillPie(brush, -info.bodySize, -info.bodySize, info.bodySize * 2, info.bodySize * 2, 0, 360); } // render body g.DrawArc(pen, -info.bodySize, -info.bodySize, info.bodySize * 2, info.bodySize * 2, 0, 360); // render direction renderDirection(g, pen, direction, info.bodySize); // render attack angle //renderRange(g, pen_attack, direction, info.attackRange, info.attackAngle); // render guard angle //g.DrawArc(pen_guard, -info.guardRange, -info.guardRange, info.guardRange * 2, info.guardRange * 2, 0, 360); if (mFreezeTimeAtk > 0) { // fillRange(g, brush_attack, direction, info.attackRange, info.attackAngle); } if (targetPos != null && info.type == UnitInfo.UnitType.TYPE_PLAYER) { g.DrawLine(pen_path, 0, 0, targetPos.x - pos.x, targetPos.y - pos.y); } renderHP(g); //g.DrawString("123", GameWorld.global_font, new SolidBrush(Color.White), 0, 0, StringFormat.GenericDefault); } private void renderHP(Graphics g) { float sx = -info.bodySize-2; float sy = -info.bodySize-8; float sw = info.bodySize*2+4; float sh = 6; g.FillRectangle(brush_black, sx, sy, sw, sh); g.FillRectangle(brush_hp, sx + 1, sy + 1, (sw - 2) * mHP / info.HealthPoint, sh - 2); } private void renderDirection(Graphics g, Pen pen, float direction, float range) { g.DrawLine(pen, 0, 0, (float)Math.Cos(direction) * range, (float)Math.Sin(direction) * range); } private void renderRange(Graphics g, Pen pen, float direction, float range, float angle) { float startRadians = direction - angle / 2; float endRadians = direction + angle / 2; g.DrawArc(pen, -range, -range, range * 2, range * 2, RTSMath.RadiansToDegrees(startRadians), RTSMath.RadiansToDegrees(angle)); g.DrawLine(pen, 0, 0, (float)Math.Cos(startRadians) * range, (float)Math.Sin(startRadians) * range); g.DrawLine(pen, 0, 0, (float)Math.Cos(endRadians) * range, (float)Math.Sin(endRadians) * range); } private void fillRange(Graphics g, Brush pen, float direction, float range, float angle) { float startRadians = direction - angle / 2; float endRadians = direction + angle / 2; g.FillPie(pen, -range, -range, range * 2, range * 2, RTSMath.RadiansToDegrees(startRadians), RTSMath.RadiansToDegrees(angle)); } #endregion //-------------------------------------------------------------------------------------------- override public void doEvent(ObjectEvent e) { if (e is UnitIdleEvent) { this.State = UnitStateType.IDLE; //Parent.showLog("UnitIdleEvent", pos.x, pos.y); } else if (e is UnitMoveEvent) { UnitMoveEvent me = (UnitMoveEvent)e; this.State = UnitStateType.MOVE; this.targetPos = new Vector2(me.x, me.y); } else if (e is UnitSlipEvent) { UnitSlipEvent me = e as UnitSlipEvent; this.targetPos = null; } else if (e is UnitFollowEvent) { UnitFollowEvent me = (UnitFollowEvent)e; this.State = UnitStateType.MOVE; } else if (e is UnitLaunchSkillEvent) { UnitLaunchSkillEvent me = (UnitLaunchSkillEvent)e; SkillState ss; if (mSkillStatus.TryGetValue(me.skill_id, out ss)) { ss.launch(); } } else if (e is UnitActionkEvent) { UnitActionkEvent me = (UnitActionkEvent)e; this.State = UnitStateType.ACTION; } else if (e is UnitAttackEvent) { UnitAttackEvent me = (UnitAttackEvent)e; this.mFreezeTimeAtk = me.freeze_time; } else if (e is UnitHitEvent) { UnitHitEvent me = (UnitHitEvent)e; if (me.damage) { this.State = UnitStateType.DAMAGE; } this.mFreezeTimeHit = me.freeze_time; this.mHP -= me.hp; this.mHP = Math.Max(0, mHP); Parent.showLog("" + me.hp, pos.x, pos.y); } else if (e is UnitDeadEvent) { UnitDeadEvent me = (UnitDeadEvent)e; this.State = UnitStateType.DEAD; Parent.showLog("UnitDeadEvent", pos.x, pos.y); } } override public void update() { if (mFreezeTimeAtk > 0) { mFreezeTimeAtk--; } if (mFreezeTimeHit > 0) { mFreezeTimeHit--; } switch (state) { case UnitStateType.IDLE: break; case UnitStateType.MOVE: break; case UnitStateType.DAMAGE: break; case UnitStateType.ACTION: break; default: break; } foreach (SkillState ss in mSkillStatus.Values) { ss.update(); } } //----------------------------------------------------------------------------------------------- #region SkillState // Skills private IDictionary mSkillStatus = new SortedDictionary(); public class SkillState { readonly public SkillTemplate Data; private int cool_down_time; public SkillState(SkillTemplate data) { this.Data = data; } internal void launch() { this.cool_down_time = Data.cool_down; } internal void update() { if (cool_down_time > 0) { cool_down_time--; } } public float getCDPercent() { if (Data.cool_down == 0) { return 0; } return (cool_down_time / (float)Data.cool_down); } public bool isCD() { return cool_down_time > 0; } } public ICollection getSkillStatus() { return new List(mSkillStatus.Values); } #endregion } //----------------------------------------------------------------------------------------------- public class GameUnitActor : GameUnit { public GameUnitActor(GameWorld wd, UnitInfo info, int id) : base(wd, info, id) { } } public class GameUnitNpc : GameUnit { public GameUnitNpc(GameWorld wd, UnitInfo info, int id) : base(wd, info, id) { } } //----------------------------------------------------------------------------------------------- public class GameSpellObject : GameObject { private SpellTemplate info; private Pen pen = new Pen(Color.FromArgb(0xff, 0xff, 0xff, 0x00)); private float size; public GameSpellObject(GameWorld wd, SpellTemplate sp, int id, GameUnit launcher, GameUnit target) : base(wd, id) { this.info = sp; this.size = info.bodySize; } override public RectangleF Bounds { get { return new RectangleF( pos.x - info.bodySize, pos.y - info.bodySize, info.bodySize * 2, info.bodySize * 2); } } public override void doEvent(ObjectEvent e) { } public override void update() { if (info.motionType == SpellTemplate.MotionType.AOE) { size += info.motionSpeed; } } public override void render(Graphics g) { if (info.motionType == SpellTemplate.MotionType.Laser) { g.DrawLine(pen, 0, 0, (float)Math.Cos(direction) * info.bodySize, (float)Math.Sin(direction) * info.bodySize); } else { // render body g.DrawArc(pen, -size, -size, size * 2, size * 2, 0, 360); g.DrawLine(pen, 0, 0, (float)Math.Cos(direction) * info.bodySize, (float)Math.Sin(direction) * info.bodySize); } } } //----------------------------------------------------------------------------------------------- }