cocos2dx3.2技术之数学类Vec2/Size/Rect浅析

【唠叨】

数学类Vec2、Size、Rect,是cocos2dx中比较常用的类。

比如设置图片位置,设置图片大小,两图片的碰撞检测等等。

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


【Vec2】

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

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

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

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

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

cocos2dx3.2技术之数学类Vec2/Size/Rect浅析 - 第1张  | 游戏开发网-最好的游戏编程开发技术网站!

1、创建方式

//
/**
 * Vec2只有两个成员变量x , y
 */
    floatx; //X坐标
    floaty; //Y坐标
/**
 * 构造函数
 */
    Vec2();                                   //(0 , 0)
    Vec2(floatxx, floatyy);                 //(xx , yy)
    Vec2(constfloat* array);                 //(array[0] , array[1])
    Vec2(constVec2& copy);                   //copy
    Vec2(constVec2& p1, constVec2& p2);     //p2 – p1
//

2、设置向量坐标

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

//
    voidset(floatxx, floatyy);             //(xx , yy)
    voidset(constfloat* array);             //(array[0] , array[1])
    voidset(constVec2& v);                  //v
    voidset(constVec2& p1, constVec2& p2); //p2 – p1
//

3、向量运算

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

//
/**
 * 向量运算
 *     void     : 自身运算    , 值会改变
 *     有返回值 : 返回运算结果, 值不会改变
 */
    voidadd(constVec2& v);                      //相加( x+v.x , y+v.y )
    voidsubtract(constVec2& v);                 //相减( x-v.x , y-v.y )
    voidclamp(constVec2& min, constVec2& max); //将向量值限制在[min,max]区间内
    voidnegate();                                //向量取负( -x , -y )
    voidnormalize();                             //标准化向量. 若为零向量,忽略
    voidscale(floatscalar);                     //x,y坐标同时放缩
    voidscale(constVec2& scale);                //x,y坐标分别放缩
    voidrotate(constVec2& point, floatangle);  //绕point点, 旋转angle弧度
    floatdot(constVec2& v) const;               //点积: x*v.x + y*v.y
    floatcross(constVec2& v) const;             //叉积: x*v.y – y*v.x
    Vec2  project(constVec2& v) const;           //投影: 向量在v上的投影向量
    floatdistance(constVec2& v) const;          //与v的距离.
    floatdistanceSquared(constVec2& v) const;   //与v的距离平方.
    floatlength() const;                         //向量长度.     即与原点的距离
    floatlengthSquared() const;                  //向量长度平方. 即与原点的距离平方
    Vec2 getNormalized() const;                   //获取向量的标准化形式. 若为零向量,返回(0,0)
    inlineVec2 getPerp() const;                  //逆时针旋转90度. Vec2(-y, x);
    inlineVec2 getRPerp() const//顺时针旋转90度. Vec2(y, -x);
    inlinefloatgetAngle() const;                //与X轴的夹角(弧度)
    floatgetAngle(constVec2& v) const;   //与v向量的夹角(弧度)
    inlineVec2 getMidpoint(constVec2& v) const; //计算两点间的中点
    //将向量值限制在[min,max]区间内,返回该点
    inlineVec2 getClampPoint(constVec2& min, constVec2& max) const
    {
        returnVec2(clampf(x, min.x, max.x), clampf(y, min.y, max.y));
    }
    boolisZero() const; //是否为(0,0)
    boolisOne() const;  //是否为(1,1)
    //判断target是否在坐标点模糊偏差为var的范围内.
    //if( (x – var <= target.x && target.x <= x + var) &&
    //    (y – var <= target.y && target.y <= y + var) )
    //      return true;
    boolfuzzyEquals(constVec2& target, floatvariance) const;
    //以pivot为轴, 逆时针旋转angle度(弧度)
    Vec2 rotateByAngle(constVec2& pivot, floatangle) const;
    //绕other向量旋转
    //返回向量: 角度 this.getAngle() +other.getAngle();
    //          长度 this.getLength()*other.getLength();
    inlineVec2 rotate(constVec2& other) const{
        returnVec2(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()么?)
    inlineVec2 unrotate(constVec2& other) const{
        returnVec2(x*other.x + y*other.y, y*other.x – x*other.y);
    };
    //两个点a和b之间的线性插值
    //alpha ==0 ? a alpha ==1 ? b 否则为a和b之间的一个值
    inlineVec2 lerp(constVec2& other, floatalpha) const{
        return*this* (1.f – alpha) + other * alpha;
    };
    //平滑更新向量的当前位置,指向目标向量target.
    //responseTime定义了平滑时间量,该值越大结果越平滑,相应的延迟时间越长。
    //如果希望向量紧跟target向量,提供一个相对elapsedTime小很多的responseTime值即可。
    //参数
    //target        目标值
    //elapsedTime   消逝时间
    //responseTime  响应时间
    voidsmooth(constVec2& target, floatelapsedTime, floatresponseTime);
/**
 * 自定义运算
 *     compOp
 */
    //对该点向量形式的各分量进行function参数来指定的运算,
    //如absf,floorf,ceilf,roundf等,
    //任何函数拥有如下形式:float func(float)均可。
    //例如:我们对x,y进行floor运算,则调用方法为p.compOp(floorf);
    //3.0
    inlineVec2 compOp(std::function<float(float)> function) const
    {
        returnVec2(function(x), function(y));
    }
/**
 * 兼容代码
 *     估计是要被抛弃了~(>_<)~
 */
    voidsetPoint(floatxx, floatyy);           //同set(float xx, float yy)
    boolequals(constVec2& target) const;       //同==
    floatgetLength() const;                      //同length()
    floatgetLengthSq() const;                    //同lengthSquared()
    floatgetDistance(constVec2& other) const;   //同distance(const Vec2& v)
    floatgetDistanceSq
4、运算符重载
//
    inlineconstVec2 operator+(constVec2& v) const; //( x+v.x , y+v.y )
    inlineconstVec2 operator-(constVec2& v) const; //( x-v.x , y-v.y )
    inlineconstVec2 operator*(floats) const;       //( x*s , y*s )
    inlineconstVec2 operator/(floats) const;       //( x/s , y/s )
    inlineconstVec2 operator-() const;              //( -x , -y )
    inlineVec2& operator+=(constVec2& v);           //(x,y) = ( x+v.x , y+v.y )
    inlineVec2& operator-=(constVec2& v);           //(x,y) = ( x-v.x , y-v.y )
    inlineVec2& operator*=(floats);                 //(x,y) = ( x*s , y*s )
    inlinebooloperator<(constVec2& v) const;
    inlinebooloperator==(constVec2& v) const;
    inlinebooloperator!=(constVec2& v) const;
//
5、静态函数与常量
//
/**
 * 静态方法
 */
    staticvoidadd(constVec2& v1, constVec2& v2, Vec2* dst);                    //dst = v1 + v2
    staticvoidsubtract(constVec2& v1, constVec2& v2, Vec2* dst);               //dst = v1 – v2
    staticvoidclamp(constVec2& v, constVec2& min, constVec2& max, Vec2* dst); //将向量v限制在[min,max]区间内,结果存入dst
    staticfloatangle(constVec2& v1, constVec2& v2);                            //两向量夹角(弧度)
    staticfloatdot(constVec2& v1, constVec2& v2);                              //两向量点积
    staticinlineVec2 forAngle(constfloata);                                    //返回向量坐标 x=cos(a) , y=sin(a)
/**
 * 静态常量
 */
    staticconstVec2 ZERO;                 //Vec2(0, 0)
    staticconstVec2 ONE;                  //Vec2(1, 1)
    staticconstVec2 UNIT_X;               //Vec2(1, 0)
    staticconstVec2 UNIT_Y;               //Vec2(0, 1)
    staticconstVec2 ANCHOR_MIDDLE;        //Vec2(0.5, 0.5)
    staticconstVec2 ANCHOR_BOTTOM_LEFT;   //Vec2(0, 0)
    staticconstVec2 ANCHOR_TOP_LEFT;      //Vec2(0, 1)
    staticconstVec2 ANCHOR_BOTTOM_RIGHT;  //Vec2(1, 0)
    staticconstVec2 ANCHOR_TOP_RIGHT;     //Vec2(1, 1)
    staticconstVec2 ANCHOR_MIDDLE_RIGHT;  //Vec2(1, 0.5)
    staticconstVec2 ANCHOR_MIDDLE_LEFT;   //Vec2(0, 0.5)
    staticconstVec2 ANCHOR_MIDDLE_TOP;    //Vec2(0.5, 1)
    staticconstVec2 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是否平行
    staticboolisLineParallel(constVec2& A, constVec2& B, constVec2& C, constVec2& D);
    //直线AB与线段CD是否重叠
    staticboolisLineOverlap(constVec2& A, constVec2& B, constVec2& C, constVec2& D);
    //直线AB与直线CD是否相交
    staticboolisLineIntersect(constVec2& A, constVec2& B, constVec2& C, constVec2& D,
                                 float*S = nullptr, float*T = nullptr);
    //线段AB与线段CD是否重叠
    staticboolisSegmentOverlap(constVec2& A, constVec2& B, constVec2& C, constVec2& D,
                                 Vec2* S = nullptr, Vec2* E = nullptr);
    //线段AB与线段CD是否相交
    staticboolisSegmentIntersect(constVec2& A, constVec2& B, constVec2& C, constVec2& D);
    //返回直线AB与直线CD的交点
    staticVec2 getIntersectPoint(constVec2& A, constVec2& B, constVec2& C, constVec2& D);

【Size】

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

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

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

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

1、主要函数如下

//
classCC_DLL Size
{
/**
 * Size只有两个成员变量width , height
 */
    floatwidth;   //宽
    floatheight;  //高
/**
 * 构造函数
 */
    Size();                           //(0, 0)
    Size(floatwidth, floatheight);  //(width, height)
    Size(constSize& other);          //other
    explicitSize(constVec2& point); //(显式)构造函数. 构造时Size size = Size(Vec2&), 而不能Size size = vec2;
/**
 * 相关操作
 *     – setSize
 *     – equals
 *     – Vec2()
 */
    voidsetSize(floatwidth, floatheight); //设置尺寸
    boolequals(constSize& target) const;   //判断是否等于target
    //Size::Vec2()
    //返回类型为Vec2
    operator Vec2() const{ returnVec2(width, height); }
/**
 * 静态常量
 */
    staticconstSize ZERO; //(0, 0)
/**
 * 运算符重载
 */
    Size& operator= (constSize& other);
    Size& operator= (constVec2& point); //可以用Vec2赋值
    Size operator+(constSize& right) const;
    Size operator-(constSize& right) const;
    Size operator*(floata) const;
    Size operator/(floata) const;
};
//

【Rect】

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

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

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

值得注意的是Rect类中:

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

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

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

cocos2dx3.2技术之数学类Vec2/Size/Rect浅析 - 第2张  | 游戏开发网-最好的游戏编程开发技术网站!

1、主要函数如下

//
classCC_DLL Rect
{
public:
    Vec2 origin; //起始坐标: 矩形左下角坐标
    Size  size;  //尺寸大小
/**
 * 构造函数
 */
    Rect();
    Rect(floatx, floaty, floatwidth, floatheight);
    Rect(constRect& other);
/**
 * 运算符重载
 *     只重载了 “=” 运算符
 */
    Rect& operator= (constRect& other);
/**
 * 相关操作
 *     – setRect
 *     – getMinX , getMidX , getMaxX
 *     – getMinY , getMidY , getMaxY
 *     – equals , containsPoint , intersectsRect
 *     – unionWithRect
 */
    //设置矩形
    voidsetRect(floatx, floaty, floatwidth, floatheight);
    //获取矩形信息
    floatgetMinX() const; //origin.x
    floatgetMidX() const; //origin.x + size.width/2
    floatgetMaxX() const; //origin.x + size.width
    floatgetMinY() const; //origin.y
    floatgetMidY() const; //origin.y + size.height/2
    floatgetMaxY() const; //origin.y + size.height
    //判断是否与rect相同. 原点相同,尺寸相同.
    boolequals(constRect& rect) const;
    //判断point是否包含在矩形内或四条边上
    boolcontainsPoint(constVec2& point) const;
    //判断矩形是否相交. 常常用作碰撞检测.
    boolintersectsRect(constRect& rect) const;
    //与rect矩形合并. 并返回结果. v3.0
    //不会改变原矩形的值
    Rect unionWithRect(constRect & rect) const;
/**
 * 静态常量
 *     Rect::ZERO
 */
    staticconstRect ZERO;
};
//

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

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

> Sprite::create(const std::string& filename, const Rect& rect)

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

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

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

如下图所示:

cocos2dx3.2技术之数学类Vec2/Size/Rect浅析 - 第3张  | 游戏开发网-最好的游戏编程开发技术网站!

3、矩形合并函数unionWithRect

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

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

    cocos2dx3.2技术之数学类Vec2/Size/Rect浅析 - 第4张  | 游戏开发网-最好的游戏编程开发技术网站!cocos2dx3.2技术之数学类Vec2/Size/Rect浅析 - 第5张  | 游戏开发网-最好的游戏编程开发技术网站!

cocos2dx3.2技术之数学类Vec2/Size/Rect浅析 - 第6张  | 游戏开发网-最好的游戏编程开发技术网站!


转自:http://www.yxkfw.com/?p=12955

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值