2013-10-21 51 views
1

對於有關此遊戲的常見問題,我很抱歉,但我不知道在哪裏以及如何在我的遊戲中實現gameloop。我想gameloop這樣的工作:在Windows窗體中實現gameloop

Settings(); 
if (startClicked == true) 
{ 
    Spawn(); 
} 
while (enemyKilled == true) 
{ 
    Spawn(); 
} 

這裏是我的代碼:

public partial class Form1 : Form 
{ 
    public int score1 = 0; 
    public PictureBox enemy = new PictureBox(); 
    public PictureBox missile = new PictureBox(); 
    public int enemyX; 
    public int enemyY; 
    public int missileX; 
    public int missileY; 
    public bool enemyKilled; 
    public bool startClicked; 
    public Form1() 
    { 
     InitializeComponent(); 
     logo.Visible = false; 
     startbutton.Visible = false; 
     spaceship.Visible = false; 
     score.Visible = false; 
     labelEnemyX.Visible = false; 
     labelEnemyY.Visible = false; 
     labelMissileX.Visible = false; 
     labelMissileY.Visible = false; 

    } 

    private void Settings() 
    { 
     logo.Visible = true; 
     startbutton.Visible = true; 
     score.Text = Convert.ToString(score1); 
    } 

    private void Spawn() 
    { 
     enemy.Visible = true; 
     missile.Visible = true; 
     System.Timers.Timer enemyMove = new System.Timers.Timer(); 
     enemyMove.Interval = 100; 
     Random enemyPosition = new Random(); 
     int enemyX = enemyPosition.Next(30, 400); 
     int enemyY = enemy.Location.Y; 
     enemy.Location = new Point(enemyX, 0); 
     enemy.Image = WindowsFormsApplication16.Properties.Resources.Enemy2; 
     enemy.Width = 36; 
     enemy.Height = 29; 
     this.Controls.Add(enemy); 
     enemyMove.Elapsed += (sender, args) => 
      { 
       enemy.Location = new Point(enemyX, enemy.Location.Y + 2); 
       enemyX = enemy.Location.X; 
       enemyY = enemy.Location.Y; 
       labelEnemyX.Text = Convert.ToString(enemyX); 
       labelEnemyY.Text = Convert.ToString(enemyY); 
       if (enemyY <= -10) 
       { 
        enemyKilled = false; 
       } 
      }; enemyMove.Start(); 
    } 

    private void AddScore() 
    { 
     if (enemyKilled == true) 
     { 
      score1++; 
      score.Text = Convert.ToString(score1); 
     } 
    } 

    private void MissileMove() 
    { 
     System.Timers.Timer missileMove = new System.Timers.Timer(); 
     missileMove.Interval = 30; 
     missileMove.Elapsed += (sender, args) => 
      { 
       if (missile.Location.Y >= -30) 
       { 
        missile.Location = new Point(missile.Location.X, missile.Location.Y - 15); 
        missileX = missile.Location.X; 
        missileY = missile.Location.Y; 
        labelMissileX.Text = Convert.ToString(missileX); 
        labelMissileY.Text = Convert.ToString(missileY); 
        int enemyToMissileLocationX = Convert.ToInt32(labelEnemyX.Text); 
        int enemyToMissileLocationY = Convert.ToInt32(labelEnemyY.Text); 
        if ((missileX - enemyToMissileLocationX <= 20 && missileY - enemyToMissileLocationY <= 20 && missileX - enemyToMissileLocationX >= 0 && missileY - enemyToMissileLocationY >= 0) || (enemyToMissileLocationX - missileX <= 20 && enemyToMissileLocationY - missileY <= 20 && enemyToMissileLocationX - missileX >= 0 && enemyToMissileLocationY - missileY >= 0)) 
        { 
         missile.Visible = false; 
         enemy.Visible = false; 
         enemyKilled = true; 
        } 
       } 
      }; missileMove.Start(); 

    } 

    void Form1_Load(object sender, EventArgs e) 
    { 
     Settings(); 
     if (startClicked == true) 
     { 
      Spawn(); 
     } 
     while (enemyKilled == true) 
     { 
      Spawn(); 
     } 
    } 

    private void startbutton_Click(object sender, EventArgs e) 
    { 
     this.startClicked = true; 
     logo.Visible = false; 
     startbutton.Visible = false; 
     spaceship.Visible = true; 
     score.Visible = true; 
     startbutton.Enabled = false; 

    } 

    private void Form1_KeyDown(object sender, KeyEventArgs e) 
    { 
     if (e.KeyCode == Keys.Right) 
     { 
      if (spaceship.Location.X <= 370) 
      { 
       spaceship.Location = new Point(spaceship.Location.X + 10, spaceship.Location.Y); 
      } 
     } 
     if (e.KeyCode == Keys.Left) 
     { 
      if (spaceship.Location.X >= 0) 
      { 
       spaceship.Location = new Point(spaceship.Location.X - 10, spaceship.Location.Y); 
      } 
     } 
     if (e.KeyCode == Keys.Space) 
     { 
      missile.Image = WindowsFormsApplication16.Properties.Resources.Missile; 
      missile.Height = 42; 
      missile.Width = 12; 
      missile.Location = new Point(spaceship.Location.X + 28, spaceship.Location.Y + 15); 
      this.Controls.Add(missile); 
      MissileMove(); 

     } 
    } 
} 

更新:

private void MissileMove() 
    { 
     System.Timers.Timer missileMove = new System.Timers.Timer(); 
     missileMove.Interval = 30; 
     missileMove.Elapsed += (sender, args) => 
      { 
       if (missile.Location.Y >= -30) 
       { 
        missile.Location = new Point(missile.Location.X, missile.Location.Y - 15); 
        missileX = missile.Location.X; 
        missileY = missile.Location.Y; 
        labelMissileX.Text = Convert.ToString(missileX); 
        labelMissileY.Text = Convert.ToString(missileY); 
        int enemyToMissileLocationX = Convert.ToInt32(labelEnemyX.Text); 
        int enemyToMissileLocationY = Convert.ToInt32(labelEnemyY.Text); 
        if ((missileX - enemyToMissileLocationX <= 20 && missileY - enemyToMissileLocationY <= 20 && missileX - enemyToMissileLocationX >= 0 && missileY - enemyToMissileLocationY >= 0) || (enemyToMissileLocationX - missileX <= 20 && enemyToMissileLocationY - missileY <= 20 && enemyToMissileLocationX - missileX >= 0 && enemyToMissileLocationY - missileY >= 0)) 
        { 
         missile.Visible = false; 
         enemy.Visible = false; 
         enemyKilled = true; 
         System.Threading.Thread.Sleep(100); 
         Application.DoEvents(); 
         Spawn(); 
        } 
       } 
      }; missileMove.Start(); 

試圖與類要做到這一點,是的,它釀出的敵人再一次,但動畫是竊聽,我可以看到敵人從一個位置跳到另一個位置。 謝謝你的幫助。

+3

請添加您的questin更多詳細信息 – Krekkon

+0

我希望每次殺死敵人時都能產生敵人。 –

+0

這是一個巨大的長碼,沒有人會認爲它是一個想法。 請更新您的問題,以獲得更多答案。清理unneccery代碼或方法體 – Krekkon

回答

1

這看起來像一個Windows窗體。因此,我建議你有一個在while循環中運行的後臺線程,並處理遊戲的所有移動/更新邏輯。複雜的部分將管理Windows窗體線程和遊戲線程之間的狀態。您需要確保您是按鈕點擊的事件處理程序等等,這些更新遊戲狀態以線程安全的方式執行,因爲它們將位於GUI線程中。遊戲循環線程將需要在GUI上更新狀態,這將需要稱爲marshelling,因爲只有GUI線程被允許訪問窗體上存在的按鈕等控件。

線程主題管理,線程安全和marshelling我會留給你去研究。

這假設它是某種實時遊戲,而不是基於回合。如果它是基於回合的,那麼你並不需要一個遊戲循環。您可以通過使用狀態圖和純粹的事件驅動設計來實現相同的目標。

+1

不需要爲遊戲循環引入多線程的所有複雜性嗎?只要循環包含'Application.DoEvents()'並以合理的幀速率運行(所以DoEvents頻繁發生),所有內容都應該在單個線程上輕鬆運行。這就是Scrolling Game Development Kit 2(http://sgdk2.sf.net/)創建的遊戲的運作方式。 – BlueMonkMN

+1

@BlueMonkMN我的建議確實沒有「需要」去做。但是,依賴於DoEvents的體系結構有時被認爲是不好的做法,因爲它使UI的響應性依賴於每個DoEVents調用之間的每段代碼的**響應性,以保證**速度更快。這就是說,我鼓勵你發表你的建議作爲答案,因爲我認爲這是平等的考慮到權衡。這確實會更容易實施。 – AaronLS

+0

我試圖做到這一點,但問題是,它產生更多的敵人從一個敵人跳到另一個敵人。我用它添加了第三部分代碼。 –

2

我的建議是實現遊戲循環,你必須像函數(或main功能,如果你熟悉集成是爲Windows窗體應用程序),但增加了呼叫Application.DoEvents在循環內進行確定窗口仍然響應諸如移動和調整大小以及點擊按鈕等事件。除此之外,您可能需要澄清您目前使用的解決方案遇到的問題,以獲得更全面,更詳細的答案。