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; using CommonAI.RTS.Manhattan; namespace CommonTest { public class GameWorld : GameBase, InstanceZoneListener { private ZoneInfo mZoneInfo; private int mWidth; private int mHeight; private int mCellW; private int mCellH; private int mGridXCount; private int mGridYCount; private SceneLOL zone; private Dictionary units = new Dictionary(); private List logs = new List(); private float timer; private long mLastUpdateTime; private int mFPS = 0; private GameWorld(InitZoneInfo zinf) { this.mZoneInfo = zinf.Info; this.mGridXCount = RTSMath.roundMod(mZoneInfo.TotalWidth, mZoneInfo.GridCellW); this.mGridYCount = RTSMath.roundMod(mZoneInfo.TotalHeight, mZoneInfo.GridCellH); this.mWidth = mZoneInfo.TotalWidth; this.mHeight = mZoneInfo.TotalHeight; this.mCellW = mZoneInfo.GridCellW; this.mCellH = mZoneInfo.GridCellH; this.zone = new SceneLOL(this, mZoneInfo, SpaceDIV); zinf.initGame(zone); } //----------------------------------------------------------------------------------------------- // instructions //----------------------------------------------------------------------------------------------- #region TEST_________________________________ public static GameWorld create3C() { InitZoneInfo zinfo = test_InitZoneInfo(null); test_init3C(zinfo); GameWorld gw = new GameWorld(zinfo); return gw; } public static GameWorld create4A() { InitZoneInfo zinfo = test_InitZoneInfo(null); test_init4A(zinfo); GameWorld gw = new GameWorld(zinfo); return gw; } public static GameWorld createLOL(Bitmap mapmask) { InitZoneInfo zinfo = test_InitZoneInfo(mapmask); test_initLOL(zinfo); GameWorld gw = new GameWorld(zinfo); return gw; } public void test_AddActor(string name) { float x = random.Next(0, mWidth); float y = random.Next(0, mHeight); x = mWidth / 2; y = mHeight / 2; UnitInfo info = test_InitUnitInfo(SceneLOL.UNIT_FORCE_A, name, false, false); info.type = UnitInfo.UnitType.TYPE_PLAYER; info.force = SceneLOL.UNIT_FORCE_A; info.name = name; info.HealthPoint = 100000000; info.baseSkillID = SKILL_MELEE_ATTACK_4; //info.skills.Add(SKILL_ORBIT_CYCLE); /* info.skills.Add(SKILL_MELEE_ATTACK_4); info.skills.Add(SKILL_STRAIGHT); info.skills.Add(SKILL_AOE); info.skills.Add(SKILL_LASER); info.skills.Add(SKILL_BINDING); info.skills.Add(SKILL_MISSILE); info.skills.Add(SKILL_ACTOR_SLIP); info.skills.Add(SKILL_STRAIGHT_CLUSTER); */ zone.pushAction(new AddUnitAction(info, x, y, 0)); } public void test_AddUnit(string name) { int force = random.Next(0, 100) % 2; float x = 1; float y = 1; UnitInfo info = test_InitUnitInfo(force, name, random.Next()%2==0, false); info.type = UnitInfo.UnitType.TYPE_NPC; info.name = name; if (force == 0) { x = random.Next(0, mWidth / 2); y = random.Next(0, mHeight); info.force = SceneLOL.UNIT_FORCE_A; } else { x = random.Next(mWidth / 2, mWidth); y = random.Next(0, mHeight); info.force = SceneLOL.UNIT_FORCE_B; } zone.pushAction(new AddUnitAction(info, x, y, 0)); } public void test_UnitMove(int unit_id, float x, float y) { zone.pushAction(new UnitMoveAction(unit_id, x, y, false)); } public void test_UnitSlip(int unit_id, float x, float y) { zone.pushAction(new UnitSlipAction(unit_id, x, y)); } public void test_UnitTransport(int unit_id, float x, float y) { zone.pushAction(new UnitTransportAction(unit_id, x, y)); } public void test_UnitAttack(int unit_id, int skillID) { zone.pushAction(new UnitLaunchSkillAction(unit_id, skillID)); } #endregion public int Width { get { return mWidth; } } public int Height { get { return mHeight; } } public int CellW { get { return mCellW; } } public int CellH { get { return mCellH; } } public int UnitCount { get { return units.Count; } } public int FPS { get { return mFPS; } } //----------------------------------------------------------------------------------------------------------------- // windows #region WINDOW private RectangleF mWindow = new RectangleF(0, 0, 512, 512); private float cameraX = 0; private float cameraY = 0; private float cameraScale = 1; public void setWindow(RectangleF window) { this.mWindow.X = window.X; this.mWindow.Y = window.Y; this.mWindow.Width = window.Width; this.mWindow.Height = window.Height; } public float screenToWorldSize(float s) { return s / cameraScale; } public float worldToScreenSize(float s) { return s * cameraScale; } public float screenToWorldX(float x) { return (x - mWindow.Width / 2) / cameraScale + cameraX; } public float screenToWorldY(float y) { return (y - mWindow.Height / 2) / cameraScale + cameraY; } public float worldToScreenX(float x) { return (x - cameraX) * cameraScale + mWindow.Width / 2; } public float worldToScreenY(float y) { return (y - cameraY) * cameraScale + mWindow.Height / 2; } public void setCamera(float x, float y) { this.cameraX = x; this.cameraY = y; } public void setCameraScale(float scale) { cameraScale = scale; cameraScale = Math.Max(cameraScale, 0.01f); } public float getCameraScale() { return cameraScale; } #endregion //----------------------------------------------------------------------------------------------------------------- #region RENDER public void renderWorld(Graphics g) { GraphicsState gs = g.Save(); { g.TranslateTransform( mWindow.Width / 2, mWindow.Height / 2); g.ScaleTransform( cameraScale, cameraScale); g.TranslateTransform( -cameraX, -cameraY); renderWorld(g, new RectangleF( screenToWorldX(0), screenToWorldY(0), screenToWorldSize(mWindow.Width), screenToWorldSize(mWindow.Height))); } g.Restore(gs); } public void renderHUD(Graphics g, GameUnit unit) { Brush brush = new SolidBrush(Color.White); GraphicsState gs = g.Save(); { g.DrawString("FPS=" + FPS + " TotalUnit=" + UnitCount, global_font, brush, 1, 1, StringFormat.GenericDefault); renderUnitStatusHUD(g, unit); } g.Restore(gs); } private void renderUnitStatusHUD(Graphics g, GameUnit unit) { if (unit != null) { Pen pen_B = new Pen(Color.Gray); Brush brush_C = new SolidBrush(Color.FromArgb(0xFF, 0x40, 0x40, 0x40)); Brush brush_CD = new SolidBrush(Color.FromArgb(0x80, 0xFF, 0xFF, 0xFF)); Brush brush_T = new SolidBrush(Color.Blue); float sw = 50; float sh = 50; float sx = 0; float sy = mWindow.Height - sh; ICollection status = unit.getSkillStatus(); foreach (GameUnit.SkillState ss in status) { float x = sx + 2; float y = sy + 2; float w = sw - 4; float h = sh - 4; g.SetClip(new RectangleF(x, y, w, h)); g.FillRectangle(brush_C, x, y, w, h); g.DrawRectangle(pen_B, x, y, w-1, h-1); if (ss.isCD()) { g.FillPie(brush_CD, x - w, y - h, w * 3, h * 3, -90, 360 * ss.getCDPercent()); } g.DrawString("" + ss.Data.name, global_font, brush_T, x, y, StringFormat.GenericDefault); g.ResetClip(); sx += sw; } } } private void renderWorld(Graphics g, RectangleF rect) { renderTerrain(g, rect); renderSpaceDiv(g, rect); renderUnits(g, rect); renderLogs(g); } private void renderTerrain(Graphics g, RectangleF rect) { int sx = (int)(rect.X / mCellW); int sy = (int)(rect.Y / mCellH); int sw = (int)(rect.Width / CellW) + 1; int sh = (int)(rect.Height / CellH) + 1; int lw = (int)(rect.Width + CellW * 2); int lh = (int)(rect.Height + CellH * 2); Brush bru_0 = new SolidBrush(Color.FromArgb(0xff, 0x20, 0x20, 0x20)); Brush bru_1 = new SolidBrush(Color.FromArgb(0xff, 0x20, 0x40, 0x20)); for (int x = sx + sw; x >= sx; --x) { for (int y = sy + sh; y >= sy; --y) { if (x < mGridXCount && x >= 0 && y < mGridYCount && y >= 0) { if (mZoneInfo.TerrainMatrix[x, y] != 0) { g.FillRectangle(bru_1, x * mCellW, y * mCellH, mCellW, mCellH); } else { g.FillRectangle(bru_0, x * mCellW, y * mCellH, mCellW, mCellH); } } } } } private void renderSpaceDiv(Graphics g, RectangleF rect) { int sx = (int)(rect.X / SpaceDIV); int sy = (int)(rect.Y / SpaceDIV); int sw = (int)(rect.Width / SpaceDIV) + 1; int sh = (int)(rect.Height / SpaceDIV) + 1; int lw = (int)(rect.Width + SpaceDIV * 2); int lh = (int)(rect.Height + SpaceDIV * 2); Pen pen = new Pen(Color.FromArgb(0x10, 0xff, 0xff, 0xff)); for (int x = sx + sw; x >= sx; --x) { g.DrawLine(pen, x * SpaceDIV, sy * SpaceDIV, x * SpaceDIV, sy * SpaceDIV + lh); } for (int y = sy + sh; y >= sy; --y) { g.DrawLine(pen, sx * SpaceDIV, y * SpaceDIV, sx * SpaceDIV + lw, y * SpaceDIV); } } private void renderUnits(Graphics g, RectangleF rect) { foreach (GameObject u in units.Values) { if (rect.IntersectsWith(u.Bounds)) { GraphicsState state = g.Save(); g.TranslateTransform(u.pos.x, u.pos.y); u.render(g); g.Restore(state); } } } private void renderLogs(Graphics g) { for (int i = logs.Count - 1; i >= 0; --i) { DisplayLog u = logs[i]; GraphicsState state = g.Save(); g.TranslateTransform(u.pos.x, u.pos.y); u.render(g); g.Restore(state); if (!u.Alive) { logs.RemoveAt(i); } } } #endregion //----------------------------------------------------------------------------------------------------------------- public void update() { zone.update(); foreach (GameObject u in units.Values) { u.update(); } timer++; long curTime = CommonLang.CUtils.CurrentTimeMS(); if (curTime != mLastUpdateTime) { mFPS = (int)(1000 / (curTime - mLastUpdateTime)); } mLastUpdateTime = curTime; } //----------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------- public GameUnit getUnit(int unitID) { GameObject go; if (units.TryGetValue(unitID, out go)) { if (go is GameUnit) { return go as GameUnit; } } return null; } public GameUnit getUnitByName(string name) { foreach (GameObject u in units.Values) { if (u is GameUnit) { if (name.Equals((u as GameUnit).Info.name)) { return u as GameUnit; } } } return null; } //----------------------------------------------------------------------------------------------- // events //----------------------------------------------------------------------------------------------- public void onEventHandler(Event e) { if (e is AddUnitEvent) { doAddUnitEvent(e as AddUnitEvent); } else if (e is AddSpellEvent) { doAddSpellEvent(e as AddSpellEvent); } else if (e is RemoveObjectEvent) { doRemoveObjectEvent(e as RemoveObjectEvent); } else if (e is SyncPosEvent) { doSyncPosEvent(e as SyncPosEvent); } else if (e is ObjectEvent) { ObjectEvent oe = e as ObjectEvent; GameObject gu; if (units.TryGetValue(oe.object_id, out gu)) { gu.doEvent(oe); } } } //----------------------------------------------------------------------------------------------- private void doAddUnitEvent(AddUnitEvent e) { GameUnit gu = null; if (e.info.force == 0) { gu = new GameUnitActor(this, e.info, e.unit_id); } else { gu = new GameUnitNpc(this, e.info, e.unit_id); } gu.pos.x = e.x; gu.pos.y = e.y; gu.direction = e.direction; units[gu.ID] = gu; } private void doAddSpellEvent(AddSpellEvent e) { SpellTemplate sp = TemplateManager.getInstance().getSpell(e.spell_template_id); if (sp != null) { GameSpellObject gs = new GameSpellObject( this, sp, e.spell_id, getUnit(e.launcher_unit_id), null); gs.pos.x = e.x; gs.pos.y = e.y; gs.direction = e.direction; units[gs.ID] = gs; } } private void doRemoveObjectEvent(RemoveObjectEvent e) { units.Remove(e.object_id); } private void doSyncPosEvent(SyncPosEvent e) { GameObject gu; for (int i = 0; i < e.unitsID.Length; ++i) { if (units.TryGetValue(e.unitsID[i], out gu)) { gu.syncPos(e.unitsX[i], e.unitsY[i], e.unitsD[i]); } } } public void showLog(string text, float x, float y) { logs.Add(new DisplayLog(text, x, y)); } public class DisplayLog { static private Pen pen = new Pen(Color.Black); static private Brush brush = new SolidBrush(Color.White); public Vector2 pos = new Vector2(); private int time = 20; private string text = ""; private SizeF size; public DisplayLog(string text, float x, float y) { this.text = text; this.time = 20; this.pos.x = x; this.pos.y = y; } public void render(Graphics g) { size = g.MeasureString(text, global_font); g.DrawString( text, global_font, brush, -size.Width / 2, -size.Height / 2 - 20 + time, StringFormat.GenericDefault); time--; } public bool Alive { get { return time > 0; } } } } //----------------------------------------------------------------------------------------------- }