自己写的自动跟踪导弹算法,内有自己引擎的一些变量,有点乱,但主要算法是有的,思想最重要.
MyAmmoClass.java
package game;
import game.config.dConfig;
import game.object.CObject;
import game.object.IObject;
import game.object.dActor;
import game.pak.Camera;
import android.graphics.Point;
import android.util.Log;
import com.changle.ui.Graphics;
import com.cl.libgdxjar.LibgdxImage;
/**
* (导弹) 弹药,军火; (自动跟踪导弹)
* @author maxuehuai
*
*/
public class MyAmmoClass {
Ammo ammo/*=new Ammo()*/;
// double speed=5;//导弹飞行速度 //ok1
// double speed=10;//导弹飞行速度
double speed=15;//导弹飞行速度
// int AmmoX;//导弹X
// int AmmoY;//导弹Y
// double Ammorotation;//导弹角度
final int GST_START=0;
final int GST_FLYING=1;
final int GST_DIE=2;
final static int GST_DIEEX=3;
int currentstate;
double radian;//导弹和目标的弧度
Point target=new Point();//目标
short[] targetBox=new short[4];
Point inittarget=new Point();//目标
// Point ammo=new Point();
double angle;
double vx;//导弹x速度
double vy;//导弹y速度
// final int angularVelocity=5;// 因为角度需要慢慢的旋转到目标角度,所以给出一个常量角速度
// final double angularVelocity=3;//ok1
// final double angularVelocity=4;
// final double angularVelocity=6;
final double angularVelocity=8;
double thisAngle;
double tempAngleV;
double ammoRadian;
double other;
CObject targetObj=null;
CObject startObj=null;
/**
* 传对象
* @param bombImage1
* @param bombImage2
* @param AmmoImage
* @param Ammorotation
* @param startobj
* @param targetobj
*/
public MyAmmoClass(LibgdxImage bombImage1,LibgdxImage bombImage2,LibgdxImage AmmoImage,int Ammorotation,CObject startobj,CObject targetobj){
startObj=startobj;
targetObj=targetobj;
ammo=new Ammo(bombImage1,bombImage2,AmmoImage,startobj.m_x>>8,startobj.m_y>>8,Ammorotation);
target.set(targetobj.m_x>>8, (targetobj.m_y>>8)-50);
inittarget.set(targetobj.m_x>>8, (targetobj.m_y>>8)-50);
targetObj.cObj_getActorBoxInfo(dActor.BOX_COLLIDE, targetBox);// 得到碰撞框
// targetBox[0]=(short)(targetobj.m_x>>8);
// targetBox[1]=(short)((targetobj.m_y>>8));
// targetBox[2]=(short)((targetobj.m_x>>8)+20);
// targetBox[3]=(short)((targetobj.m_y>>8)+20);
currentstate=GST_START;
}
/**
* 传坐标
* @param bombImage1
* @param bombImage2
* @param AmmoImage
* @param Ammox
* @param Ammoy
* @param Ammorotation
* @param targetx
* @param targety
*/
public MyAmmoClass(LibgdxImage bombImage1,LibgdxImage bombImage2,LibgdxImage AmmoImage,int Ammox,int Ammoy,int Ammorotation,int targetx,int targety ){
ammo=new Ammo(bombImage1,bombImage2,AmmoImage,Ammox,Ammoy,Ammorotation);
target.set(targetx, targety);
inittarget.set(targetx, targety);
targetBox[0]=(short)targetx;
targetBox[1]=(short)targety;
targetBox[2]=(short)(targetx+20);
targetBox[3]=(short)(targety+20);
currentstate=GST_START;
// initammoRadian= (Math.PI / 180 * ammo.initrotation);
}
void init(){
ammo.x=ammo.initx;
ammo.y=ammo.inity;
ammo.rotation=ammo.initrotation;
ammo.endx=ammo.initendx;
ammo.endy=ammo.initendy;
time=0;
// target=inittarget;
target.set(inittarget.x, inittarget.y);
}
int time;
public void doLogic(){
switch(currentstate){
case GST_START:
if(time<10){
time++;
ammo.rotation=-ammo.initrotation;
ammoRadian= (Math.PI / 180 * (ammo.rotation));
double aa=Math.cos(ammoRadian);
double bb=Math.cos(ammoRadian);
vx = (Math.cos(ammoRadian) * speed);
vy = (Math.sin(ammoRadian) * speed);
ammo.x += vx;
ammo.y += vy;
ammo.endx=ammo.x-(ammo.image.getWidth()*Math.cos(ammo.initammoRadian));
ammo.endy=ammo.y+(ammo.image.getHeight()*Math.sin(ammo.initammoRadian));
//更新导弹碰撞框
ammo.ammoBox[0]=(short)ammo.x;
ammo.ammoBox[1]=(short)ammo.y;
ammo.ammoBox[2]=(short)(ammo.x+ammo.image.getWidth());
ammo.ammoBox[3]=(short)(ammo.y+ammo.image.getHeight());
// return;
}else{
currentstate=GST_FLYING;
// break;
}
break;
case GST_FLYING:
time++;
//如果已死亡或未被激活
if(targetObj.cObj_testFlag(dActor.FLAG_BASIC_DIE)||targetObj.cObj_testFlag(dActor.FLAG_BASLIC_NOT_LOADABLE)){
Log.e("GST_FLYING****************************************************", "targetObj.cObj_m_actorID:"+targetObj.cObj_m_actorID);
currentstate=GST_DIE;
targetObj=null;
return;
}
if(targetObj!=null){//add by mxh 2013-11-7
if(targetObj.cObj_m_currentState==IObject.ST_ACTOR_DIE||targetObj.cObj_m_currentState==IObject.ST_ACTOR_DIEEX){
targetObj=null;
Log.e("GST_FLYING##########################", "targetObj=null");
currentstate=GST_DIE;
return;
}
}
if(ammo_testColliding(targetBox)||time>120){
currentstate=GST_DIE;
return;
}
if(targetObj!=null){//如果目标对象存在 //add by mxh 2013-11-7 有BUG死机 (对象死亡时targetObj并未置为null)
if(target.x!=(targetObj.m_x>>8)){//坐标改变时更新坐标
set_targetpodition(targetObj.m_x>>8,(targetObj.m_y>>8)-50);
}
}
radian=Math.atan2( (target.y - ammo.y), target.x - ammo.x );// 使用 Math.atan2可以计算到导弹和目标的弧度。
angle=(radian * 180 / Math.PI); 将弧度转换为角度
angle = to360Angle(angle);
//如果导弹的角度较大则减。
thisAngle= to360Angle(ammo.rotation);
// Log.e("doLogic", "thisAngle:"+thisAngle);
if (thisAngle < angle){
// tempAngleV = angularVelocity;
if((angle-thisAngle)<angularVelocity){//角度调整 mxh add 防止导弹头浮动不平稳
tempAngleV =angle-thisAngle;
}else{
tempAngleV = angularVelocity;
}
}else if (thisAngle > angle){
// tempAngleV = -angularVelocity;
if((angle-thisAngle)>-angularVelocity){//角度调整 mxh add 防止导弹头浮动不平稳
tempAngleV = angle-thisAngle;
}else{
tempAngleV = -angularVelocity;
}
}else{
tempAngleV = 0;
}
other = 360 - Math.abs(angle - thisAngle);
// 如果反方向的角度较小,则调换下角速度。
if (other < Math.abs(angle - thisAngle))
{
tempAngleV *= -1;
}
// 旋转导弹角度
ammo.rotation += tempAngleV;
ammoRadian= (Math.PI / 180 * ammo.rotation);
vx = (Math.cos(ammoRadian) * speed);
vy = (Math.sin(ammoRadian) * speed);
ammo.x += vx;
ammo.y += vy;
ammo.endx=ammo.x-(ammo.image.getWidth()*Math.cos(ammo.initammoRadian));
ammo.endy=ammo.y+(ammo.image.getHeight()*Math.sin(ammo.initammoRadian));
//更新导弹碰撞框
ammo.ammoBox[0]=(short)ammo.x;
ammo.ammoBox[1]=(short)ammo.y;
ammo.ammoBox[2]=(short)(ammo.x+ammo.image.getWidth());
ammo.ammoBox[3]=(short)(ammo.y+ammo.image.getHeight());
break;
case GST_DIE:
if(CGame.curLevelID==1){//add by mxh 2013-11-4 导弹消失时生成炸弹(爆炸动画效果和受伤处理)
CObject EnemyCreate = new CObject();//出场对象临时变量
EnemyCreate = CObject.cObj_allocActor(35, (int)(((int)ammo.x)<<8), (int)(((int)ammo.y)<<8), false,true);
EnemyCreate.cObj_setState(IObject.ST_ACTOR_ATTACK);
EnemyCreate.cObj_setAnimAction(2, false);
// currentstate=GST_DIEEX;
}else if(CGame.curLevelID==2){//add by mxh 2013-11-4 导弹消失时生成炸弹(爆炸动画效果和受伤处理)
CObject EnemyCreate = new CObject();//出场对象临时变量
EnemyCreate = CObject.cObj_allocActor(43, (int)(((int)ammo.x)<<8), (int)(((int)ammo.y)<<8), false,true);
EnemyCreate.cObj_setState(IObject.ST_ACTOR_ATTACK);
EnemyCreate.cObj_setAnimAction(2, false);
// currentstate=GST_DIEEX;
}else if(CGame.curLevelID==7){//add by mxh 2013-11-4 导弹消失时生成炸弹(爆炸动画效果和受伤处理)
CObject EnemyCreate = new CObject();//出场对象临时变量
EnemyCreate = CObject.cObj_allocActor(34, (int)(((int)ammo.x)<<8), (int)(((int)ammo.y)<<8), false,true);
EnemyCreate.cObj_setState(IObject.ST_ACTOR_ATTACK);
EnemyCreate.cObj_setAnimAction(2, false);
// currentstate=GST_DIEEX;
}
currentstate=GST_DIEEX;
if(targetObj!=null){
targetObj.IsAmmo=false;
}
break;
case GST_DIEEX:
break;
}
}
// if(time<20){
// time++;
// ammo.rotation=-ammo.initrotation;
// ammoRadian= (Math.PI / 180 * (ammo.rotation));
//
// double aa=Math.cos(ammoRadian);
// double bb=Math.cos(ammoRadian);
//
// vx = (Math.cos(ammoRadian) * speed);
// vy = (Math.sin(ammoRadian) * speed);
//
vx =0;
vy =-speed;
//
// ammo.x += vx;
// ammo.y += vy;
// ammo.endx=ammo.x-(ammo.image.getWidth()*Math.cos(ammo.initammoRadian));
// ammo.endy=ammo.y+(ammo.image.getHeight()*Math.sin(ammo.initammoRadian));
ammo.endx=ammo.x-ammo.image.getWidth();
ammo.endy=ammo.y;
//
// //更新导弹碰撞框
// ammo.ammoBox[0]=(short)ammo.x;
// ammo.ammoBox[1]=(short)ammo.y;
// ammo.ammoBox[2]=(short)(ammo.x+ammo.image.getWidth());
// ammo.ammoBox[3]=(short)(ammo.y+ammo.image.getHeight());
//
// return;
// }else if(time==20){
time++;
int xx=(int)(ammo.initx+inittarget.x/2);
int yy=inittarget.y;
set_targetpodition(xx,yy-60);
//
if(time==150){
init();
return;
}
// }else if(time==60){
// time++;
init();
// }
//
if(ammo.x>target.x){
if(target.x!=inittarget.x){
set_targetpodition(inittarget.x,inittarget.y);
}
}
//
// if(ammo_testColliding(targetBox)){
//
time++;
Log.e("doLogic!", "打中了!!!!!");
// //init();
// return;
// }
//
// double aa=Math.atan2(1,1);
// double bb=(aa * 180 / Math.PI); 将弧度转换为角度
Log.e("doLogic", "aa:"+aa);
// radian=Math.atan2( (target.y - ammo.y), target.x - ammo.x );// 使用 Math.atan2可以计算到导弹和目标的弧度。
// angle=(radian * 180 / Math.PI); 将弧度转换为角度
// angle = to360Angle(angle);
// //Log.e("", "")
System.err.println("angle:" + angle);
// //如果导弹的角度较大则减。
// thisAngle= to360Angle(ammo.rotation);
Log.e("doLogic", "thisAngle:"+thisAngle);
//
// if (thisAngle < angle){
// // tempAngleV = angularVelocity;
// if((angle-thisAngle)<angularVelocity){
// tempAngleV =angle-thisAngle;
// }else{
// tempAngleV = angularVelocity;
// }
// }else if (thisAngle > angle){
// // tempAngleV = -angularVelocity;
// if((angle-thisAngle)>-angularVelocity){
// tempAngleV = angle-thisAngle;
// }else{
// tempAngleV = -angularVelocity;
// }
// }else{
// tempAngleV = 0;
// }
// other = 360 - Math.abs(angle - thisAngle);
// // 如果反方向的角度较小,则调换下角速度。
// if (other < Math.abs(angle - thisAngle))
// {
// tempAngleV *= -1;
// }
// // 旋转导弹角度
// ammo.rotation += tempAngleV;
// ammoRadian= (Math.PI / 180 * ammo.rotation);
// vx = (Math.cos(ammoRadian) * speed);
// vy = (Math.sin(ammoRadian) * speed);
// ammo.x += vx;
// ammo.y += vy;
//
// //更新导弹碰撞框
// ammo.ammoBox[0]=(short)ammo.x;
// ammo.ammoBox[1]=(short)ammo.y;
// ammo.ammoBox[2]=(short)(ammo.x+ammo.image.getWidth());
// ammo.ammoBox[3]=(short)(ammo.y+ammo.image.getHeight());
//
endx=x-AmmoImage.getWidth()*Math.cos(rotation);
endy=y+AmmoImage.getWidth()*Math.sin(rotation);
ammo.endx=ammo.x-(ammo.image.getWidth()*Math.cos(ammo.rotation));
ammo.endy=ammo.y+(ammo.image.getWidth()*Math.sin(ammo.rotation));
//
ammo.endx=ammo.x-ammo.image.getWidth();
ammo.endy=ammo.y;
//
// ammo.endx=ammo.x-(ammo.image.getWidth()*Math.cos(ammo.initammoRadian));
// ammo.endy=ammo.y+(ammo.image.getHeight()*Math.sin(ammo.initammoRadian));
//
ammo.rotation= to360Angle(ammo.rotation);
Log.e("****", "ammo.initammoRadian:"+ammo.initammoRadian);
Log.e("%%%%%%%", "ammo.x:"+ammo.x+" | "+"ammo.y"+ammo.y);
Log.e("&&&&&&&&&&&&&&", "ammo.endx:"+ammo.endx+" | "+"ammo.endy"+ammo.endy);
// }
public void doLogic_old(){
// if(time<150){
// time++;
// }
if(time<20){
time++;
ammo.rotation=-ammo.initrotation;
ammoRadian= (Math.PI / 180 * (ammo.rotation));
double aa=Math.cos(ammoRadian);
double bb=Math.cos(ammoRadian);
vx = (Math.cos(ammoRadian) * speed);
vy = (Math.sin(ammoRadian) * speed);
// vx =0;
// vy =-speed;
ammo.x += vx;
ammo.y += vy;
ammo.endx=ammo.x-(ammo.image.getWidth()*Math.cos(ammo.initammoRadian));
ammo.endy=ammo.y+(ammo.image.getHeight()*Math.sin(ammo.initammoRadian));
// ammo.endx=ammo.x-ammo.image.getWidth();
// ammo.endy=ammo.y;
//更新导弹碰撞框
ammo.ammoBox[0]=(short)ammo.x;
ammo.ammoBox[1]=(short)ammo.y;
ammo.ammoBox[2]=(short)(ammo.x+ammo.image.getWidth());
ammo.ammoBox[3]=(short)(ammo.y+ammo.image.getHeight());
return;
}else if(time==20){
// time++;
// int xx=(int)(ammo.initx+inittarget.x/2);
// int yy=inittarget.y;
// set_targetpodition(xx,yy-60);
// if(time==150){
// init();
// return;
// }
}else if(time==60){
time++;
// init();
}
// if(ammo.x>target.x){
// if(target.x!=inittarget.x){
// set_targetpodition(inittarget.x,inittarget.y);
// }
// }
if(ammo_testColliding(targetBox)){
// time++;
// Log.e("doLogic!", "打中了!!!!!");
//init();
return;
}
double aa=Math.atan2(1,1);
double bb=(aa * 180 / Math.PI); 将弧度转换为角度
// Log.e("doLogic", "aa:"+aa);
radian=Math.atan2( (target.y - ammo.y), target.x - ammo.x );// 使用 Math.atan2可以计算到导弹和目标的弧度。
angle=(radian * 180 / Math.PI); 将弧度转换为角度
angle = to360Angle(angle);
//Log.e("", "")
// System.err.println("angle:" + angle);
//如果导弹的角度较大则减。
thisAngle= to360Angle(ammo.rotation);
// Log.e("doLogic", "thisAngle:"+thisAngle);
if (thisAngle < angle){
// tempAngleV = angularVelocity;
if((angle-thisAngle)<angularVelocity){
tempAngleV =angle-thisAngle;
}else{
tempAngleV = angularVelocity;
}
}else if (thisAngle > angle){
// tempAngleV = -angularVelocity;
if((angle-thisAngle)>-angularVelocity){
tempAngleV = angle-thisAngle;
}else{
tempAngleV = -angularVelocity;
}
//
}else{
tempAngleV = 0;
}
other = 360 - Math.abs(angle - thisAngle);
// 如果反方向的角度较小,则调换下角速度。
if (other < Math.abs(angle - thisAngle))
{
tempAngleV *= -1;
}
// 旋转导弹角度
ammo.rotation += tempAngleV;
ammoRadian= (Math.PI / 180 * ammo.rotation);
vx = (Math.cos(ammoRadian) * speed);
vy = (Math.sin(ammoRadian) * speed);
ammo.x += vx;
ammo.y += vy;
//更新导弹碰撞框
ammo.ammoBox[0]=(short)ammo.x;
ammo.ammoBox[1]=(short)ammo.y;
ammo.ammoBox[2]=(short)(ammo.x+ammo.image.getWidth());
ammo.ammoBox[3]=(short)(ammo.y+ammo.image.getHeight());
// endx=x-AmmoImage.getWidth()*Math.cos(rotation);
// endy=y+AmmoImage.getWidth()*Math.sin(rotation);
// ammo.endx=ammo.x-(ammo.image.getWidth()*Math.cos(ammo.rotation));
// ammo.endy=ammo.y+(ammo.image.getWidth()*Math.sin(ammo.rotation));
// ammo.endx=ammo.x-ammo.image.getWidth();
// ammo.endy=ammo.y;
ammo.endx=ammo.x-(ammo.image.getWidth()*Math.cos(ammo.initammoRadian));
ammo.endy=ammo.y+(ammo.image.getHeight()*Math.sin(ammo.initammoRadian));
// ammo.rotation= to360Angle(ammo.rotation);
// Log.e("****", "ammo.initammoRadian:"+ammo.initammoRadian);
// Log.e("%%%%%%%", "ammo.x:"+ammo.x+" | "+"ammo.y"+ammo.y);
// Log.e("&&&&&&&&&&&&&&", "ammo.endx:"+ammo.endx+" | "+"ammo.endy"+ammo.endy);
}
public void set_targetpodition(int x,int y){
target.set(x, y);
// targetBox[0]=(short)x;
// targetBox[1]=(short)y;
// targetBox[2]=(short)(x+20);
// targetBox[3]=(short)(y+20);
if(targetObj!=null){
targetObj.cObj_getActorBoxInfo(dActor.BOX_COLLIDE, targetBox);// 得到碰撞框
}
}
boolean bombglg=false;
// double initammoRadian;
public void paint(){
if(currentstate==GST_DIE||currentstate==GST_DIEEX){
return;
}
if(ammo.image!=null){
// Log.e("paint###########", "ammo.rotation:"+ammo.rotation);
ammo.image.setRorate(true, (int)(-(ammo.rotation)-ammo.initrotation), ammo.image.getWidth()/2, ammo.image.getHeight()/2);
ammo.image.draw((int)ammo.x-Camera.cameraLeft, (int)ammo.y-Camera.cameraTop, 0);
// ammo.image.draw((int)ammo.endx, (int)ammo.endy, 0);
if(bombglg){
bombglg=false;
ammo.bombimage2.setRorate(true, (int)(-(ammo.rotation)-ammo.initrotation), (int)(ammo.image.getWidth()/2+ammo.image.getWidth()*Math.cos(ammo.initammoRadian)), (int)(ammo.image.getHeight()/2+ammo.image.getHeight()*Math.sin(ammo.initammoRadian)));
ammo.bombimage2.draw((int)ammo.endx-Camera.cameraLeft, (int)ammo.endy-Camera.cameraTop, 0);
// int xxx=(int)(int)(ammo.image.getWidth()/2+ammo.image.getWidth()*Math.cos(ammo.initammoRadian));
// int yyy=(int)(ammo.image.getHeight()/2-ammo.image.getHeight()*Math.sin(ammo.initammoRadian));
// Log.e("&&&&&&&&&&&&&&", "xxx:" +xxx+ " || "+"yyy:"+yyy);
}else{
bombglg=true;
ammo.bombimage1.setRorate(true, (int)(-(ammo.rotation)-ammo.initrotation),(int)(ammo.image.getWidth()/2+ammo.image.getWidth()*Math.cos(ammo.initammoRadian)), (int)(ammo.image.getHeight()/2+ammo.image.getHeight()*Math.sin(ammo.initammoRadian)));
ammo.bombimage1.draw((int)ammo.endx-Camera.cameraLeft, (int)ammo.endy-Camera.cameraTop, 0);
}
}
}
//此方法返回的角度为0~360度。
double to360Angle(double angle)
{
angle = angle % 360;
if (angle < 0)
angle += 360;
return angle;
}
public boolean ammo_testColliding(short[] box){
if(CTools.isIntersecting(ammo.ammoBox, box)){
return true;
}
return false;
}
public void set_ammoState(int state){
currentstate=state;
}
public void dispose(){
}
}
class Ammo {
LibgdxImage image;
LibgdxImage bombimage;
LibgdxImage bombimage1;
LibgdxImage bombimage2;
double x;//导弹X
double y;//导弹Y
double rotation;//导弹角度
double initx;//导弹X
double inity;//导弹Y
double initrotation;//初始导弹角度
double initendx;//导弹尾焰X
double initendy;//导弹尾焰Y
double endx;//导弹尾焰X
double endy;//导弹尾焰Y
double initammoRadian;
short[] ammoBox=new short[4];
public Ammo(){
}
public Ammo(LibgdxImage BombImage1,LibgdxImage BombImage2,LibgdxImage AmmoImage,double Ammox,double Ammoy,double Ammorotation){
// bombimage=BombImage;
bombimage1=BombImage1;
bombimage2=BombImage2;
image=AmmoImage;
x=Ammox-AmmoImage.getWidth()/2;
y=Ammoy-AmmoImage.getHeight()/2;
rotation=Ammorotation;
initx=x;
inity=y;
initrotation=Ammorotation;
// endx=x-AmmoImage.getWidth();
// endy=y;
initammoRadian= (Math.PI / 180 * initrotation);
endx=x-(image.getWidth()*Math.cos(initammoRadian));
endy=y+(image.getHeight()*Math.sin(initammoRadian));
initendx=x;
initendy=endy;
ammoBox[0]=(short)x;
ammoBox[1]=(short)y;
ammoBox[2]=(short)(x+AmmoImage.getWidth());
ammoBox[3]=(short)(y+AmmoImage.getHeight());
// endx=x-AmmoImage.getWidth()*Math.cos(rotation);
// endy=y+AmmoImage.getWidth()*Math.sin(rotation);
}
}