用两直线交点分有向向量所成的比计算子弹精灵与屏幕边界矩形的碰撞点
入射向量z_1=(x_1,y_1)=碰撞点p-碰撞前轨迹起点v_1
平分向量(法线向量)z_0,有几种取值情况:
碰撞点只在上下边界时,z_0=(1,0)或(-1,0)皆可
碰撞点只在左右边界时,z_0=(0,1)或(0,-1)皆可
碰撞点在四个顶点时,
左下顶点或右上顶点:z_0=(-1,1)或(1,-1)
右下顶点或左上顶点:z_0=(-1,-1)或(1,1)
出射向量(反射向量)z_2=(rcosθ,rsinθ)的计算:
θ=argz_2=2argz_0-argz_1=2atan2(y_0,x_0)-atan2(y_1,x_1)
r=|z_2|=|z_1|=sqrt(x_1^2+y_1^2),|z_2|作为CMoveBy的第二个参数,实际上用一个像5000这样比较的大的数代替|z_1|
根据碰撞前轨迹起点v_1,碰撞后边界外点v_2,屏幕边界矩形{pt[0],pt[1],pt[2],pt[3]}计算碰撞点p的算法由下面C++程序中的segment_cross_Rect函数实现。
【捕鱼其它公式】
精灵帧资源头部朝向θ,例如θ=pi,pi/2,0分别表示鱼头水平向左、垂直向上、水平向右,运行轨迹方向用z或argz表示,则精灵的rotation属性应设为(θ-argz)*180/pi。
r是炮弹的射程,根据触摸位置(x_2,y_2)和船的位置(x_1,y_1)可以求出炮弹的轨迹角度θ=atan2(y_2-y_1,x_2-x_1),根据射程和轨迹角度求出轨迹终点z=(rcosθ,rsinθ)。
collisionLib.h中的C++代码
#ifndef __COLLISION_LIB_H__
#define __COLLISION_LIB_H__
#include <cocos2d.h>
#include<math.h>
// 求两直线交点
// 直线 1 上的两点:(ax1, ay1), (ax2, ay2)
// 直线 2 上的两点:(bx1, by1), (bx2, by2)
// 返回值:true: 有交点,保存在 (ix, iy) 中
// :false: 两直线平行
bool Intersection(float ax1, float ay1, float ax2, float ay2, float bx1, float by1, float bx2, float by2, float *ix, float *iy)
{
float d = (ay2-ay1) * (bx2-bx1) - (by2-by1) * (ax2-ax1);
#if 1
if (fabs(d)<0.01)
#else
if (d==0)
#endif
return false; // 两直线平行就退出,避免除数为 0 的情况
*ix = ( (ax2-ax1)*(bx2-bx1)*(by1-ay1)+(ay2-ay1)*(bx2-bx1)*ax1-(by2-by1)*(ax2-ax1)*bx1 ) / d;
*iy = ( (ay2-ay1)*(by2-by1)*(bx1-ax1)+(ax2-ax1)*(by2-by1)*ay1-(bx2-bx1)*(ay2-ay1)*by1 ) / -d;
return true;
}
//求线段AB与线段CD的交点
bool segment_cross_segment(CCPoint& a,CCPoint& b,CCPoint& c,CCPoint& d,CCPoint& cross_point)
{
CCPoint retpt;
if (Intersection(a.x,a.y,b.x,b.y,c.x,c.y,d.x,d.y,&retpt.x,&retpt.y) )
{
//交点分~AB所成的比,交点一定不与B点重合
float k=(retpt.x-a.x)/(b.x-retpt.x);
if(k>0)
{
cross_point=retpt;
return true;
}
e