我正在嘗試使用 Winforms 在 C# 中創建一個游戲,其中形狀隨機出現,您必須盡快單擊形狀(一次一個)。
創建形狀后,會啟動一個計時器,該計時器會計算您單擊該形狀所花費的時間,然后單擊該形狀后,該形狀將被洗掉。我在洗掉形狀部分時遇到問題。我有計時器,我讓它等待計時器停止,但是每當我嘗試洗掉形狀時,我都會在該行收到以下錯誤:g.clear(Color.black).
System.ArgumentException:“引數無效。”
完整的錯誤跟蹤是:
System.ArgumentException
HResult=0x80070057
Message=Parameter is not valid.
Source=System.Drawing
StackTrace:
at System.Drawing.Graphics.Clear(Color color)
at NumbersGame.ShapesRound.<ShapesWindow_Paint>d__9.MoveNext() in
C:\Users\Matthew\Desktop\AHProject\NumbersGame\NumbersGame\ShapesRound.cs:line 92
這是我所有的游戲代碼:
namespace NumbersGame
{
public partial class ShapesRound : UserControl
{
public ShapesRound()
{
InitializeComponent();
}
public bool GameStarted = false;
public GraphicsPath path;
public Rectangle currentShape = new Rectangle();
Stopwatch timer = new Stopwatch();
public bool timerIsRunning = false;
public bool ShapeClicked(Point location)
{
bool clicked = false;
if (currentShape.Contains(location))
{
clicked = true;
}
return clicked;
}
private void ShapesRound_Load(object sender, EventArgs e)
{
path = new GraphicsPath();
nameBox.Text = "Matthew";
// nameBox.Text = Welcome.name;
scoreBox.Text = Welcome.totalScore.ToString();
}
private void ShapesRound_MouseDown(object sender, MouseEventArgs e)
{
if (ShapeClicked(e.Location))
{
// MessageBox.Show("CLICKED");
//end timer
timer.Stop();
var timeP = timer.ElapsedMilliseconds / 1000;
// MessageBox.Show(timeP.ToString() " SECONDS");
}
}
private async void ShapesWindow_Paint(object sender, PaintEventArgs e)
{
if (GameStarted == false) { return; } //if the game hasnt started (ie the start button has not been clicked), do nothing
else
{
using (Graphics g = e.Graphics)
{
g.SmoothingMode = SmoothingMode.AntiAlias;
currentShape = new Rectangle(10, 100, 75, 75); //assign coordinates to the global CurrentShape variable
g.FillEllipse(new SolidBrush(Color.Black), currentShape);
//INVALID PAARAM?//fill the currentshape on screen
//start a timer
timer.Start(); //start a timer
while (timer.IsRunning) //while the timer is running (ie shape isnt clicked) wait
{
await Task.Delay(500);
}
g.Clear(Color.Black);
// currentShape = null;
// MessageBox.Show("DELETING");
var bckCol = ShapesWindow.BackColor;
// e.Graphics.FillEllipse(new SolidBrush(bckCol), currentShape);
// e.Graphics.Clear(Color.Black); //INVALID PAARAM?
ShapesWindow.Refresh();
}
}
}
private void StartButton_Click(object sender, EventArgs e)
{
GameStarted = true;
ShapesWindow.Paint = new PaintEventHandler(ShapesWindow_Paint);
ShapesWindow.Refresh();
}
}
}
uj5u.com熱心網友回復:
如果我理解正確,您正在繪制一個形狀。然后,當單擊該形狀時,您要洗掉該形狀并繪制一個新形狀,然后重復該程序。
如果我是對的,那就顛倒你的邏輯。現在,您正在繪制一個形狀,等待,然后嘗試清除。但你可以先清除,然后繪制形狀。這樣,當您檢測到點擊時,您只需觸發重繪 。
private void ShapesRound_MouseDown(object sender, MouseEventArgs e)
{
if (ShapeClicked(e.Location))
{
// MessageBox.Show("CLICKED");
//end timer
timer.Stop();
var timeP = timer.ElapsedMilliseconds / 1000;
// MessageBox.Show(timeP.ToString() " SECONDS");
ShapesWindow.Refresh();
}
}
private async void ShapesWindow_Paint(object sender, PaintEventArgs e)
{
if (GameStarted == false) { return; } //if the game hasnt started (ie the start button has not been clicked), do nothing
else
{
using (Graphics g = e.Graphics)
{
g.Clear(Color.Black);
g.SmoothingMode = SmoothingMode.AntiAlias;
currentShape = new Rectangle(10, 100, 75, 75); //assign coordinates to the global CurrentShape variable
g.FillEllipse(new SolidBrush(Color.Black), currentShape);
//start a timer
timer.Start(); //start a timer
}
}
}
如果您不想繪制新形狀,請宣告一個bool值,告訴它不要繪制新形狀。每當您不想繪制新值時設定它,并在清除后在您的繪制事件中檢查它,例如:
...
g.Clear(Color.Black);
if (dontDrawNewShape) return;
...
uj5u.com熱心網友回復:
這并不是對您最初問題的真正答案,而是對您的評論的回答:
也許我在這里遺漏了一些東西。我試圖在單擊最后一個物件時繪制一個物件。這涉及洗掉第一個物件,并在單擊舊物件時繪制一個新物件。你建議我怎么做?以非“argh”誘導方式。
正如 rene 和 Flydog57 指出的那樣,您的方法非常不標準。與其從您所在的位置開始,讓我僅擴展他們的評論并解釋構建 Windows 表單應用程式(如您正在嘗試構建的應用程式)的標準方法。
- 在控制元件的成員變數中跟蹤控制元件的“狀態”(哪些物件可見等)。
- 該
Paint事件僅用于一次重繪 控制元件或其中的一部分。如果發生會影響控制元件外觀的事情,請Invalidate()從導致狀態更改的任何事件處理程式呼叫,并信任 Windows 在方便時通過 Paint 事件通知您的控制元件。注意:Invalidate()不會像Refresh()dos那樣導致同步繪制(這通常是過分熱心的);當 Windows 完成處理更高優先級的訊息(如滑鼠移動)時,它會排隊重繪。 - 請記住,
Graphics您在Paint處理程式中傳遞的物件僅適用于一次重繪。一旦您從該處理程式回傳,或者像在您的代碼中那樣,您開始一個新的重繪(就像您對 所做的那樣Refresh,使您的Paint處理程式遞回,這是它如此引人入勝的一部分),它就會變得無效。 - 請記住,您在
Paint事件處理程式中繪制的內容不是持久的。也就是說,如果有東西遮擋了視窗,或者您將它拖到螢屏外,或者發生了其他任何事情導致分配給您的控制元件的視頻記憶體無效,Windows 將觸發該Paint事件讓您重繪之前的任何內容。這是您希望在成員變數中跟蹤狀態的另一個原因——您的控制元件可能會被要求在其狀態未更改時重新繪制自身。您不能依靠顯存來準確地表示過去繪制的內容。 - 如果需要影片或在經過一段時間后發生某些事情,請創建 a
System.Windows.Forms.Timer作為成員變數,注冊Tick處理程式和Start()計時器。處理程式應根據Tick需要更新控制元件的持久狀態并呼叫Invalidate(). 如果計時器用于一次性操作,Stop()則它。 - 對于您繪制的形狀上的命中測驗,處理控制元件
Click或MouseDown事件并針對您用于保持狀態的成員變數進行測驗。如果您最后繪制的形狀是 aRectangle,則將其保存Rectangle在成員變數中并從 . 測驗滑鼠EventArgs位置Rectangle。如果是時候繪制不同的形狀,請創建一個表示新形狀的新持久物件并呼叫Invalidate().
如果您對此一般大綱有任何疑問,請告訴我,我會相應地更新我的答案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/418015.html
標籤:
