2

我正在使用 Windows 窗体应用程序编写自己的游戏。应该是多人游戏。每个球员都可以控制砖块将球保持在球场上,但问题是两名球员不能同时按下控制键。在第一个玩家的移动过程中,第二个玩家每按一次键,第一个玩家的积木就会停止。但是,如果他们同时按下键,两块砖都会移动。我使用了KeyDown事件:

  private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.W && one.BrickLocationY > 0)
        {
            one.BrickLocationY -= 17;
        }
        if (e.KeyCode == Keys.S && one.BrickLocationY + Brick.BrickHeight < screenHeight)
        {
            one.BrickLocationY += 17;
        }
        if (e.KeyCode == Keys.Up)
        {
            two.BrickLocationY -= 17;
        }
        if (e.KeyCode == Keys.Down && two.BrickLocationY + Brick.BrickHeight < screenHeight)
        {
            two.BrickLocationY += 17;
        }
        if (e.KeyCode == Keys.Escape)
        {
            Application.Exit();
        }
    }

好的,这让我可以上下移动砖块。如果我同时按下两个键,两块砖都会朝想要的方向移动。砖块是在间隔设置为 1 的计时器滴答触发的绘制事件上绘制的。

  private void Form1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.DrawEllipse(ellipsePen, x, y, ballSize, ballSize );
        e.Graphics.FillEllipse(Brushes.White ,x+1, y+1, ballSize, ballSize);

        e.Graphics.FillRectangle(Brushes.White, one.BrickLocationX+1, one.BrickLocationY+1, Brick.BrickWidth, Brick.BrickHeight);

        e.Graphics.FillRectangle(Brushes.White, two.BrickLocationX+1, two.BrickLocationY+1, Brick.BrickWidth, Brick.BrickHeight);
    }

我也尝试过结合KeyUpKeyPress来做到这一点,但没有成功。我唯一想到的就是穿线砖,但不知道该怎么做。我有什么方法可以在没有线程的情况下处理这样的多人游戏控件?

PS键盘能够同时处理多个按钮。

4

2 回答 2

1

当 KeyDown 事件触发时,您需要检查每次按下了哪些按钮。是我在快速搜索该主题时发现的。

using System; 
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Collections.Generic;

namespace WindowsFormsApplication1
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
      this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(Form1_FormClosing);
      tm.Tick += new System.EventHandler(DoSomethingWithKeyboardInput);
      this.Load += new System.EventHandler(Form1_Load);
      textBox1.KeyDown += new System.Windows.Forms.KeyEventHandler(textbox1_KeyDown);
      textBox1.KeyUp += new System.Windows.Forms.KeyEventHandler(textbox1_KeyDown);
    }

    private Timer tm = new Timer();
    private List<System.Windows.Forms.Keys> MovementKeys = new List<System.Windows.Forms.Keys>();
    private _MyInputKeys MyInputKeys = new _MyInputKeys();

    private struct _MyInputKeys
    {
      public bool Jump;
      public bool Left;
      public bool Right;
    }

    private void Form1_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
    {
      tm.Stop();
    }

    public void DoSomethingWithKeyboardInput(object sender, EventArgs e)
    {
      textBox1.Text = (MyInputKeys.Left ? "(left)" : "") + 
        (MyInputKeys.Right ? "(right)" : "") + (MyInputKeys.Jump ? "(jump)" : "");
    }

    private void Form1_Load(object sender, System.EventArgs e)
    {
      //define keys used for movement

      MovementKeys.Add(Keys.Up); //Jump ?
      MovementKeys.Add(Keys.Left); //Left Arrow - Move Left
      MovementKeys.Add(Keys.Right); //Rigth Arrow - Move Right
      tm.Interval = 50;
      tm.Start();
    }

    private void textbox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
    {
      if (MovementKeys.IndexOf(e.KeyCode) != -1)
      {
        e.Handled = true;
        MyInputKeys.Jump = IsKeyDown(Keys.Up);
        MyInputKeys.Left = IsKeyDown(Keys.Left);
        MyInputKeys.Right = IsKeyDown(Keys.Right);
      }
    }

    public static bool IsKeyDown(Keys key)
    {
      return (GetKeyState(Convert.ToInt16(key)) & 0X80) == 0X80;
    }
    /// <summary>
    ///  If the high-order bit is 1, the key is down; otherwise, it is up.
    ///  If the low-order bit is 1, the key is toggled. 
    ///  A key, such as the CAPS LOCK key, is toggled if it is turned on. 
    ///  The key is off and untoggled if the low-order bit is 0. 
    ///  A toggle key's indicator light (if any) on the keyboard will be on when 
    ///  the key is toggled, and off when the key is untoggled.
    /// </summary>
    /// <param name="nVirtKey"></param>
    [DllImport("user32.dll")]
    public extern static Int16 GetKeyState(Int16 nVirtKey);
  }
}
于 2013-09-06T15:18:34.810 回答
0

I believe you'll need to track this yourself. Basically on key down you recognize the w and consider it being held until key up releases the w. same with the s key.

Then in your run loop, you just look for what keys are active and do your direction logic there.

于 2013-09-06T15:11:05.183 回答