当前位置: 移动技术网 > IT编程>移动开发>WP > 如何在WP7上用XNA写2D游戏(四)

如何在WP7上用XNA写2D游戏(四)

2018年10月13日  | 移动技术网IT编程  | 我要评论

不文斋,应聘自我介绍,研究生毕业自我鉴定

 

第 3 章 创建xna 游戏菜单 
3.1 wp7里xna游戏的触控操作
      上一章节,我们了解了制作xna 2d游戏的常用已及使用screenmanage管理场景。可以说对xna 2d游戏有了入门,不过我们玩游戏不会一开始就进入到游戏场景里的,总是会有启动界面,loading界面,然后到了游戏菜单。然后让用户选择“开始”,“继续”,“帮助”等选项,如下图3-1,就是一个常见的游戏界面。

          \

 

图3-1

 

和pc上的运行的xna游戏不同,我们在wp7上是靠触摸屏操作的,这和用鼠标操作还是不同的。那么我们就需要先了解wp7里xna的触控操作。

                                                         

现在的触摸屏手机基本都支持“多点触控”,比如拉伸,缩放,玩过iphone上《愤怒的小鸟》就明白游戏画面可以用两个手指拉伸和缩放。还有很有名的《水果忍者》也是“多点触控”的好游戏,你用三个手指在屏幕上划拉,屏幕上就显出三个爪子印。

当然啦"单点触摸"也是支持的,你用一个指头也能操作的,比如你用一个指头在《愤怒的小鸟》里拉动弹弓。我们就从简单的“单点触控”开始了解吧。

当我们把一个指头在屏幕上操作,可能会有这样三种动作:按,移动,移开。就拿《愤怒的小鸟》里拉动弹弓这个动作,首先我们是按下一个指头,然后向后移动,然后在屏幕上移开这个手指。

那么这三个操作在wp7的xna里如何获取呢?我们就需要了解xna里的touchpanel和touchcollection这两个类。

 

		touchcollection touchstate= touchpanel.getstate();
		foreach(touchlocation location in touchstate)
		{
		        switch(location.state)
		        {
		            case touchlocationstate.pressed://按下
		             ……
		            break;
		case touchlocationstate.moved://移动
		             ……
		            break;
		case touchlocationstate.released://释放
		             ……
		            break;
		 
		}
		 
		}

 

和触控操作类似的还有叫“手势”的,也算复杂的触控吧。

touchpanel.enabledgestures = gesturetype.freedrag;//用来指定手势,必须要先设定,否则报错

if (touchpanel.enabledgestures != gesturetype.none)

{

switch (touchpanel.readgesture())

{

case gesturetype.tap: //单击

break;

case gesturetype.doubletap://双击

break;

case gesturetype.freedrag://自由拖动

break;

case gesturetype.dragcomplete://拖动完成

break;

case gesturetype.flick://轻弹

break;

case gesturetype.hold://按住不动

break;

case gesturetype.horizontaldrag://横向拖动

break;

case gesturetype.none://无手势

break;

case gesturetype.pinch://捏

break;

case gesturetype.pinchcomplete://捏完

break;

case gesturetype.verticaldrag://纵向拖动

break;

}

}

 

3.2        编写menuentry类

如图3-1每一个菜单界面里都有多个菜单项,为了表示单个菜单项,我们就需要写一个menuentry类。

    菜单项可以在屏幕上输出文字来表示,为了美化还可以绘制图片来完成。菜单项一般都是纵向排列的,每个菜单项的坐标都不同,所以有这样两个属性:

        /// <summary>

        /// 菜单项文本内容

        /// </summary>

        public string text

        {

            get { return text; }

            set { text = value; }

        }

 

        /// <summary>

        /// 菜单项文本的位置

        /// </summary>

        public vector2 position

        {

            get { return position; }

            set { position = value; }

        }

 

  由于每个菜单项都会响应点击事件,所以我们需要声明一个事件:

        /// <summary>

        ///菜单项的选中事件

        /// </summary>

        public event eventhandler selected;

 

        /// <summary>

        ///选中菜单项函数

        /// </summary>

        internal void onselectentry()

        {

            if (selected != null)

            {

                ispress = true;

           

            }

        }

 

如果菜单项是图片构成的,为了让菜单项有按下动感,我们用图3-2里的三个图片来做一个三帧动画。


\

                                                    图3-2

      所以我们要用到四个变量:public texture2d menutexture,showtexture,presstexture,releasetexture;

      在菜单项的update函数里要做这样的处理

   private timespan duration = timespan.fromseconds(0.4);//菜单动画的执行时间为0.2秒

   public void update(bool isselected, gametime gametime)

        {

            if(ispress)

            {

                duration -=gametime.elapsedgametime;

               if (duration <= timespan.fromseconds(0.2)&& duration > timespan.fromseconds(0.1))

                {

                    showtexture = presstexture; //0.2-0.1秒之间显示三张图片中第二个图片

                }

                else  if (duration<= timespan.fromseconds(0.1) &&duration>timespan.zero)

                {

                    showtexture =eleasetexture;//0.1-0秒间显示三张图片中第三个图片

                }

                else if (duration <= timespan.zero)

                {

                    selected(this, new playerindexeventargs(playerindex));//菜单项按下动画完成触发selected事件

                    duration = timespan.fromseconds(0.4);           

                    ispress = false;

                }

            }

        }

3.3 编写menuscreen类

      由于菜单界面也是一个特殊的场景,所以menuscreen继承于gamescreen。

   如图3-3,menuscreen类结构如下:


\
 

                       图3-3

     我们着重分析下handleinput方法:

public override void handleinput(inputhelper input)

        {

                touchcollection touchstate =touchpanel.getstate();

                bool  touchdetected = false; //是否触碰菜单

                vector2 touchposition = new vector2();

               foreach(touchlocation location in touchstate)

               {

                     switch(location.state)

                    {

                             case touchlocationstate.pressed:

                                      touchdetected = true;

                                      touchposition = location.position;

                                      break;

                             case touchlocationstate.moved:

                                      break;

                             case touchlocationstate.released:

                                      break;

                  }

               }

      if(touchdetected)

{

foreach (menuentrymenuentry in menuentries)

                    {

                            rectangle    touchrect = new rectangle((int)touchposition.x - 5, (int)touchposition.y- 5,10, 10);

                            rectangle entryrect = new rectangle((int)menuentry.position.x- 5, (int)menuentry.position.y -                 5,menuentry.getwidth(this), menuentry.getheight(this));                             

                    if(entryrect.intersects(touchrect)) //如果触摸点在菜单项的矩形区域内

               menuentry.onselectentry();//触发菜单选中事件。

                }

      }

      ………………….

}

3.4编写mainmenuscreen类

      对于游戏主菜单界面而言,点击“play” 菜单项意味着要切入到游戏主场景里,点击“exit game”菜单意味着退出游戏,那么就需要在menuscreen扩展游戏场景切换的方法。在前一章节里我们简单介绍了游戏场景的管理类screenmanager,在这里就派上用途了。

      首先我们让mainmenuscreen继承于menuscreen:

public class mainmenuscreen:menuscreen

      {

}

然后我们添加了如下等方法:

/// <summary>

           /// 增加菜单项

           /// </summary>

          /// <param name="name">菜单文字</param>

          /// <param name="screen">点击对应要启动的screen</param>

          /// <param name="isexititem">是否是退出菜单</param>

          /// <param name="isshowloading">是否显示loading界面</param>

         /// <param name="position">菜单的坐标</param>
   public void addmainmenuitem(string name, gamescreen screen, bool isexititem, bool isshowloading,vector2 position)

       {

           this.isshowloading= isshowloading;

           menuentry entry = new menuentry(name,screen,isexititem, position);

           entry.selected += new system.eventhandler(entry_selected);

           menuentries.add(entry);

       }

       /// <summary>

       /// 菜单点击事件

       /// </summary>

       /// <param name="sender"></param>

       /// <param name="e"></param>

     void entry_selected(object sender, eventargs e)

       {

           menuentry menu = sender as menuentry;

           if(menu.isexititem) //如果是退出菜单

           {

               screenmanager.game.exit();

           }

           else

           {          
                screenmanager.addscreen(menu.screen,null);

           }

       }

此外,我们还需要写上inputhelper类,修改上一章节的gamescreen类,screenmanager类,在这两个类里加上对输入的支持。

在gamescreen类里我们加上handleinput方法:

                 public virtual void handleinput(inputhelper input)

                 {
 

                 }

    在screenmanager里我们需要修改update方法,增加对screen的输入响应:

       if(!otherscreenhasfocus)

        {

              screen.handleinput(input);

              otherscreenhasfocus = true;

        }

      具体代码修改请看具体的xnagamesample3这个demo。

     然后在game1.cs里的initialize()方法里我们就加上如下代码即可:

        mainmenuscreen mainmenu = newmainmenuscreen("castle defense");

        gamemainscreen main = new gamemainscreen();

        vector2 position = new vector2{ x = 0f, y = 0f };

        mainmenu.addmainmenuitem("play", main, false,true, position);

        mainmenu.addmainmenuitem("exit", null,true, false,position);

        screenmanager.addscreen(mainmenu, null);
 

 最后的代码运行效果如图3-4:



\

 

demo 下载地址:

 

   本文版权属于williams所有

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网