cocos2dx[3.2](9) ——数学类Vec2/Size/Rect
【唠叨】
数学类Vec2、Size、Rect,是cocos2dx中比较常用的类。
比如设置图片位置,设置图片大小,两图片的碰撞检测等等。
比起2.x版本,在3.x中本质上其实没有太大的变化,主要的变化就是将全局宏定义相关的操作封装到各自的类中而已。比如:Vec2的向量运算宏定义ccp***(),现在都已经封装到Vec2类里面去了。
【番外】
在V2.x中,底层数学库使用的是:Kazmath数学库。
而在V3.1中,由于Sprite3D需要我们提供更多的API给开发者,这是Kazmath库所不能提供的,而cocos2d-x内部拥有多个数学库是没有意义的。
所以V3.1中,底层选择了新的数学库:GamePlay3D数学库。
【Vec2】
Vec2原名Point,它既可以表示一个二维坐标点,又可以表示一个二维向量。
同时Vec2对运算符进行了重载,可以很方便的完成Vec2的赋值、加减乘除等操作。另外还有与坐标向量相关的:距离、角度、点积、叉积、投影、标准化等操作。
此外在3.x中,还将2.x里的函数定义ccp***(如ccp,ccpAdd,ccpSub)相关的操作都封装到了这个Vec2的类中,这样就可以更加系统化地管理向量的运算操作了。
此外,除了Vec2。还有两个坐标类:Vec3、Vec4,分别代表了三维、四维坐标向量。
查看2.x与3.x的变化请移步:http://shahdza.blog.51cto.com/2410787/1549850
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©);//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.xVec2project(constVec2&v)const;//投影:向量在v上的投影向量floatdistance(constVec2&v)const;//与v的距离.floatdistanceSquared(constVec2&v)const;//与v的距离平方.floatlength()const;//向量长度.即与原点的距离floatlengthSquared()const;//向量长度平方.即与原点的距离平方Vec2getNormalized()const;//获取向量的标准化形式.若为零向量,返回(0,0)inlineVec2getPerp()const;//逆时针旋转90度.Vec2(-y,x);inlineVec2getRPerp()const//顺时针旋转90度.Vec2(y,-x);inlinefloatgetAngle()const;//与X轴的夹角(弧度)floatgetAngle(constVec2&v)const;//与v向量的夹角(弧度)inlineVec2getMidpoint(constVec2&v)const;//计算两点间的中点//将向量值限制在[min,max]区间内,返回该点inlineVec2getClampPoint(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))//returntrue;boolfuzzyEquals(constVec2&target,floatvariance)const;//以pivot为轴,逆时针旋转angle度(弧度)Vec2rotateByAngle(constVec2&pivot,floatangle)const;//绕other向量旋转//返回向量:角度this.getAngle()+other.getAngle();//长度this.getLength()*other.getLength();inlineVec2rotate(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()么?)inlineVec2unrotate(constVec2&other)const{returnVec2(x*other.x+y*other.y,y*other.x-x*other.y);};//两个点a和b之间的线性插值//alpha==0?aalpha==1?b否则为a和b之间的一个值inlineVec2lerp(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等,//任何函数拥有如下形式:floatfunc(float)均可。//例如:我们对x,y进行floor运算,则调用方法为p.compOp(floorf);//3.0inlineVec2compOp(std::function<float(float)>function)const{returnVec2(function(x),function(y));}/***兼容代码*估计是要被抛弃了~(>_<)~*/voidsetPoint(floatxx,floatyy);//同set(floatxx,floatyy)boolequals(constVec2&target)const;//同==floatgetLength()const;//同length()floatgetLengthSq()const;//同lengthSquared()floatgetDistance(constVec2&other)const;//同distance(constVec2&v)floatgetDistanceSq(constVec2&other)const;//同distanceSquared(constVec2&v)//
4、运算符重载
//inlineconstVec2operator+(constVec2&v)const;//(x+v.x,y+v.y)inlineconstVec2operator-(constVec2&v)const;//(x-v.x,y-v.y)inlineconstVec2operator*(floats)const;//(x*s,y*s)inlineconstVec2operator/(floats)const;//(x/s,y/s)inlineconstVec2operator-()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+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);//两向量点积staticinlineVec2forAngle(constfloata);//返回向量坐标x=cos(a),y=sin(a)/***静态常量*/staticconstVec2ZERO;//Vec2(0,0)staticconstVec2ONE;//Vec2(1,1)staticconstVec2UNIT_X;//Vec2(1,0)staticconstVec2UNIT_Y;//Vec2(0,1)staticconstVec2ANCHOR_MIDDLE;//Vec2(0.5,0.5)staticconstVec2ANCHOR_BOTTOM_LEFT;//Vec2(0,0)staticconstVec2ANCHOR_TOP_LEFT;//Vec2(0,1)staticconstVec2ANCHOR_BOTTOM_RIGHT;//Vec2(1,0)staticconstVec2ANCHOR_TOP_RIGHT;//Vec2(1,1)staticconstVec2ANCHOR_MIDDLE_RIGHT;//Vec2(1,0.5)staticconstVec2ANCHOR_MIDDLE_LEFT;//Vec2(0,0.5)staticconstVec2ANCHOR_MIDDLE_TOP;//Vec2(0.5,1)staticconstVec2ANCHOR_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的交点staticVec2getIntersectPoint(constVec2&A,constVec2&B,constVec2&C,constVec2&D);//
【Size】
Size比较简单,只是一个用来表示尺寸大小的类。宽为width,高为height。
和Vec2一样,也对一些运算符进行了重载。
与2.x相比,没有太大的变化。
PS: 因为和Vec2一样,都只有两个成员变量,所以Size和Vec2之间可以相互转换。
1、主要函数如下
//classCC_DLLSize{/***Size只有两个成员变量width,height*/floatwidth;//宽floatheight;//高/***构造函数*/Size();//(0,0)Size(floatwidth,floatheight);//(width,height)Size(constSize&other);//otherexplicitSize(constVec2&point);//(显式)构造函数.构造时Sizesize=Size(Vec2&),而不能Sizesize=vec2;/***相关操作*-setSize*-equals*-Vec2()*/voidsetSize(floatwidth,floatheight);//设置尺寸boolequals(constSize&target)const;//判断是否等于target//Size::Vec2()//返回类型为Vec2operatorVec2()const{returnVec2(width,height);}/***静态常量*/staticconstSizeZERO;//(0,0)/***运算符重载*/Size&operator=(constSize&other);Size&operator=(constVec2&point);//可以用Vec2赋值Sizeoperator+(constSize&right)const;Sizeoperator-(constSize&right)const;Sizeoperator*(floata)const;Sizeoperator/(floata)const;};//
【Rect】
Rect是一个矩形类。包含两个成员属性:起始坐标(左下角)Vec2、矩阵尺寸大小Size。
Rect只对“=”运算符进行了重载。
与2.x相比,多了一个函数unionWithRect,用于合并两个矩形。
值得注意的是Rect类中:
intersectsRect函数,可以用作两个Rect矩形是否相交,即碰撞检测。
containsPoint 函数,可以用作判断点Vec2是否在Rect矩形中。
unionWithRect 函数,可以用做将两矩形进行合并操作。
1、主要函数如下
//classCC_DLLRect{public:Vec2origin;//起始坐标:矩形左下角坐标Sizesize;//尺寸大小/***构造函数*/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//不会改变原矩形的值RectunionWithRect(constRect&rect)const;/***静态常量*Rect::ZERO*/staticconstRectZERO;};//
2、精灵创建中的一种方式
还记得Sprite的几种创建方式吗?里面有一种创建方式如下:
> Sprite::create(const std::string& filename, const Rect& rect)
若用Rect来作为创建Sprite精灵的参数,需要注意,从大图中截取某一区域的图片的Rect rect的构造应该是这样的:
>Rect("小图左上角坐标x", "小图左上角坐标y", 小图宽, 小图高);
使用的是UIKit坐标系,而不是cocos2dx的OpenGL坐标系是不一样的。
如下图所示:
3、矩形合并函数unionWithRect
看几张图,你应该就会明白了。
两个黑色矩形区域,使用unionWithRect合并后,变成红色矩形区域。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。