Advertisement Jump to content
Sign in to follow this  
detlion1643

Creating levels via code?

This topic is 1739 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Currently I have added about 5 levels to my "Arkanoid" clone game. I just made a static LevelGenerator class and call that, which then creates the objects needed and adds them to the screen. I have opted to do this via code so the "bricks" can be manipulated with any x,y location and any width/height combination (also powerups, # of hits, etc). However, even with 5 levels, the code is very repeated with minor differences.

Before I start making more levels, does anyone have any suggestions about this?

*FYI: IBasePlugin, ScreenManager, and screen variables, and the OM.* namespaces are part of the framework I'm working within.

public class LevelGenerator
    {

        public static int MaxLevel = 4;

        private static Bricks br;
        private static int brickWidth;
        private static int brickHeight;
        private static int BrickAreaTop = OM.Host.ClientArea[0].Top + 30;

        private static void AddBrick(Bricks Brick, ScreenManager _Manager, List<Bricks> _Bricks, int screen)
        {
            _Manager[screen, "mainPanel"].addControl(Brick);
            _Bricks.Add(Brick);
        }

        
        public static void GenerateLevel(IBasePlugin OMBricks, ScreenManager Manager, int screen, int gameLevel, List<Bricks> _Bricks)
        {
            switch (gameLevel)
            {
                case 1:
                    for (int i = 0; i < 7; i++)
                    {
                        br = new Bricks();
                        if (i == 0)
                            br.PowerUp = PowerUps.PowerUps.Life;
                        else if (i == 5)
                            br.PowerUp = PowerUps.PowerUps.MultiBall;
                        br.Name = String.Format("Brick.{0}", i.ToString());
                        br.Left = 200 + (br.Width * i) + (10 * i);
                        br.Top = 200;
                        br.BrickLevel = 1;
                        br.Breakable = true;
                        AddBrick(br, Manager, _Bricks, screen);
                    }
                    break;
                case 2:
                    for (int i = 0; i < 7; i++)
                    {

                        for (int j = 0; j < 2; j++)
                        {
                            br = new Bricks();
                            if (i == 2 && j == 1)
                            {
                                br.PowerUp = PowerUps.PowerUps.Laser;
                                br.Name = String.Format("Laser.{0}", i.ToString());
                            }
                            br.Name = String.Format("Brick.{0}.{1}", i.ToString(), j.ToString());
                            br.Left = 200 + (br.Width * i) + (10 * i);
                            br.Top = 200 - (br.Height * j) - (10 * j);
                            br.BrickLevel = 1;
                            br.Breakable = true;
                            Manager[screen, "mainPanel"].addControl(br);
                            _Bricks.Add(br);
                        }
                    }
                    break;
                case 3:
                    for (int i = 0; i < 4; i++)
                    {
                        br = new Bricks();
                        if (i < 2)
                            br.Left = OM.Host.ClientArea[0].Left + (br.Width * i) + (10 * i);
                        else
                            br.Left = OM.Host.ClientArea[0].Left + OM.Host.ClientArea[0].Width - (br.Width * (i - 1)) - (10 * (i - 1));
                        br.Top = OM.Host.ClientArea[0].Top + OM.Host.ClientArea[0].Height - 100;
                        br.Breakable = false;
                        Manager[screen, "mainPanel"].addControl(br);
                        _Bricks.Add(br);
                    }
                    for (int i = 0; i < 4; i++)
                    {
                        br = new Bricks();
                        if (i < 2)
                            br.Left = OM.Host.ClientArea[0].Left + (br.Width * i) + (10 * i);
                        else
                            br.Left = OM.Host.ClientArea[0].Left + OM.Host.ClientArea[0].Width - (br.Width * (i - 1)) - (10 * (i - 2));
                        br.Top = OM.Host.ClientArea[0].Top + OM.Host.ClientArea[0].Height - 135;
                        br.Breakable = true;
                        br.BrickLevel = 1;
                        Manager[screen, "mainPanel"].addControl(br);
                        _Bricks.Add(br);
                    }
                    brickWidth = (OM.Host.ClientArea[0].Left + OM.Host.ClientArea[0].Width - 40) / 5;
                    for (int i = 0; i < 5; i++)
                    {
                        br = new Bricks();
                        if(i == 0 || i == 4)
                            br.PowerUp = PowerUps.PowerUps.Laser;
                        br.Left = OM.Host.ClientArea[0].Left + (brickWidth * i) + (10 * i);
                        br.Top = OM.Host.ClientArea[0].Top + OM.Host.ClientArea[0].Height - 170;
                        br.Width = brickWidth;
                        br.Breakable = true;
                        br.BrickLevel = 2;
                        Manager[screen, "mainPanel"].addControl(br);
                        _Bricks.Add(br);
                    }
                    break;
                case 4:
                    brickWidth = OM.Host.ClientArea[0].Width / 15;
                    brickHeight = (OM.Host.ClientArea[0].Height - 15) / 15;
                    for (int i = 0; i < 15; i++)
                    {
                        br = new Bricks();
                        br.Width = brickWidth;
                        br.Left = OM.Host.ClientArea[0].Left + (i * brickWidth);
                        br.Top = OM.Host.ClientArea[0].Top + 15 + (i * brickHeight);
                        br.Height = brickHeight;
                        br.Breakable = true;
                        if (i < 5)
                            br.BrickLevel = 3;
                        else if (i < 10)
                            br.BrickLevel = 2;
                        else
                            br.BrickLevel = 1;
                        AddBrick(br, Manager, _Bricks, screen);
                    }
                    for (int i = 0; i < 15; i++)
                    {
                            br = new Bricks();
                            br.Width = brickWidth;
                            br.Left = (OM.Host.ClientArea[0].Left + OM.Host.ClientArea[0].Width) - ((i + 1) * brickWidth);
                            br.Top = OM.Host.ClientArea[0].Top + 15 + (i * brickHeight);
                            br.Height = brickHeight;
                            br.Breakable = true;
                            if (i < 5)
                                br.BrickLevel = 3;
                            else if (i < 10)
                                br.BrickLevel = 2;
                            else
                                br.BrickLevel = 1;
                            AddBrick(br, Manager, _Bricks, screen);
                    }
                    break;
                case 5:
                    brickWidth = OM.Host.ClientArea[0].Width / 3;
                    for (int i = 0; i < 3; i++)
                    {
                        br = new Bricks();
                        br.Width = brickWidth;
                        br.Left = OM.Host.ClientArea[0].Left + (i * brickWidth);
                        br.Top = OM.Host.ClientArea[0].Top + ((OM.Host.ClientArea[0].Height / 5) * 3);
                        br.BrickLevel = 3;
                        br.Breakable = true;
                        AddBrick(br, Manager, _Bricks, screen);
                    }
                    break;
            }
        }
    }

Share this post


Link to post
Share on other sites
Advertisement

Hi,

Sorry, I dont have time to help, im just logging off, but your code is unreadable.. its just one huge line ! Just a word of advise, try and format it into a more readable version if you want people to have a look at it :) 

Share this post


Link to post
Share on other sites

there's no real secrets to procedurally generated content. juts make it as cool and/or realistic/believable (depending on game type) as possible.

 

try to avoid repetition.

 

you can have a set of say 6 basic types of generators, and pick three at random, and combine their effects to make a single level. that kind of stuff. this allows a great variety of content with little code.

 

as you write more generators for a given title, you'll get more creative at what you generate with them. sometimes your later generators make your earlier ones look bad, and you have to go back and improve them.

Share this post


Link to post
Share on other sites

There's indeed no secret to procedural generation but there's a trick or two that you may not have considered :)

 

In a previous roguelike project of mine, I experimented with mixing code and data for level generation. Many nice looking patterns (to the human eye) can be extremely / time consuming to generate purely by code. You could have data/text files (or even 2D arrays) with such patterns. Then you would use code to randomly select those files and put them in the level according to some formula of your choosing.

 

Another few advices more directly related with this kind of game:

- I'd suggest to have some kind of symmetry in your levels, it just look better.

- Uses some sin/cos formula to make waves of blocks

Share this post


Link to post
Share on other sites


Many nice looking patterns (to the human eye) can be extremely / time consuming to generate purely by code. You could have data/text files (or even 2D arrays) with such patterns. Then you would use code to randomly select those files and put them in the level according to some formula of your choosing.

 

yes, this is sometimes referred to as the "tiled chunks" approach. Elder scrolls IV Oblivion used this for their dungeons. but there, the chunks were assembled in a level editor by hand, not combined using code.

Share this post


Link to post
Share on other sites

Some thoughts:

You might want to load them from files before it gets too ungainly.

You might also want to generate the levels procedurally but save them to files, take the best, edit them by hand if you want do any tweaking, and save them as the final levels.

 

If you do want to always procedurally generate your content, you may want two modes, one that ensures that level 1 always looks the same for all users, as does levels 1,2,3,4, etc and so on, so that players can kibitz over how hard level 7 is, or how pretty it is, or compare scores on a certain level.   And you might also want a mode that is always random, so that a player can always see new levels. (with an option to play a specific level by saving/displaying the seed, and letting them enter it.)

Share this post


Link to post
Share on other sites
I think I will create a new project that just produces random symmetrical levels to files. I'll handpick through these then and use the files to load. That should be good enough. Ferrous, the 2 different modes (1 normal and 1 random) was already planned out. An "Arcade" mode with predetermined levels and an endless mode that progressively produces more bricks. Thanks everyone!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!