zoukankan      html  css  js  c++  java
  • 【转】Cocos2d-x 3.x基础学习: 总结数学类Vec2/Size/Rect

    转载:http://www.taikr.com/article/1847

     在Cocos2d-x 3.x中,数学类Vec2、Size、Rect,是比较常用的类。比如设置图片位置,图片大小,两图片的碰撞检测等等。今天我们以Cocos2d-x 3.2版本为例,学习和总结一下这三个常用类。

            比起2.x版本,在3.2版本中本质上其实没有太大的变化,主要的变化就是将全局宏定义相关的操作封装到各自的类中而已。比如:Vec2的向量运算宏定义ccp***(),现在都已经封装到Vec2类里面去了。

    【Vec2】

    Vec2原名Point,它既可以表示一个二维坐标点,又可以表示一个二维向量。

    同时Vec2对运算符进行了重载,可以很方便的完成Vec2的赋值、加减乘除等操作。另外还有与坐标向量相关的:距离、角度、点积、叉积、投影、标准化等操作。

    此外在3.x中,还将2.x里的函数定义ccp***(如ccp,ccpAdd,ccpSub)相关的操作都封装到了这个Vec2的类中,这样就可以更加系统化地管理向量的运算操作了。

    此外,除了Vec2。还有两个坐标类:Vec3、Vec4,分别代表了三维、四维坐标向量。

    查看2.x与3.x的变化请查看:《总结Cocos2d-x 3.x版本的一些变化》

    Vec2可以是一个二维坐标点,也可以是一个二维向量。

    wKioL1Ps8TCROQmnAAAu3KSrIzs480.jpg

    1、创建方式

    //

    /**

    * Vec2只有两个成员变量x , y

    */

    float x; //X坐标

    float y; //Y坐标

    /**

    * 构造函数

    */

    Vec2(); //(0 , 0)

    Vec2(float xx, float yy); //(xx , yy)

    Vec2(const float* array); //(array[0] , array[1])

    Vec2(const Vec2& copy); //copy

    Vec2(const Vec2& p1, const Vec2& p2); //p2 - p1

    //

    2、设置向量坐标

    使用set可以给向量重新设置新坐标值。

    //

    void set(float xx, float yy); //(xx , yy)

    void set(const float* array); //(array[0] , array[1])

    void set(const Vec2& v); //v

    void set(const Vec2& p1, const Vec2& p2); //p2 - p1

    //

    3、向量运算

    其中包含了一些2.x中的ccp***()宏定义的函数,都全部封装到了Vec2类中。

    //

    /**

    * 向量运算

    * void : 自身运算 , 值会改变

    * 有返回值 : 返回运算结果, 值不会改变

    */

    void add(const Vec2& v); //相加( x+v.x , y+v.y )

    void subtract(const Vec2& v); //相减( x-v.x , y-v.y )

    void clamp(const Vec2& min, const Vec2& max); //将向量值限制在[min,max]区间内

    void negate(); //向量取负( -x , -y )

    void normalize(); //标准化向量. 若为零向量,忽略

    void scale(float scalar); //x,y坐标同时放缩

    void scale(const Vec2& scale); //x,y坐标分别放缩

    void rotate(const Vec2& point, float angle); //绕point点, 旋转angle弧度

    float dot(const Vec2& v) const; //点积: x*v.x + y*v.y

    float cross(const Vec2& v) const; //叉积: x*v.y - y*v.x

    Vec2 project(const Vec2& v) const; //投影: 向量在v上的投影向量

    float distance(const Vec2& v) const; //与v的距离.

    float distanceSquared(const Vec2& v) const; //与v的距离平方.

    float length() const; //向量长度. 即与原点的距离

    float lengthSquared() const; //向量长度平方. 即与原点的距离平方

    Vec2 getNormalized() const; //获取向量的标准化形式. 若为零向量,返回(0,0)

    inline Vec2 getPerp() const; //逆时针旋转90度. Vec2(-y, x);

    inline Vec2 getRPerp() const //顺时针旋转90度. Vec2(y, -x);

    inline float getAngle() const; //与X轴的夹角(弧度)

    float getAngle(const Vec2& v) const; //与v向量的夹角(弧度)

    inline Vec2 getMidpoint(const Vec2& v) const; //计算两点间的中点

    //将向量值限制在[min,max]区间内,返回该点

    inline Vec2 getClampPoint(const Vec2& min, const Vec2& max) const

    {

    return Vec2(clampf(x, min.x, max.x), clampf(y, min.y, max.y));

    }

    bool isZero() const; //是否为(0,0)

    bool isOne() const; //是否为(1,1)

    //判断target是否在坐标点模糊偏差为var的范围内.

    //if( (x - var <= target.x && target.x <= x + var) &&

    // (y - var <= target.y && target.y <= y + var) )

    // return true;

    bool fuzzyEquals(const Vec2& target, float variance) const;

    //以pivot为轴, 逆时针旋转angle度(弧度)

    Vec2 rotateByAngle(const Vec2& pivot, float angle) const;

    //绕other向量旋转

    //返回向量: 角度 this.getAngle() +other.getAngle();

    // 长度 this.getLength()*other.getLength();

    inline Vec2 rotate(const Vec2& other) const {

    return Vec2(x*other.x - y*other.y, x*other.y + y*other.x);

    };

    //绕other向量旋转前的向量值

    //返回向量: 角度 this.getAngle() -other.getAngle();

    // 长度 this.getLength()*other.getLength();

    //(这里是不是有点问题,难道不应该是this.getLength()/other.getLength()么?)

    inline Vec2 unrotate(const Vec2& other) const {

    return Vec2(x*other.x + y*other.y, y*other.x - x*other.y);

    };

    //两个点a和b之间的线性插值

    //alpha ==0 ? a alpha ==1 ? b 否则为a和b之间的一个值

    inline Vec2 lerp(const Vec2& other, float alpha) const {

    return *this * (1.f - alpha) + other * alpha;

    };

    //平滑更新向量的当前位置,指向目标向量target.

    //responseTime定义了平滑时间量,该值越大结果越平滑,相应的延迟时间越长。

    //如果希望向量紧跟target向量,提供一个相对elapsedTime小很多的responseTime值即可。

    //参数

    //target 目标值

    //elapsedTime 消逝时间

    //responseTime 响应时间

    void smooth(const Vec2& target, float elapsedTime, float responseTime);

    /**

    * 自定义运算

    * compOp

    */

    //对该点向量形式的各分量进行function参数来指定的运算,

    //如absf,floorf,ceilf,roundf等,

    //任何函数拥有如下形式:float func(float)均可。

    //例如:我们对x,y进行floor运算,则调用方法为p.compOp(floorf);

    //3.0

    inline Vec2 compOp(std::function function) const

    {

    return Vec2(function(x), function(y));

    }

    /**

    * 兼容代码

    * 估计是要被抛弃了~(>_<)~

    */

    void setPoint(float xx, float yy); //同set(float xx, float yy)

    bool equals(const Vec2& target) const; //同==

    float getLength() const; //同length()

    float getLengthSq() const; //同lengthSquared()

    float getDistance(const Vec2& other) const; //同distance(const Vec2& v)

    float getDistanceSq(const Vec2& other) const; //同distanceSquared(const Vec2& v)

    //

    4、运算符重载

    //

    inline const Vec2 operator+(const Vec2& v) const; //( x+v.x , y+v.y )

    inline const Vec2 operator-(const Vec2& v) const; //( x-v.x , y-v.y )

    inline const Vec2 operator*(float s) const; //( x*s , y*s )

    inline const Vec2 operator/(float s) const; //( x/s , y/s )

    inline const Vec2 operator-() const; //( -x , -y )

    inline Vec2& operator+=(const Vec2& v); //(x,y) = ( x+v.x , y+v.y )

    inline Vec2& operator-=(const Vec2& v); //(x,y) = ( x-v.x , y-v.y )

    inline Vec2& operator*=(float s); //(x,y) = ( x*s , y*s )

    inline bool operator<(const Vec2& v) const;

    inline bool operator==(const Vec2& v) const;

    inline bool operator!=(const Vec2& v) const;

    //

    5、静态函数与常量

    //

    /**

    * 静态方法

    */

    static void add(const Vec2& v1, const Vec2& v2, Vec2* dst); //dst = v1 + v2

    static void subtract(const Vec2& v1, const Vec2& v2, Vec2* dst); //dst = v1 - v2

    static void clamp(const Vec2& v, const Vec2& min, const Vec2& max, Vec2* dst); //将向量v限制在[min,max]区间内,结果存入dst

    static float angle(const Vec2& v1, const Vec2& v2); //两向量夹角(弧度)

    static float dot(const Vec2& v1, const Vec2& v2); //两向量点积

    static inline Vec2 forAngle(const float a); //返回向量坐标 x=cos(a) , y=sin(a)

    /**

    * 静态常量

    */

    static const Vec2 ZERO; //Vec2(0, 0)

    static const Vec2 ONE; //Vec2(1, 1)

    static const Vec2 UNIT_X; //Vec2(1, 0)

    static const Vec2 UNIT_Y; //Vec2(0, 1)

    static const Vec2 ANCHOR_MIDDLE; //Vec2(0.5, 0.5)

    static const Vec2 ANCHOR_BOTTOM_LEFT; //Vec2(0, 0)

    static const Vec2 ANCHOR_TOP_LEFT; //Vec2(0, 1)

    static const Vec2 ANCHOR_BOTTOM_RIGHT; //Vec2(1, 0)

    static const Vec2 ANCHOR_TOP_RIGHT; //Vec2(1, 1)

    static const Vec2 ANCHOR_MIDDLE_RIGHT; //Vec2(1, 0.5)

    static const Vec2 ANCHOR_MIDDLE_LEFT; //Vec2(0, 0.5)

    static const Vec2 ANCHOR_MIDDLE_TOP; //Vec2(0.5, 1)

    static const Vec2 ANCHOR_MIDDLE_BOTTOM; //Vec2(0.5, 0)

    //

    6、线段相交检测

    这些用于检测线段相交的函数,也都是静态的成员函数。

    //

    /**

    线段相交检测 v3.0

    参数:

    A 为线段L1起点. L1 = (A - B)

    B 为L1终点 . L1 = (A - B)

    C 为线段L2起点. L2 = (C - D)

    D 为L2终点 . L2 = (C - D)

    S 为L1上计算各点的插值参数,计算方法为:p = A + S*(B - A)

    T 为L2上计算各点的插值参数,计算方法为:p = C + T*(D - C)

    */

    //直线AB与线段CD是否平行

    static bool isLineParallel(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D);

    //直线AB与线段CD是否重叠

    static bool isLineOverlap(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D);

    //直线AB与直线CD是否相交

    static bool isLineIntersect(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D,

    float *S = nullptr, float *T = nullptr);

    //线段AB与线段CD是否重叠

    static bool isSegmentOverlap(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D,

    Vec2* S = nullptr, Vec2* E = nullptr);

    //线段AB与线段CD是否相交

    static bool isSegmentIntersect(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D);

    //返回直线AB与直线CD的交点

    static Vec2 getIntersectPoint(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D);

    //

    【Size】

    Size比较简单,只是一个用来表示尺寸大小的类。宽为width,高为height。

    和Vec2一样,也对一些运算符进行了重载。

    与2.x相比,没有太大的变化。

    PS:因为和Vec2一样,都只有两个成员变量,所以Size和Vec2之间可以相互转换。

    主要函数如下:

    //

    class CC_DLL Size

    {

    /**

    * Size只有两个成员变量width , height

    */

    float width; //宽

    float height; //高

    /**

    * 构造函数

    */

    Size(); //(0, 0)

    Size(float width, float height); //(width, height)

    Size(const Size& other); //other

    explicit Size(const Vec2& point); //(显式)构造函数. 构造时Size size = Size(Vec2&), 而不能Size size = vec2;

    /**

    * 相关操作

    * - setSize

    * - equals

    * - Vec2()

    */

    void setSize(float width, float height); //设置尺寸

    bool equals(const Size& target) const; //判断是否等于target

    //Size::Vec2()

    //返回类型为Vec2

    operator Vec2() const { return Vec2(width, height); }

    /**

    * 静态常量

    */

    static const Size ZERO; //(0, 0)

    /**

    * 运算符重载

    */

    Size& operator= (const Size& other);

    Size& operator= (const Vec2& point); //可以用Vec2赋值

    Size operator+(const Size& right) const;

    Size operator-(const Size& right) const;

    Size operator*(float a) const;

    Size operator/(float a) const;

    };

    //

    【Rect】

    Rect是一个矩形类。包含两个成员属性:起始坐标(左下角)Vec2、矩阵尺寸大小Size。

    Rect只对“=”运算符进行了重载。

    与2.x相比,多了一个函数unionWithRect,用于合并两个矩形。

    值得注意的是Rect类中:

    intersectsRect函数,可以用作两个Rect矩形是否相交,即碰撞检测。

    containsPoint函数,可以用作判断点Vec2是否在Rect矩形中。

    unionWithRect函数,可以用做将两矩形进行合并操作。

    wKiom1Ps83TytTN3AABEUdrO2HE928.jpg

    1、主要函数如下:

    //

    class CC_DLL Rect

    {

    public:

    Vec2 origin; //起始坐标: 矩形左下角坐标

    Size size; //尺寸大小

    /**

    * 构造函数

    */

    Rect();

    Rect(float x, float y, float width, float height);

    Rect(const Rect& other);

    /**

    * 运算符重载

    * 只重载了 “=” 运算符

    */

    Rect& operator= (const Rect& other);

    /**

    * 相关操作

    * - setRect

    * - getMinX , getMidX , getMaxX

    * - getMinY , getMidY , getMaxY

    * - equals , containsPoint , intersectsRect

    * - unionWithRect

    */

    //设置矩形

    void setRect(float x, float y, float width, float height);

    //获取矩形信息

    float getMinX() const; //origin.x

    float getMidX() const; //origin.x + size.width/2

    float getMaxX() const; //origin.x + size.width

    float getMinY() const; //origin.y

    float getMidY() const; //origin.y + size.height/2

    float getMaxY() const; //origin.y + size.height

    //判断是否与rect相同. 原点相同,尺寸相同.

    bool equals(const Rect& rect) const;

    //判断point是否包含在矩形内或四条边上

    bool containsPoint(const Vec2& point) const;

    //判断矩形是否相交. 常常用作碰撞检测.

    bool intersectsRect(const Rect& rect) const;

    //与rect矩形合并. 并返回结果. v3.0

    //不会改变原矩形的值

    Rect unionWithRect(const Rect & rect) const;

    /**

    * 静态常量

    * Rect::ZERO

    */

    static const Rect ZERO;

    };

    //

    2、精灵创建中的一种方式:

    还记得Sprite的几种创建方式吗?里面有一种创建方式如下:

    1Sprite::create(conststd::string&filename,constRect&rect)

    若用Rect来作为创建Sprite精灵的参数,需要注意,从大图中截取某一区域的图片的Rectrect的构造应该是这样的:

    Rect("小图左上角坐标x","小图左上角坐标y",小图宽,小图高);

    使用的是UIKit坐标系,而不是cocos2dx的OpenGL坐标系是不一样的。

    如下图所示:

    wKioL1P1nT-juGOSAADARBo6V0E608.jpg

    3、矩形合并函数unionWithRect

    看几张图,你应该就会明白了。

    两个黑色矩形区域,使用unionWithRect合并后,变成红色矩形区域。

  • 相关阅读:
    Count and Say leetcode
    Find Minimum in Rotated Sorted Array II leetcode
    Find Minimum in Rotated Sorted Array leetcode
    Search in Rotated Sorted Array II leetcode
    search in rotated sorted array leetcode
    Substring with Concatenation of All Words
    Subsets 子集系列问题 leetcode
    Sudoku Solver Backtracking
    Valid Sudoku leetcode
    《如何求解问题》-现代启发式方法
  • 原文地址:https://www.cnblogs.com/eggtomcato/p/10113560.html
Copyright © 2011-2022 走看看