Point Size 和Rect都是在游戏中经常使用到的类。Point为坐标,经常用来标示一个对象的位置。Size为尺寸,用来标示一个对象的大小。Rect则是Point 和Size的集合体,可以认为是一个包围盒,经常用来判断是否发生碰撞。
SEMath.h
#ifndef __SDL_Math_H__
#define __SDL_Math_H__
/*SDL_Engine Math*/
#include<cstdlib>
#include<cmath>
#include "PlatformMarcos.h"
NS_SDL_BEGIN
#ifndef FLT_EPSILON
#define FLT_EPSILON 1.192092896e-07F /* smallest such that 1.0+FLT_EPSILON != 1.0 */
#endif
#define MAX_UINT 0xffffffff
#define SDL_REPEAT_FOREVER (MAX_UINT - 1)
#define MAX(x,y) ((x)>(y)?(x):(y))
#define MIN(x,y) ((x)>(y)?(y):(x))
#define RANDOM(start,end) (fmodf((float)rand(),(end)-(start))+(start))/*[start,end) 不需要自己手动调用srand,已经在Director中调用*/
#define RANDOM_0_1() (rand()/double(RAND_MAX))
#define SDL_ANGLE_TO_DEGREE(angle) (3.1415926/180 * (angle))/*角度转弧度*/
#define SDL_DEGREE_TO_ANGLE(degree) (180.0/3.1415926 *(degree))/*弧度转角度*/
NS_SDL_END
#endif
SEMath.h包含了游戏开发中一些常用的功能,并用宏函数实现。另外这个文件名称一开始是Math.h,但是在移植android平台时,会报错,原因是与c语言提供的math.h发生了冲突,故而添加了一个前缀
SE(SDL_Engine)。
Point.h
#ifndef __SDL_Point_H__
#define __SDL_Point_H__
#include<cmath>
#include<string>
#include "SDL.h"
#include "PlatformMarcos.h"
NS_SDL_BEGIN
class Point
{
public:
float x;
float y;
public:
static const Point ZERO;
public:
Point(float x = 0.f, float y = 0.f):x(x), y(y){}
Point(const Point&point);
Point(const SDL_Point&point);
~Point(){}
float getX()const;
void setX(float x);
float getY()const;
void setY(float y);
void set(float x,float y);
float length()const
{
return sqrt(x * x + y * y);
}
void normalize()
{
float l = length();
if (l > 0)
{
(*this) *= 1/l;
}
}
/*重载*/
//+
Point operator+(const Point &v2) const
{
return Point(x + v2.x,y + v2.y);
}
//*
Point operator*(float scalar)
{
return Point(x * scalar,y * scalar);
}
//*=
Point& operator*=(float scalar)
{
x *= scalar;
y *= scalar;
return *this;
}
//-
Point operator-(const Point& v2) const
{
return Point(x - v2.x,y - v2.y);
}
// /÷
Point operator/(float scalar)
{
return Point(x /scalar,y/scalar);
}
// /=
Point& operator/=(float scalar)
{
x /= scalar;
y /= scalar;
return *this;
}
/*友元*/
//+=
friend Point& operator+=(Point &v1,const Point &v2)
{
v1.x += v2.x;
v1.y += v2.y;
return v1;
}
//-=
friend Point& operator-=(Point& v1,const Point& v2)
{
v1.x -= v2.x;
v1.y -= v2.y;
return v1;
}
friend bool operator!=(const Point&p1,const Point&p2)
{
return !p1.equals(p2);
}
friend bool operator==(const Point&p1,const Point&p2)
{
return p1.equals(p2);
}
inline Point rotate(const Point& other) const {
return Point(x*other.x - y*other.y, x*other.y + y*other.x);
};
Point rotateByAngle(const Point& pivot, float angle) const;
bool equals(const Point &point) const;
inline Point lerp(const Point& other, float alpha) const
{
return Point(x*(1.f - alpha) + other.x*alpha,y*(1.f - alpha) + other.y*alpha);
}
static inline Point forAngle(const float a)
{
return Point(cosf(a), sinf(a));
}
/** A general line-line intersection test
@param A the startpoint for the first line L1 = (A - B)
@param B the endpoint for the first line L1 = (A - B)
@param C the startpoint for the second line L2 = (C - D)
@param D the endpoint for the second line L2 = (C - D)
@param S the range for a hitpoint in L1 (p = A + S*(B - A))
@param T the range for a hitpoint in L2 (p = C + T*(D - C))
@return whether these two lines intersects.
Note that to truly test intersection for segments we have to make
sure that S & T lie within [0..1] and for rays, make sure S & T > 0
the hit point is C + T * (D - C);
the hit point also is A + S * (B - A);
*/
static bool
isLineIntersect(const Point& A, const Point& B,
const Point& C, const Point& D, float *S = nullptr, float *T = nullptr);//return SDL_PointSDL_Point getSDL_Point()const;};NS_SDL_END#endif
Point.cpp
#include "Point.h"
#include "SEMath.h"
NS_SDL_BEGIN
const Point Point::ZERO=Point(0.0f,0.0f);
Point::Point(const Point &point)
:x(point.x),y(point.y)
{
}
Point::Point(const SDL_Point&point)
:x((float)point.x),y((float)point.y)
{
}
float Point::getX()const
{
return x;
}
void Point::setX(float x)
{
this->x = x;
}
float Point::getY()const
{
return y;
}
void Point::setY(float y)
{
this->y = y;
}
void Point::set(float x,float y)
{
this->x = x;
this->y = y;
}
Point Point::rotateByAngle(const Point& pivot, float angle) const
{
return pivot + (*this - pivot).rotate(Point::forAngle(angle));
}
bool Point::equals(const Point &point) const
{
return fabs(x - point.x) < FLT_EPSILON
&& fabs(y - point.y) < FLT_EPSILON;
}
// cross product of 2 vector. A->B X C->D
float crossProduct2Vector(const Point& A, const Point& B, const Point& C, const Point& D)
{
return (D.y - C.y) * (B.x - A.x) - (D.x - C.x) * (B.y - A.y);
}
bool Point::isLineIntersect(const Point& A, const Point& B,
const Point& C, const Point& D,
float *S, float *T)
{
// FAIL: Line undefined
if ( (A.x==B.x && A.y==B.y) || (C.x==D.x && C.y==D.y) )
{
return false;
}
const float denom = crossProduct2Vector(A, B, C, D);
if (denom == 0)
{
// Lines parallel or overlap
return false;
}
if (S != nullptr) *S = crossProduct2Vector(C, D, C, A) / denom;
if (T != nullptr) *T = crossProduct2Vector(A, B, C, A) / denom;
return true;
}
SDL_Point Point::getSDL_Point()const
{
SDL_Point point={(int)x,(int)y};
return point;
}
NS_SDL_END
值得注意的是,Point类的x,y属性是public,这也就意味着,其他对象可以直接访问。Point对象有一个ZERO静态常量成员对象,ZERO主要是为了方便赋值,这点同Size Rect。然后就是getSDL_Point()函数,能返回SDL_Point结构体,这个结构体是SDL所定义。可以简单地认为Point和SDL_Point相对应。
Size.h
#ifndef __SDL_Size_H__
#define __SDL_Size_H__
#include<cmath>
#include<string>
#include "SDL.h"
#include "PlatformMarcos.h"
NS_SDL_BEGIN
class Size
{
public:
float width;
float height;
static const Size ZERO;
public:
Size(float w=0.f,float h = 0.f);
~Size(){}
//复制构造函数
Size(const Size& s);
Size&operator=(const Size &other);
Size operator+(Size &size);
Size operator-(Size &size);
Size operator*(float a) const;
Size operator/(float a) const;
Size operator/(const Size&other)const;
bool operator==(const Size&other)const;
bool operator!=(const Size&other)const;
void setSize(float width,float height);
bool equals(const Size &s) const;
};
NS_SDL_END
#endif
Size.cpp
#include "Size.h"
#include "SEMath.h"
NS_SDL_BEGIN
const Size Size::ZERO = Size(0.f,0.f);
Size::Size(float w,float h)
:width(w),height(h)
{
}
Size::Size(const Size &s)
:width(s.width),height(s.height)
{
}
Size &Size::operator=(const Size&other)
{
setSize(other.width,other.height);
return *this;
}
Size Size::operator+(Size &size)
{
return Size(width + size.width,height + size.height);
}
Size Size::operator-(Size &size)
{
return Size(width - size.width,height - size.height);
}
Size Size::operator*(float a) const
{
return Size(width * a,height * a);
}
Size Size::operator/(float a) const
{
SDLASSERT(a != 0,"CCSize division by 0.");
return Size(width / a,height / a);
}
Size Size::operator/(const Size&other)const
{
return Size(width / other.width,height / other.height);
}
bool Size::operator==(const Size&other)const
{
return width == other.width&&
height == other.height;
}
bool Size::operator!=(const Size&other)const
{
return width != other.width ||
height != other.height;
}
void Size::setSize(float width,float height)
{
this->width = width;
this->height = height;
}
bool Size::equals(const Size & s) const
{
return fabs(width - s.width) < FLT_EPSILON
&& fabs(height - s.height) < FLT_EPSILON;
}
NS_SDL_END
Size在SDL中没有对应的结构体。
Rect.h
#ifndef __SDL_Rect_H__
#define __SDL_Rect_H__
#include<string>
#include "SDL.h"
#include "PlatformMarcos.h"
#include "Point.h"
#include "Size.h"
NS_SDL_BEGIN
class Rect
{
public:
Point origin;
Size size;
static const Rect ZERO;
public:
Rect(float x=0.f,float y=0.f,float w=0.f,float h=0.f);
Rect(const Rect&rect);
Rect(const SDL_Rect&other);
Rect(const Point&origin,const Size&size);
Rect(float x,float y,const Size&size);
Rect(const Point&origin,float w,float h);
~Rect(){}
//重载运算符
Rect&operator=(const Rect&rect);
void setRect(float x,float y,float w,float h);
void setRect(const Rect&rect);
float getMinX() const {return origin.x;}
float getMidX() const {return origin.x + size.width/2;}
float getMaxX() const {return origin.x + size.width;}
float getMinY() const {return origin.y;}
float getMidY() const {return origin.y + size.height/2;}
float getMaxY() const {return origin.y + size.height;}
//是否相等
bool equals(const Rect &rect) const;
//是否包含点
bool containsPoint(const Point &point)const;
//两rect是否相交或包含
bool intersectRect(const Rect&rect)const;
//矩形是否和线段交叉
bool intersectLine(const Point&pos1,const Point&pos2)const;
//返回SDL_Rect
SDL_Rect getSDL_Rect()const;
};
NS_SDL_END
#endif
Rect.cpp
#include "Rect.h"
NS_SDL_BEGIN
const Rect Rect::ZERO = Rect(0.f,0.f,0.f,0.f);
Rect::Rect(float x,float y,float w,float h)
:origin(x,y),size(w,h)
{
}
Rect::Rect(const Rect&rect)
:origin(rect.origin),size(rect.size)
{
}
Rect::Rect(const SDL_Rect&other)
:origin(other.x,other.y),size(other.w,other.h)
{
}
Rect::Rect(const Point&origin,const Size&size)
:origin(origin),size(size)
{
}
Rect::Rect(float x,float y,const Size&size)
:origin(x,y),size(size)
{
}
Rect::Rect(const Point&origin,float w,float h)
:origin(origin),size(w,h)
{
}
Rect& Rect::operator=(const Rect &rect)
{
setRect(rect.origin.x,rect.origin.y,rect.size.width,rect.size.height);
return *this;
}
void Rect::setRect(float x,float y,float w,float h)
{
origin.x = x;
origin.y = y;
size.width = w;
size.height = h;
}
void Rect::setRect(const Rect&rect)
{
setRect(rect.origin.x,rect.origin.y,rect.size.width,rect.size.height);
}
bool Rect::equals(const Rect&rect) const
{
return origin.equals(rect.origin)
&&size.equals(rect.size);
}
bool Rect::containsPoint(const Point&point)const
{
return (point.x > getMinX() && point.x < getMaxX())
&&(point.y > getMinY() && point.y < getMaxY());
}
bool Rect::intersectRect(const Rect&rect)const
{
return !( getMaxX() < rect.getMinX() ||
rect.getMaxX() < getMinX() ||
getMaxY() < rect.getMinY() ||
rect.getMaxY() < getMinY());
}
bool Rect::intersectLine(const Point&pos1,const Point&pos2)const
{
SDL_Rect rect;
rect.x = (int)origin.x;
rect.y = (int)origin.y;
rect.w = (int)size.width;
rect.h = (int)size.height;
int x1 = (int)pos1.x;
int y1 = (int)pos1.y;
int x2 = (int)pos2.x;
int y2 = (int)pos2.y;
return SDL_IntersectRectAndLine(&rect
,&x1,&y1,&x2,&y2) == SDL_TRUE;
}
SDL_Rect Rect::getSDL_Rect()const
{
SDL_Rect rect = { (int)origin.x,(int)origin.y
,(int)size.width,(int)size.height};
return rect;
}
NS_SDL_END
Rect是Point和Size的集合体。它使用相当广泛,从简单的矩形碰撞,再到以后的按钮检测等等,都是使用Rect 的containsPoint或者intersectRect函数进行判断的。Rect内部的一些函数有的使用了SDL提供的部分函数(也可以自己实现)。需要注意的是,上面三个类是没有继承自Object的。
本节只是简单添加了3个类。不再进行测试。
本节代码:链接:https://pan.baidu.com/s/1IfGemOPg21OGVs6Ch060Hg 密码:eblp