c#简单实现打字母小游戏的编程思想

打字母小游戏案例

模块一(划分游戏界面和控制界面)

分析:

1、整个界面由游戏界面和控制界面组成

​ 所以,要用到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控件添加到窗体中

2、创建飞机

​ 所以,要用到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控件中

3、创建字母

(1)因为创建字母是有一定的时间间隔,所以我要添加计时器来控制它创建字母的时间
(2)因为要创建字母,所以,我们要找到一个容器(label)来存储这个字母
(3)因为不可能说是只创建同样的字母,同样的位置、同样的颜色以及同样的大小等等,所以要用到随机对象。

​ 如何创建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控件中
        }

4、控制字母(label控件)下降

​ (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;//那么就让这个控件下降
                 }
             }
          }   

模块二(当按下字符时触发的事件)

分析:

(1)当字母下落的时候,我们按下键盘上对应的字符,飞机移动到对应字母的下方,这里要添加KeyPress事件

 this.KeyPress += Form1_KeyPress;//在窗体下添加键盘事件
 //KeyPress是一个事件  表示在控件有焦点的情况下,字符、空格或退格键发生

(2)然后我们要找到对应的字母控件来与按下的字符进行匹配,既然是找控件那么就一定用到Foreach循环遍历,来判断字母控件中的文本是否与按下键盘上的键字母一样,这里要用到e.keychar来判断

(3)如果匹配成功,就让飞机(picturebox)控件移动到对应字母的下方(要计算飞机控件的位置)

//按下字符的触发事件
        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;//就让飞机控件和对应的字母对齐
                    
                }
            }
        }

模块三(子弹的创建和发射)

分析1:子弹的创建

(1)一般情况下,当飞机移动到对应字母的下方时,我们就要创建出子弹,所以要在picturebox1移动位置后来写

(2)因为子弹也是一张图片,所以也要有一个容器来存储它,所以要用到picturebox控件,所以要创建picturebox2控件,并导入图片,最后将其添加到panel1控件中

(3)最后我们要设置子弹(picturebox2)控件的位置(通过计算)

​ ①因为它是在飞机(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控件中
                }
            }
        }

分析2:子弹的发射

难点:(1)因为子弹是在字母创建后发射的,所以我们要写在字母下降的事件中

​ (2)因为在这个判断条件前我们已经循环遍历了panel1控件中的控件集合,所以我们只需用判断,遍历的控件是否是子弹控件

​ (3)如果是,那么我们就让子弹发射上去,其实就是改变top的距离,因为是向上,所以是减

if (item.Tag.ToString()=="zd")//判断item是否遍历到tag属性叫zd的控件集合
                {
                    item.Top -= 30;//那么,就让item控件集合的上边缘距离逐渐减小
                }

模块四(子弹打掉对应字母)

分析:

(1)既然是打掉对应的字母,那么就一定要碰撞对应的字母,但是此时我们不知道对应的字母控件是谁

​ 所以,循环遍历字母的时候,当按下键盘上的字符与label1中的控件文本匹配的时候,我们就给这个匹配的item控件重新命名一个标记,这个时候就产生了两种字母标记,一个是zm,一个是bg

​ 这个时候下降的字母就是两个,所以我们要在字母下降的条件中添加新的条件

 if (item.Tag.ToString()=="zm" ||  item.Tag.ToString()=="bg")//判断item是否遍历到tag属性叫zm或者bg的控件集合

(2)既然是碰撞,那么就一定是当子弹发射后与对应字母碰撞,所以要在子弹发射后判断循环遍历找到tag标记叫bg的对应字母

(3)然后判断是否碰撞,因为字母是向下,子弹是向上,所以肯动是字母>子弹,对应字母下落的上边缘距离加上它自身的高度如果大于等于子弹子上边缘的距离,那么就是碰撞了

(4)如果碰撞了,我们就让对用的字母和子弹消失####

判断是否碰撞(计算)当对应字母的上边缘距离+对应字母的高度>=子弹上上边缘的距离(因为字母往下落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();//那么就让他释放所有资源
                    }

细节部分:

问题:当panel1出现两个相同的字母时,按下键盘上对应的字符会发出两个子弹

分析:出现这种情况是因为,当按下键盘上对应的字符时,子弹在foreach循环遍历中执行了两次

解决:当执行完一次后,跳出循环,用到return跳出循环

return;//跳出foreach循环,就是说碰到两个相同的字母,就按一下键盘打一个

优化部分:

在子弹和对应字母消失后播放爆炸声,要用到SoundPlayer

(1)导入音频所需要的数据包

using System.Media;//导入音频所需要的数据包

(2)创建音频控件,并插入音频

 SoundPlayer player = new SoundPlayer("../../sound/use_bomb.wav");//创建音频控件,并插入音频

(3)在碰撞消失后播放音频

  player.Play();//打开播放音频

爆炸效果

在子弹和字母碰撞后,触发爆炸效果(其实是由多张图片连续播放做成的效果图)

分析:

(1)因为是在字母和子弹碰撞后触发的,所以要写在子弹和字母配碰撞后

(2)因为是由多张图片组成的,所以应该用picturebox控件来存储并导入第一张图片序号0

(3)然后计算其爆炸的位置

(4)因为是由多张图片组成,所以播放的时候是有时间间隔的,那么这里就用到了计时器控件,并且插入触发事件

(5)我们不能直接将picturebox控件导入timer计时器,所以,我们要将picturebox中的所有属性打包存储到timer的tag属性中,此时timer的tag属性中就有了picturebox的所有参数属性

(6)因为每一张图片都是事件的发起者,所以,我们要将sender参数存储到timer计时器中,此时,计时器同时拥有picturebox的属性和sender事件参数

(7)然后我们要在计时器事件中创建新的picturebox控件,并将上一次的picturebox属性和触发事件的对象一并打包(其实就是timer的tag属性)都给新定义创建的picturebox控件中,此时这个新的picturebox控件就继承了上一次picturebox的所有属性

(8)两种方法调用imagelist图片集合中的图片

​ ①需要定义一个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();
            }
        }

你可能感兴趣的:(IT)