【转】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可以是一个二维坐标点,也可以是一个二维向量。

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函数,可以用做将两矩形进行合并操作。

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坐标系是不一样的。
如下图所示:

3、矩形合并函数unionWithRect
看几张图,你应该就会明白了。
两个黑色矩形区域,使用unionWithRect合并后,变成红色矩形区域。
【转】Cocos2d-x 3.x基础学习: 总结数学类Vec2/Size/Rect的更多相关文章
- Yaf零基础学习总结5-Yaf类的自动加载
Yaf零基础学习总结5-Yaf类的自动加载 框架的一个重要功能就是类的自动加载了,在第一个demo的时候我们就约定自己的项目的目录结构,框架就基于这个目录结构来自动加载需要的类文件. Yaf在自启动的 ...
- java基础学习总结——Object类
一.Object类介绍
- C++基础学习8:类的定义(class)
先来说说C和C++中结构体的不同 a) C语言中的结构体不能为空,否则会报错(??) b) C语言中内存为空结构体分配大小为0,C++中为结构体和类分配大小为1byte c) C语言中的结构体只涉及到 ...
- Objective-C 学习记录--toches、Motion/Size/Rect/Point/CGFloat/protocol
- (void)touchesBegan touchesEnd touchesCancelled touchesMoved //代表的是手指在屏幕上的动作,开始 结束 取消 移动 //还有就是代表摇动 ...
- 如何从零基础学习VR
转载请声明转载地址:http://www.cnblogs.com/Rodolfo/,违者必究. 近期很多搞技术的朋友问我,如何步入VR的圈子?如何从零基础系统性的学习VR技术? 本人将于2017年1月 ...
- 转载-java基础学习汇总
共2页: 1 2 下一页 Java制作证书的工具keytool用法总结 孤傲苍狼 2014-06-24 11:03 阅读:25751 评论:3 Java基础学习总结——Java对象的序列化和 ...
- salesforce 零基础学习(五十二)Trigger使用篇(二)
第十七篇的Trigger用法为通过Handler方式实现Trigger的封装,此种好处是一个Handler对应一个sObject,使本该在Trigger中写的代码分到Handler中,代码更加清晰. ...
- IOS基础学习-2: UIButton
IOS基础学习-2: UIButton UIButton是一个标准的UIControl控件,UIKit提供了一组控件:UISwitch开关.UIButton按钮.UISegmentedContro ...
- HTML5零基础学习Web前端需要知道哪些?
HTML零基础学习Web前端网页制作,首先是要掌握一些常用标签的使用和他们的各个属性,常用的标签我总结了一下有以下这些: html:页面的根元素. head:页面的头部标签,是所有头部元素的容器. b ...
随机推荐
- 【汇编】SI DI 的用法
一.汇编语言中,为什么SI和DI不能同时使用汇编 其实你可以想一下,这两个寄存器的意思,SI源变址寄存器,DI目地变址寄存器,既然是变址寄存器,那么他们肯定是在某个地址的基础上进行偏移变化,由此我们就 ...
- Tidb数据库导入数据出现oom问题
今天使用insert操作向tidb中插入数据,发现正在导入的过程中出现如下错误: mysql: [Warning] Using a password on the command line inter ...
- 'javac' 不是内部或外部命令,也不是可运行的程序
今天在命令行中运行javac命令时发现 但是运行java命令却可以 查找jdk的安装路径发现,安装目录里面同时有jdk的文件夹和jre的文件夹 查看了jdk的目录发现jdk目录中也有一个jre文件夹 ...
- PyQt5--MenuBar
# -*- coding:utf-8 -*- ''' Created on Sep 13, 2018 @author: SaShuangYiBing ''' import sys from PyQt5 ...
- 详解coredump
一,什么是coredump 我们经常听到大家说到程序core掉了,需要定位解决,这里说的大部分是指对应程序由于各种异常或者bug导致在运行过程中异常退出或者中止,并且在满足一定条件下(这里为什么说需要 ...
- [luogu2172] 部落战争
题面 我们可以将'.'抽象为一个可以通过的点, 将'x'抽象为一个不可通过的点. 那么题意便可以转化为: 一条路径可以看做从任意一个没有到达过的可通过的点出发到任意一个其他的可以通过却没有被到 ...
- ethereum/EIPs-170 Contract code size limit
eip title author type category status created 170 Contract code size limit Vitalik Buterin Standards ...
- App常见产品问题及预防方法
01界面适配 a:手机分辨率为1920x7080的高分辨率手机,在调整手机字体大小时,会导致页面显示出现变形: b:因用户设置的特殊字体导致列表的字母条不显示: c:某些banner 图片在部分机型只 ...
- WorldWind源码剖析系列:日志类Log
Utility工程中的日志类Log主要用来输出Debug状态下的调试信息.该类的类图如下: 日志类Log中使用到的类和内嵌结构体类型主要有以下这些: public class LogEventArgs ...
- Kafka设计解析(二十二)Flink + Kafka 0.11端到端精确一次处理语义的实现
转载自 huxihx,原文链接 [译]Flink + Kafka 0.11端到端精确一次处理语义的实现 本文是翻译作品,作者是Piotr Nowojski和Michael Winters.前者是该方案 ...