Exemplo n.º 1
0
 public Level(Game game, SpriteBatch batch)
 {
     completeCode = CompleteCode.NotLoaded;
     this.game    = game;
     player       = new Player(this, game.joeTexture, game.tomatoTexture, 0, ScreenHeight - BlockSize - Player.Height);
     camera       = new Camera(batch, this);
 }
Exemplo n.º 2
0
        public void LoadRandomLevel(int difficulty)
        {
            difficulty *= 5;
            difficulty += 0;
            // land constants
            const int   maxLandHeight    = 8;                   // the maximum height from the bottom of the screen that land can appear
            const int   maxJumpHeight    = 3;                   // the maximum vertical distance that Joe can jump upwards
            const float maxFlatJumpWidth = 6.6f;                // the maximum horizontal jumping distance if both ledges are the same height
            const float jumpDifferential = 0.8f;                // the amount the maximum horizontal distance changes per vertical square

            // item constants
            const int   avgRegTomatoDist  = 20;             // the average number of squares between a regular tomato and the next tomato
            const int   avgGoldTomatoDist = 60;             // the average number of squares between a golden tomato and the next tomato
            const int   varRegTomatoDist  = 5;              // the variance in number of squares between a regular tomato and the next tomato
            const int   varGoldTomatoDist = 20;             // the variance in number of squares between a golden tomato and the next tomato
            const float avgOddsOfGolden   = 0.15f;          // the average chance that a spawned tomato will be golden
            const float avgOddsofExLife   = 0.002f;         // the average chance each square that an extra life will be spawned

            const int minItemHeight = 3;                    // the minimum height above the ground that an item can be spawned
            const int maxItemHeight = 5;                    // the maximum height above the ground that an item can be spawned

            // calculate the length of the level and initialize
            int avgLength   = 150 + difficulty;
            int levelLength = rand.Next(avgLength * 20 / 100, avgLength * 120 / 100);             // length can vary 20% from the average

            land      = new int[levelLength];
            itemList  = new List <Item>();
            enemyList = new List <Enemy>();
            List <Item.Temp> tempItemList = new List <Item.Temp>();

            completeCode = CompleteCode.Incomplete;

            // generate random background color
            int red   = 255 - difficulty - rand.Next(100 + difficulty);
            int green = 255 - difficulty - rand.Next(100 + difficulty);
            int blue  = 255 - difficulty - rand.Next(100 + difficulty);

            if (red < 0)
            {
                red = rand.Next(100);
            }
            if (green < 0)
            {
                green = rand.Next(100);
            }
            if (blue < 0)
            {
                blue = rand.Next(100);
            }
            backgroundColor = new Color(red, green, blue);

            // begin generating land
            int curLandHeight = 4;

            for (int i = 0; i < 3; ++i)
            {
                curLandHeight += rand.Next(-1, 1);
            }
            int  prevHeight    = curLandHeight;
            int  curLength     = 0;        // tell it to generate a fresh length
            bool isHole        = true;     // ...as if a hole just ended
            int  curTomatoDist = curTomatoDist = avgRegTomatoDist * 2 + rand.Next(-varRegTomatoDist * 2, varRegTomatoDist * 2);

            for (int square = 0; square < levelLength;)
            {
                // is the last section finished?
                if (curLength <= 0)
                {
                    curLength = 0;
                    // generate a new length for the next section
                    // did we just finish a hole?
                    if (isHole)
                    {
                        // add a new section of land (land height is already specified, lets get the length)
                        isHole = false;
                        int odds = 200;
                        curLength = 0;
                        while (rand.Next(200) < odds)
                        {
                            odds -= 10 + rand.Next(difficulty);
                            ++curLength;
                        }
                    }
                    // did we just finish a section of land?
                    else
                    {
                        // determine the height difference with the next section
                        int heightDifference = 0;
                        for (int i = 0; i < 8; ++i)
                        {
                            if (rand.Next(200) < 50 + difficulty)
                            {
                                heightDifference += rand.Next(-1, 1);
                            }
                        }
                        // if land is already at max or min height, reverse the height change if necessary
                        if (curLandHeight == maxLandHeight && heightDifference > 0 || curLandHeight == 1 && heightDifference < 0)
                        {
                            heightDifference *= -1;
                        }
                        // if the height change is higher than Joe can jump, reduce it to his maximum jump height
                        if (heightDifference > maxJumpHeight)
                        {
                            heightDifference = maxJumpHeight;
                        }
                        // if the change will take the land higher than maximum, set it to the maximum difference
                        if (curLandHeight + heightDifference > maxLandHeight)
                        {
                            heightDifference = maxLandHeight - curLandHeight;
                        }
                        // if the change will take the land lower than minimum, set it to the minimum difference
                        if (curLandHeight + heightDifference < 1)
                        {
                            heightDifference = 1 - curLandHeight;
                        }
                        // make sure we haven't ended up with an invalid land height somehow!
                        if (curLandHeight + heightDifference > maxLandHeight + heightDifference || curLandHeight < 1)
                        {
                            throw new Exception("Level Randomizer Error #1: INVALID Land Height!");
                        }

                        // determine whether we should next add a hole, or just a conjoined section of land
                        if (rand.Next(50) < 10 + rand.Next(difficulty))
                        {
                            // calculate the maximum length of the hole
                            int maxHoleLength = (int)(0.5f + maxFlatJumpWidth - jumpDifferential * heightDifference);
                            // early in the level, shorten the max hole length
                            if (square < 20)
                            {
                                maxHoleLength -= 2;
                            }

                            // determine the length that this hole should be, based on difficulty and randomness
                            curLength = 0;
                            for (int i = 0; i < maxHoleLength; ++i)
                            {
                                if (rand.Next(50) < 20 + rand.Next(difficulty))
                                {
                                    ++curLength;
                                }
                            }
                        }

                        // regardless of whether we're adding a new hole or a conjoined section, we need to set these
                        isHole         = true;
                        prevHeight     = curLandHeight;
                        curLandHeight += heightDifference;
                        // is the length still zero?
                        if (curLength <= 0)
                        {
                            // lets go back and add on a new conjoined section of land
                            continue;
                        }
                    }
                }

                // continue adding the current section of land
                if (isHole)
                {
                    land[square] = 0;
                }
                else
                {
                    land[square] = curLandHeight;
                }
                --curLength;

                // continue adding tomatoes where necessary
                if (curTomatoDist <= 0)
                {
                    // add a new tomato
                    Item.Temp tomato = new Item.Temp(square - 1,
                                                     prevHeight + rand.Next(minItemHeight, maxItemHeight), Item.Type.Food);
                    // should we add a golden tomato?
                    if (rand.NextDouble() < avgOddsOfGolden)
                    {
                        // make it a golden tomato
                        tomato.type = Item.Type.Gold;
                        // determine the distance to the next tomato
                        curTomatoDist = avgGoldTomatoDist + rand.Next(-varGoldTomatoDist, varGoldTomatoDist);
                        // increase the distance haphazardly based on difficulty
                        curTomatoDist += rand.Next(difficulty) * varGoldTomatoDist / 50;
                        // make sure the distance to next tomato isn't too far
                        if (curTomatoDist > avgGoldTomatoDist + varGoldTomatoDist * 4)
                        {
                            curTomatoDist = avgGoldTomatoDist;
                            for (int i = 0; i < 4; ++i)
                            {
                                curTomatoDist += rand.Next(varGoldTomatoDist);
                            }
                        }
                    }
                    // should we add a regular tomato?
                    else
                    {
                        // make it a regular tomato
                        tomato.type = Item.Type.Food;
                        // determine the distance to the next tomato
                        curTomatoDist = avgRegTomatoDist + rand.Next(-varRegTomatoDist, varRegTomatoDist);
                        // increase the distance haphazardly based on difficulty
                        curTomatoDist += rand.Next(difficulty) * varRegTomatoDist / 50;
                        // make sure the distance to next tomato isn't too far
                        if (curTomatoDist > avgRegTomatoDist + varRegTomatoDist * 4)
                        {
                            curTomatoDist = avgRegTomatoDist;
                            for (int i = 0; i < 4; ++i)
                            {
                                curTomatoDist += rand.Next(varRegTomatoDist);
                            }
                        }
                    }
                    // add the tomato item to the temp list
                    tempItemList.Add(tomato);
                }
                --curTomatoDist;

                // should we add an extra life?
                if (rand.NextDouble() < avgOddsofExLife * (50 + difficulty) / 50)
                {
                    Item.Temp life = new Item.Temp(square - 1,
                                                   prevHeight + rand.Next(minItemHeight, maxItemHeight), Item.Type.Life);
                    tempItemList.Add(life);
                }

                // only go to the next square if we've finished all the tasks for this square
                ++square;
            }
            // add the items to the main list
            foreach (Item.Temp temp in tempItemList)
            {
                itemList.Add(new Item(game.itemTexture, temp.column, temp.row, temp.type));
            }
        }
Exemplo n.º 3
0
        public void Load(int levelNum)
        {
            /* TEMP
             * itemList = new List<Item>();
             * completeCode = CompleteCode.Incomplete;
             * backgroundColor = Color.CornflowerBlue;
             * //this.levelNum = levelNum; TODO:CHECK?
             *
             * switch (levelNum)
             * {
             *      case 1: // the first test level
             *              backgroundColor = Color.LightSkyBlue;
             *              land = new int[] { 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 0, 0, 3, 3, 3, 3, 0, 0, 2, 2, 2, 2, 2, 2, 5, 5,
             *                      5, 5, 5, 6, 6, 6, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2,
             *                      2, 2, 2, 5, 5, 5, 3, 3, 3, 3, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, };
             *              itemList.Add(new Item(game.itemTexture, 23, 8, Item.Type.Food));
             *              itemList.Add(new Item(game.itemTexture, 61, 5, Item.Type.Food));
             *              itemList.Add(new Item(game.itemTexture, 84, 6, Item.Type.Food));
             *              break;
             *      case 2: // the second test level
             *              backgroundColor = Color.DarkKhaki;
             *              land = new int[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 0, 0, 0,
             *                      0, 2, 2, 2, 2, 2, 0, 0, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 0, 4, 4, 4, 4, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0,
             *                      2, 2, 2, 2, 5, 5, 5, 0, 0, 0, 6, 6, 0, 0, 6, 6, 6, 0, 0, 0, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 3, 3, 3,
             *                      3, 3, 3, };
             *              itemList.Add(new Item(game.itemTexture, 2, 6, Item.Type.Food));
             *              itemList.Add(new Item(game.itemTexture, 63, 8, Item.Type.Gold));
             *              break;
             *      case 3: // the hard test level
             *              backgroundColor = Color.Crimson;
             *              land = new int[] {
             *              //  0  1  2  3  4  5  6  7  8  9
             *                      2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 10
             *                      0, 0, 0, 0, 2, 2, 0, 0, 0, 4, // 20
             *                      4, 4, 0, 0, 0, 0, 4, 0, 0, 0, // 30
             *                      0, 4, 0, 0, 0, 6, 6, 6, 0, 0, // 40
             *                      0, 0, 0, 2, 2, 2, 2, 2, 4, 4, // 50
             *              //  0  1  2  3  4  5  6  7  8  9
             *                      4, 0, 0, 0, 0, 0, 2, 0, 0, 0, // 60
             *                      0, 2, 2, 0, 0, 0, 0, 3, 3, 3, // 70
             *                      0, 0, 0, 0, 4, 4, 0, 0, 0, 0, // 80
             *                      0, 3, 3, 0, 0, 0, 0, 0, 0, 1, // 90
             *                      1, 1, 1, 0, 0, 0, 0, 3, 0, 0, // 100
             *              //  0  1  2  3  4  5  6  7  8  9
             *                      0, 0, 4, 0, 0, 0, 0, 5, 0, 0, // 110
             *                      0, 0, 0, 3, 0, 0, 0, 0, 0, 2, // 120
             *                      2, 2, 2, };
             *              itemList.Add(new Item(game.itemTexture, 46, 5, Item.Type.Food));
             *              itemList.Add(new Item(game.itemTexture, 58, 4, Item.Type.Food));
             *              break;
             *      default: // an empty level
             *              land = new int[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, };
             *              break;
             * }
             * /*/// TEMP

            if (levelNum < 0 || levelNum > 99)
            {
                levelNum = 0;
            }
            game.LevelNum = levelNum;

            // load a random level?
            if (randomLevels)
            {
                LoadRandomLevel(levelNum);
                return;
            }

            // load the level file
            string filename = "Level";

            if (levelNum < 10)
            {
                filename += '0';
            }
            filename += levelNum.ToString() + ".txt";

            string       path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Levels/" + filename);
            string       lineOfText;
            StreamReader sr;

            try {
                sr = new StreamReader(path);
            } catch (FileNotFoundException)
            {
                Load(levelNum + 1);
                return;
            }

            itemList        = new List <Item>();
            enemyList       = new List <Enemy>();
            completeCode    = CompleteCode.Incomplete;
            backgroundColor = Color.CornflowerBlue;

            const int TabWidth       = 8;
            const int MaxLevelLength = 1000;
            const int MaxVars        = 10;

            int levelLength = 0;
            int levelHeight = 0;

            int[]             tempLand      = new int[MaxLevelLength];
            List <Item.Temp>  tempItemList  = new List <Item.Temp>();
            List <Enemy.Temp> tempEnemyList = new List <Enemy.Temp>();

            string[] tempVarNames  = new string[MaxVars];
            string[] tempVarValues = new string[MaxVars];
            for (int i = 0; i < MaxVars; ++i)
            {
                tempVarNames[i]  = "";
                tempVarValues[i] = "";
            }
            //List<string> tempVarName = new List<string>();
            //List<string> tempVarValue = new List<string>();
            string tempVarData = "";
            int    curVars     = 0;
            int    varState    = 0;

            for (int lineNum = 0; (lineOfText = sr.ReadLine()) != null; ++lineNum)
            {
                int length = lineOfText.Length;
                if (length > MaxLevelLength)
                {
                    length = MaxLevelLength;
                }

                for (int cursor = 0, colNum = 0; cursor < length; ++cursor, ++colNum)
                {
                    if (varState == 0)
                    {
                        bool modified = false;
                        switch (lineOfText[cursor])
                        {
                        case '#':
                            modified = true;
                            if (tempLand[colNum] == 0)
                            {
                                tempLand[colNum] = lineNum + 1;
                            }
                            break;

                        case 'c':
                            modified = true;
                            tempItemList.Add(new Item.Temp(colNum - 1, lineNum, Item.Type.Food));
                            break;

                        case 'g':
                            modified = true;
                            tempItemList.Add(new Item.Temp(colNum - 1, lineNum, Item.Type.Gold));
                            break;

                        case 'e':
                            modified = true;
                            tempItemList.Add(new Item.Temp(colNum - 1, lineNum, Item.Type.Life));
                            break;

                        case 'F':
                            modified = true;
                            tempEnemyList.Add(new Enemy.Temp(colNum - 1, lineNum,
                                                             Enemy.Type.Gobbler, (int)Gobbler.SubType.Blue));
                            break;

                        case 'G':
                            modified = true;
                            tempEnemyList.Add(new Enemy.Temp(colNum - 1, lineNum,
                                                             Enemy.Type.Gobbler, (int)Gobbler.SubType.Green));
                            break;

                        case 'H':
                            modified = true;
                            tempEnemyList.Add(new Enemy.Temp(colNum - 1, lineNum,
                                                             Enemy.Type.Gobbler, (int)Gobbler.SubType.Yellow));
                            break;

                        case 'I':
                            modified = true;
                            tempEnemyList.Add(new Enemy.Temp(colNum - 1, lineNum,
                                                             Enemy.Type.Gobbler, (int)Gobbler.SubType.Purple));
                            break;

                        case '\t':
                            colNum += TabWidth - (colNum % TabWidth) - 1;
                            break;

                        case '!':
                            varState = 1;
                            break;
                        }
                        if (modified)
                        {
                            if (levelLength < colNum + 1)
                            {
                                levelLength = colNum + 1;
                            }
                            if (levelHeight < lineNum + 1)
                            {
                                levelHeight = lineNum + 1;
                            }
                        }
                    }
                    else
                    {
                        char c = lineOfText[cursor];
                        if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
                        {
                            tempVarData += c;
                        }
                        else if (varState == 1 && c == '=')
                        {
                            tempVarNames[curVars] = tempVarData;
                            tempVarData           = "";
                            varState = 2;
                        }
                        else if (varState == 2 && c == '!')
                        {
                            tempVarValues[curVars] = tempVarData;
                            tempVarData            = "";
                            varState = 1;
                            ++curVars;
                        }
                    }
                }
            }
            if (varState == 2)
            {
                tempVarValues[curVars] = tempVarData;
            }

            // assign and correct land heights
            land = new int[levelLength];
            for (int i = 0; i < levelLength; ++i)
            {
                if (tempLand[i] == 0)
                {
                    land[i] = 0;
                }
                else
                {
                    land[i] = levelHeight + 1 - tempLand[i];
                }
            }

            // add items and enemies and correct initial heights
            foreach (Item.Temp temp in tempItemList)
            {
                itemList.Add(new Item(game.itemTexture, temp.column, levelHeight - temp.row, temp.type));
            }
            foreach (Enemy.Temp temp in tempEnemyList)
            {
                temp.row = levelHeight - temp.row;
                enemyList.Add(Enemy.Create(game, this, temp));
            }

            // load options
            for (int i = 0; i < MaxVars; ++i)
            {
                string varName = tempVarNames[i].ToLower();
                if (varName == "color")
                {
                    PropertyInfo colorProperty = typeof(Color).GetProperty(tempVarValues[i]);
                    try
                    {
                        backgroundColor = (Color)colorProperty.GetValue(null, null);
                    }
                    catch (Exception)
                    {
                        backgroundColor = Color.DarkGray;
                    }
                    continue;
                }
                if (varName == "author")
                {
                    author = tempVarValues[i];
                    if (author == "")
                    {
                        author = "Tim";
                    }
                    continue;
                }
            }

            // TEMP */
        }