THEmaker2 Ответов: 2

Как заставить пистолет стрелять несколькими пулями, как пулемет, если вы нажмете клавишу?


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp17
    {
        public partial class Form1 : Form
        {
            public Form1()
            {


                InitializeComponent();
                CenterToScreen();
                Bullet.Visible = false;
            }
           ;
            Boolean Up, Lef, Righ, Down;
            private void Form1_KeyDown(object sender, KeyEventArgs e)
                    
        
            if (e.KeyCode == Keys.Z)
            {
               Bullet.Location = new Point(Gun.Location.X + 7,Gun.Location.Y - 20);
                Bullet.Visible = true;

            }
            if (e.KeyCode == Keys.Right)
            {
                Righ = true;
                Gun.Left = Gun.Left + 8;

            }
            if (e.KeyCode == Keys.Up)
            {
                Up = true;
                Gun.Top = Gun.Top + -8;
            }
            if (e.KeyCode == Keys.Down)
            {
                Down = true;
                Gun.Top =Gun.Top + 8;
            }
            if (e.KeyCode == Keys.Left)
            {
                Lef = true;
                Gun.Left = Gun.Left + -8;

            }
        }
        private void timer1_Tick(object sender, EventArgs e)
        {

            Bullet.Top -= 20;
        }

ну ... это мой код, и я хочу, чтобы этот "пистолет" стрелял несколькими пулями, когда вы нажимаете клавишу.

Что я уже пробовал:

Я пробовал некоторые сценарии ... но они стреляют только по одной пуле за раз, когда вы нажимаете и удерживаете клавишу. Я хочу, чтобы мой "пистолет" стрелял много пуль, как полностью автоматическая винтовка, когда вы нажимаете клавишу и держите ее.

F-ES Sitecore

Вам понадобится возможность иметь несколько пуль, и каждые "x" миллисекунд удержания ключа огня вы создаете новую пулю, которая имеет свое собственное положение. Вы можете держать экземпляры пули в списке, и каждый щелчок таймера проходит через список пуль и перемещает их\обнаруживает попадания и т. д.

THEmaker2

Ничего, если я попрошу вас дать мне пример кода?

THEmaker2

Спасибо за пример кода! Это работает, когда пуля представляет собой метку. Однако он делает ошибку, если я изменяю его на picturebox. Кроме того, всякий раз, когда я изменяю интервал timerControl или timerBullet interval...it останавливает проект и делает ошибку

2 Ответов

Рейтинг:
2

Ralf Meier

Я бы сделал это вот так :
С помощью кнопки вашего выбор вы установить переменную "ShotRepeater" истина с событием keydown-событие и присвоить ему значение false с клавиша вверх события.
Внутри вашего таймера-события вы проверяете, является ли "ShotRepeater" истинным, и если да, то выпускаете выстрел каждый тик таймера ...
Для этого ваш таймер-обработчик должен иметь только правильную скорость тика для вашей цели ...


THEmaker2

Что ж....Я попробовал...но ничего не вышло

Ralf Meier

В этом случае вы должны показать свой код, который не работает ...
В основном мое предложение работает так, как описано ...

THEmaker2

Ну...может быть, я не понял, о чем вы говорили ... не могли бы вы дать мне пример кода?

Ralf Meier

Не в данный момент - извините ... но я думаю, что мое описание уникально ...
Если это не работает для вас, мы должны посмотреть на ваш код ...

Рейтинг:
1

F-ES Sitecore

Базовый пример кода управления динамической коллекцией элементов

using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        private List<Bullet> Bullets;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Bullets = new List<Bullet>();

            timerControls.Interval = 500;
            timerControls.Start();

            timerBullets.Interval = 100;
            timerBullets.Start();

        }

        private void timerBullets_Tick(object sender, EventArgs e)
        {
            // we'll process the bullets on it's own thread to keep the UI thread free for input
            System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(ProcessBullets));
            t.Start();
        }

        private void ProcessBullets()
        {
            // update all bullets
            foreach (var b in Bullets)
            {
                b.Update();
            }

            var deadBullets = Bullets.Where(b => b.Destroy).ToList();
            if (deadBullets.Count == 0)
            {
                return;
            }

            // We use Invoke to run the code on the same thread that created the bullet
            deadBullets.First().BulletUI.Invoke((MethodInvoker)delegate { deadBullets.ForEach(b => this.Controls.Remove(b.BulletUI)); });
            Bullets.RemoveAll(b => b.Destroy);
        }

        private void timerControls_Tick(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine(System.Threading.Thread.CurrentThread.GetHashCode());
            Bullet b = new Bullet();
            // hard-coded position, this will be the position of your gun
            b.Location = new Point(10, 200);
            b.Speed = 10;

            // I'm using a label to represent the bullet, you can use an image or anything else
            Label lbl = new Label { Text = "X", Left = b.Location.X, Top = b.Location.Y };
            b.BulletUI = lbl;
            this.Controls.Add(lbl);
            Bullets.Add(b);
        }
    }

    public class Bullet
    {
        public Point Location { get; set; }
        public Label BulletUI { get; set; }
        public DateTime Created { get; set; }
        public int Speed { get; set; }
        public bool Destroy { get; private set; }

        public Bullet()
        {
            Created = DateTime.Now;
        }

        public void Update()
        {
            Location = new Point(Location.X, Location.Y - Speed);

            if (Location.Y <= 0 || (DateTime.Now - Created).TotalMilliseconds >= 5000)
            {
                Destroy = true;
                return;
            }

            // We use Invoke to run the code on the same thread that created the bullet
            BulletUI.Invoke((MethodInvoker)delegate { BulletUI.Left = Location.X; BulletUI.Top = Location.Y; });
        }
    }
}


THEmaker2

Спасибо!