/// <summary> /// A gaming screen which consists of a single Camera and multiple entities /// </summary> public LevelScreen() { _graphics = new GraphicsDeviceManager(this); _graphics.SynchronizeWithVerticalRetrace = false; _graphics.PreparingDeviceSettings += (sender, e) => { e.GraphicsDeviceInformation.PresentationParameters.PresentationInterval = PresentInterval.Immediate; }; _graphics.ApplyChanges(); Content.RootDirectory = "Content"; GameDatas.AssetManager = Content; // Setting properties IsMouseVisible = true; //Window.Position = Point.Zero; _adapter = new BoxingViewportAdapter(Window, GraphicsDevice, GameSettings.Width, GameSettings.Height); GameDatas.MainCamera = new ControllableCamera2D(_adapter, 100); // Launch the GameLogic thread _physicLoop = new PhysicsLoop(GameSettings.PhysicRefreshingRate); //_graphicsLoop = new GraphicsLoop(GameSettings.GraphicRefreshingRate, this); _graphicsLoop = new GraphicsLoop(0, this); _level = new ALevel("Content/Map/map_test.json"); }
public static void Main(string[] args) { graphicsLoop = GraphicsLoop.CreateWithNewWindow(1280, 720, InitFlags.DisableVerticalSync | InitFlags.EnableDebugStats); var gameFactory = new GameFactory(); game = gameFactory.Create(); player = game.EntityService.CreateEntity(); game.EntityService.AddEntityComponent(player, new MovementComponent { WorldPosition = new DoubleVector3(-450, -450, 0), BaseRadius = 30, BaseSpeed = 100, IsPathfindingEnabled = true, PathingDestination = new DoubleVector3(-450, -450, 0) }); baddie = game.EntityService.CreateEntity(); game.EntityService.AddEntityComponent(baddie, new MovementComponent { WorldPosition = new DoubleVector3(0, 0, 0), BaseRadius = 30, BaseSpeed = 100, IsPathfindingEnabled = true, PathingDestination = new DoubleVector3(0, 0, 0) }); var r = new Random(0); for (var i = 0; i < 10; i++) { var rock = game.EntityService.CreateEntity(); game.EntityService.AddEntityComponent(rock, new MovementComponent { WorldPosition = new DoubleVector3(r.Next(-500, 500), r.Next(-500, 500), 0), BaseRadius = 10, BaseSpeed = 100, IsPathfindingEnabled = false }); rocks.Add(rock); } var scene = new Scene(); debugCanvas = new Canvas3DDebugMultiCanvasHost.Canvas3DDebugCanvas(graphicsLoop.GraphicsFacade, graphicsLoop.Presets, scene); for (var frame = 0; graphicsLoop.IsRunning(out var renderer, out var input); frame++) { scene.Clear(); Step(graphicsLoop, game, input, scene); Render(scene, renderer); } }
public static Canvas3DDebugMultiCanvasHost CreateAndShowCanvas(Size size) { var sceneQueue = new ConcurrentQueue <IScene>(); var scenes = new List <IScene>(); var activeSceneIndex = -1; GraphicsLoop graphicsLoop = null; IPresetsStore presets = null; var initLatch = new ManualResetEvent(false); var thread = new Thread(() => { graphicsLoop = GraphicsLoop.CreateWithNewWindow(size, InitFlags.EnableDebugStats); presets = graphicsLoop.Presets; initLatch.Set(); var rotation = 80 * Math.PI / 180.0; var lookat = new DoubleVector3(0, 0, 0); //var lookat = new DoubleVector3(0, 0, 0); // originally offset -10, -100, 70) //var offset = new DoubleVector3(-100, 100, 200) * 7;// DoubleVector3.FromRadiusAngleAroundXAxis(400, rotation) + new DoubleVector3(100, -50, -100); // var offset = new DoubleVector3(-10, -100, 70) * 30;// DoubleVector3.FromRadiusAngleAroundXAxis(400, rotation) + new DoubleVector3(100, -50, -100); // var offset = new DoubleVector3(-10, -100, 30) * 30;// DoubleVector3.FromRadiusAngleAroundXAxis(400, rotation) + new DoubleVector3(100, -50, -100); var offset = new DoubleVector3(0, -30, 200) * 5; // DoubleVector3.FromRadiusAngleAroundXAxis(400, rotation) + new DoubleVector3(100, -50, -100); var up = new DoubleVector3(-1, 0, 0).Cross(offset).ToUnit(); //DoubleVector3.FromRadiusAngleAroundXAxis(1, rotation - Math.PI / 2); Console.WriteLine(offset); IScene lastScene = null; while (graphicsLoop.IsRunning(out var renderer, out var input)) { while (sceneQueue.TryDequeue(out var res)) { res.SetCamera(Vector3.Zero, Matrix.Identity); scenes.Add(res); if (activeSceneIndex == scenes.Count - 2) { activeSceneIndex = scenes.Count - 1; } } var scene = activeSceneIndex == -1 ? new Scene() : scenes[activeSceneIndex]; lock (scene) { var view = MatrixCM.ViewLookAtRH(ToV3(lookat + offset), ToV3(lookat), ToV3(up)); var verticalFov = 105.0f * (float)Math.PI / 180.0f; var aspect = size.Width / (float)size.Height; var proj = MatrixCM.PerspectiveFovRH(verticalFov, aspect, 1.0f, 10000.0f); void DrawAxes(Matrix transform, float scale = 1.0f) { float length = 1.0f * scale; float thickness = 0.06f * scale; scene.AddRenderable( graphicsLoop.Presets.UnitCube, transform * MatrixCM.Translation(length / 2, 0, 0) * MatrixCM.Scaling(length, thickness, thickness), new MaterialDescription { Resources = { BaseColor = Color.Red }, Properties = { Metallic = 0.0f, Roughness = 0.04f }, }); scene.AddRenderable( graphicsLoop.Presets.UnitCube, transform * MatrixCM.Translation(0, length / 2, 0) * MatrixCM.Scaling(thickness, length, thickness), new MaterialDescription { Resources = { BaseColor = Color.Lime }, Properties = { Metallic = 0.0f, Roughness = 0.04f }, }); scene.AddRenderable( graphicsLoop.Presets.UnitCube, transform * MatrixCM.Translation(0, 0, length / 2) * MatrixCM.Scaling(thickness, thickness, length), new MaterialDescription { Resources = { BaseColor = Color.Blue }, Properties = { Metallic = 0.0f, Roughness = 0.04f }, }); } if (scene != lastScene) { lastScene = scene; scene.SetCamera(ToV3(lookat + offset), Matrix.Multiply(proj, view)); scene.AddSpotlight( ToV3(lookat + offset * 3), ToV3(lookat), ToV3(up), (float)Math.PI * 0.49f, Color.White, 100f, 100000.0f, 1, 1, 1000); //DrawAxes(Matrix.Identity, 200); DrawAxes(MatrixCM.Translation((float)lookat.X, (float)lookat.Y, (float)lookat.Z), 200); //scene.AddRenderable( // graphicsLoop.Presets.UnitCube, // MatrixCM.Translation(1200, 500, 0) * MatrixCM.Scaling(100.0f), // new MaterialDescription { // Resources = { BaseColor = Color.White }, // Properties = { Metallic = 0.0f, Roughness = 0.04f }, // }); } renderer.RenderScene(scene.ExportSnapshot()); } } }); thread.SetApartmentState(ApartmentState.STA); thread.Start(); initLatch.WaitOne(); return(new Canvas3DDebugMultiCanvasHost(sceneQueue, graphicsLoop.GraphicsFacade, presets)); }
private static void Step(GraphicsLoop graphicsLoop, Game game, InputSomethingOSDJFH input, Scene scene) { var expectedTicks = (int)(graphicsLoop.Statistics.FrameTime.TotalSeconds * 60); while (game.GameTimeService.Ticks < expectedTicks) { game.Tick(); } var viewProj = ComputeProjViewMatrix(graphicsLoop.Form.ClientSize); viewProj.Transpose(); var ray = Ray.GetPickRay(input.X, input.Y, new ViewportF(0, 0, 1280, 720, 1.0f, 100.0f), viewProj); var terrainOverlayNetwork = game.TerrainService.CompileSnapshot().OverlayNetworkManager.CompileTerrainOverlayNetwork(0); // rmb moves if (input.IsMouseDown(MouseButtons.Right)) { foreach (var node in terrainOverlayNetwork.TerrainNodes) { var origin = node.SectorNodeDescription.LocalToWorld(DoubleVector2.Zero); var normal = node.SectorNodeDescription.LocalToWorldNormal(DoubleVector3.UnitZ); var plane = new SDXPlane(ToSharpDX(origin), ToSharpDX(normal)); if (!plane.Intersects(ref ray, out SDXVector3 intersection)) { continue; } var intersectionLocal = node.SectorNodeDescription.WorldToLocal(intersection.ToOpenMoba()); if (!node.LandPolyNode.PointInLandPolygonNonrecursive(intersectionLocal.XY.LossyToIntVector2())) { continue; } // recompute intersectionWorld because floating point error in raycast logic var intersectionWorld = node.SectorNodeDescription.LocalToWorld(intersectionLocal.XY); game.MovementSystemService.Pathfind(player, intersectionWorld); } } // lazaars if (input.IsKeyDown(Keys.Q)) { foreach (var node in terrainOverlayNetwork.TerrainNodes) { var origin = node.SectorNodeDescription.LocalToWorld(DoubleVector2.Zero); var normal = node.SectorNodeDescription.LocalToWorldNormal(DoubleVector3.UnitZ); var plane = new SDXPlane(ToSharpDX(origin), ToSharpDX(normal)); if (!plane.Intersects(ref ray, out SDXVector3 intersection)) { continue; } var intersectionLocal = node.SectorNodeDescription.WorldToLocal(intersection.ToOpenMoba()); if (!node.SectorNodeDescription.StaticMetadata.LocalBoundary.Contains(new SDPoint((int)intersectionLocal.X, (int)intersectionLocal.Y))) { continue; } if (!node.LandPolyNode.PointInLandPolygonNonrecursive(player.MovementComponent.LocalPositionIv2)) { continue; } // recompute intersectionWorld because floating point error in raycast logic var intersectionWorld = node.SectorNodeDescription.LocalToWorld(intersectionLocal.XY); var barriersBvh = node.LandPolyNode.FindContourAndChildHoleBarriersBvh(); var q = new IntLineSegment2(player.MovementComponent.LocalPositionIv2, intersectionLocal.XY.LossyToIntVector2()); debugCanvas.Transform = node.SectorNodeDescription.WorldTransform; debugCanvas.DrawLine(q, StrokeStyle.RedHairLineSolid); foreach (var seg in barriersBvh.Segments) { debugCanvas.DrawLine(seg, StrokeStyle.RedThick5Solid); } var intersectingLeaves = barriersBvh.FindPotentiallyIntersectingLeaves(q); var tFar = 1.0; foreach (var bvhNode in intersectingLeaves) { for (var i = bvhNode.SegmentsStartIndexInclusive; i < bvhNode.SegmentsEndIndexExclusive; i++) { if (GeometryOperations.TryFindNonoverlappingSegmentSegmentIntersectionT(ref q, ref bvhNode.Segments[i], out var t)) { Console.WriteLine(t); tFar = Math.Min(tFar, t); } } } debugCanvas.Transform = Matrix4x4.Identity; debugCanvas.DrawLine(player.MovementComponent.WorldPosition, node.SectorNodeDescription.LocalToWorld(q.PointAt(tFar)), StrokeStyle.LimeThick5Solid); } } // i love rocks var rocksExisting = new List <Entity>(); foreach (var rock in rocks) { var distance = rock.MovementComponent.WorldPosition.To(player.MovementComponent.WorldPosition).Norm2D(); if (distance > player.MovementComponent.ComputedRadius) { rocksExisting.Add(rock); continue; } game.EntityService.RemoveEntity(rock); } rocks = rocksExisting; // W draws walls if (input.IsKeyJustDown(Keys.W)) { foreach (var node in terrainOverlayNetwork.TerrainNodes) { var origin = node.SectorNodeDescription.LocalToWorld(DoubleVector2.Zero); var normal = node.SectorNodeDescription.LocalToWorldNormal(DoubleVector3.UnitZ); var plane = new SDXPlane(ToSharpDX(origin), ToSharpDX(normal)); if (!plane.Intersects(ref ray, out SDXVector3 intersection)) { continue; } var intersectionLocal = node.SectorNodeDescription.WorldToLocal(intersection.ToOpenMoba()); if (!node.SectorNodeDescription.StaticMetadata.LocalBoundary.Contains(new SDPoint((int)intersectionLocal.X, (int)intersectionLocal.Y))) { continue; } // recompute intersectionWorld because floating point error in raycast logic var intersectionWorld = node.SectorNodeDescription.LocalToWorld(intersectionLocal.XY); fred.Add(intersectionWorld.XY.LossyToIntVector2()); // todo: we really need to iterate over LGVs rather than tnodes break; } } if (input.IsKeyJustDown(Keys.E)) { if (fred.Count > 0) { fred.RemoveAt(fred.Count - 1); } } if (input.IsKeyJustDown(Keys.R) && fred.Count >= 2) { var polyTree = PolylineOperations.ExtrudePolygon(fred, 10); var boundsLower = fred.Aggregate(new IntVector2(int.MaxValue, int.MaxValue), (a, b) => new IntVector2(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y))); var boundsUpper = fred.Aggregate(new IntVector2(int.MinValue, int.MinValue), (a, b) => new IntVector2(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y))); var bounds = new SDRectangle(boundsLower.X, boundsLower.Y, boundsUpper.X - boundsLower.X, boundsUpper.Y - boundsLower.Y); var holeStaticMetadata = new PrismHoleStaticMetadata( bounds, new[] { new Polygon2(polyTree.Childs[0].Contour) }, polyTree.Childs[0].Childs.Map(c => new Polygon2(((IEnumerable <IntVector2>)c.Contour).Reverse().ToList()))); var terrainHole = game.TerrainService.CreateHoleDescription(holeStaticMetadata); game.TerrainService.AddTemporaryHoleDescription(terrainHole); if (!input.IsKeyDown(Keys.ShiftKey)) { var removeEvent = game.CreateRemoveTemporaryHoleEvent(new GameTime(game.GameTimeService.Now.Ticks + 90), terrainHole); game.GameEventQueueService.AddGameEvent(removeEvent); } fred.Clear(); } }