2017-02-01 3 views
3

Я делаю небольшую программу, в которой два прямоугольника движутся вокруг дорожки гоночного автомобиля. Когда я запускаю программу, все идет так, как планировалось, и я могу перемещать прямоугольники вокруг трека, используя клавиши со стрелками для одного и A, S, D, W для другого. Проблема в том, что я, если я перемещаю один со стрелками, и пытаюсь нажать D, чтобы переместить другой прямоугольник вправо в одно и то же время, тот, который перемещается с помощью клавиш со стрелками, останавливается. Цель состоит в том, чтобы иметь возможность двигаться одновременно. Что мне делать?C#: Перемещение двух прямоугольников в одно и то же время с разными клавишами

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

namespace Race_Game 
{ 
     public partial class Form1 : Form 
     { 
      private int x1 = 24; 
      private int y1 = 16; 
      private int size1 = 115; 
      private int size2 = 50; 
      private Rectangle _rect1; 
      private int x2 = 24; 
      private int y2 = 74; 
      private int size3 = 115; 
      private int size4 = 50; 
      private Rectangle _rect2; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void pictureBox1_Paint_1(object sender, PaintEventArgs e) 
     { 
      _rect1 = new Rectangle(x1, y1, size1, size2); 
      e.Graphics.FillRectangle(Brushes.Red, _rect1); 
      _rect2 = new Rectangle(x2, y2, size3, size4); 
      e.Graphics.FillRectangle(Brushes.Black, _rect2); 
     } 

     private void pictureBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) 
     { 
      this.KeyPreview = true; 

      this.KeyDown += new KeyEventHandler(Form1_KeyDown); 
     } 

     private void Form1_KeyDown(object sender, KeyEventArgs e) 
     { 
      if (e.KeyData == Keys.Right) 
      { 
       x1 += 15; 
      } 
      if (e.KeyData == Keys.Left) 
      { 
       x1 -= 15; 
      } 
      if (e.KeyData == Keys.Up) 
      { 
       y1 -= 15; 
      } 
      if (e.KeyData == Keys.Down) 
      { 
       y1 += 15; 
      } 
      if (e.KeyData == Keys.D) 
      { 
       x2 += 15; 
      } 
      if (e.KeyData == Keys.A) 
      { 
       x2 -= 15; 
      } 
      if (e.KeyData == Keys.W) 
      { 
       y2 -= 15; 
      } 
      if (e.KeyData == Keys.S) 
      { 
       y2 += 15; 
      } 
     } 

     private void timer1_Tick(object sender, EventArgs e) 
     { 
      pictureBox1.Invalidate(); 
     } 
    } 
} 

Visual Studio Сформирован Design Код:

namespace Race_Game 
{ 
    partial class Form1 
    { 
    /// <summary> 
    /// Required designer variable. 
    /// </summary> 
    private System.ComponentModel.IContainer components = null; 

    /// <summary> 
    /// Clean up any resources being used. 
    /// </summary> 
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
    protected override void Dispose(bool disposing) 
    { 
     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

    #region Windows Form Designer generated code 

    /// <summary> 
    /// Required method for Designer support - do not modify 
    /// the contents of this method with the code editor. 
    /// </summary> 
    private void InitializeComponent() 
    { 
     this.components = new System.ComponentModel.Container(); 
     System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); 
     this.timer1 = new System.Windows.Forms.Timer(this.components); 
     this.pictureBox1 = new System.Windows.Forms.PictureBox(); 
     ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); 
     this.SuspendLayout(); 
     // 
     // timer1 
     // 
     this.timer1.Enabled = true; 
     this.timer1.Interval = 1; 
     this.timer1.Tick += new System.EventHandler(this.timer1_Tick); 
     // 
     // pictureBox1 
     // 
     this.pictureBox1.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pictureBox1.BackgroundImage"))); 
     this.pictureBox1.Location = new System.Drawing.Point(0, 0); 
     this.pictureBox1.Name = "pictureBox1"; 
     this.pictureBox1.Size = new System.Drawing.Size(1944, 1066); 
     this.pictureBox1.TabIndex = 0; 
     this.pictureBox1.TabStop = false; 
     this.pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(this.pictureBox1_Paint_1); 
     this.pictureBox1.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.pictureBox1_PreviewKeyDown); 
     // 
     // Form1 
     // 
     this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
     this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
     this.ClientSize = new System.Drawing.Size(1916, 1053); 
     this.Controls.Add(this.pictureBox1); 
     this.Name = "Form1"; 
     this.Text = "Form1"; 
     this.WindowState = System.Windows.Forms.FormWindowState.Maximized; 
     this.Paint += new System.Windows.Forms.PaintEventHandler(this.pictureBox1_Paint_1); 
     this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown); 
     ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); 
     this.ResumeLayout(false); 

    } 

    #endregion 

    private System.Windows.Forms.Timer timer1; 
    private System.Windows.Forms.PictureBox pictureBox1; 
} 

}

+0

Это общая проблема дизайна. Вопрос должен оставаться открытым. – ja72

+0

'private Rectangle _rect1 = new Rectangle();' не требуется, потому что 'Rectangle' - это тип значения, а также он перезаписывается при событии рисования. – ja72

+0

Спасибо за подсказку, но это не решило проблему:/@ ja72 – jholsch29

ответ

3

То, что я решил сделать это на ключ вниз, чтобы назначить скорость, и на замочную до нуля скорость. Это и объединить координаты x и y в Point и Size объектов.

Вы можете перемещать коробки независимо и непрерывно.

scr

public partial class Form1 : Form 
{ 
    const int velocity = 15; 
    Point position_A = new Point(24, 16); 
    Point position_B = new Point(24, 74); 
    Size size_A = new Size(115, 50); 
    Size size_B = new Size(115, 50); 
    Size velocity_A = new Size(0, 0); 
    Size velocity_B = new Size(0, 0); 

    public Rectangle Shape_A 
    { 
     get 
     { 
      return new Rectangle(position_A, size_A); 
     } 
    } 
    public Rectangle Shape_B 
    { 
     get 
     { 
      return new Rectangle(position_B, size_B); 
     } 
    } 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void pictureBox1_Resize(object sender, EventArgs e) 
    { 
     pictureBox1.Refresh(); 
    } 

    private void pictureBox1_Paint(object sender, PaintEventArgs e) 
    { 
     e.Graphics.FillRectangle(Brushes.Red, Shape_A); 
     e.Graphics.FillRectangle(Brushes.Black, Shape_B); 
    } 

    private void timer1_Tick(object sender, EventArgs e) 
    { 
     this.position_A+=velocity_A; 
     this.position_B+=velocity_B; 
     pictureBox1.Refresh(); 
    } 

    private void Form1_KeyDown(object sender, KeyEventArgs e) 
    { 
     Debug.WriteLine($"KeyDown Code:{e.KeyCode}"); 
     switch (e.KeyCode) 
     { 
      case Keys.Up: 
       this.velocity_A=new Size(velocity_A.Width, -velocity); 
       break; 
      case Keys.Down: 
       this.velocity_A=new Size(velocity_A.Width, +velocity); 
       break; 
      case Keys.Left: 
       this.velocity_A=new Size(-velocity, velocity_A.Height); 
       break; 
      case Keys.Right: 
       this.velocity_A=new Size(+velocity, velocity_A.Height); 
       break; 
      case Keys.W: 
       this.velocity_B=new Size(velocity_B.Width, -velocity); 
       break; 
      case Keys.S: 
       this.velocity_B=new Size(velocity_B.Width, +velocity); 
       break; 
      case Keys.A: 
       this.velocity_B=new Size(-velocity, velocity_B.Height); 
       break; 
      case Keys.D: 
       this.velocity_B=new Size(+velocity, velocity_B.Height); 
       break; 
      case Keys.Escape: 
       this.Close(); 
       break; 
     } 
     pictureBox1.Invalidate(); 
    } 

    private void Form1_KeyUp(object sender, KeyEventArgs e) 
    { 
     switch (e.KeyCode) 
     { 
      case Keys.Up: 
      case Keys.Down: 
       this.velocity_A=new Size(velocity_A.Width, 0); 
       break; 
      case Keys.Right: 
      case Keys.Left: 
       this.velocity_A=new Size(0, velocity_A.Height); 
       break; 
      case Keys.W: 
      case Keys.S: 
       this.velocity_B=new Size(velocity_B.Width, 0); 
       break; 
      case Keys.A: 
      case Keys.D: 
       this.velocity_B=new Size(0, velocity_B.Height); 
       break; 
     } 
    } 
} 
+0

Я пытался выяснить, могу ли я обойти утверждения get, но я решил, что мой код будет идентичен вашему, чтобы быть в безопасности. Кроме того, я думаю, что я сформулировал свой вопрос странно, и было возможно неправильное толкование. Моя цель, например, иметь возможность удерживать клавишу D и перемещать черный прямоугольник вправо, в то же время удерживая клавишу со стрелкой вправо, и красный прямоугольник перемещается вправо одновременно с черным прямоугольником.Я могу снова проверить, чтобы убедиться, что у меня есть все, что вы сказали, но на данный момент, похоже, не работает @ ja72 – jholsch29

+0

Теперь я понимаю, в чем проблема. Попробуйте этот новый метод из моего пересмотренного кода выше. – ja72

+0

Спасибо! Я понимаю это и могу использовать его, но как бы я мог сделать это так, чтобы прямоугольники не двигались по диагонали, если стрелка вверх нажата, пока прямоугольник движется горизонтально? @ ja72 – jholsch29

1

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

Для следующей примерной установки я использую форму с двумя элементами NumericUpDown («numericUpDownA» и «numericUpDownLeft») и таймер «timerCheckKeyboard» с интервалом 100 мс и установлен в режим разрешен. Таймер имеет обработчик события OnClick «timerCheckKeyboard_Tick».

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    [DllImport("USER32.dll")] 
    static extern short GetKeyState(int nVirtKey); 


    private const int KEY_PRESSED = 0x8000; 

    private const int VK_W = (int)'W'; 
    private const int VK_A = (int)'A'; 
    private const int VK_S = (int)'S'; 
    private const int VK_D = (int)'D'; 
    private const int VK_LEFT = 0x25; 
    private const int VK_UP = 0x26; 
    private const int VK_RIGHT = 0x27; 
    private const int VK_DOWN = 0x28; 

    private bool IsKeyPressed(int key) 
    { 
     return (GetKeyState(key) & KEY_PRESSED) != 0; 
    } 

    private void timerCheckKeyboard_Tick(object sender, EventArgs e) 
    { 
     if (IsKeyPressed(VK_A)) 
     { 
      numericUpDownA.Value++; 
     } 

     if (IsKeyPressed(VK_LEFT)) 
     { 
      numericUpDownLeft.Value++; 
     } 
    } 
} 

Значение в элементе NumericUpDownA увеличивается при нажатии клавиши A. Значение в элементе NumericUpDownLeft увеличивается при нажатии клавиши курсора влево. Вы можете одновременно нажать «A» и «Cursor left», а значения в обоих элементах NumericUpDown увеличатся.


Обратите внимание, что это будет работать даже при нажатии клавиш, пока ваше приложение не является активным. Таким образом, вы можете протестировать это сначала в Timer-Tick-Event или полностью отключить таймер, в то время как форма не имеет фокуса. (События Activate, Deactivate формы).

Смежные вопросы