碰撞检测在几乎任何游戏都是很关键的一个部分,而碰撞检测又决定了游戏的流畅性,它对流畅性的影响如何之大的原因,在于碰撞检测算法越是精确到位,游戏将会运行得越缓慢。在碰撞检测方面,很明显需要在准确性和性能之间进行权衡。

实现碰撞检测最简单和快速的方式是通过包围盒算法。当用一个包围盒算法时,就需要在屏幕上的每个物体(纹理图像)周围“画“一个盒子(矩形块),然后检查这些盒子是否相交,如果产生相交(怎么听起来这么耳熟?),就即可判断出是产生碰撞了。经典的碰撞游戏可以看看如今某I设备上风靡全球的小鸟

通过物理算法和碰撞检测等实现这只小鸟欺负小猪的传说,这点是很值得借鉴滴。

本篇学习文章将会有两个纹理图,一个图片做为碰撞块例如上图的小鸟,另一个图片做为需要在某一地方去检测是否与之产生碰撞的纹理,例如上图的小猪或者城墙。这两张图片分别是这样的:

我是用来检测是否有人撞到我的。。。。。

 我没事喜欢撞人。。。。。。

好了。素材己经有了,下面就到了如何为这两个纹理图像添加各种出场的告白动作了。首先,还是国际惯例一把,先给出效果图:

看上图效果,天上掉下了好多尖尖的小块呀,快逃命呀,不过小人跑不够快,被一个尖尖的小块砸到了,顿时满脸是血,屏幕都被染红了。悲催咯。。。。

要实现这个功能首先我们需要得到小人的碰撞点,和每一个三角形的碰撞点。以获得小人碰撞点为例,需要得到小人所在的x 坐标和y坐标,并且得到小人的宽度和高度。当我们获取到这个数据的时候,就可以为小人添加一个包围圈也叫矩形检测块:

// 获得小人的磁撞大小和碰撞的地点 
            //公式为:得到小人所在的x、y 地点,然后在那个x、y点的区域高宽
            Rectangle personRectangle =
                new Rectangle((int)personPosition.X, (int)personPosition.Y,
                personTexture.Width, personTexture.Height); 

当得到这个矩形块时。再依次获取得到每个三角形的矩形和其位置使用矩形自带的函数Intersects 来检测两个矩形之者是否产生交接:

 // 与上面获得小人的碰撞点类似
                Rectangle blockRectangle =
                    new Rectangle((int)blockPositions[i].X, (int)blockPositions[i].Y,
                    blockTexture.Width, blockTexture.Height);

// 如果小人与其中某一个碰撞纹理的碰撞点产生碰撞
                if (personRectangle.Intersects(blockRectangle))

personHit = true;   //这时的碰撞检测将生效

如上,如果产生交接即在调用Draw 的时候改变屏幕的颜色,即可产生碰撞时的效果,DEMO源码为:

 /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D personTexture;    //小人纹理图像
        Texture2D blockTexture;     //撞击点纹理图像

// Person 
        Vector2 personPosition;     //小人2D坐标
        const int PersonMoveSpeed = 5;  //小人移动速度

// Blocks
        List<Vector2> blockPositions = new List<Vector2>(); //撞击点集合
        float BlockSpawnProbability = 0.1f;     //控制撞击点的下降个数
        const int BlockFallSpeed = 10;  //撞击点下降速度

Random random = new Random();
         
        bool personHit = false;         //是否产生碰撞
         
        Rectangle safeBounds; 
        const float SafeAreaPortion = 0.05f;
        Viewport viewport;  //获得当前窗口的宽高对象

public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content"; 
            // Frame rate is 30 fps by default for Windows Phone.
            TargetElapsedTime = TimeSpan.FromTicks(333333);
        }

/// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
              viewport = graphics.GraphicsDevice.Viewport;
            safeBounds = new Rectangle(
                (int)(viewport.Width * SafeAreaPortion),    //40
                (int)(viewport.Height * SafeAreaPortion),   //24
                (int)(viewport.Width * (1 - 2 * SafeAreaPortion)),  //720
                (int)(viewport.Height * (1 - 2 * SafeAreaPortion)));    //432

// Start the player in the center along the bottom of the screen
            
            base.Initialize();
        }

/// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        { 
            spriteBatch = new SpriteBatch(GraphicsDevice);
            blockTexture = Content.Load<Texture2D>("Block");
            personTexture = Content.Load<Texture2D>("Person");
            personPosition.X = (safeBounds.Width - personTexture.Width) / 2;    //小人的坐标纵向在屏幕居中
            personPosition.Y = safeBounds.Height - personTexture.Height;    //小人的坐标竖向在屏幕底下居中
         
            // TODO: use this.Content to load your game content here
        }

/// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

/// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

TouchCollection touch = TouchPanel.GetState();
            if (touch.Count>0)
            {
                if (touch[0].Position.X > viewport.Width / 2)
                {
                    personPosition.X += PersonMoveSpeed;
                }
                else
                {
                    personPosition.X -= PersonMoveSpeed;
                }
            }

double ran = random.NextDouble();
            // TODO: Add your update logic here
            if (ran < BlockSpawnProbability)    //随机循环Double 型如果随机的double 小于0.01f这样做是避免产生的撞击 点太多
            { 
                float x = (float)random.NextDouble() *//在屏幕随机出现 
                    (graphics.GraphicsDevice.Viewport.Width - blockTexture.Width);//为了不超出屏幕 
                Vector2 v = new Vector2(x, 1);
                blockPositions.Add(v);
            }

// 获得小人的磁撞大小和碰撞的地点 
            //公式为:得到小人所在的x、y 地点,然后在那个x、y点的区域高宽
            Rectangle personRectangle =
                new Rectangle((int)personPosition.X, (int)personPosition.Y,
                personTexture.Width, personTexture.Height);

// Update each block
            personHit = false;  //默认为不碰撞状态
            for (int i = 0; i < blockPositions.Count; i++)  //循环所有在集合里面的碰撞纹理
            {
                // 使里面的所有元素全部下降
                blockPositions[i] =
                    new Vector2(blockPositions[i].X,    //X坐标不变
                                blockPositions[i].Y + BlockFallSpeed);  //竖坐标为当前的Y座标每次加上下降的速度常量

// 与上面获得小人的碰撞点类似
                Rectangle blockRectangle =
                    new Rectangle((int)blockPositions[i].X, (int)blockPositions[i].Y,
                    blockTexture.Width, blockTexture.Height);

// 如果小人与其中某一个碰撞纹理的碰撞点产生碰撞
                if (personRectangle.Intersects(blockRectangle))
                    personHit = true;   //这时的碰撞检测将生效

// 如果有碰撞纹理超屏幕
                if (blockPositions[i].Y > graphics.GraphicsDevice.Viewport.Height)
                {   
                    //从集合里面移出该碰撞点
                    blockPositions.RemoveAt(i);
                     
                    //当删除了其中一个碰撞点时,下一个碰撞点的索引将跟当前移除的碰撞点是一样的,所以循环变量自动减1 
                    i--;
                }
            }
            base.Update(gameTime);
        }

/// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            GraphicsDevice device = graphics.GraphicsDevice;
            // TODO: Add your drawing code here
            if (personHit)  //当产生碰撞
            {
                device.Clear(Color.Red);
            }
            else
            {
                device.Clear(Color.CornflowerBlue);
            }

spriteBatch.Begin();

// Draw person
            spriteBatch.Draw(personTexture, personPosition, Color.White);

// Draw blocks
            foreach (Vector2 blockPosition in blockPositions)
                spriteBatch.Draw(blockTexture, blockPosition, Color.White);

spriteBatch.End();

base.Draw(gameTime);
        }

}

轻轻松松的调用几个现成的方法和利用刷新机制就可以实现这个碰撞检测功能。当然碰撞检测还不止这么简单,还可以更详细的使用逐点检测的方法检测碰撞。

 本文转自 terry_龙 51CTO博客,原文链接:http://blog.51cto.com/terryblog/527186,如需转载请自行联系原作者

WP7进阶】——XNA游戏平面矩形碰撞检测相关推荐

  1. WP7平衡球游戏开发教程--初识XNA Faeseer Magic

    小时候,我就想要自己做游戏,今天的技术已经发展得如此便利,我们可以很容易地创建简单的游戏.本文试图建立一个可重用的基于组件的游戏框架,减少了我们建立基于物理引擎的XNA游戏所需的时间. 我认为我们应该 ...

  2. xnawindowsphCocos2d-x for XNA游戏引擎全面支持WP7

    近日,开源社区cocos2d-x.org针对微软移动操作系统WindowsPhone7平台发布了一款新的游戏引擎,并正式命名为cocos2d-xforXNA.从此,开发者无需学习XNA绘图接口就可采用 ...

  3. [Cocos2d-x For WP8]矩形碰撞检测

    在游戏中我们通常会涉及到两个精灵之间的碰撞的计算,那么在Cocos2d-x里面我们通常会用矩形碰撞检测来计算两个精灵在运动的过程中是否碰撞到了.原理很简单,就是当运动的时候通过精灵的矩形坐标进行遍历来 ...

  4. 碰撞检测碰撞Java简单游戏开发之碰撞检测

    最近研究碰撞检测碰撞,稍微总结一下,以后继续补充: 前言 未几之前在论坛上有人发贴,使用java编写的超级马里奥如何实现碰撞检测,笔者自己以前 也做过Tank大战.里面一样涉及到碰撞检测,翻翻U盘里的 ...

  5. J2ME下的游戏精灵的碰撞检测(转)

    碰撞检测又称为冲突检测,是确定精灵之间是否相互冲突的一种方法.碰撞检测用来确定精灵之间何时会发生物理的相互作 用.例如,在游戏中,如果玩家精灵与小飞机精灵发生碰撞,玩家生命值将会降低.碰撞检测就是用来 ...

  6. Java ME游戏开发中,碰撞检测算法在Java?ME中的实现(

    2019独角兽企业重金招聘Python工程师标准>>> 在Java ME游戏开发中,碰撞检测算法在Java?ME中的实现(百搜技术) 在Java ME游戏开发中,经常需要进行碰撞检测 ...

  7. XNA游戏:Hello XNA

    下面创建一个简单的Windows Phone 7的XNA 程序,只是一个Hello XNA的文本,从屏幕的左上角一直往右下角移动,通过该例子来开始Windows Phone 7 XNA的游戏编程. 新 ...

  8. Win8 Metro App里玩XNA:移植XNA游戏到Win8

    Win8 Metro App里玩XNA:移植XNA游戏到Win8   Ready ! 在本文中,将把一个WindowsPhoneXNA的游戏移植到Win8 Metro(Modern)风格上,直接在Wi ...

  9. 手游《奔跑吧?骚年!》技术分享(四):矩形碰撞检测

    手游<奔跑吧?骚年!>技术分享(四):矩形碰撞检测 今天来分享一下游戏中的碰撞处理,基本上横版2D游戏内的物体,都可以用矩形来表示(有时也需要用三角形来检测).通常就判断一下是否碰撞是不够 ...

最新文章

  1. CoBigICP:一种基于相关熵以及双向匹配的鲁棒且准确的配准方法
  2. python 对字典排序
  3. PostgreSQL — 外键关联操作
  4. Docker容器通过独立IP暴露给局域网的方法
  5. tensorflow3 非线性回归、mnist、简单神经网络
  6. 神经网络-损失函数:
  7. 什么是MPLS?多协议标签交换
  8. 【报告分享】2020年中国企业直播服务市场研究报告.pdf(附下载链接)
  9. [VSCode] Ubuntu 16.04 安装/更新 vscode
  10. python如何存储numpy数组_python – 如何将numpy数组作为对象存储在pandas数据框中?...
  11. LINUX下Android NDK下载并配置
  12. 陈绪:7月24日阿里云上海峰会出品人
  13. 关于typedef的使用
  14. Android ROM 制作教程
  15. net.sf.json.JSONObject.fromObject()方法的一个小秘密
  16. Synopsys Mentor Candence
  17. Word编辑公式的快捷键与命令
  18. 总结几款国内外在线的神级抠图工具
  19. 计算机应用 一级学科,一级学科、二级学科,考研专业哪个包含了计算机考研方向...
  20. 【Python PIL】用PIL绘制中国象棋棋盘

热门文章

  1. 程序员面试题精选100题(04)-二元树中和为某一值的所有路径[数据结构]
  2. 海量数据处理算法—Bit-Map
  3. Java.math包中常用的类
  4. IIS7 授权配置错误
  5. Create Custom Instruments
  6. Nexys3学习手记1:写在前面的话
  7. mysql保存中文乱码的原因和解决办法
  8. 解读JavaScript代码 var ie = !-[1,]
  9. 8月下旬国内域名注册商净增量Top10
  10. 让你的网页达到最好的视觉效果