Игра танки тормозит при появлении 6 и более врагов - C#

Узнай цену своей работы

Формулировка задачи:

как то писал курсач -"танки". c# знал плохо, ооп вообще не понимал. сейчас стал кое что понимать решил повторить попытку. столкнулся с тем, что при появлении >= 6 врагов игра начинает тормозить. делаю все на WinForm. контролы танков - PictureBox'ы.
class _Bullet
    {
        public PictureBox Box { get; set; }
        public _Orientation Or;
        public int Velocity { get; set; }
        public bool IsRunning { get; set; }
 
        int maxWidth, maxHeight;
        
        public _Bullet(int maxWidth, int maxHeight)
        {
            Box = new PictureBox()
            {
                Location = new Point(-10, -10),
                Size = new Size(6, 6),
                Image = x3004.Properties.Resources.bulletImage
            };
 
            Velocity = 2;
 
            this.maxWidth = maxWidth;
            this.maxHeight = maxHeight;
        }
 
        /// <summary>
        /// подготовка пули к выстрелу(вычисляем начальное положение и направление)
        /// </summary>
        /// <param name="pictureBox"> picBox героя, который производит выстрел</param>
        /// <param name="orientation"> направление движения героя </param>
        public void Shoot(PictureBox pictureBox, _Orientation orientation)
        {
            switch (orientation)
            {
                case _Orientation.Up:
                    {
                        Box.Location = new Point(pictureBox.Left + pictureBox.Width / 2 - Box.Width / 2, pictureBox.Top - Box.Height / 2);
                        break;
                    }
 
                case _Orientation.Down:
                    {
                        Box.Location = new Point(pictureBox.Left + pictureBox.Width / 2 - Box.Width / 2, pictureBox.Bottom - Box.Height / 2);
                        break;
                    }
 
                case _Orientation.Left:
                    {
                        Box.Location = new Point(pictureBox.Left - Box.Width / 2, pictureBox.Top + pictureBox.Height / 2 - Box.Height / 2);
                        break;
                    }
 
                case _Orientation.Right:
                    {
                        Box.Location = new Point(pictureBox.Right - Box.Width / 2, pictureBox.Top + pictureBox.Height / 2 - Box.Height / 2);
                        break;
                    }
            }
 
            Or = orientation;
            IsRunning = true;
        }
 
        /// <summary>
        /// сброс параметров пули(остановка пули)
        /// </summary>
        public void Reset()
        {
            IsRunning = false;
            Box.Location = new Point(-10, -10);
        }

        /// <summary>
        /// обновляем параметры
        /// </summary>
        /// <param name="timeInterval"> интервал обновлений </param>
        /// <param name="blocks"> список препятствий </param>
        /// <param name="panel"> панель </param>
        public void Update(int timeInterval, ref List<_Block> blocks, ref Panel panel)
        {
            int dx = 0, dy = 0;
 
            if (IsRunning)
            {
                if (Or == _Orientation.Up)
                    dy = -Velocity * timeInterval;
                else
                    if (Or == _Orientation.Down)
                        dy = Velocity * timeInterval;
                    else
                        if (Or == _Orientation.Left)
                            dx = -Velocity * timeInterval;
                        else
                            if (Or == _Orientation.Right)
                                dx = Velocity * timeInterval;
            }
 
            Rectangle boxRect = new Rectangle(Box.Location, Box.Size);
            boxRect.Offset(dx, dy);
 
            if (boxRect.Left > 0 && boxRect.Right < maxWidth && boxRect.Top > 0 && boxRect.Bottom < maxHeight)
            {
                Box.Location = boxRect.Location;
            }
            else
                Reset();
 
            for (int i = 0; i < blocks.Count; i++)
            {
                if (RectIntersect(new Rectangle(blocks[i].Box.Location, blocks[i].Box.Size), boxRect))
                {
                    panel.Controls.Remove(blocks[i].Box);
                    blocks.RemoveAt(i);
                    Reset();
                }
            }
        }
 
        /// <summary>
        /// проверка на пересечение 2х прямоугольников
        /// </summary>
        /// <param name="rect1"> прямоугольник 1 </param>
        /// <param name="rect2"> прямоугольник 2 </param>
        /// <returns></returns>
        bool RectIntersect(Rectangle rect1, Rectangle rect2)
        {
            bool intersect = false;
 
            if (rect1.Left >= rect2.Left && rect1.Left <= rect2.Right && rect1.Top >= rect2.Top && rect1.Top <= rect2.Bottom
               || rect1.Left >= rect2.Left && rect1.Left <= rect2.Right && rect1.Bottom >= rect2.Top && rect1.Bottom <= rect2.Bottom
               || rect1.Right >= rect2.Left && rect1.Right <= rect2.Right && rect1.Top >= rect2.Top && rect1.Top <= rect2.Bottom
               || rect1.Right >= rect2.Left && rect1.Right <= rect2.Right && rect1.Bottom >= rect2.Top && rect1.Bottom <= rect2.Bottom)
                intersect = true;
 
            return intersect;
        }
    }
 class _Hero
    {
        public PictureBox Box { get; set; }
        public _Orientation Or;
        public int Velocity { get; set; }
        public bool IsRunning { get; set; }
 
        public _Bullet Bullet { get; set; }
 
        int maxWidth, maxHeight;
 
        /// <summary>
        /// конструктор
        /// </summary>
        /// <param name="startPosition"> стартовая позиция танка </param>
        /// <param name="maxWidth"> ширина поля, по которому танк может перемещаться </param>
        /// <param name="maxHeight"> высота поля, по которому танк может перемещаться </param>
        public _Hero(Point startPosition, int maxWidth, int maxHeight)
        {
            Box = new PictureBox()
            {
                Location = startPosition,
                Size = new Size(32, 32)
            };
            Velocity = 1;
            Or = _Orientation.Up;
 
            Bullet = new _Bullet(maxWidth, maxHeight);
 
            this.maxWidth = maxWidth;
            this.maxHeight = maxHeight;
        }
 
        /// <summary>
        /// обновляем параметры
        /// </summary>
        /// <param name="timeInterval"> интервал обновлений(интервал таймера) </param>
        /// <param name="blocks"> список препятствий </param>
        /// <param name="panel"> панель(игровое поле) </param>
        public void Update(int timeInterval,ref List<_Block> blocks, ref Panel panel)
        {
            int dx = 0, dy = 0;
 
            if (IsRunning)
            {
                if (Or == _Orientation.Up)
                    dy = -Velocity * timeInterval;
                else
                    if (Or == _Orientation.Down)
                        dy = Velocity * timeInterval;
                    else
                        if (Or == _Orientation.Left)
                            dx = -Velocity * timeInterval;
                        else
                            if (Or == _Orientation.Right)
                                dx = Velocity * timeInterval;
            }
 
            bool intersect=false;
            Rectangle boxRect = new Rectangle(Box.Location, Box.Size);
            boxRect.Offset(dx, dy);
 
            Box.Image = Rotation();
 
            foreach (_Block block in blocks)
            {
                Rectangle rect = new Rectangle(block.Box.Location, block.Box.Size);
                if (RectIntersect(rect, boxRect))
                    intersect = true;
            }
 
            if (boxRect.Left > 0 && boxRect.Right < maxWidth && boxRect.Top > 0 && boxRect.Bottom < maxHeight && !intersect)
            {
                Box.Location = boxRect.Location;
            }
 
            Bullet.Update(timeInterval,ref blocks, ref panel);
        }
 
        /// <summary>
        /// старт выстрела
        /// </summary>
        public void StartShoot()
        {
            Bullet.Shoot(Box, Or);
        }
 
        /// <summary>
        /// поворот изображения танка
        /// </summary>
        /// <returns> возвращает текущее изображение танка </returns>
        Image Rotation()
        {
            Image temp = x3004.Properties.Resources.heroImage;
 
            switch (Or)
            {
                case _Orientation.Up: break;
                case _Orientation.Down: temp.RotateFlip(RotateFlipType.Rotate180FlipNone); break;
                case _Orientation.Left: temp.RotateFlip(RotateFlipType.Rotate270FlipNone); break;
                case _Orientation.Right: temp.RotateFlip(RotateFlipType.Rotate90FlipNone); break;
            }
 
            return temp;
        }
 
        /// <summary>
        /// проверяет, пересекаются ли 2 прямоугольника
        /// </summary>
        /// <param name="rect1"> 1 прямоугольник </param>
        /// <param name="rect2"> 2 прямоугольник </param>
        /// <returns> true - пересекаются, false - не пересекаются </returns>
        bool RectIntersect(Rectangle rect1, Rectangle rect2)
        {
            bool intersect = false;
 
            if (rect1.Left >= rect2.Left && rect1.Left <= rect2.Right && rect1.Top >= rect2.Top && rect1.Top <= rect2.Bottom
               || rect1.Left >= rect2.Left && rect1.Left <= rect2.Right && rect1.Bottom >= rect2.Top && rect1.Bottom <= rect2.Bottom
               || rect1.Right >= rect2.Left && rect1.Right <= rect2.Right && rect1.Top >= rect2.Top && rect1.Top <= rect2.Bottom
               || rect1.Right >= rect2.Left && rect1.Right <= rect2.Right && rect1.Bottom >= rect2.Top && rect1.Bottom <= rect2.Bottom)
                intersect = true;
 
            return intersect;
        }
    }
 class _Enemy
    {
        public PictureBox Box { get; set; }
        public _Orientation Or;
        public int Velocity { get; set; }
 
        int maxWidth, maxHeight;
 
        public _Bullet Bullet { get; set; }
 
        /// <summary>
        /// конструктор
        /// </summary>
        /// <param name="startPosition"> стартовая позиция врага </param>
        /// <param name="maxWidth"> на поля, по которому танк может перемещаться </param>
        /// <param name="maxHeight"> высота  поля, по которому танк может перемещаться </param>
        public _Enemy(Point startPosition, int maxWidth, int maxHeight)
        {
            Box = new PictureBox()
            {
                Location = startPosition,
                Size = new Size(32, 32)
            };
            Velocity = 1;
 
            NewOrientation();
 
            Bullet = new _Bullet(maxWidth, maxHeight);
 
            this.maxWidth = maxWidth;
            this.maxHeight = maxHeight;
        }
 
        /// <summary>
        /// изменение направлерия движения врага
        /// </summary>
        void NewOrientation()
        {
            Random rnd = new Random();
 
            switch (rnd.Next(7))
            {
                case 0: Or = _Orientation.Down; break;
                case 1: Or = _Orientation.Up; break;
                case 2: Or = _Orientation.Down; break;
                case 3: Or = _Orientation.Left; break;
                case 4: Or = _Orientation.Down; break;
                case 5: Or = _Orientation.Right; break;
                case 6: Or = _Orientation.Down; break;
            }
        }
 
        int timeForNewOr;
        int timeForShoot;
        /// <summary>
        /// обновляем параметры
        /// </summary>
        /// <param name="timeInterval"> интервал обновления </param>
        /// <param name="blocks"> список препятствий </param>
        /// <param name="panel"> панель </param>
        public void Update(int timeInterval, ref List<_Block> blocks, ref Panel panel)
        {
            int dx = 0, dy = 0;
 
            if (Or == _Orientation.Up)
                dy = -Velocity * timeInterval;
            else
                if (Or == _Orientation.Down)
                    dy = Velocity * timeInterval;
                else
                    if (Or == _Orientation.Left)
                        dx = -Velocity * timeInterval;
                    else
                        if (Or == _Orientation.Right)
                            dx = Velocity * timeInterval;
 
            bool intersect = false;
            Rectangle boxRect = new Rectangle(Box.Location, Box.Size);
            boxRect.Offset(dx, dy);
 
            Box.Image = Rotation();
 
            foreach (_Block block in blocks)
            {
                Rectangle rect = new Rectangle(block.Box.Location, block.Box.Size);
                if (RectIntersect(rect, boxRect))
                    intersect = true;
            }
 
            if (boxRect.Left > 0 && boxRect.Right < maxWidth && boxRect.Top > 0 && boxRect.Bottom < maxHeight && !intersect)
            {
                Box.Location = boxRect.Location;
            }

            timeForShoot++;
            if (timeForShoot > maxWidth / Bullet.Velocity)
            {
                timeForShoot = 0;
                Bullet.Reset();
                StartShoot();
            }
 
            Bullet.Update(timeInterval, ref blocks, ref panel);
 
            timeForNewOr++;
            if (timeForNewOr == 100)
            {
                timeForNewOr = 0;
                NewOrientation();
            }
        }
 
        /// <summary>
        /// старт выстрела
        /// </summary>
        public void StartShoot()
        {
            Bullet.Shoot(Box, Or);
        }
 
        /// <summary>
        /// поворот изображения героя
        /// </summary>
        /// <returns> возвращает текущее изображение героя </returns>
        Image Rotation()
        {
            Image temp = x3004.Properties.Resources.heroImage;
 
            switch (Or)
            {
                case _Orientation.Up: break;
                case _Orientation.Down: temp.RotateFlip(RotateFlipType.Rotate180FlipNone); break;
                case _Orientation.Left: temp.RotateFlip(RotateFlipType.Rotate270FlipNone); break;
                case _Orientation.Right: temp.RotateFlip(RotateFlipType.Rotate90FlipNone); break;
            }
 
            return temp;
        }
 
        /// <summary>
        /// проверка прямоугольников на пересечение
        /// </summary>
        /// <param name="rect1"> 1 прямоугольник </param>
        /// <param name="rect2"> 2 прямоугольник </param>
        /// <returns> true - пересекаются, false - не пересекаются </returns>
        bool RectIntersect(Rectangle rect1, Rectangle rect2)
        {
            bool intersect = false;
 
            if (rect1.Left >= rect2.Left && rect1.Left <= rect2.Right && rect1.Top >= rect2.Top && rect1.Top <= rect2.Bottom
               || rect1.Left >= rect2.Left && rect1.Left <= rect2.Right && rect1.Bottom >= rect2.Top && rect1.Bottom <= rect2.Bottom
               || rect1.Right >= rect2.Left && rect1.Right <= rect2.Right && rect1.Top >= rect2.Top && rect1.Top <= rect2.Bottom
               || rect1.Right >= rect2.Left && rect1.Right <= rect2.Right && rect1.Bottom >= rect2.Top && rect1.Bottom <= rect2.Bottom)
                intersect = true;
 
            return intersect;
        }
    }
/// <summary>
    /// тип препятствия
    /// </summary>
    enum _BlockType
    {
        Brick,
        Concrete
    }
 
    class _Block
    {
        public PictureBox Box { get; set; }  //препятствие
        public _BlockType BlockType { get; set; }  //тип препятствия
 
        /// <summary>
        /// конструктор
        /// </summary>
        /// <param name="location"> положение препятствия </param>
        /// <param name="blockType"> тип препятствия </param>
        public _Block(Point location, _BlockType blockType)
        {
            Box = new PictureBox()
            {
                Location = location,
                Size = new Size(16, 16)
            };
            switch (blockType)
            {
                case _BlockType.Brick: Box.Image = x3004.Properties.Resources.brickImage; break;
            }
        }
    }
    enum _Orientation
    {
        Up,
        Down,
        Left,
        Right
    }
 
    public partial class Form1 : Form
    {
        Button
            startButton,
            exitButton;
 
        static Panel panel;
        Timer timer;
 
        _Hero
            player1;
 
        List<_Enemy> enemys;
 
        List<_Block> blocks;
        int currentLevel;
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            ClientSize = new System.Drawing.Size(650,490);
 
            panel = new Panel()
            {
                Location = new Point(5, 5),
                Size = new Size(ClientSize.Width - 10, ClientSize.Height - 10)
            };
            Controls.Add(panel);
 
            int x = panel.Width / 2 - 50, y = panel.Height / 2 - 30;
 
            startButton = new Button()
            {
                Location = new Point(x, y),
                Size = new Size(100, 25),
                Text = "start"
            };
            startButton.Click += new EventHandler(startButton_Click);
 
            y += 40;
 
            exitButton = new Button()
            {
                Location = new Point(x, y),
                Size = startButton.Size,
                Text = "exit"
            };
            exitButton.Click += new EventHandler(exitButton_Click);
 
            panel.Controls.AddRange(new Control[] { startButton, exitButton });
 
            startRects = new Rectangle[3] 
            { 
                new Rectangle(5, 5, 32, 32), 
                new Rectangle(panel.Width / 2 - 16, 5, 32, 32), 
                new Rectangle(panel.Width - 37, 5, 32, 32) 
            };
 
            timer = new Timer();
            timer.Interval = 1;
            timer.Tick += new EventHandler(Update);
        }
 
        void exitButton_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
 
        void startButton_Click(object sender, EventArgs e)
        {
            startButton.Enabled= startButton.Visible=  exitButton.Enabled=exitButton.Visible=false;
            player1 = new _Hero(new Point(panel.Width / 2 - 16, panel.Height - 40), panel.Width, panel.Height);
            panel.Controls.AddRange(new Control[] { player1.Box, player1.Bullet.Box });
 
            enemys = new List<_Enemy>();
            _Enemy enemy = new _Enemy(new Point(5, 5), panel.Width, panel.Height);
            enemys.Add(enemy);
            panel.Controls.AddRange(new Control[] { enemy.Box, enemy.Bullet.Box });

            currentLevel = 1;
            CreateLevel(currentLevel);
 
            timer.Start();
        }
 
        /// <summary>
        /// загрузка уровня
        /// </summary>
        /// <param name="currentLevel"> загружаемый уровень </param>
        private void CreateLevel(int currentLevel)
        {
            int x = 0, y = 0;
            blocks = new List<_Block>();
 
            string filePath = @"levels/level" + currentLevel.ToString() + ".txt";
            string[] text = File.ReadAllLines(filePath);
 
            foreach (string s in text)
            {
                foreach (char c in s)
                {
                    if (c == 'X')
                        blocks.Add(new _Block(new Point(x, y), _BlockType.Brick));
                    x += 16;
                }
                x = 0;
                y += 16;
            }
 
            foreach (_Block block in blocks)
            {
                panel.Controls.Add(block.Box);
            }
        }
 
        int timeForNewEnemy;
        public void Update(object sender, EventArgs e)
        {
            player1.Update(timer.Interval, ref blocks, ref panel);
 
            foreach (_Enemy enemy in enemys)
            {
                enemy.Update(timer.Interval, ref blocks, ref panel);
            }
 
            timeForNewEnemy++;
            if (timeForNewEnemy == 100)
            {
                timeForNewEnemy = 0;
                _Enemy enemy = new _Enemy(EnemyStartPoint(), panel.Width, panel.Height);
                enemys.Add(enemy);
                panel.Controls.AddRange(new Control[] { enemy.Box, enemy.Bullet.Box });
 
                currentStartPoint++;
                if (currentStartPoint == 3)
                    currentStartPoint = 0;
            }
        }
 
        protected override void OnKeyDown(KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Up:
                    {
                        StartRun(player1, _Orientation.Up);
                        break;
                    }
 
                case Keys.Down:
                    {
                        StartRun(player1, _Orientation.Down);
                        break;
                    }
 
                case Keys.Left:
                    {
                        StartRun(player1, _Orientation.Left);
                        break;
                    }
 
                case Keys.Right:
                    {
                        StartRun(player1, _Orientation.Right);
                        break;
                    }
 
                case Keys.M:
                    {
                        if (!player1.Bullet.IsRunning)
                            player1.StartShoot();
                        break;
                    }
            }
 
            base.OnKeyDown(e);
        }
 
        protected override void OnKeyUp(KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Up:
                case Keys.Down:
                case Keys.Left:
                case Keys.Right:
                    {
                        player1.IsRunning = false; 
                        break;
                    }
            }
 
            base.OnKeyUp(e);
        }
 
        /// <summary>
        /// старт движения игрока
        /// </summary>
        /// <param name="player"> игрок </param>
        /// <param name="orientation"> направление </param>
        void StartRun(_Hero player, _Orientation orientation)
        {
            player.IsRunning = true;
            player.Or = orientation;
        }
 
        int currentStartPoint;
        Rectangle[] startRects;
        /// <summary>
        /// выбор стартовой позиции врага
        /// </summary>
        /// <returns> возвращает стартовую позицию врага </returns>
        Point EnemyStartPoint()
        {
            bool intersect = false;
 
            do
            {
                intersect = false;
                foreach (_Enemy enemy in enemys)
                {
                    if (RectIntersect(new Rectangle(enemy.Box.Location, enemy.Box.Size), startRects[currentStartPoint]))
                        intersect = true;
                }
                if (intersect)
                    currentStartPoint++;
                if (currentStartPoint == 3)
                    currentStartPoint = 0;
            } while (intersect != false);
 
            return startRects[currentStartPoint].Location;
        }
 
        /// <summary>
        /// проверка прямоугольников на пересечение
        /// </summary>
        /// <param name="rect1"></param>
        /// <param name="rect2"></param>
        /// <returns></returns>
        bool RectIntersect(Rectangle rect1, Rectangle rect2)
        {
            bool intersect = false;
 
            if (rect1.Left >= rect2.Left && rect1.Left <= rect2.Right && rect1.Top >= rect2.Top && rect1.Top <= rect2.Bottom
               || rect1.Left >= rect2.Left && rect1.Left <= rect2.Right && rect1.Bottom >= rect2.Top && rect1.Bottom <= rect2.Bottom
               || rect1.Right >= rect2.Left && rect1.Right <= rect2.Right && rect1.Top >= rect2.Top && rect1.Top <= rect2.Bottom
               || rect1.Right >= rect2.Left && rect1.Right <= rect2.Right && rect1.Bottom >= rect2.Top && rect1.Bottom <= rect2.Bottom)
                intersect = true;
 
            return intersect;
        }
    }
как избавиться от торможения? может что то сделать по другому?

Решение задачи: «Игра танки тормозит при появлении 6 и более врагов»

textual
Листинг программы
         public void CreateLevel(int level)
        {
            blocks = new List<_Block>();
            string levelFilePath = @"levels/level" + level + ".txt";
            string[] fileStr = File.ReadAllLines(levelFilePath);
 
            int x=0,y=0;
 
            foreach (string s in fileStr)
            {
                foreach (char c in s)
                {
                    if (c=='X')
                    {
                        _Block block = new _Block(new Point(x, y), _BlockType.Brick);
                        blocks.Add(block);
                    }
 
                    x += 16;
                }
                x = 0;
                y += 16;
            }
            blocks.Add(new _Block(panel.Width, panel.Height));
        }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

13   голосов , оценка 4 из 5
Похожие ответы