package org.ourunix.android.jpct.ball;
import com.threed.jpct.Object3D;
/*
* 功能说明:此类为球的对象类,包括了球的所有参数值,控制球移动的函数
* 球的绘制方法等
*
*/
class Ball3D
{
static final float TOP_SPEED = 6.0f; //击球最高速
static final float MIN_SPEED = 0.6f; //击球最低速
static final float DEFAULT_SPEED = 3.6f; //
static final float WEIGHT = 1.5f; //重量
static final float RADIUS = 1.25f; //-球半径
static final float stopvi = 0.1f; //球子停止移动的速度
static float friction = 0.0338f; //球子与台的磨擦力,因速度不同而改变,这里只用定值
Object3D model; //--球子模型在m3g里的节点
int index; //--球子号码
static int whiteballnum = 0; //index为0的是白球
float[] position = new float[3]; //球的xyz位置
float[] velocity = new float[2]; //球的速度向量
float[] extForce = new float[2]; //外界的其它力的方向向量,回旋力与前旋力
float power = 0; //球前进的力量.
float direction = 0; //球打出的移动方向角度0~360,默认为0,就是右
//两个旋转参数的范围为-30到30,绝对值越大,打完后球的转速越高
float MAXCIR = 50; //最快速度的旋转为1贞60度
float UDcir = 0; //上下旋转比例
float Zcir = 0; //左右旋转比例
// 球当时对台的磨擦动力
float nowUDPower = 0; //(float)(2*7*UDcir*3.1416f/180*RADIUS)
float UDpower = 0; //前后旋最终要达到的力大小
float UDsignx = 0; //标志球原来开始回旋的速度正负方向
float UDsigny = 0; //
//球自转的轴的角速度与角度变量
//---前后旋有可能系缘X或Y转的,要看在哪个位置打,而左右旋则一定缘Z转转的.
float xcir = 0; //球在台上进行上下滚动时自转角速度
float ycir = 0; //球在台上进行左右滚动时发生缘Y轴的自转角速度
float xyanglev = 0; //自由前滚的自转角速度
float udanglev = 0; //前后旋转的自转角速度
float zanglev = 0; //球在台上进行左右旋转时缘Z轴的自转角速度
boolean willinPocket = false;//球将要进的标志,用来做是否画球下袋动画的判断.
float[] willposi = new float[2]; //球进洞的位置,进了的移到这显示,好看些.
//boolean willColl = false; //判断球是否将会碰撞,因为有碰撞,此贞不再移动位置标志
boolean inPocket = false;//球已进的标志
//-----游戏规则或其它里用到的,每打一手都重置参数一次的.
boolean istouchwall = false; //是否碰到墙
int inwhichp = -1; //记录下球掉进的是第几号的球洞0 1 2 3 4 5 ]
boolean isindirectIN = false; //是否间接的进球.
//---游戏里出杆前统计球在每一贞的移动路径的参数..
//boolean recordposition = false;
static final int runsLength = 200;
float runsPosition[][] = new float[runsLength][3]; //参数为贞,X,Y 用来记录每杆所有球经过的位置
float runsState[][] = new float[runsLength][6]; //udcir,z,direction记录当时球的旋转方向
float tempud=0,tempxy=0,tempz=0;//用来记录球的旋转度数
Ball3D(int _index)
{
try{
index = _index; //--球号
// if (index < Model.BALLNUM)//如果大于10个球则是临时用的球,不用与模型对应...
// model = Model.BallModel[index];//--取得Model中已经从M3G中取得的车辆节点
resetBall();
}catch(Exception e){System.out.println("new ball error"+e);}
//init();
}
//--初始化球的所有信息
void resetBall()
{
tempud=0;
tempxy=0;
tempz=0;
//torque = 0; //不转弯
power = 0; //不动
direction = 0;//360 288 216 144 72 五个车的车头方向????
velocity[0] = 0; //速度向量
velocity[1] = 0;
//angVelocity = 0; //角速度
extForce[0] =0; //外在力向量
extForce[1] =0;
//model = Model.BallModel[index];//--取得Model中已经从M3G中取得的车辆节点
// if (index < Model.BALLNUM)
// {
// position[0] = Model.BallPos[index][0];//---取得Model中模型的设定的坐标
// position[1] = Model.BallPos[index][1];//---
// position[2] = Model.BallPos[index][2];//---
// }
willinPocket = false;
inPocket = false;
inwhichp = -1;
isindirectIN = false;
willposi[0] = 0;
willposi[1] = 0;
//LRcir = 0;
UDcir = 0;
UDpower = 0;
nowUDPower = 0;
Zcir = 0;
zanglev = 0;
udanglev = 0;
xyanglev = 0;
xcir = 0;
ycir = 0;
UDsigny = 0;
UDsignx = 0;
//willColl = false;
//collPosition[0] = 0;
//collPosition[1] = 0;
// if (index < Model.BALLNUM)
// resetRunsposition();
//updateballModel();
}
//控制放置白球的位置
float moveoffsetxy = 0.7f;
public void moveUp()
{
position[1]+=moveoffsetxy;
//Map.m_cuegroupPos[1]+=moveoffsetxy;
}
public void moveDown()
{
position[1]-=moveoffsetxy;
//Map.m_cuegroupPos[1]-=moveoffsetxy;
}
public void moveLeft()
{
position[0]-=moveoffsetxy;
//Map.m_cuegroupPos[0]-=moveoffsetxy;
}
public void moveRight()
{
position[0]+=moveoffsetxy;
//Map.m_cuegroupPos[0]+=moveoffsetxy;
}
//打球力度------------
public void hitBall()//前进加速
{
// power = Map.m_hitpower; //TOP_SPEED;
// Map.m_framepower = Map.m_hitpower; //因应打球力度调整击球杆速度
//
// Map.m_hitpower = DEFAULT_SPEED; //
//
//
// Map.runscounter = 0;//---设一打球时球的移动贞数重置
// Map.maxrunscounter = 0;
if (UDcir < 0)//
{
//-----effectPower = -(float)(UDcir*3.1416/180*RADIUS);//当UDcir为60以内时,最大的值为1.3
//effectPower = effectPower/2.0f*power; //求出大约回力
UDpower = (float)(-2f/7f*UDcir*3.1416f/180f*RADIUS)*power/TOP_SPEED;//求出旋转力最终要达到的大小0.374? 2/7
nowUDPower = 0;
}
else if (UDcir > 0)//
{
//-----effectPower = -(float)(UDcir*3.1416/180*RADIUS);//当UDcir为60以内时,最大的值为1.3
//effectPower = effectPower/2.0f*power; //求出大约回力
UDpower = (float)(2f/7f*UDcir*3.1416f/180f*RADIUS)*power/TOP_SPEED;//求出旋转力最终要达到的大小0.374? 2/7
nowUDPower = 0;
}
// Map.m_playershotnum[Map.m_whoturn]++;//打球者的每局打的杆数增加
}
public void turnLeft()//转左
{
//如果进行了移动白球的打出角度,就要更新一次白球碰到第一个球后的路径
// direction += Map.turnangle;//--球的出发方向改变
if (direction >=360)
direction -= 360;
//System.out.println(""+Map.turnangle);
}
public void turnRight()//转右
{
// direction -= Map.turnangle;
if (direction <0)
direction += 360;
}
//控制击打球点位置-----------
public void hitLeft()
{
Zcir -= 3;
if (!checkHitpoint())
{
///第二次判断,让球在边上移动
if (UDcir>0) UDcir-=3;
else if (UDcir<0) UDcir+=3;
if (!checkHitpoint())
{
Zcir += 3;
return;
}
}
}
public void hitRight()
{
Zcir += 3;
if (!checkHitpoint())
{
if (UDcir>0) UDcir-=3;
else if (UDcir<0) UDcir+=3;
if (!checkHitpoint())
{
Zcir -= 3;
return;
}
}
}
public void hitUp()
{
UDcir += 3;
if (!checkHitpoint())
{
if (Zcir>0) Zcir-=3;
else if (Zcir<0) Zcir+=3;
if (!checkHitpoint())
{
UDcir -= 3;
return;
}
}
}
public void hitDown()
{
UDcir -= 3;
if (!checkHitpoint())
{
if (Zcir>0) Zcir-=3;
else if (Zcir<0) Zcir+=3;
if (!checkHitpoint())
{
UDcir += 3;
return;
}
}
}
public boolean checkHitpoint()
{
int x1=0,y1=0;
// x1-=Map.m_whiteball.Zcir;
// y1-=Map.m_whiteball.UDcir;
//
//控制选择击点值的范围
if ((float)Math.sqrt((double)(x1*x1+y1*y1)) > MAXCIR)
return false;
return true;
}
//---------
/*
* 算出球的未来的速度,与未来的方向.
* 包括要计算球的回旋力或前旋力
*/
public void ballmove()
{
//--toRadians 角度变弧度
//1弧度=PI/180 弧度=角度*PI/180
//--求出球的移动角度方向向量
float[] dir = { 0, 0 };
//牵引力 移动的方向向量*移动的速度=球要移动的x,y坐标
float[] tractiveForce = {0,0};//只在打球的一瞬间有
if (power!=0)//优化算法用....只有力量时才运算.
{
dir[0]=(float) Math.cos(Math.toRadians(direction));
dir[1]=(float) Math.sin(Math.toRadians(direction));
tractiveForce[0]=dir[0] * power;
tractiveForce[1]=dir[1] * power;
if (Tools.myabs(tractiveForce[0]) < stopvi) tractiveForce[0]=0;
if (Tools.myabs(tractiveForce[1]) < stopvi) tractiveForce[1]=0;
power = 0;//--打完球后打的力量就消失了,之后就靠惯性或旋转力了.
}
//让磨擦力随着球的速度不同而改变
/*float xx,yy;
xx=Tools.myabs(velocity[0]);
yy = Tools.myabs(velocity[1]);
if (xx>=7f || yy>=7f)
friction = 0.033f;
else if (xx>=6f || yy>=6f)
friction = 0.033f;
else if (xx>=5f || yy>=5f)
friction = 0.033f;
else if (xx>=4f || yy>=4f)
friction = 0.033f;
else if (xx>=3f || yy>=3f)
friction = 0.033f;
else if (xx>=2f || yy>=2f)
friction = 0.033f;
else if (xx>=1f || yy>=1f)
friction = 0.033f;
else if (xx>=0.4f || yy>=0.4f)
friction = 0.033f;
else*/
//friction = 0.033f;////不用if ,这样就行优化算法...
float[] frictionalForce = { -velocity[0] * friction, -velocity[1] * friction };
float[] netForce = { 0, 0 }; //球移动的净移动X,Y值,所有力之和
/*float[] bv = {0,0};
bv[0] = velocity[0];
bv[1] = velocity[1];*/
//float nowpower = (float)Math.sqrt(velocity[0]*velocity[0]+velocity[1]*velocity[1]);
if (UDcir < 0)//回旋球的
{
nowUDPower += UDpower/20f;//回旋力加大
//System.out.println("nowUDPower:"+nowUDPower+" UDpower:"+UDpower);
if (nowUDPower >= UDpower)//如果回旋力已经到了最高峰,则让速度由磨擦力停下
{
//System.out.println("end cir");
UDcir = 0;
nowUDPower = 0;
}
else//将速度加上回旋方向的速度
{
//System.out.println(velocity[0]+" "+velocity[1]);
//System.out.println("reduce v "+UDsignx+" "+UDsigny);
float x1,y1;
//此处球的direction值是球本来向前移动的方向,但回旋时,当移动球的速度突然变为0
//则球就有可能向后移动,但球此时的direction仍是向前的..
x1 =Tools.myabs(nowUDPower/2*(float)Math.cos(Math.toRadians(direction)));
y1 =Tools.myabs(nowUDPower/2*(float)Math.sin(Math.toRadians(direction)));
extForce[0] = -UDsignx*x1;
extForce[1] = -UDsigny*y1;
}
}
else if (UDcir > 0)//前旋球的
{
nowUDPower += UDpower/20f;//前旋力加大
if (nowUDPower >= UDpower)//如果回旋力已经到了最高峰,则让速度由磨擦力停下
{
//System.out.println("end cir");
UDcir = 0;
nowUDPower = 0;
}
else//将速度加上回旋方向的速度
{
//System.out.println(velocity[0]+" "+velocity[1]);
//System.out.println("reduce v "+UDsignx+" "+UDsigny);
float x1,y1;
x1 =Tools.myabs(nowUDPower/2*(float)Math.cos(Math.toRadians(direction)));
y1 =Tools.myabs(nowUDPower/2*(float)Math.sin(Math.toRadians(direction)));
extForce[0] = UDsignx*x1;
extForce[1] = UDsigny*y1;
}
}
//总的方向向量为前进的加反现的摩擦力与外界的反弹力之和
netForce[0] = frictionalForce[0] + tractiveForce[0] + extForce[0];
netForce[1] = frictionalForce[1] + tractiveForce[1] + extForce[1];
/*if (Map.runscounter>2 && runsPosition[Map.runscounter-1][0] == runsPosition[Map.runscounter-2][0]&&
runsPosition[Map.runscounter-1][1] == runsPosition[Map.runscounter-2][1]&&
runsPosition[Map.runscounter-1][2] == runsPosition[Map.runscounter-2][2])
{
//--如果球没有移动过就不减速
}
else
{*/
velocity[0] += netForce[0];//原来的速度向量加上 净增力向量来改变速度
velocity[1] += netForce[1];
//}
extForce[0] = 0;
extForce[1] = 0;
if (UDsignx == 0 && UDsigny == 0)//没记过的就记下之前移动的XY符号
{
UDsignx = numbersign(velocity[0]);
UDsigny = numbersign(velocity[1]);
}
///--如果速度太慢了,就停了他.因为前边的减速参数是以速度为单位的,如果不判断会一直动下去.
if (UDcir==0 && Tools.myabs(velocity[0])<stopvi && Math.abs(velocity[1])<stopvi)
{
velocity[0] = 0;
velocity[1] = 0;
UDsignx = 0;
UDsigny = 0;
UDcir = 0;
nowUDPower = 0;
}
}
//--跟据已知的球的速度与方向移动球体
public void recordruns() //更新球子位置等信息
{
if (direction >= 360)//---球的移动方向角度
direction -= 360;
if (direction < 0)
direction += 360;
//记录下每贞时每个球的位置
// runsPosition[Map.runscounter][0] = position[0];
// runsPosition[Map.runscounter][1] = position[1];
// runsPosition[Map.runscounter][2] = position[2];
//
// runsState[Map.runscounter][0] = direction;
//
// float lv = (float)Math.sqrt(velocity[0]*velocity[0]+velocity[1]*velocity[1]);
// float av = (float)(lv/(3.1416f/180f*RADIUS));//自然旋转时前滚的角速度,也就是Y轴旋转增加量
// runsState[Map.runscounter][3] = av;
// runsState[Map.runscounter][4] = -numbersign(velocity[0]);
// runsState[Map.runscounter][5] = -numbersign(velocity[1]);
//
// if (runsState[Map.runscounter][3]!=0) udanglev = UDcir*2;//如果速度为0时不转动,因为此时转动轴为0
// else udanglev = 0;
// runsState[Map.runscounter][1] = udanglev;
// zanglev = Zcir*2;
// runsState[Map.runscounter][2] = zanglev;
//updateballModel();//此处已不用再更新球的显示位置,但可以在这里用于测试查看
}
public void updatePosition()
{
// position[0] = runsPosition[Map.runscounter][0];
// position[1] = runsPosition[Map.runscounter][1];
// position[2] = runsPosition[Map.runscounter][2];
//
// direction = runsState[Map.runscounter][0];
// udanglev = runsState[Map.runscounter][1];
// zanglev = runsState[Map.runscounter][2];
// xyanglev = runsState[Map.runscounter][3];
// xcir = runsState[Map.runscounter][4];
// ycir = runsState[Map.runscounter][5];
updateballModel();
}
//--初始化球的移动路径
public void resetRunsposition()
{
for (int i = 0; i <runsLength; i++)
{
runsPosition[i][0] = -99;
runsPosition[i][1] = -99;
runsPosition[i][2] = -99;
runsState[i][0] = 0;
runsState[i][1] = 0;
runsState[i][2] = 0;
runsState[i][3] = 0;
runsState[i][4] = 0;
runsState[i][5] = 0;
// Game.playsoundlist[i] = -1;
}
}
public void updateballModel()
{
//--按扭矩算出显示出要显示的动态模型
try{
//model.animate(0);
// model.setTranslation(position[0], position[1], position[2]);//设置模型的平移到位置的坐标
//
//
// tempz += -zanglev;
// tempud += udanglev;
// tempxy += xyanglev;
// if (zanglev!=0)
// {
// //model.preRotate(-zanglev,0,0,1);
// model.setOrientation(tempz, 0, 0, 1);//--设置模型的顺时针旋转的角度与旋转轴
// }
// else if (udanglev!=0)
// {
// //model.preRotate(udanglev,ycir,-xcir, 0);//加速后旋
// model.setOrientation(tempud, ycir, -xcir, 0);//--设置模型的顺时针旋转的角度与旋转轴
// }
// else if (xyanglev!=0)
// {
// //model.preRotate(xyanglev,ycir,-xcir, 0);
// model.setOrientation(tempxy, ycir, -xcir, 0);//--设置模型的顺时针旋转的角度与旋转轴
// }
//设置新转动的角度击中球的位置的左右旋转参数,如果没有左右旋转的就以球的前后击中方向旋转,
//如果是击中球心则以球移动方向来向前进的方向转动
/*if (zanglev!=0)
{
model.preRotate(-zanglev,0,0,1);
}
else if (udanglev!=0)
{
//if (UDcir>0)
model.preRotate(udanglev,ycir,-xcir, 0);//加速后旋
//else
// model.preRotate(udanglev,-numbersign(ycir),numbersign(xcir), 0);//加速前旋
}
else
model.preRotate(xyanglev,ycir,-xcir, 0);*/
udanglev = 0;
xyanglev = 0;xcir = 0;ycir = 0;//不播放动画时不转
}
catch(Exception e)
{System.out.println("updateballModel error:"+e);
}
}
//返回球是否在移动
public boolean isballMove()
{
if((velocity[0] == 0 && velocity[1] == 0) || inPocket)
return false;
return true;
}
public int numbersign(float b)
{
if (b == 0.0f)
return 0;
return (int)(Tools.myabs(b)/(float)b);
}
}