Esempio n. 1
0
        /// <summary>
        /// Imports a level file. You can read the Level file format description on this file header
        /// </summary>
        /// <param name="path">The path.</param>
        /// <returns></returns>
        /// <exception cref="System.Exception">Exception Loading level file:  + path</exception>
        public LevelModel ImportLevel(string path)
        {
            string line = string.Empty;
            BlockTypeEnum blockType = BlockTypeEnum.EMPTY;

            LevelModel model = new LevelModel();

            try
            {
                // Read the level file
                using (Stream fs = WaveServices.Storage.OpenContentFile(path))
                //using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read))
                using (BufferedStream bs = new BufferedStream(fs, 8388608)) // 8Mb buffer it's a good buffer for files.
                using (StreamReader sr = new StreamReader(bs))
                {
                    float blockScaleX = 1.0f;
                    float blockScaleY = 1.0f;
                    float blockScaleZ = 1.0f;

                    // FIRST LINE of the file: Block X scale
                    if (!sr.EndOfStream)
                    {
                        line = sr.ReadLine();
                        float.TryParse(line, NumberStyles.Number, CultureInfo.InvariantCulture, out blockScaleX);
                        ModelFactoryService.Instance.Scale.X= blockScaleX;
                    }

                    // SECOND LINE of the file: Block Y Scale
                    if (!sr.EndOfStream)
                    {
                        line = sr.ReadLine();
                        float.TryParse(line, NumberStyles.Number, CultureInfo.InvariantCulture, out blockScaleY);
                        ModelFactoryService.Instance.Scale.Y = blockScaleY;
                    }

                    // THIRD LINE of the file: Block Z Scale
                    if (!sr.EndOfStream)
                    {
                        line = sr.ReadLine();
                        float.TryParse(line, NumberStyles.Number, CultureInfo.InvariantCulture, out blockScaleZ);
                        ModelFactoryService.Instance.Scale.Z = blockScaleZ;
                    }

                    // The rest of the file is the level
                    while (!sr.EndOfStream)
                    {
                        line = sr.ReadLine();

                        if(!string.IsNullOrWhiteSpace(line)) // line must be filled with data
                        {
                            string[] splitted = line.Split(SEPARATOR); // split the line
                            if(splitted.Count() > 0)
                            {
                                Column column = new Column(); // creates the column
                                foreach(string value in splitted)
                                {
                                    blockType = BlockTypeEnum.EMPTY; // default value if reading error or out of block type error
                                    Enum.TryParse<BlockTypeEnum>(value, out blockType);
                                    column.Add(blockType);
                                }
                                model.ColumnCollection.Enqueue(column);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Exception Loading level file: " + path, ex);
            }

            return model;
        }
Esempio n. 2
0
        /// <summary>
        /// Allows this instance to execute custom logic during its 
        /// <c>Update</c>.
        /// </summary>
        /// <param name="gameTime">The game time.</param>
        /// <remarks>
        /// This method will not be executed if it are not 
        /// <c>Active</c>.
        /// </remarks>
        protected override void Update(TimeSpan gameTime)
        {
            float elapsedGameTime = (float)gameTime.TotalSeconds;

            // Game Tri-state machine
            switch (GameState)
            {
                // Initial level state
                case GameState.INIT:
                    // Loads the level, reloads every time player dead to reset the collection and column order... 
                    // it can be done in everywhere we want, in scene too, but then we need to call a Reset method or similar
                    this.LevelModel = ImportService.Instance.ImportLevel("Content/Levels/level1A.level");

                    // Restart Camera, Player states and positions
                    this.playScene.Player.FindComponent<PlayerBehavior>().Restart();
                    this.boostVelocity = 0.0f;

                    // put player over the first ground block
                    // FIRST BLOCK OF LEVEL SHOULD BE A GROUND, logically
                    this.playerTransform.Position = new Vector3(0f, this.modelFactoryService.Scale.Y, 0.0f);
                    this.playScene.GameCamera.Position = cameraPlayerPosition;
                    this.playScene.GameCamera.LookAt = cameraPlayerLookat;

                    // fills the intiial Buffer, we need to load some elements prior playing
                    float currentZ = 0;
                    for (int i = 0; i < BLOCKBUFFERSIZE; i++)
                    {
                        // Create Column
                        this.CreateNextColumnEntity(currentZ);
                        currentZ += this.modelFactoryService.Scale.Z;
                    }
                    GameState = GameState.PLAY;
                    break;

                // Playing State of game:
                case GameState.PLAY:
                    // new player position, using acceleration, falling, etc... where applicable
                    this.UpdatePlayerPosition(elapsedGameTime);

                    // Check if dead by level platform falling down
                    if (this.playerTransform.Position.Y <= UNDERDEADLEVEL)
                    {
                        this.GameState = Enums.GameState.DIE;
                    }

                    // used for find the block limits.
                    var middleSize = this.modelFactoryService.Scale.Z / 2;

                    // Selects the current and next column, selects the columns to free too.
                    // the current column and next column are used to check collisions, only with those two columns, others are ignored
                    for (int i = 0; i < this.ColumnCollection.Count - 1; i++)
                    {
                        Entity column = this.ColumnCollection[i];
                        var columnTransform = column.FindComponent<Transform3D>();

                        // Remove passedby columns by distance
                        if (columnTransform.Position.Z < this.playerTransform.Position.Z - PASSEDBYBLOCKSTODISCARDCOLUMN * this.modelFactoryService.Scale.Z)
                        {
                            // removes column
                            this.modelFactoryService.FreeColumn(column);
                            this.playScene.EntityManager.Remove(column);
                            this.ColumnCollection.RemoveAt(i);

                            // Create new column at the end
                            this.CreateNextColumnEntity(columnTransform.Position.Z + BLOCKBUFFERSIZE * this.modelFactoryService.Scale.Z);
                        }
                        // check if player is over this column and sets current and next column
                        else if (this.playerTransform.Position.Z < columnTransform.Position.Z + this.modelFactoryService.Scale.Z
                           && this.playerTransform.Position.Z >= columnTransform.Position.Z)
                        {
                            this.CurrentColumn = column;
                            this.NextColumn = this.ColumnCollection[i + 1];

                            // update the ground level for current and next columns
                            this.CheckGroundPosition();
                            break;
                        }
                    }

                    // if there are a current column checks the collision in current and next column
                    if (this.CurrentColumn != null)
                    {
                        // creates the union of each column entities
                        List<Entity> collidableCollection = this.CurrentColumn.ChildEntities.ToList();
                        collidableCollection.AddRange(this.NextColumn.ChildEntities.ToList());

                        // check if collides
                        foreach (Entity block in collidableCollection)
                        {
                            var blockTransform = block.FindComponent<Transform3D>();
                            var blockCollider = block.FindComponent<BoxCollider>();
                            // updates the block boundingbox to check collision
                            this.tempBoundingBox.Max = blockTransform.Position + blockCollider.Size / 2;
                            this.tempBoundingBox.Min = blockTransform.Position - blockCollider.Size / 2;

                            // we use intersects of boundboxes cause collider class has not a Intersects with boundingboxes
                            if (this.tempBoundingBox.Intersects(this.playerBoundingBox))
                            {
                                BlockTypeEnum blockType = BlockTypeEnum.EMPTY;
                                Enum.TryParse<BlockTypeEnum>(block.Tag, out blockType);

                                // if player colliders with the block, we must to check the block effect:
                                switch (blockType)
                                {
                                    case BlockTypeEnum.EMPTY:
                                        break;
                                    // ground and box obstacles can walk over they, but if crash horizontally player dies
                                    case BlockTypeEnum.GROUND:
                                    case BlockTypeEnum.BOX:
                                        if (this.playerTransform.Position.Y - this.modelFactoryService.Scale.Y / 2 < blockTransform.Position.Y)
                                        {
                                            this.GameState = Enums.GameState.DIE;
                                        }
                                        break;
                                    case BlockTypeEnum.PYRAMID:
                                        // pyramid collision dies player
                                        this.GameState = Enums.GameState.DIE;
                                        break;
                                    case BlockTypeEnum.SPEEDERBLOCK:
                                        // if collide with speeder then player accelerates
                                        this.boostVelocity += ACCELERATION * elapsedGameTime;
                                        break;
                                    default:
                                        break;
                                }
                            }
                        }
                    }
                    break;

                // player die state
                case GameState.DIE:
                    // free every column entity and remove containers from entitymanager
                    foreach (Entity column in this.ColumnCollection)
                    {
                        this.modelFactoryService.FreeColumn(column);
                        this.playScene.EntityManager.Remove(column);
                    }

                    // clears the collection and colums
                    this.ColumnCollection.Clear();
                    this.CurrentColumn = null;
                    this.NextColumn = null;

                    // just init
                    GameState = GameState.INIT;
                    break;
            }
        }