通过数组操作的基本图像刷新问题

本文关键字:图像 刷新 新问题 数组 操作 | 更新日期: 2023-09-27 18:01:44

我正在尝试制作一个简单的tile游戏引擎并遇到问题。当我必须重新绘制贴图时,我卡住了。

        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();
    }

这是我的计时器函数,应该"操纵"数组值,所以当程序运行时,可以通过键决定打开/关闭哪个tile。

无论如何,我的问题是刷新涉及'invalidate()'函数调用的图像。虽然,我确实有一种感觉,它可以改变数组值在飞行中,我似乎不能刷新图像跳转到另一个瓷砖。

这是我一直在做的完整项目的链接:http://www.mediafire.com/?g10a0zzt8hru11v

这是我几天前问过的一个类似但不同的问题:设置基本游戏和调试基本问题

提前感谢!

通过数组操作的基本图像刷新问题

所以…我希望你不要对此有任何冒犯,但我浏览并整理了一些东西,并提供了一些建议/修复/评论等。

希望这对你有帮助!如果有任何建议的修改需要解释,请告诉我。

那么,让我们从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;
}

form .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
    }
}

干杯!