我正在尝试制作一个简单的平铺游戏引擎并遇到问题。当我不得不重新绘制瓷砖时,我会陷入困境。
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 :(得分: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
}
}
干杯!