/// <summary> /// Check if this crate landed on another crate /// </summary> /// <param name="crate">The other crate</param> /// <param name="sides">The sides of this crate that there was a collision on</param> public override void CollideWith(Crate crate, IEnumerable <Side> sides) { if (sides.Contains(Side.Bottom)) { //Add to crates above and crates below accordingly crate.StepOnto(this); cratesBelow.Add(crate); } }
/// <summary> /// Remove this crate from the other crates above list /// </summary> /// <param name="crate">The other crate</param> public void StepOff(Crate crate) => cratesAbove.Remove(crate);
/// <summary> /// Add this crate to another crates above list /// </summary> /// <param name="crate">The other crate</param> public void StepOnto(Crate crate) => cratesAbove.Add(crate);
/// <summary> /// Loads all the gameobject in the level /// </summary> /// <param name="path">the level file path</param> private void LoadLevelFromFile(string path) { //Stores the number of keys in th elevel numKeys = 0; numGems = 0; //removes all the gameobjects from last level gameObjects.Clear(); //stores all the lines in the file string[] lines = File.ReadAllLines(path); //loops over all the charachters for (int r = 0; r < NUM_CELLS_HEIGHT; ++r) { for (int c = 0; c < NUM_CELLS_WIDTH; ++c) { //adds the corresponding gameobject switch (lines[r][c]) { case '0': //save an addition refrence to the player before adding it player = new Player(c * CELL_SIDE_LENGTH, r * CELL_SIDE_LENGTH); gameObjects.Add(player); break; case '1': gameObjects.Add(new Wall(c * CELL_SIDE_LENGTH, r * CELL_SIDE_LENGTH)); break; case '2': //Saves a refrance to the crate so it could subscribe to events Crate crate = new Crate(c * CELL_SIDE_LENGTH, r * CELL_SIDE_LENGTH); //Check that there are no gems or keys above whenever crate moves crate.CrateMove += cr => { IEnumerable <GameObject> objectsAbove = gameObjects.Where(g => Helper.IsPointInOrOnRectangle(g.TopLeftGridPoint.ToVector2(), new Rectangle(cr.Box.Location - new Point(0, cr.Box.Height), cr.Box.Size))); return(objectsAbove.Count() != 0 && (objectsAbove.First() is Gem || objectsAbove.First() is Key)); }; gameObjects.Add(crate); break; case '3': //save the position of the flag flagPos = new Point(c * CELL_SIDE_LENGTH, r * CELL_SIDE_LENGTH); break; case '4': gameObjects.Add(new Door(c * CELL_SIDE_LENGTH, r * CELL_SIDE_LENGTH)); break; case '5': gameObjects.Add(new Spike(c * CELL_SIDE_LENGTH, r * CELL_SIDE_LENGTH)); break; case '6': gameObjects.Add(new Gem(c * CELL_SIDE_LENGTH, r * CELL_SIDE_LENGTH)); ++numGems; break; case '7': gameObjects.Add(new Key(c * CELL_SIDE_LENGTH, r * CELL_SIDE_LENGTH)); ++numKeys; break; } } } //subscribe to the crate event for colliding with gems and keys (add them to the player count) gameObjects.OfType <Crate>().ToList().ForEach(c => c.CollideWithGem += () => player.AddGem()); gameObjects.OfType <Crate>().ToList().ForEach(c => c.CollideWithKey += () => player.AddKey()); //Notify Game of how many collectibles there are this level KeysAndGemsCounted.Invoke(numKeys, numGems); //add the 4 walls around the screem gameObjects.AddRange(new[] { new Wall(-SCREEN_WALL_WIDTH, 0, SCREEN_WALL_WIDTH, HEIGHT), new Wall(WIDTH, 0, SCREEN_WALL_WIDTH, HEIGHT), new Wall(0, -SCREEN_WALL_WIDTH, WIDTH, SCREEN_WALL_WIDTH), new Wall(0, HEIGHT, WIDTH, SCREEN_WALL_WIDTH) }); //subscribe to the move and delete events of all the gameobjects gameObjects.ForEach(g => g.MoveReady += gameObject => MoveGameObject(gameObject)); gameObjects.ForEach(g => g.DeleteReady += gameObject => gameObjects.Remove(gameObject)); //subscribe to the players hit spike event with a function that ends the level player.HitSpike += () => { //clears commands and pauses the game commands = new Queue <char>(); GamePaused = true; //Notify game that the player hit a spike RunCompleteFailed.Invoke("The player hit a spike : press ENTER to try again."); }; //subscribe to the players collect gem and key events (notify Game when happenes) player.KeyCollected += nk => playerKeyCollected.Invoke(nk); player.GemCollected += ng => playerGemCollected.Invoke(ng); }
private void LoadLevel(string levelFileName) { readFile = new StreamReader(levelFileName); int numLines = 0; string line; /* * 0 = Player * 1 = Wall * 2 = Crate * 3 = Goal * 4 = Door * 5 = Spike * 6 = Gem * 7 = Key */ //Clearing all rectangle lists in case a level was previously loaded terrainRecs.Clear(); crateDestRecs.Clear(); gemDestRecs.Clear(); spikeDestRecs.Clear(); doorDestRecs.Clear(); //Resetting counters numGemsCollected = 0; numKeysCollected = 0; //Adding all level borders //The floor of the level terrainRecs.Add(new Rectangle(0, (LEVEL_TILES_H)*TILE_SIZE, NUM_TILES_W * TILE_SIZE, TILE_SIZE)); //The left wall of the level terrainRecs.Add(new Rectangle(-TILE_SIZE, 0, TILE_SIZE, NUM_TILES_H * TILE_SIZE)); //The Right wall of the level terrainRecs.Add(new Rectangle(NUM_TILES_W * TILE_SIZE, 0, TILE_SIZE, NUM_TILES_H * TILE_SIZE)); //The ceiling of the level terrainRecs.Add(new Rectangle(0, -TILE_SIZE, NUM_TILES_W * TILE_SIZE, TILE_SIZE)); while ((line = readFile.ReadLine()) != null) { numLines++; if (numLines > NUM_TILES_H) { throw new FormatException($"There are too many tiles. The level must be no larger than {NUM_TILES_H} tiles in height."); } if (line.Length > NUM_TILES_W) { throw new FormatException($"There are too many tiles. The level must be no larger than {NUM_TILES_W} tiles in width."); } for (int i = 0; i < line.Length; i++) { switch (line[i]) { //Player case '0': playerDestRec = new Rectangle(i * TILE_SIZE, numLines * TILE_SIZE, TILE_SIZE, TILE_SIZE - 10); break; //Terrain case '1': terrainRecs.Add(new Rectangle(i * TILE_SIZE, numLines * TILE_SIZE, TILE_SIZE, TILE_SIZE)); break; //Crates case '2': crateDestRecs.Add(new Rectangle(i * TILE_SIZE, numLines * TILE_SIZE, TILE_SIZE, TILE_SIZE)); break; //Flag case '3': flagPoleDestRec = new Rectangle(i * TILE_SIZE, numLines * TILE_SIZE, TILE_SIZE, TILE_SIZE); break; //Doors case '4': doorDestRecs.Add(new Rectangle(i * TILE_SIZE, numLines * TILE_SIZE, TILE_SIZE, TILE_SIZE)); break; //Spikes case '5': spikeDestRecs.Add(new Rectangle(i * TILE_SIZE, numLines * TILE_SIZE, TILE_SIZE, TILE_SIZE)); break; //Gems case '6': gemDestRecs.Add(new Rectangle(i * TILE_SIZE, numLines * TILE_SIZE, TILE_SIZE, TILE_SIZE)); break; //Keys case '7': keyDestRecs.Add(new Rectangle(i * TILE_SIZE, numLines * TILE_SIZE, TILE_SIZE, TILE_SIZE)); break; } } } //Initializing all game object arrays crates = new Crate[crateDestRecs.Count]; gems = new Gem[gemDestRecs.Count]; keys = new Key[keyDestRecs.Count]; doors = new Door[doorDestRecs.Count]; spikes = new Spike[spikeDestRecs.Count]; //Setting totalNumGems variable totalNumGems = gems.Length; //Initializing all crates for (int i = 0; i < crates.Length; i++) { crates[i] = new Crate(crateSprite, crateDestRecs[i], crateSrcRec); } //Initializing all gems for (int i = 0; i < gems.Length; i++) { gems[i] = new Gem(gemSprite, gemDestRecs[i], gemSrcRec); } //Initializing all keys for (int i = 0; i < keys.Length; i++) { keys[i] = new Key(keySprite, keyDestRecs[i], keySrcRec); } //Initializing all doors for (int i = 0; i < doors.Length; i++) { doors[i] = new Door(doorSprite, doorDestRecs[i], doorSrcRec); } //Initializing all spikes for (int i = 0; i < spikes.Length; i++) { spikes[i] = new Spike(spikeSprite, spikeDestRecs[i], spikeSrcRec); } player = new Player(idleSprite, playerDestRec, playerSrcRec, playerSprites); //Crating the entities array to store all game entities entities = new GameEntity[crates.Length + 1]; entities[0] = player; //Adding the crates to the entity array for (int i = 1; i < entities.Length; i++) { entities[i] = crates[i - 1]; } try { } catch (FileNotFoundException e) { Console.WriteLine(e.Message); } catch (FormatException e) { Console.WriteLine(e.Message); } }