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);
}
}
}
//-----------------------------------------------------------------------------------------------
}