通过数组操作的基本图像刷新问题
本文关键字:图像 刷新 新问题 数组 操作 | 更新日期: 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
}
}
干杯!