由于最近刚进出c#,想快速上手,所以决定写几个小游戏(后面会陆续更新)来熟悉语言,并且记录学习winform的一些相关问题和解决方法。
首先给我的感觉winform和c++中的界面设计MFC还是非常类似的(很可惜当时MFC深入浅出没吃透彻),下面我们就从最基础简单的来实现俄罗斯方块:
1首先弄出一个窗体:
我是在pictureBox控件上面实现画图的(因为没找到图片资源,所以我的方块都是GDI绘制的)然后就是设置一个定时器,再点击开始菜单的时候启动定时器,具体时间间隔自己决定,其中可能要用到的定时器的函数和属性:
timer.Enable :表示定时器是否启动,true是启动,false是关闭。
timer.Interval:表示定时器的间隔时间。
然后是逻辑的设计:采用一个二维数组记住pictureBox,然后1表示该格子是有方块的,每次计时器中调用刷新函数来刷新窗体,这样就可以调用paint函数来绘制图形,然后逻辑的操作其实都是对二维数组的操作,最后传给paint函数的都是操作后的结果数组。
this.Invalidate() :刷新窗体,可以调用到paint函数。
然后再PictureBox上面画图的时候要注意,如果是直接绘制的话,会出现一些很奇怪的问题,所以我们采用绘制再位图上面然后再贴在pictureBox上面(详情请见上一篇)
下面贴上一些部分关键代码:
public partial class Form1 : Form
{
public int Down_Type; //方块的大种类
public int Type_Direction; //方块的什么朝向
public int Down_Speed = 25;
public int Control_Speed = 25; //左右的速度
public int[][] map; //pictureBox的二维地图映射
public Boolean IsLand = true; //是否该产生块
public Point CorePosition; //左上角用来刷新的时候定位用的点
public Boolean Is_Go_Left = false;
public Boolean Is_Go_Down = false;
public Boolean Is_Go_Up = false;
public Boolean Is_Go_Right = false; //是否右前进
public int Max_Right,Max_Buttom; //最右边的横坐标和最下面的竖着的坐标
public int Score = 0; //记分器
public int level = 1; //难度级别
public Form1()
{
InitializeComponent();
this.ScorePain.Text = "0";
}
下面是擦除的函数,实现动画效果我是直接擦除上一次的痕迹然后重新绘制,但是由于可以按“↑”来改变图形,多以在擦除的代码应该分情况。
public void ClearScreen()
{
switch (Down_Type)
{
//14列大概是中点
case 1:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down && CorePosition.X > 0)
CorePosition.X -= 1;
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X + 1][CorePosition.Y] = 0;
map[CorePosition.X][CorePosition.Y+1] = map[CorePosition.X+1][CorePosition.Y+1] = 0;
break;
}
case 2:
{
switch (Type_Direction)
{
case 1:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if(!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X+1][CorePosition.Y] = 0;
map[CorePosition.X+2][CorePosition.Y] = map[CorePosition.X + 2][CorePosition.Y + 1] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X+1][CorePosition.Y] = 0;
map[CorePosition.X + 1][CorePosition.Y + 1] = map[CorePosition.X + 1][CorePosition.Y + 2] = 0;
}
break;
}
case 2:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if(!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y+1] = 0;
map[CorePosition.X][CorePosition.Y+2] = map[CorePosition.X -1][CorePosition.Y+2] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X+1][CorePosition.Y] = 0;
map[CorePosition.X+2][CorePosition.Y] = map[CorePosition.X + 2][CorePosition.Y + 1] = 0;
}
break;
}
case 3:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if(!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X+1][CorePosition.Y] = 0;
map[CorePosition.X + 1][CorePosition.Y + 1] = map[CorePosition.X + 1][CorePosition.Y + 2] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y+1] = 0;
map[CorePosition.X][CorePosition.Y+2] = map[CorePosition.X -1][CorePosition.Y+2] = 0;
}
break;
}
}
break;
}
case 3:
{
switch (Type_Direction)
{
case 1:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if (!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X + 1][CorePosition.Y + 1] = map[CorePosition.X + 1][CorePosition.Y + 2] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X + 1][CorePosition.Y] = 0;
map[CorePosition.X][CorePosition.Y + 1] = map[CorePosition.X - 1][CorePosition.Y + 1] = 0;
}
break;
}
case 2:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if (!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X + 1][CorePosition.Y] = 0;
map[CorePosition.X][CorePosition.Y + 1] = map[CorePosition.X - 1][CorePosition.Y + 1] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X + 1][CorePosition.Y + 1] = map[CorePosition.X + 1][CorePosition.Y + 2] = 0;
}
break;
}
}
break;
}
case 4:
{
switch (Type_Direction)
{
case 1:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if (!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X][CorePosition.Y + 2] = map[CorePosition.X][CorePosition.Y + 3] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X + 1][CorePosition.Y] = 0;
map[CorePosition.X + 2][CorePosition.Y] = map[CorePosition.X + 3][CorePosition.Y] = 0;
}
break;
}
case 2:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if (!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X + 1][CorePosition.Y] = 0;
map[CorePosition.X + 2][CorePosition.Y] = map[CorePosition.X + 3][CorePosition.Y] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X][CorePosition.Y + 2] = map[CorePosition.X][CorePosition.Y + 3] = 0;
}
break;
}
}
break;
}
case 5:
{
switch (Type_Direction)
{
case 1:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if (!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X][CorePosition.Y + 2] = map[CorePosition.X - 1][CorePosition.Y + 1] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X + 1][CorePosition.Y + 1] = map[CorePosition.X - 1][CorePosition.Y + 1] = 0;
}
break;
}
case 2:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if (!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X][CorePosition.Y + 2] = map[CorePosition.X + 1][CorePosition.Y + 1] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X][CorePosition.Y + 2] = map[CorePosition.X - 1][CorePosition.Y + 1] = 0;
}
break;
}
case 3:
{
//this.Timer.Text = (CorePosition.X + 1).ToString();
//擦除
if (Is_Go_Left)
CorePosition.Y += 1;
if (Is_Go_Right)
CorePosition.Y -= 1;
if (Is_Go_Down)
CorePosition.X -= 1;
if (!Is_Go_Up)
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X + 1][CorePosition.Y + 1] = map[CorePosition.X - 1][CorePosition.Y + 1] = 0;
}
else
{
map[CorePosition.X][CorePosition.Y] = map[CorePosition.X][CorePosition.Y + 1] = 0;
map[CorePosition.X][CorePosition.Y + 2] = map[CorePosition.X + 1][CorePosition.Y + 1] = 0;
}
break;
}
}
break;
}
}
}
然后是难度的选择,难度窗体我是在设计的一个窗体,所以需要在两个窗体中传递数据,但是操作起来并没有想象中的那么难,直接添加变量就可以完成操作。:
private void menuItem5_Click(object sender, EventArgs e)
{
Level L = new Level();
L.Text = "难度选择";
L.ShowDialog();
level = L.level;
//MessageBox.Show(level.ToString());
}
然后是radioButton,有多个的时候想要在初始的时候选中其中一个,那么它有个属性Checked可以选择上为True就行了。
还有一个Key的事件的问题:注意下面的
其中我使用的枚举值Keys.Up等是用KeyData来实现的:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
//MessageBox.Show("Left!");
if (e.KeyData == Keys.Left && !Is_Go_Left)
{
if (CorePosition.Y > 0)
{
CorePosition.Y -= 1;
Is_Go_Left = true;
}
}
else if (e.KeyData == Keys.Right && !Is_Go_Right)
{
if (Max_Right < 16)
{
CorePosition.Y += 1;
Is_Go_Right = true;
}
}
else if (e.KeyData == Keys.Down && !Is_Go_Down)
{
if (Max_Buttom < 20)
{
CorePosition.X += 1;
Is_Go_Down = true;
}
}
else if (e.KeyData == Keys.Up && !Is_Go_Up)
{
Is_Go_Up = true;
}
}