【唠叨】
数学类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可以是一个二维坐标点,也可以是一个二维向量。
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); //copyVec2(constVec2& p1, constVec2& p2); //p2 – p1//
2、设置向量坐标
使用set可以给向量重新设置新坐标值。
//voidset(floatxx, floatyy); //(xx , yy)voidset(constfloat* array); //(array[0] , array[1])voidset(constVec2& v); //vvoidset(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.yfloatcross(constVec2& v) const; //叉积: x*v.y – y*v.xVec2 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.0inlineVec2 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
//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;//
///*** 静态方法*/staticvoidadd(constVec2& v1, constVec2& v2, Vec2* dst); //dst = v1 + v2staticvoidsubtract(constVec2& v1, constVec2& v2, Vec2* dst); //dst = v1 – v2staticvoidclamp(constVec2& v, constVec2& min, constVec2& max, Vec2* dst); //将向量v限制在[min,max]区间内,结果存入dststaticfloatangle(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); //otherexplicitSize(constVec2& point); //(显式)构造函数. 构造时Size size = Size(Vec2&), 而不能Size size = vec2;/*** 相关操作* – setSize* – equals* – Vec2()*/voidsetSize(floatwidth, floatheight); //设置尺寸boolequals(constSize& target) const; //判断是否等于target//Size::Vec2()//返回类型为Vec2operator 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 函数,可以用做将两矩形进行合并操作。
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.xfloatgetMidX() const; //origin.x + size.width/2floatgetMaxX() const; //origin.x + size.widthfloatgetMinY() const; //origin.yfloatgetMidY() const; //origin.y + size.height/2floatgetMaxY() 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坐标系是不一样的。
如下图所示:
3、矩形合并函数unionWithRect
看几张图,你应该就会明白了。
两个黑色矩形区域,使用unionWithRect合并后,变成红色矩形区域。