public GameWorld(Game game, Camera cam) : base(game) { _cam = cam; _tileMap = new TileMap(); _collisionEngine = new CollisionEngine(); CollisionComponent.CreatedCollisionComponent += RegisterCollisionBox; }
public RaceEngine() { _collisionEngine = new CollisionEngine(4, 250); m_physicsEngine = new PhysicsEngine(); m_obstacles = new List <TireObstacle>(100); m_cars = new List <RaceCar>(4); m_physicsEngine.UpdateForcesEvent += PhysicsEngine_UpdateForcesEvent; }
public void CheckCollision() { if (CollisionEngine.CollisionCheck(new Rectangle((int)(pos.X - dims.X / 2), (int)(pos.Y - dims.Y / 2), (int)dims.X, (int)dims.Y), Globals.currWorld.levels[Globals.currWorld.currLevel].platforms)) { parent.DeleteProjectile(this); } if (CollisionEngine.CollisionCheck(new Rectangle((int)pos.X, (int)pos.Y, (int)dims.X, (int)dims.Y), ((CollisionObject)Globals.currWorld.hero).GetCollisionBox())) { ((Entity)Globals.currWorld.hero).GetHit(damage); parent.DeleteProjectile(this); } }
/// <summary> /// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// </summary> protected override void Initialize() { this.IsMouseVisible = true; var w = (float)graphics.PreferredBackBufferWidth; var h = (float)graphics.PreferredBackBufferHeight; CollisionEngine.Init(new Region(0, (float)w, 0, (float)h), 10); PE = new PhysicsEngine(); var w0 = new VertWallBody(new Vector2(0, h / 2), h); var w1 = new VertWallBody(new Vector2(w, h / 2), h); var w2 = new HorizWallBody(new Vector2(w / 2, 0), w); var w3 = new HorizWallBody(new Vector2(w / 2, h), w); PE.MapBodies.Add(w0); PE.MapBodies.Add(w1); PE.MapBodies.Add(w2); PE.MapBodies.Add(w3); var c0 = new CircleBody(30, 300, new Vector2(600, h / 2)); c0.Velocity = -1000 * Vector2.UnitX; PE.ActiveBodies.Add(c0); Random rand = new Random(); int nx = 40; int ny = 30; var rad = 4f; var buf = 0f; var pos = new Vector2(w / 2 - nx * (2f * rad + buf) / 2f, h / 2 - ny * (2f * rad + buf) / 2f); for (int xi = 0; xi < nx; xi++) { for (int yi = 0; yi < ny; yi++) { var cent = pos + new Vector2((2f * rad + buf) * xi, (2f * rad + buf) * yi); var ball = new CircleBody(rad, rad, cent); PE.ActiveBodies.Add(ball); } } base.Initialize(); }
private void GenerateMaze(Player player) { var message = GetComponents <DebugMessageBuilder>().First(); var entireMaze = BoundingBox.CreateMerged(new Cell(0, 0).GetBoundingBox(), new Cell(_width - 1, _height - 1).GetBoundingBox()); var collisionEngine = new CollisionEngine(entireMaze); Add(collisionEngine); var chunkManager = new ChunkManager(RenderContext, message, collisionEngine, _width, _height); collisionEngine.Add(player); Add(chunkManager); }
/// <summary> /// Calculates all the collisionforces acting on a CollisionObject. /// </summary> /// <param name="obj">The CollisionObject on which the collisions act.</param> /// <param name="objects">The other CollisionObjects which act on obj.</param> /// <returns>The sum of all the collision forces.</returns> public static Vector2 CollisionForces(CollisionObject obj, CollisionObject[] objects) { Vector2 output = Vector2.Zero; for (int j = 0; j < objects.Length; j++) { if (obj != objects[j]) { Vector2 collision = CollisionEngine.CollisionSide(obj, objects[j]); if (collision != Vector2.Zero) { output += CollisionForce(obj, objects[j], collision); } } } return(output); }
public AbstractScene(string sceneName, bool preload = false, bool alwaysActive = false, bool useLoadingScreen = false) { if (sceneName == null || sceneName.Length == 0) { throw new Exception("The scene must have a non-null, non-empty unique name!"); } this.sceneName = sceneName; Preload = preload; AlwaysActive = alwaysActive; UseLoadingScreen = useLoadingScreen; UI = new UserInterface(); LayerManager = new LayerManager(this); LayerManager.InitLayers(); CollisionEngine = new CollisionEngine(); GridCollisionChecker = new GridCollisionChecker(); }
public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; currentStage = new Stage(); currentStage.camera.position.Y = -0; currentCollisionEngine = new CollisionEngines.Octree.OctreeEngine(new BoundingBox(new Vector3(-1024, -1024, -1024), new Vector3(1024, 1024, 1024)), 4); Actors.Misc.Box box1 = new Actors.Misc.Box(new Vector3(-100, -100, -100), new Vector3(100, 100, 100)); box1.position = new Vector3(-200, 0, 0); box1.velocity = new Vector3(1, (float)0.4, 0); Actors.Misc.Box box2 = new Actors.Misc.Box(new Vector3(-50, -50, -100), new Vector3(50, 50, 50)); box2.position = new Vector3(200, 0, 0); box2.velocity = new Vector3(-1, (float)-0.3, 0); Actors.Misc.Box wall1 = new Actors.Misc.Box(new Vector3(-1, -200, -300), new Vector3(1, 200, 300)); wall1.position = new Vector3(-300, 0, 0); Actors.Misc.Box wall2 = new Actors.Misc.Box(new Vector3(-1, -200, -300), new Vector3(1, 200, 300)); wall2.position = new Vector3(300, 0, 0); Actors.Misc.Box wall3 = new Actors.Misc.Box(new Vector3(-300, -1, -300), new Vector3(300, 1, 300)); wall3.position = new Vector3(0, -200, 0); Actors.Misc.Box wall4 = new Actors.Misc.Box(new Vector3(-300, -1, -300), new Vector3(300, 1, 300)); wall4.position = new Vector3(0, 200, 0); currentStage.RegisterActor(box1); currentStage.RegisterActor(box2); currentStage.RegisterActor(wall1); currentStage.RegisterActor(wall2); currentStage.RegisterActor(wall3); currentStage.RegisterActor(wall4); }
/// <summary> /// Load graphics content for the game. /// </summary> public override void LoadContent() { if (content == null) content = new ContentManager(ScreenManager.Game.Services, "Content"); _collisions = new CollisionEngine(); _objectsToBeWrapped = new List<hasPosition2D>(); DisplayedMessages = new Dictionary<string, string>(); SpriteBatchDrawable = new SpriteBatch(ScreenManager.Game.GraphicsDevice); // A real game would probably have more content than this sample, so // it would take longer to load. We simulate that by delaying for a // while, giving you a chance to admire the beautiful loading screen. // Note by Jason: Awesome... lol Thread.Sleep(1000); FontSprite = ScreenManager.Game.Content.Load<SpriteFont>("Fonts\\Arial"); MoritoModel = ScreenManager.Game.Content.Load<Model>("Models\\morito"); BulletModel = ScreenManager.Game.Content.Load<Model>("Models\\missile"); //setup a camera Camera1 = new Camera(); Level = new Level(); Level.LoadContent(this); //Level.saveLevelToFile(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\MoritoLevel.xml"); // once the load has finished, we use ResetElapsedTime to tell the game's // timing mechanism that we have just finished a very long frame, and that // it should not try to catch up. ScreenManager.Game.ResetElapsedTime(); }
/// <summary> /// Splits the maze into chunks. /// </summary> /// <param name="renderContext"></param> /// <param name="cells"></param> /// <param name="collisionEngine"></param> /// <returns></returns> private List <MazeChunk> GenerateChunks(IRenderContext renderContext, Cell[,] cells, CollisionEngine collisionEngine) { var maxSize = MazeChunk.ChunkSize; // instead of creating arrays per chunk we point to the source array by using indices, this is far faster and saves ram var w = cells.GetLength(0); var h = cells.GetLength(1); var chunks = new List <MazeChunk>(); int yCount = (int)Math.Ceiling(h / (float)maxSize); int xCount = (int)Math.Ceiling(w / (float)maxSize); for (int y = 0; y < yCount; y++) { for (int x = 0; x < xCount; x++) { var startX = x * maxSize; var startY = y * maxSize; var endX = Math.Min((x + 1) * maxSize, w); var endY = Math.Min((y + 1) * maxSize, h); var id = y * yCount + x; var chunk = new MazeChunk(renderContext, cells, startX, startY, endX, endY, id, collisionEngine); chunks.Add(chunk); } } return(chunks); }
public ChunkManager(IRenderContext renderContext, DebugMessageBuilder messageBuilder, CollisionEngine collisionEngine, int width, int height) { _messageBuilder = messageBuilder; var start = new Cell(0, 0).GetBoundingBox(); var end = new Cell(width - 1, height - 1).GetBoundingBox(); var fullGrid = BoundingBox.CreateMerged(start, end); _quadtree = new Quadtree <MazeChunk>(fullGrid); var cells = GenerateNewMaze(width, height); var chunks = GenerateChunks(renderContext, cells, collisionEngine); _totalVertices = chunks.Sum(c => c.Vertices); _totalChunks = chunks.Count; foreach (var c in chunks) { _quadtree.Add(c); } }
/// <summary> /// Determines what the AI will do based on wether the player is on view and where he is on the platform. /// </summary> public void ComputeInput() { if (VisionBox().Intersects(((CollisionObject)Globals.currWorld.hero).GetCollisionBox()) || VisionBox().Contains(((CollisionObject)Globals.currWorld.hero).GetCollisionBox()) || ((CollisionObject)Globals.currWorld.hero).GetCollisionBox().Contains(VisionBox())) { if (!CollisionEngine.CollisionCheck(Globals.currWorld.levels[Globals.currWorld.currLevel].platforms, new Segment(new Vector2(GetCollisionBox().Center.X, GetCollisionBox().Top), new Vector2(Globals.currWorld.hero.GetCollisionBox().Center.X, Globals.currWorld.hero.GetCollisionBox().Top)))) { if (!isAttacking) { viewingDistance *= 2; } if (pos.X > Globals.currWorld.hero.pos.X) { lastDirRight = false; } else { lastDirRight = true; } Attack(); vector = Vector2.Zero; isAttacking = true; } } else { if (isAttacking) { viewingDistance /= 2; } isAttacking = false; attackingCounter = new TimeSpan(0, 0, 0, 1, 250); } if (!isAttacking) { if (physicsVector.Y > 0.1f) { walkingSegment = null; } else { if (walkingSegment != null) { if (Math.Sign(physicsVector.X) != Math.Sign(goingTo.X - pos.X) && Math.Sign(physicsVector.X) != 0 && Math.Abs(physicsVector.X) > 0.5) { if (goingTo == walkingSegment.defPoint1) { goingTo = walkingSegment.defPoint2; } else { goingTo = walkingSegment.defPoint1; } } if (Math.Abs(goingTo.X - pos.X) < dims.X) { if (goingTo == walkingSegment.defPoint1) { goingTo = walkingSegment.defPoint2; } else { goingTo = walkingSegment.defPoint1; } } if (Math.Sign(goingTo.X - pos.X) < 0) { if (vector.X > -speed) { vector.X += Math.Sign(goingTo.X - pos.X) * walkingAccelaration; } } else { if (vector.X < speed) { vector.X += Math.Sign(goingTo.X - pos.X) * walkingAccelaration; } } } else { FindNewWalkingSegment(); if (walkingSegment != null) { if (lastDirRight) { if (walkingSegment.defPoint1.X > walkingSegment.defPoint2.X) { goingTo = walkingSegment.defPoint1; } else { goingTo = walkingSegment.defPoint2; } } else { if (walkingSegment.defPoint1.X > walkingSegment.defPoint2.X) { goingTo = walkingSegment.defPoint2; } else { goingTo = walkingSegment.defPoint1; } } } } } } }
/// <summary> /// Initializes a new maze chunk by generating the appropriate mesh for the specific part of the mesh. /// </summary> /// <param name="renderContext"></param> /// <param name="cells">The cells from which to generate the mesh. Note that a subset of cells is used by using the indices.</param> /// <param name="startXIndex">The start x index inside the cell array to use.</param> /// <param name="startYIndex">The start y index inside the cell array to use.</param> /// <param name="endX">The (excluded) end x value inside the cell array. Cells from <paramref name="startXIndex"/> to <paramref name="endX"/> - 1 are used.</param> /// <param name="endY">The (excluded) end y value inside the cell array. Cells from <paramref name="startYIndex"/> to <paramref name="endY"/> - 1 are used.</param> /// <param name="id">The id is used to give each chunk floor a different color so the user can easily see where chunks end.</param> /// <param name="collisionEngine">The collision engine to which to add the walls to.</param> public MazeChunk(IRenderContext renderContext, Cell[,] cells, int startXIndex, int startYIndex, int endX, int endY, int id, CollisionEngine collisionEngine) { var floorMeshBuilder = new TexturedMeshDescriptionBuilder(); var wallMeshBuilder = GenerateWallMesh(cells, startXIndex, startYIndex, endX, endY, collisionEngine); // get a boundingbox that contains the entire chunk by using CreateMerged on two cells that are at the opposite end of the chunk var topLeft = cells[startXIndex, startYIndex]; var bottomRight = cells[endX - 1, endY - 1]; var merged = BoundingBox.CreateMerged(topLeft.GetBoundingBox(), bottomRight.GetBoundingBox()); // generate only one big floor plane for this chunk floorMeshBuilder.AddPlane(merged, Plane.NegativeY, false, TileSize); BoundingBox = merged; _maze = renderContext.MeshCreator.CreateMesh(wallMeshBuilder); _floor = renderContext.MeshCreator.CreateMesh(floorMeshBuilder); _wallBrush = new SolidColorBrush(Color.DarkGray); _floorBrush = new SolidColorBrush(_colors[id % _colors.Length]); }
/// <summary> /// This method will generate the mesh structure inside the provided boundaries. It will already reduce the vertex count by merging walls within a corridor. /// Note that this is not the most efficient algorithm (in regards to optimization). It is however very fast. /// It runs two steps: first only merging in x direction then in y direction, this will result in a mesh like this. /// <example> /// XXX /// X X /// XXX /// </example> /// into /// <example> /// 111 /// 2 3 /// 444 /// </example> /// Note that the left side (124) could technically also be merged if the algorithm would consider faces, however since it is cell-based it will only merge each cell once. /// </summary> /// <param name="cells"></param> /// <param name="startXIndex"></param> /// <param name="startYIndex"></param> /// <param name="endX"></param> /// <param name="endY"></param> /// <param name="collisionEngine"></param> /// <returns></returns> public static IMeshDescription GenerateWallMesh(Cell[,] cells, int startXIndex, int startYIndex, int endX, int endY, CollisionEngine collisionEngine) { var skip = MergeCells(cells, startXIndex, startYIndex, endX, endY); var wallMeshBuilder = new TexturedMeshDescriptionBuilder(); for (int y = startYIndex; y < endY; y++) { for (int x = startXIndex; x < endX; x++) { var c = cells[x, y]; var cellBox = c.GetBoundingBox(); if (c.Mode == CellMode.Wall) { if (skip[x - startXIndex, y - startYIndex] == 3) { // has already been merged with previous cells, do not add again continue; } // look at the cells to the right if they can be merged if (x + 1 < endX) { // walk to the right as long as possible int count = 0; int i = 1; while (x + i < endX && skip[x - startXIndex + i, y - startYIndex] == 1) { count = i; i++; } // yes, merge var lastCell = cells[x + count, y].GetBoundingBox(); cellBox = BoundingBox.CreateMerged(cellBox, lastCell); // flag all as already merged if (count > 0) { do { skip[x - startXIndex + count, y - startYIndex] = 3; count--; } while (count > 0); wallMeshBuilder.AddBox(cellBox, TileSize); collisionEngine.Add(new Wall(cellBox)); continue; } } // look at the cells bellow if they can be merged if (y + 1 < endY) { int count = 0; int i = 1; while (y + i < endY && skip[x - startXIndex, y - startYIndex + i] == 2) { count = i; i++; } // yes, merge var lastCell = cells[x, y + count].GetBoundingBox(); cellBox = BoundingBox.CreateMerged(cellBox, lastCell); // flag all as already merged do { skip[x - startXIndex, y - startYIndex + count] = 3; count--; } while (count > 0); wallMeshBuilder.AddBox(cellBox, TileSize); collisionEngine.Add(new Wall(cellBox)); continue; } // no merging possible, just place default cell sized box wallMeshBuilder.AddBox(cellBox, TileSize); collisionEngine.Add(new Wall(cellBox)); } } } return(wallMeshBuilder); }