游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2198|回复: 4

关于碰撞检测!

[复制链接]

7

主题

27

帖子

27

积分

注册会员

Rank: 2

积分
27
发表于 2009-5-21 19:00:00 | 显示全部楼层 |阅读模式
关于碰撞检测这个问题,在游戏中如何判定?
我自学到这里,不知道如何前进了,
比如2D游戏,人物与边界怎么检测碰撞,如果用矩形检测,那岂不是要不停的算距离?
那么要如何正确的取到和人物挨着的那个矩形呢?
那位给点代码或者讲解下,谢谢,论坛的哪几篇没怎么看懂!

59

主题

404

帖子

404

积分

中级会员

Rank: 3Rank: 3

积分
404
发表于 2009-5-21 19:06:00 | 显示全部楼层

Re:关于碰撞检测!

要如何正确的取到和人物挨着的那个矩形呢?

循环场景中所有可能会碰撞的物体, 然后检测是否碰撞.

一般把一个大场景划分成许多个小区, 只要循环和物体同一小区内的物体就可以了. 大大降低了运行成本.

关于碰撞检测, 你可以想想如何判断两个RECT是否相交.

或者判断两个点之间的距离. 如果距离小于xx则说明碰撞了.

更精确的碰撞检测是"矢量碰撞", 如 线-线 相交检测, 三角形-三角形 检测, 三角形-点 检测(用于高精度 鼠标与UI 的碰撞检测).

59

主题

404

帖子

404

积分

中级会员

Rank: 3Rank: 3

积分
404
发表于 2009-5-21 19:08:00 | 显示全部楼层

Re:关于碰撞检测!

给一个 三角形- 点 的碰撞检测代码:



#ifndef _Hit_h_
#define _Hit_h_

#include <math.h>
#include <vector>

#define MIN_FLOAT        0.00001f
#define FLOAT_EQUAL(_a, _b)    (fabs((_a) - (_b)) < MIN_FLOAT)
#define HTP_LEFT        0x1
#define HTP_RIGHT        0x2
#define HTP_UP            0x4
#define HTP_DOWN        0x8

// 直线
typedef struct _Line
{
    float    x, y, dx, dy;    // 经过的一个点坐标
    float    k;                // 斜率
    bool    v;                // 是否垂直(忽略斜率)
    char    side;            // 正确的面
   
    _Line() : x(0), y(0), dx(0), dy(0), k(0), v(false), side(0) {}
   
    _Line(float x1, float y1, float x2, float y2, char s)
    {
        FillLine(x1, y1, x2, y2, s);
    }
   
    void FillLine(float x1, float y1, float x2, float y2, char s)
    {
        // 分母为0
        if(FLOAT_EQUAL(x2, x1))
        {
            x = x1;
            y = y1;
            k = 0;
            v = true;
        }
        else
        {
            x = x1;
            y = y1;
            k = (y2 - y1) / (x2 - x1);
            v = false;
        }
        dx = x2;
        dy = y2;
        side = s;
    }
   
    // 返回的是点相对于线的位置
    char TestPoint(float px, float py) const
    {
        char flag = 0;
        float t;
        
        // 垂直
        if(v)
        {
            t = px - x;
            if(t >= 0) flag |= HTP_RIGHT;
            if(t <= 0) flag |= HTP_LEFT;
        }
        // 水平
        else if(fabs(k) < MIN_FLOAT)
        {
            t = py - y;
            if(t >= 0) flag |= HTP_DOWN;
            if(t <= 0) flag |= HTP_UP;
        }
        else
        {
            float ox = (py - y) / k;
            float tmpx = x + ox;

            t = px - tmpx;
            if(t >= 0) flag |= HTP_RIGHT;
            if(t <= 0) flag |= HTP_LEFT;
            
            float oy = t * k;
            if(oy >= 0) flag |= HTP_UP;
            if(oy <= 0) flag |= HTP_DOWN;
        }
        return flag;
    }

    bool HitPoint(float px, float py) const
    {
        char flag = TestPoint(px, py);

        bool bLR = false, bUD = false;

        if(side & HTP_LEFT)
        {
            if(flag & HTP_LEFT) bLR = true;
        }
        else if(side & HTP_RIGHT)
        {
            if(flag & HTP_RIGHT) bLR = true;
        }
        else bLR = true;

        if(side & HTP_UP)
        {
            if(flag & HTP_UP) bUD = true;
        }
        else if(side & HTP_DOWN)
        {
            if(flag & HTP_DOWN) bUD = true;
        }
        else bUD = true;

        return bLR && bUD;
    }

    void SetSide(float px, float py)
    {
        char flag = TestPoint(px, py);
        side = flag;
    }

    bool operator == (const _Line& ln) const
    {
        return (v == ln.v) && FLOAT_EQUAL(x, ln.x) && FLOAT_EQUAL(y, ln.y) && FLOAT_EQUAL(k, ln.k);
    }

    bool operator != (const _Line& ln) const
    {
        return !(*this == ln);
    }
   
} Line;

// 检测三角形是否与点成功碰撞
#define IS_HITTING(_val)    ((_val) == 0xF)

// 三角形
class Triangle
{
public:
    Triangle() {}

    Triangle(float x1, float y1, float x2, float y2, float x3, float y3, char s1, char s2, char s3)
    {
        FillTriangle(x1, y1, x2, y2, x3, y3, s1, s2, s3);
    }

    void FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3, char s1, char s2, char s3)
    {
        m_Edges[0].FillLine(x1, y1, x2, y2, s1);
        m_Edges[1].FillLine(x2, y2, x3, y3, s2);
        m_Edges[2].FillLine(x3, y3, x1, y1, s3);
    }

    bool HitPoint(float px, float py) const
    {
        bool bOK = true;
        bOK = bOK && m_Edges[0].HitPoint(px, py);
        bOK = bOK && m_Edges[1].HitPoint(px, py);
        bOK = bOK && m_Edges[2].HitPoint(px, py);
        return bOK;
    }

    void GetEdges(Line edges[3]) const
    {
        edges[0] = m_Edges[0];
        edges[1] = m_Edges[1];
        edges[2] = m_Edges[2];
    }

    void SetSide(float px, float py)
    {
        m_Edges[0].SetSide(px, py);
        m_Edges[1].SetSide(px, py);
        m_Edges[2].SetSide(px, py);
    }

    bool operator == (const Triangle& tri) const
    {
        return (m_Edges[0] == tri.m_Edges[0]) && (m_Edges[1] == tri.m_Edges[1]) && (m_Edges[2] == tri.m_Edges[2]);
    }

    bool operator != (const Triangle& tri) const
    {
        return !(*this == tri);
    }
   
private:
    // 三边
    Line    m_Edges[3];
};

// 多边形
class Shape
{
public:
    virtual ~Shape() {}

    void AddTriangle(const Triangle& tri)
    {
        m_Polygon.push_back(tri);
    }

    void Clear()
    {
        m_Polygon.clear();
    }

    bool HitPoint(float px, float py) const
    {
        for(TriangleList::const_iterator i = m_Polygon.begin(); i != m_Polygon.end(); i++)
        {
            if(i->HitPoint(px, py)) return true;
        }
        return false;
    }
   
protected:
    typedef std::vector<Triangle>    TriangleList;
    TriangleList    m_Polygon;
};

#endif

30

主题

146

帖子

152

积分

注册会员

Rank: 2

积分
152
发表于 2009-5-21 19:21:00 | 显示全部楼层

Re:关于碰撞检测!

windows游戏编程大师技巧

7

主题

27

帖子

27

积分

注册会员

Rank: 2

积分
27
 楼主| 发表于 2009-5-21 22:02:00 | 显示全部楼层

Re:关于碰撞检测!

谢谢大家,有点领悟了
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-12-20 07:52

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表