public static Level LoadLevel(int levelNum) { NumberFormatInfo nfi = new CultureInfo("en-US", false).NumberFormat; Func<XElement, string, float> fParse = (e, n) => float.Parse(e.Attribute(n).Value, nfi); var doc = XDocument.Load("Levels\\Level1.xml"); var level = new Level(); level.Poligons = doc.Root.Elements("Scene").Elements("Poligon").Select(x => { var p = new Poligon(); p.Points = x.Elements("Point").Select(y => new Vector2(float.Parse(y.Attribute("x").Value), float.Parse(y.Attribute("y").Value))).ToArray(); return p; } ).ToList(); level.Images = doc.Root.Elements("Scene").Elements("Image").Select(x => { var i = new Image(); i.pos = new Vector2(float.Parse(x.Attribute("x").Value), float.Parse(x.Attribute("y").Value)); i.textureName = x.Attribute("name").Value; i.width = float.Parse(x.Attribute("w").Value); i.height = float.Parse(x.Attribute("h").Value); i.angle = float.Parse(x.Attribute("ang").Value); return i; } ).ToList(); level.Teleports = doc.Root.Elements("Scene").Elements("Teleport").Select(x => { var t = new Teleport(); Gate g = new Gate(); g.Center = new Vector2(fParse(x, "x1"), fParse(x, "y1")); g.Angle = float.Parse(x.Attribute("ang1").Value); g.Teleport = t; t.GateA = g; g = new Gate(); g.Center = new Vector2(fParse(x, "x2"), fParse(x, "y2")); g.Angle = float.Parse(x.Attribute("ang2").Value); g.Teleport = t; t.GateB = g; t.GateA.Pair = t.GateB; t.GateB.Pair = t.GateA; t.lenght = float.Parse(x.Attribute("len").Value); return t; } ).ToList(); var player = new Player(); player.Pos = new Vector2(float.Parse(doc.Root.Element("Player").Attribute("x").Value), float.Parse(doc.Root.Element("Player").Attribute("y").Value)); player.direction = float.Parse(doc.Root.Element("Player").Attribute("direction").Value); level.Player = player; return level; }
void drawGateShadow(World.Gate gate, Vector2 pos, float dir) { var a = gate.Vertexes[0].Position; var b = gate.Vertexes[1].Position; var oldRenderTargets = graphics.GraphicsDevice.GetRenderTargets(); graphics.GraphicsDevice.SetRenderTarget(gateShadow); effect.View = Matrix.CreateTranslation(-pos.X, -pos.Y, 0) * Matrix.CreateRotationZ(MathHelper.ToRadians(-dir)); effect.CurrentTechnique.Passes[0].Apply(); graphics.GraphicsDevice.Clear(Color.Transparent); drawShadow(new Vector3(pos, 0), a, b, Color.White); //затираем тенями var lA = a; var lB = b; level.Poligons.ForEach(x => toStartShadowLine(pos, x.Points, null, (sh1, sh2) => { if (Vector.testShasow(pos, new Vector2(sh1.X, sh1.Y), new Vector2(sh2.X, sh2.Y), new Vector2(lA.X, lA.Y), new Vector2(lB.X, lB.Y))) { drawShadow(new Vector3(pos, 0), new Vector3(sh1, 0), new Vector3(sh2, 0), Color.Black); } }) ); drawPlayer(); graphics.GraphicsDevice.SetRenderTargets(oldRenderTargets); }
RenderTarget2D DrawLevelRecursive(Vector2 pos, float direction, int depth, World.Gate gate) { if (depth >= telepotDepth) { return(null); } var oldRenderTargets = graphics.GraphicsDevice.GetRenderTargets(); graphics.GraphicsDevice.SetRenderTarget(mainView[depth]); graphics.GraphicsDevice.Clear(debugMode ? LevelColor[depth] : Color.White); //Рисуем полигоны уровня if (depth >= startDepth) { DrawLelel(pos, direction, gate); } //Рисуем то, что за телепортами var gates = level.Teleports.SelectMany(x => new World.Gate[] { x.GateA, x.GateB }).OrderByDescending(x => (x.Center - pos).Length()) .Where(x => Vector2.Dot(x.Direction, (pos - x.Center)) > 0).ToList(); gates.ForEach(x => { var gPos = positionFromGate(x, pos); var gDir = directionFromGate(x, direction); var rt = DrawLevelRecursive(gPos, gDir, depth + 1, x.Pair); if (rt == null) { return; } if (depth >= startDepth) { drawGateShadow(x, pos, direction); } else { fillGateShadow(); } MixTexture(rt, gateShadow); }); graphics.GraphicsDevice.SetRenderTargets(oldRenderTargets); return(mainView[depth]); }
Vector2 positionFromGate(World.Gate gate, Vector2 pos) { //1. Совмещаем текущие врата с нулём var tg1 = Matrix.CreateTranslation(-gate.Center.X, -gate.Center.Y, 0); //2. Поворачиваем текущие врата, чтобы совместить их наклон с выходными var rg1 = Matrix.CreateRotationZ(MathHelper.ToRadians(gate.Pair.Angle - (gate.Angle + 180))); //3. Совмещаем положение текущих врат с выходными var tg2 = Matrix.CreateTranslation(new Vector3(gate.Pair.Center, 0)); //4. Положение персонажа относительно выходных врат var altPlayer = Vector2.Transform(pos, tg1 * rg1 * tg2); return(altPlayer); }
void DrawLelel(Vector2 pos, float direction, World.Gate gate) { var t = effect.View; effect.View = Matrix.CreateTranslation(new Vector3(-pos, 0)) * Matrix.CreateRotationZ(MathHelper.ToRadians(-direction)); GraphicsDevice.RasterizerState = RasterizerState.CullNone; effect.TextureEnabled = true; effect.VertexColorEnabled = false; GraphicsDevice.BlendState = BlendState.AlphaBlend; level.Images.ForEach(x => { effect.Texture = x.texture; effect.CurrentTechnique.Passes[0].Apply(); GraphicsDevice.DrawUserPrimitives <VertexPositionTexture>(PrimitiveType.TriangleList, x.Vertexs, 0, 2); }); effect.TextureEnabled = false; effect.VertexColorEnabled = true; effect.CurrentTechnique.Passes[0].Apply(); drawPlayer(); level.Poligons.ForEach(x => { drawPoligonShadow(pos, x.Points, gate, debugMode ? Color.Red : Color.Black); graphics.GraphicsDevice.DrawUserPrimitives <VertexPositionColor>(PrimitiveType.TriangleList, x.Vertexs, 0, x.TringleCount); }); if (debugMode) { level.Teleports.ForEach(x => { graphics.GraphicsDevice.DrawUserPrimitives <VertexPositionColor>(PrimitiveType.LineList, x.GateA.Vertexes, 0, 1); graphics.GraphicsDevice.DrawUserPrimitives <VertexPositionColor>(PrimitiveType.LineList, x.GateB.Vertexes, 0, 1); }); } effect.View = t; }
void toStartShadowLine(Vector2 pos, Vector2[] vertexs, World.Gate gate, Action <Vector2, Vector2> callback) { Vector2?a = null; Vector2?b = null; Action <Vector2> extremePoints = point => { if (a == null) { a = point - pos; //минимальный градус b = point - pos; //максимальный градус } var sample = point - pos; if (a.Value.X * (-sample.Y) + a.Value.Y * sample.X > 0) { a = sample; } if (b.Value.X * (-sample.Y) + b.Value.Y * sample.X < 0) { b = sample; } }; if (gate == null) { vertexs.ForEach(extremePoints); } else { Vector.cutShape(pos, vertexs, new Segment2(gate.Vertexes[0].Position.ToVector2(), gate.Vertexes[1].Position.ToVector2()), extremePoints); } if (a != null) { callback(pos + a.Value, pos + b.Value); } }
float directionFromGate(World.Gate gate, float direction) { return(direction + gate.Pair.Angle - (gate.Angle + 180)); }
void drawPoligonShadow(Vector2 pos, Vector2[] vertexs, World.Gate gate, Color color) { //всё просто, нужно определить крайние точки из vertexs toStartShadowLine(pos, vertexs, gate, (a, b) => drawShadow(new Vector3(pos, 0), new Vector3(a, 0), new Vector3(b, 0), color)); }
public static Level LoadLevel(int levelNum) { NumberFormatInfo nfi = new CultureInfo("en-US", false).NumberFormat; Func <XElement, string, float> fParse = (e, n) => float.Parse(e.Attribute(n).Value, nfi); var doc = XDocument.Load("Levels\\Level1.xml"); var level = new Level(); level.Poligons = doc.Root.Elements("Scene").Elements("Poligon").Select(x => { var p = new Poligon(); p.Points = x.Elements("Point").Select(y => new Vector2(float.Parse(y.Attribute("x").Value), float.Parse(y.Attribute("y").Value))).ToArray(); return(p); } ).ToList(); level.Images = doc.Root.Elements("Scene").Elements("Image").Select(x => { var i = new Image(); i.pos = new Vector2(float.Parse(x.Attribute("x").Value), float.Parse(x.Attribute("y").Value)); i.textureName = x.Attribute("name").Value; i.width = float.Parse(x.Attribute("w").Value); i.height = float.Parse(x.Attribute("h").Value); i.angle = float.Parse(x.Attribute("ang").Value); return(i); } ).ToList(); level.Teleports = doc.Root.Elements("Scene").Elements("Teleport").Select(x => { var t = new Teleport(); Gate g = new Gate(); g.Center = new Vector2(fParse(x, "x1"), fParse(x, "y1")); g.Angle = float.Parse(x.Attribute("ang1").Value); g.Teleport = t; t.GateA = g; g = new Gate(); g.Center = new Vector2(fParse(x, "x2"), fParse(x, "y2")); g.Angle = float.Parse(x.Attribute("ang2").Value); g.Teleport = t; t.GateB = g; t.GateA.Pair = t.GateB; t.GateB.Pair = t.GateA; t.lenght = float.Parse(x.Attribute("len").Value); return(t); } ).ToList(); var player = new Player(); player.Pos = new Vector2(float.Parse(doc.Root.Element("Player").Attribute("x").Value), float.Parse(doc.Root.Element("Player").Attribute("y").Value)); player.direction = float.Parse(doc.Root.Element("Player").Attribute("direction").Value); level.Player = player; return(level); }