所以,要用到panel控件来完成,并且还要设置panel控件的大小,边框,背景,以及背景样式等,最后还要将创建的panel控件添加到窗体中
Panel panel1 = new Panel(); //创建panel1控件
panel1.Size = new Size(800, 600);//设置panel1的宽高大小
panel1.BorderStyle = BorderStyle.Fixed3D;//设置其边框样式
panel1.BackgroundImage = Image.FromFile("../../imgs/background.png");//插入背景图片
panel1.BackgroundImageLayout = ImageLayout.Tile;//将图片平铺与整个控件中
panel1.Left = 10;//设置左边缘的距离
panel1.Top = 10;//设置上边缘的距离
this.Controls.Add(panel1);//将创建好的panel1控件添加到窗体中
所以,要用到picturebox控件来完成,并且要计算它的位置和设置大小,最终将创建的picturebox控件添加到panel控件中来
(1)先让picturebox1向右移动,就是设置它的左边缘left的距离,使它在panel1中居中,就是panel1宽度的一半再减去它自身宽度的一半
(2)在让picturebox2向下移动,就是设置上边缘top的距离,使它在panel1的下边,就是panel1的高度减去picturebox1自身的高度
PictureBox picturebox1 = new PictureBox();//创建picturebox1控件来装飞机
picturebox1.Image = Image.FromFile("../../imgs/hero1.png");//插入图片
picturebox1.SizeMode = PictureBoxSizeMode.AutoSize;//设置控件的的大小为自适应图片大小
//设置picturebox1的位置
picturebox1.Left = panel1.Width / 2 - picturebox1.Width / 2;//设置picturebox1左边缘的距离
picturebox1.Top = panel1.Height - picturebox1.Height-10;//设置picturebox1上边缘的距离
panel1.Controls.Add(picturebox1);//将创建的picturebox1控件添加到panel1控件中
如何创建timer对象?并且添加事件和属性呢?
Random ra = new Random();//创建随机数对象
//创建字母的触发事件
private void Timer1_Tick(object sender, EventArgs e)
{
Label lab1 = new Label();//创建lab1控件来随机字母
lab1.Text =((char) ra.Next(97, 123)).ToString();//用来在lab1控件文本中随机小写字母
lab1.ForeColor = Color.FromArgb(ra.Next(255), ra.Next(255), ra.Next(255));//字体颜色随机
lab1.Font = new Font("楷体", ra.Next(23, 34), FontStyle.Bold);//设置lab1的字体,字体大小和加粗
lab1.AutoSize = true;//设置lab1控件的大小根据文本内容的大小自适应
lab1.Left = ra.Next(panel1.Width - lab1.Width);
panel1.Controls.Add(lab1);//将创建的lab1控件添加到panel1控件中
}
(1)字母下降的过程是有一定时间的,有一个东西控制它,这里可以用timer来控制它下降,所以要创建timer控件,并且要添加触发事件,以及其他的属性
Timer timer2 = new Timer();//创建计timer2来控制字母下落
timer2.Tick += Timer2_Tick;//添加timer2的事件
timer2.Interval = 100;//100毫秒下落一次
timer2.Start();//打开计时器2
(2)让字母下落说白了其实就是让label控件下降,既然是让控件下降,那么就用到了Foreach循环遍历
(3)遍历就是遍历panel1中的控件集合,目前panel1控件中有两种控件,一个是picturebox,另一种是label,所以这里我们要用到if判断来判断item遍历的控件是否是label,如果是那么就让他下降
(3)用到了if判断控件,那么就一定要给两个控件都命名一个标签,所以这里用到了Tag属性
picturebox1.Tag = "fj";//设置标签
lab2.Tag = "zd";//设置标签
private void Timer2_Tick(object sender, EventArgs e)//计时器下落事件
{
foreach (Control item in panel1.Controls)//遍历panel1控件中的控件集合
{
if (item.Tag.ToString()=="zm" )//判断item是否遍历到tag属性叫zm的控件集合
{
item.Top += 10;//那么就让这个控件下降
}
}
}
this.KeyPress += Form1_KeyPress;//在窗体下添加键盘事件
//KeyPress是一个事件 表示在控件有焦点的情况下,字符、空格或退格键发生
//按下字符的触发事件
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
foreach (Control item in panel1.Controls)//遍历panel1控件中的控件集合
{
//e.KeyChar 表示获取或设置与按下的键对应的字符 是char类型
if (item.Text==e.KeyChar.ToString())//判断item遍历的控件集合的文本是否是键盘输入的字符(字母)
{
//判断结果成立
picturebox1.Left = item.Left + item.Width / 2 - picturebox1.Width / 2;//就让飞机控件和对应的字母对齐
}
}
}
①因为它是在飞机(picturebox1)控件的上方,所以就先让设置它的左边缘距离,就是飞机控件左边缘的距离加上他自身宽度的一班(找到中心位置)减去子弹(picturebox2)宽度的一半
②让picturebox2往下,就是设置top的值,因为在飞机的上边,所以,top就等于飞机控件的上边缘距离再减去10
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
foreach (Control item in panel1.Controls)//遍历panel1控件中的控件集合
{
//e.KeyChar 表示获取或设置与按下的键对应的字符 是char类型
if (item.Text==e.KeyChar.ToString())//判断item遍历的控件集合的文本是否是键盘输入的字符(字母)
{
item.Tag = "bg";//将遍历到的对应的字母(控件)的tag属性改为bg,表示对应的字母
//判断结果成立
picturebox1.Left = item.Left + item.Width / 2 - picturebox1.Width / 2;//就让飞机控件和对应的字母对齐
PictureBox lab2 = new PictureBox();//创建lab2控件,来组为子弹
lab2.Tag = "zd";//设置标签
lab2.Size = new Size(10, 10);//设置控件的大小
lab2.Image=Image.FromFile("../../imgs/bullet2.png");//用它来作为子弹
lab2.SizeMode = PictureBoxSizeMode.AutoSize;//控件大小自适应图片大小
//设置lab2的位置
lab2.Top = picturebox1.Top-10;
lab2.Left = picturebox1.Left + picturebox1.Width / 2 - lab2.Width / 2;
panel1.Controls.Add(lab2);//将其添加到panel1控件中
}
}
}
难点:(1)因为子弹是在字母创建后发射的,所以我们要写在字母下降的事件中
(2)因为在这个判断条件前我们已经循环遍历了panel1控件中的控件集合,所以我们只需用判断,遍历的控件是否是子弹控件
(3)如果是,那么我们就让子弹发射上去,其实就是改变top的距离,因为是向上,所以是减
if (item.Tag.ToString()=="zd")//判断item是否遍历到tag属性叫zd的控件集合
{
item.Top -= 30;//那么,就让item控件集合的上边缘距离逐渐减小
}
所以,循环遍历字母的时候,当按下键盘上的字符与label1中的控件文本匹配的时候,我们就给这个匹配的item控件重新命名一个标记,这个时候就产生了两种字母标记,一个是zm,一个是bg
这个时候下降的字母就是两个,所以我们要在字母下降的条件中添加新的条件
if (item.Tag.ToString()=="zm" || item.Tag.ToString()=="bg")//判断item是否遍历到tag属性叫zm或者bg的控件集合
判断是否碰撞(计算)当对应字母的上边缘距离+对应字母的高度>=子弹上上边缘的距离(因为字母往下落top变大,子弹网上走top变小)就证明碰撞了,消失就是释放所有资源dispose
```csharp
foreach (Control item2 in panel1.Controls)//遍历panel1控件中的控件集合
{
//是否碰撞
if (item2.Tag.ToString()=="bg")//如果item2遍历到ta属性叫bg的控件集合(就是键盘对应的字母控件)
{
if(item2.Top+item2.Height>=item.Top && item2.Left+item2.Width/2==item.Left+item.Width/2)//判断字母控件上边缘距离+字母控件的高度是否大于等于子弹控件的上边缘距离并且字母与子弹的中心位置是否相等
{
item.Dispose();//那么就让对应的字母释放所有资源(就是消失)
//Dispose 表示释放所有资源
item2.Dispose();//那么就让子弹控件释放所有资源(就是消失)
}
}
}
#### (5)如果没有按下对应的键盘字符,当对应的字母降落到飞机控件的上边时就让他消失,在字母下降下写
```c#
if (item.Top + item.Height >= picturebox1.Top)//判断item控件上边缘+自身高度的距离是否大于等于picturebox1上边缘的距离
//意思就是说当item(字母)控件的下边降落到picturebox1(飞机)控件上边的时候就让他消失
{
item.Dispose();//那么就让他释放所有资源
}
return;//跳出foreach循环,就是说碰到两个相同的字母,就按一下键盘打一个
using System.Media;//导入音频所需要的数据包
SoundPlayer player = new SoundPlayer("../../sound/use_bomb.wav");//创建音频控件,并插入音频
player.Play();//打开播放音频
在子弹和字母碰撞后,触发爆炸效果(其实是由多张图片连续播放做成的效果图)
①需要定义一个int类型的变量,赋值为0,表示第一张图片,然后将变量的值每次+1,就实现了图片的爆炸
但是,这里出现了一个问题:就是图片是有上限的,所以我们要判断这个变量是否超过了这个上限,如果超过了,就把他归零,并且要释放timer以及picturebox控件中的所有资源。
②不用定义变量,直接给上一次的picturebox控件命名标记为0,就是tag为0,因为他是object类型的所以要强制转换为int类型才能使用,然后将转化后的tag每次+1,但是它不用清零,因为,程序每次都要从tag属性进来,它每次都是0,但是也不许释放item和定义的picturebox中的所有资源。
//创建计时器来控制图像集中的爆炸效果
Timer bomtimer = new Timer();
bomtimer.Interval = 30;
bomtimer.Start();
bomtimer.Tag = bombox;//将bombox中所有属性打包存储到bomtimer.tag的属性中
bomtimer.Tick += Bomtimer_Tick;
}
}
}
}
}
}
private void Bomtimer_Tick(object sender, EventArgs e)
{
Timer bomtimer = (Timer)sender;//将触发事件的对象存储到bomtimer中
PictureBox picture = (PictureBox)bomtimer.Tag;//将bomtimer.tag(也就是bombox的所有属性)赋值给创建的picturebox控件中
picture.Image = imageList1.Images[(int)picture.Tag];//因为picture有bombox的属性
//nul++;
picture.Tag = (int)picture.Tag + 1;
if ((int)picture.Tag > 31)//因为有31张图片
{
//释放掉boxtimer和picture中的所有资源
picture.Dispose();
bomtimer.Dispose();
}
}