大三上学期c#结课项目《经典游戏》—— 推箱子

2020-01-04  本文已影响0人  木羽

经典游戏

c#这科是由赵大伟老师教的,并且打分方式是根据这个项目。而我素来对游戏比较感兴趣,而且Visual Studio操作很方便,所以当知道需要做一个结课项目的时候,我就开始构思制作一个游戏了。

推箱子

推箱子
游戏规则:通过键盘控制移动我的箱子,并且在碰撞到其他箱子的时候,与被撞到的箱子一起移动。而在撞到地形的时候,则不能移动,当目标箱子到达指定底线,游戏结束。
思路:整体显示用PictureBox控件显示图片,然后通过键盘进行操作。

移动

我的箱子

设置一个textBox控件,用键盘的keyDown事件控制textBox的移动,并且在移动事件里控制PictureBox的位置与textBox的位置一致,并且,PictureBox始终在textBox的上方将其盖住。

下面是源代码,以向左移动为例子


用到的两个控件
  private void textBox1_KeyDown(object sender, KeyEventArgs e)
        {
            //设置移动距离
            int rightLocal = myBox.Width - 1;
            int bottomLocal = myBox.Width + 2;
            //用switch语句判断键盘按下的是哪个键
            switch (e.KeyCode)
            {
                case Keys.Left:
                    //检查碰撞 没撞到的情况下返回的是true
                    if (checkLeftCrash(myBox))
                    {
                        //向左移动textBox1
                        textBox1.Left = textBox1.Left - rightLocal;
                        //判断是否撞到箱子
                        if (checkBoxLeftCrash(rightLocal, targetBox1, targetBox2))
                        {
                            //判断能不能移动目标箱子,如果可以,直接移动
                            checkLeftMove(rightLocal, targetBox1);
                        }
                        else
                        {
                            //将textBox1的位置调整回来
                            textBox1.Left = textBox1.Left + rightLocal;
                            break;
                        }
                        if (checkBoxLeftCrash(rightLocal, targetBox2, targetBox1))
                        {
                            checkLeftMove(rightLocal, targetBox2);
                        }
                        else
                        {
                            textBox1.Left = textBox1.Left + rightLocal;
                            break;
                        }
                    }
                    break;
              }
            myBox.Left = textBox1.Left;
            myBox.Top = textBox1.Top;
            showBuShu();
            showStatus();
            checkSuccess();
        }

地图设置

难点

碰撞检测

地图边缘检测

其他墙面检测

//以向上为例
public Boolean checkUpCrash(PictureBox box)
        {
            Boolean b = true;
            //边缘
            if (box.Top == 40)
            {
                b = false;
            }
            //其他墙
            if ((box.Top == 80 && box.Left == 259) || (box.Top == 80 && box.Left == 296) || (box.Top == 120 && box.Left == 37) || (box.Top == 120 && box.Left == 111) || (box.Top == 120 && box.Left == 148) || (box.Top == 120 && box.Left == 185))
            {
                b = false;
            }
            return b;
        }

目标箱子碰撞检测

//此处以向右为例
//向右推箱子
        public void checkRightMove(int local,PictureBox box)
        {
            if (myBox.Left + local >= box.Left)
            {
                //判断是否碰撞
                if (box.Top < myBox.Top || box.Top > myBox.Top || box.Left < myBox.Left)
                {
                    //没碰撞则什么都不做
                }
                else
                {
                    //目标箱子的位置就更改为我的箱子的位置+两倍的移动长度
                    if (checkRightCrash(box))
                    {
                        //目标箱子移动
                        box.Left = myBox.Left + local * 2;
                    }
                    else
                    {
                        //位置回调
                        textBox1.Left = textBox1.Left - local; 
                    }
                }
            }
        }
 //检查两个箱子紧挨时向右的碰撞
        public Boolean checkBoxRightCrash(int local,PictureBox Fbox,PictureBox Sbox)
        {
            Boolean b = false;
            //判断是否碰撞
            if (myBox.Left + local != Fbox.Left || myBox.Top!=Fbox.Top)
            {
                b = true;
            }
            else
            {
                if (Fbox.Left + local != Sbox.Left || Fbox.Top != Sbox.Top)
                {
                    b = true;
                }
            }
            return b;
        }

胜利判断

当所有目标箱子都到达指定区域的时候,游戏结束,并提示恭喜过关。

//胜利判断
        public void checkSuccess()
        {
            if (((success1.Left == targetBox1.Left && success1.Top == targetBox1.Top) || (success2.Left == targetBox1.Left && success2.Top == targetBox1.Top)) && ((success1.Left == targetBox2.Left && success1.Top == targetBox2.Top) || (success2.Left == targetBox2.Left && success2.Top == targetBox2.Top)))
            {
                MessageBox.Show("恭喜你,过关了!");
                timer1.Stop();
                String conStr = "provider=microsoft.jet.oledb.4.0;data source=fx.mdb";
                OleDbConnection conn = new OleDbConnection(conStr);
                conn.Open();
                String sql = "insert into ranklist(username,[time],stepnum) values('"+Login.username+"',"+time+","+bushu+")";
                OleDbCommand cmd = new OleDbCommand(sql, conn);
                if (cmd.ExecuteNonQuery() > 0)
                {
                    MessageBox.Show("添加记录成功");
                }
                textBox1.Enabled = false;
                textBox1.Focus();
            }
        }

不足总结

  1. 地图的设置过于麻烦,可以通过foreach简化。
  2. 在设计页面添加PictureBox,细节不够准确,会对游戏的运行有影响。
  3. 通过使用数组来简化碰撞检测。
  4. 写方法时,Boolean值设置混乱,有的是碰撞到了是true,有的是碰撞到了是false,应该统一!
  5. 检测多个箱子紧挨着的时候,写法过于笨拙,应考虑更加实用的方法。
上一篇 下一篇

猜你喜欢

热点阅读