2013-03-02 27 views
0

我正在試圖製作一個簡單的遊戲引擎並引發問題。當我必須重新繪製拼貼時,我會卡住。基本圖像刷新問題通過數組操作

 int[,] level = { 
          { 0, 0, 0, 0, 0 ,0 }, 
          { 0, 0, 0, 0, 0 ,0 }, 
          { 0, 0, 0, 0, 0 ,0 }, 
          { 0, 0, 0, 0, 0 ,0 }, 
          { 0, 0, 0, 0, 0 ,0 }, 
          { 0, 0, 0, 0, 0 ,0 }, 
         }; 

這是我的數組,因此所有的值都是0。每個對應的值都鏈接到一個獨立的圖塊,當您按下這些圖塊時會打開和關閉。

 //Event Handler (W,A,S,D) is used for movements 
    private void panel1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) 
    { 

     . 
     . 
     . 

    } 



     //Responsible for movements 
    private void tmrMov_Tick(object sender, EventArgs e) 
    { 


     level[_x, _y] = 0; 

     if (_objDirection == Direction.Right) 
     { 

      if (_x < _boardWidth - 1 && _x >= 0 && _x + 1 < _boardWidth - 1 && _x + 1 >= 0) 
       _x += 1; 
      else 
       _x = _boardWidth - 1; 
     } 

      . 
      . 
      . 

     level[_x, _y] = _k; 

     Invalidate(); 
    } 

這是被認爲「操縱」數組值所以程序正在運行時,一個可以決定通過鍵接通/關斷哪個瓦片我的定時器功能。

無論如何,我的問題是刷新關於'invalidate()'函數調用的圖像。雖然,我確實有一種感覺,它可以隨時更改數組值,但我似乎無法刷新圖像以跳到另一個圖塊。

這裏的鏈接到整個項目中,我一直在努力:http://www.mediafire.com/?g10a0zzt8hru11v

這裏有一個類似但不同的問題,我問過一些天回:Setting up basic game and debugging fundamental problems

提前感謝!

回答

0

所以......我希望你不要對此有任何冒犯,但我經歷了一些整理,並提供了一些建議/修復/評論/等。

希望這會有所幫助!讓我知道是否有任何建議的更改需要解釋。

所以,讓我們開始在designer.cs文件:

// Ahh, here's yer problem: the panel control doesn't raise PreviewKeyDowns - the form does, tho 
this.panel1.PreviewKeyDown += 
     new System.Windows.Forms.PreviewKeyDownEventHandler(
      this.panel1_PreviewKeyDown); 

    // the form will raise these, so bind the handler to it 
    // (and rename the method) 
    this.PreviewKeyDown += 
     new System.Windows.Forms.PreviewKeyDownEventHandler(
      this.Form1_PreviewKeyDown); 

啊,一個大問題下 - 沒有你的關鍵事件實際上是讓你的處理程序。讓我們回到代碼隱藏表單。

因此,在構造函數中 - 這一切都可以去:

// arrays of T (T[], int[], etc), come initialized to default(T), 
// so none of this is needed. 
level[0, 0] = 0; 
level[0, 1] = 0; 
level[0, 2] = 0; 
level[0, 3] = 0; 
level[0, 4] = 0; 

跳下去了Paint處理程序:

// The next two checks have the x and y swapped, 
    // meaning the apparent motion will not match what the 
    // actual direction should be 
//Empty Tile 
if (level[y, x] == 0) 
{ 
//Occupied Tile 
if (level[y, x] == 1) 
{ 

    // Now the render will mactch properly 
//Empty Tile 
if (level[x, y] == 0) 
{ 
//Occupied Tile 
if (level[x, y] == 1) 
{ 

冠!到Timer.Tick處理程序:

#region Timer function 
// doing this could cause flickering 
// or flashing if the paint fires while 
// we're updating things 
level[_x, _y] = 0; 

#region Timer function 
// instead, keep track temporarily 
// what they were - we'll come back to this later on 
var oldX = _x; 
var oldY = _y; 

而且到的if/else鏈:

// There's a lot of replication and style choices here that 
// will make it harder to debug/troubleshoot 
if (_objDirection == Direction.Right) 
{ 
    if (_x < _boardWidth - 1 && _x >= 0 && _x + 1 < _boardWidth - 1 && _x + 1 >= 0) 
     _x += 1; 
    else 
     _x = _boardWidth - 1; 
} 
else if (_objDirection == Direction.Left) 

讓我們看看,如果我們可以擺脫一些重複的:

// let's figure these out ahead of time 
var spaceOnLeft = _x > 0; 
var spaceOnRight = _x < _boardWidth - 1; 
var spaceOnTop = _y > 0; 
var spaceOnBottom = _y < _boardHeight - 1; 

// switch is a bit like the if/else construct you had 
switch (_objDirection) 
{ 
    case Direction.Up: 
     // this means: if(spaceOnTop) y = y-1 else y = height-1 
     _y = spaceOnTop ? _y - 1 : _boardHeight - 1; 
     break; 
    case Direction.Down: 
     _y = spaceOnBottom ? _y + 1 : 0; 
     break; 
    case Direction.Left: 
     _x = spaceOnLeft ? _x - 1 : _boardWidth - 1; 
     break; 
    case Direction.Right: 
     _x = spaceOnRight ? _x + 1 : 0; 
     break; 
} 

跳轉至最後...

// now we'll use the old position to clear... 
level[oldX, oldY] = 0; 
// then set the new position 
level[_x, _y] = _k; 

// Since we're only writing on the panel, 
// we only need to rerender the panel 
panel1.Refresh(); 

最後一位 - 按鍵處理程序:

// Hah - artificial difficulty due 
// to awkward key choice? Out of curiosity, 
// why not Keys.Up, Down, Left, Right? 
if (e.KeyCode == Keys.E) 
{ 
    _objDirection = Direction.Left; 
} 
else if (e.KeyCode == Keys.D) 
{ 
    _objDirection = Direction.Right; 
} 
else if (e.KeyCode == Keys.W) 
{ 
    _objDirection = Direction.Up; 
} 
else if (e.KeyCode == Keys.S) 
{ 
    _objDirection = Direction.Down; 
} 

// same deal here, but with keys 
    // Or switch to Up, Down, Left, Right :) 
switch (e.KeyCode) 
{ 
    case Keys.E: 
     _objDirection = Direction.Up; 
     break; 
    case Keys.D: 
     _objDirection = Direction.Down; 
     break; 
    case Keys.W: 
     _objDirection = Direction.Left; 
     break; 
    case Keys.S: 
     _objDirection = Direction.Right; 
     break; 
} 

Form1的完整代碼刪除。cs等級:

//Listing all the parameters 
public partial class Form1 : Form 
{ 

    #region Declaring Parameters 

    enum Direction 
    { 
     Left, Right, Up, Down 
    } 

    private int _x; 
    private int _y; 
    private int _k; 
    private Direction _objDirection; 
    Random rand = new Random(); 
    private int _boardWidth; 
    private int _boardHeight; 
    private int[,] level; 

    #endregion 

    //Giving values to parameters 
    public Form1() 
    { 
     InitializeComponent(); 

     #region Initialial values 

     _k = 1; 
     _boardWidth = 6; 
     _boardHeight = 6; 
     _x = rand.Next(0, _boardWidth - 1); 
     _y = rand.Next(0, _boardHeight - 1); 
     _objDirection = Direction.Left; 

     //Array that works as a board or platform which we used to distinguish tiles 
     level = new int[_boardWidth, _boardHeight]; 
     #endregion 
    } 

    //Paint is used for drawing purposes only 
    private void panel1_Paint(object sender, PaintEventArgs e) 
    { 
     /* 
       int[,] level = { 
           { 0, 0, 0, 0, 0 ,0 }, 
           { 0, 0, 0, 0, 0 ,0 }, 
           { 0, 0, 0, 0, 0 ,0 }, 
           { 0, 0, 0, 0, 0 ,0 }, 
           { 0, 0, 0, 0, 0 ,0 }, 
           { 0, 0, 0, 0, 0 ,0 }, 
          }; 
     */ 
     #region Looping through tiles 

     //Initializing first randomly filled tile 
     level[_x, _y] = _k; 

     for (int y = 0; y < _boardHeight; y++) 
     { 
      for (int x = 0; x < _boardWidth; x++) 
      { 
       //Empty Tile 
       if (level[x, y] == 0) 
       { 
        // Create pen. 
        Pen redPen = new Pen(Color.Red, 1); 

        // Create rectangle. 
        Rectangle redRect = new Rectangle(x * 50, y * 50, 50, 50); 

        // Draw rectangle to screen. 
        e.Graphics.DrawRectangle(redPen, redRect); 
       } 

       //Occupied Tile 
       if (level[x, y] == 1) 
       { 
        // Create solid brush. 
        SolidBrush blueBrush = new SolidBrush(Color.Blue); 
        // Create rectangle. 
        Rectangle rect = new Rectangle(x * 50, y * 50, 50, 50); 
        // Fill rectangle to screen. 
        e.Graphics.FillRectangle(blueBrush, rect); 
       } 
      } 
     } 
     #endregion 
    } 

    //Responsible for movements 
    private void tmrMov_Tick(object sender, EventArgs e) 
    { 
     #region Timer function 
     // instead, keep track temporarily 
     // what they were 
     var oldX = _x; 
     var oldY = _y; 

     // let's figure these out ahead of time 
     var spaceOnLeft = _x > 0; 
     var spaceOnRight = _x < _boardWidth - 1; 
     var spaceOnTop = _y > 0; 
     var spaceOnBottom = _y < _boardHeight - 1; 

     // switch is a bit like the if/else construct you had 
     switch (_objDirection) 
     { 
      case Direction.Up: 
       // this means: if(spaceOnTop) y = y-1 else y = height-1 
       _y = spaceOnTop ? _y - 1 : _boardHeight - 1; 
       break; 
      case Direction.Down: 
       _y = spaceOnBottom ? _y + 1 : 0; 
       break; 
      case Direction.Left: 
       _x = spaceOnLeft ? _x - 1 : _boardWidth - 1; 
       break; 
      case Direction.Right: 
       _x = spaceOnRight ? _x + 1 : 0; 
       break; 
     } 

     // now we'll use the old values to clear... 
     level[oldX, oldY] = 0; 
     // then set the new value 
     level[_x, _y] = _k; 
     #endregion 
     panel1.Refresh(); 
    } 

    //Event Handler (W,A,S,D) is used for movements 
    private void Form1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) 
    { 
     #region Controls 

     // same deal here, but with keys 
     switch (e.KeyCode) 
     { 
      case Keys.Up: 
       e.IsInputKey = true; 
       _objDirection = Direction.Up; 
       break; 
      case Keys.Down: 
       e.IsInputKey = true; 
       _objDirection = Direction.Down; 
       break; 
      case Keys.Left: 
       e.IsInputKey = true; 
       _objDirection = Direction.Left; 
       break; 
      case Keys.Right: 
       e.IsInputKey = true; 
       _objDirection = Direction.Right; 
       break; 
     } 
     #endregion 
    } 
} 

乾杯!

+0

太棒了!非常感謝!我是C#和winforms編程的新手,所以這對我來說真的很棒。我確實有一個問題,你添加'panel1.Refresh();'因爲那真的是我意識到的最大罪魁禍首。我也想知道designer.cs編輯背後的原因?我很抱歉我在學習階段.. – AceofSpades 2013-03-02 05:26:30

+0

@AceofSpades我的榮幸!所以,設計師編輯:你有'KeyDown'事件綁定到'Panel',這是有道理的,除了'Panel'不會引發這些事件 - 但是'Form'類呢;這就是改變的地方:將事件處理程序切換到「Form」。 – JerKimball 2013-03-02 05:29:01

+0

(也重新閱讀我的答案,我已經認識到,當我喝酒的時候,我使用了「so」這個詞) – JerKimball 2013-03-02 05:30:53