import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import java.io.*;
import java.io.IOException;
import java.util.Random;
public class CollisionDetection
extends MIDlet
implements CommandListener, Runnable {
private boolean running;//主循环的判断
private boolean FirstComet = true;//首次碰撞检测
private int AimingX;//检测线的x轴初始位置
private int AimingY;//检测线的y轴初始位置
private int AimingDirX;//检测线的x轴初始方向
private int AimingDirY;//检测线的y轴初始方向
private int Kills = 0;//杀死的次数
private int CometX;//彗星的x轴初始位置
private int CometY;//彗星的y轴初始位置
private int CometXvec;//彗星的x轴初始方向
private int CometYvec;//彗星的y轴初始方向
private int Count = 30;//
private long frameTime = 0;//
private long lastFrameTime = 0;//
private static final int SENSITIVITY = 10;//灵敏度
private int Side = 0;//
private long LastSide = 0;//
private static final int PLAYER_RADIUS = 16;//恒星的半径
private static final int ENEMY_RADIUS = 8;//彗星的半径
private int COLLISION_LENGTH = PLAYER_RADIUS+ENEMY_RADIUS;//碰撞的长度=恒星的半径+彗星的半径
private int COLLISION_LIMIT = COLLISION_LENGTH*COLLISION_LENGTH;//碰撞的区间为碰撞长度的平方
private MyCanvas myCanvas;//内部画布类
private Display display;//显示屏幕
private Graphics myGraphics;//图形参数
private Random random = new Random();//随机数
private Command quit;//退出命令
class MyCanvas extends Canvas//内部为画布类
{
protected void paint(Graphics graphics)
{
int PlayerVectorX;//检测线的X轴向量
int PlayerVectorY;//检测线的Y轴向量
int EnemyVectorX;//彗星的X轴向量
int EnemyVectorY;//彗星的Y轴向量
//中心位置
int CenterX = getWidth()/2;//X轴的中心位置为屏幕宽度的一半
int CenterY = getHeight()/2;//Y轴的中心位置为屏幕高度的一半
int LoopCount = 4;//
myGraphics = graphics;//传递图形参数
if (FirstComet)//第一次的彗星
{
NewComet();//设置新彗星的位置参数
FirstComet=false;//
}
frameTime = System.currentTimeMillis();//当前帧的时间
long Duration = frameTime-lastFrameTime;//持续时间为当前帧的时间减去上一帧的时间
while ((Duration > 5) && (LoopCount >0))//
{
LoopCount--;//计算器自减1次
myGraphics.setColor(0,0,0);//
myGraphics.drawLine (CenterX,CenterY,AimingX,AimingY);//绘制正向检测线
PlayerVectorX = (AimingX-CenterX);//检测线的X轴向量=检测线X端点到X轴中心点的矢量
PlayerVectorY = (AimingY-CenterY);//检测线的Y轴向量=检测线X端点到Y轴中心点的矢量
myGraphics.drawLine (CenterX-PlayerVectorX,CenterY-PlayerVectorY,CenterX,CenterY);//绘制反向检测线
AimingX+=AimingDirX;//检测线沿着X轴方向走
AimingY+=AimingDirY;//检测线沿着Y轴方向走
/**
左角 上边 右角
(上角) +----+ (上角)
+ +
左边 + + 右边
+ +
(下角) +----+ (下角)
左角 下边 右角
*/
if ((AimingX>=getWidth()) && (AimingY==0))//检测线超出右边上角
{
AimingX = getWidth()-1;
AimingDirX=0;
AimingDirY=1;
};
if ((AimingX<0) && (AimingY==0))//检测线超出左边上角
{
AimingX = 0;
AimingDirX=0;
AimingDirY=1;
};
if ((AimingX>=getWidth()) && (AimingY==(getHeight()-1)))//检测线超出右边下角
{
AimingX = getWidth()-1;
AimingDirX=0;
AimingDirY=-1;
};
if ((AimingX<0) && (AimingY==(getHeight()-1)))//检测线超出左边下角
{
AimingX = 0;
AimingDirX=0;
AimingDirY=-1;
};
if ((AimingY>=getHeight()) && (AimingX==0))//检测线超出下边左角
{
AimingY = getHeight()-1;
AimingDirX=1;
AimingDirY=0;
};
if ((AimingY<0) && (AimingX==0))//检测线超出上边左角
{
AimingY = 0;
AimingDirX=1;
AimingDirY=0;
};
if ((AimingY>=getHeight()) && (AimingX==(getWidth()-1)))//检测线超出下边右角
{
AimingY = getHeight()-1;
AimingDirX=-1;
AimingDirY=0;
};
if ((AimingY<0) && (AimingX==(getWidth()-1)))//检测线超出上边右角
{
AimingY = 0;
AimingDirX=-1;
AimingDirY=0;
};
Duration-=5;//持续时间自减5毫秒
//<核心检测算法部分>{
PlayerVectorX = (AimingX-CenterX);//检测线的X轴向量=检测线X端点到X轴中心点的矢量
PlayerVectorY = (AimingY-CenterY);//检测线的Y轴向量=检测线Y端点到Y轴中心点的矢量
EnemyVectorX = (CenterX-CometX);//彗星的X轴向量=X轴中心点到彗星X端点的矢量
EnemyVectorY = (CenterY-CometY);//彗星的Y轴向量=Y轴中心点到彗星Y端点的矢量
Side = EnemyVectorX * PlayerVectorY - PlayerVectorX*EnemyVectorY;//边界值=彗星的X轴向量*检测线的Y轴向量-检测线的X轴向量*彗星的Y轴向量
if (((Side >=0) && (Side < SENSITIVITY)) || ((Side<=0) && (Side > SENSITIVITY)))//
{
//碰撞检测的边界值在0与灵敏度区间的时候
Kills++;
NewComet();
}
if (Side<=0)
{
if (LastSide > 0)
{
//当前边界值为负,而上一个边界值为正时
Kills++;
NewComet();
}
} else {
if (LastSide < 0)
{
//当前边界值为正,而上一个边界值为负时
Kills++;
NewComet();
}
}
LastSide = Side;
Count--;
if (Count == 0)
{
Count = 30;
CometX+=CometXvec;
CometY+=CometYvec;
int Length = EnemyVectorX*EnemyVectorX + EnemyVectorY*EnemyVectorY;//
if (Length <= COLLISION_LIMIT)//当长度在碰撞区间内时
{
//恒星、彗星大碰撞,退出程序
destroyApp(true);
notifyDestroyed();
}
//绘制彗星
for (int i = 0;i<8;i++)
{
myGraphics.setColor(31*i,30*i,24*i);
myGraphics.fillArc(CometX-CometXvec*(7-i)-8,CometY-CometYvec*(7-i)-8,16,16,0,360);
}
}
//}<核心检测算法部分>
//绘制检测线
myGraphics.setColor(128,192,255);
myGraphics.drawLine (CenterX,CenterY,AimingX,AimingY);//绘制正向检测线
myGraphics.drawLine (CenterX-PlayerVectorX,CenterY-PlayerVectorY,CenterX,CenterY);//绘制反向检测线
lastFrameTime=frameTime;
}
//绘制恒星
myGraphics.setColor(128,160,255);//设置恒星的颜色
myGraphics.fillArc(CenterX-16,CenterY-16,32,32,0,360);//在离中心位置偏移x,y长度各为16象素的地方画直径为32的实心圆
myGraphics.drawString(" "+Kills,0,0,Graphics.LEFT | Graphics.TOP);//碰撞次数显示
}
protected void keyPressed(int keyCode)//监听手机按键事件
{
int Key;
try {
Key = getGameAction(keyCode);//取键值
} catch (Exception e)
{
Key = 0;
}
if (Key ==FIRE)//按fire或者ok键
{
AimingDirX=-AimingDirX;//取x反方向
AimingDirY=-AimingDirY;//取y反方向
}
}
}
public CollisionDetection() //构造函数
{
myCanvas = new MyCanvas();//创建画布对象
quit = new Command("Quit",Command.EXIT,2);//创建退出命令
myCanvas.addCommand(quit);//为画布添加退出命令
myCanvas.setCommandListener(this);//为画布设置命令监听器
running = true;//主循环判断赋初值
AimingY = 0;//检测线的y轴初始位置
AimingX = myCanvas.getWidth() / 2;//检测线的x轴初始位置
AimingDirX = 1;//检测线的x轴初始方向
AimingDirY = 0;//检测线的y轴初始方向
lastFrameTime = System.currentTimeMillis();//开始记录为上一帧的时间
Thread t = new Thread(this);//创建一个新线程
t.start();//启动线程
}
private void NewComet()//新的彗星产生
{
//清屏
myGraphics.setColor(0,0,0);
myGraphics.fillRect(0,0,myCanvas.getWidth(),myCanvas.getHeight());
if (rnd(2) ==0)//随机为偶数
{
//along top or bot
CometX=rnd(myCanvas.getWidth());
CometXvec=rnd(4);
if (rnd(2)==0)//随机数为偶数
{
//along top
CometY = 0;
CometYvec = 5-CometXvec;
}
else {
CometY = myCanvas.getHeight()-1;
CometYvec = -(5-CometXvec);
}
if (CometX> myCanvas.getWidth()/2)
CometXvec=-CometXvec;
} else {
//along left or right
CometY=rnd( myCanvas.getHeight());
CometYvec=rnd(4);
if (rnd(2)==0)//随机数为偶数
{
//along left
CometX = 0;
CometXvec = 5-CometYvec;
} else {
CometX = myCanvas.getWidth()-1;
CometXvec = -(5-CometYvec);
}
if (CometY> myCanvas.getHeight()/2)
CometYvec=-CometYvec;
}
}
public void startApp()//启动程序
{
Display.getDisplay(this).setCurrent(myCanvas);//当前屏幕显示为画布
myCanvas.repaint();//画布重绘
}
public void pauseApp() //暂停程序
{
myCanvas.repaint();//画布重绘
}
public void destroyApp(boolean unconditional) //销毁程序
{
}
public void commandAction(Command c, Displayable s) //命令处理
{
if (c==quit)//退出命令
{
destroyApp(true);//销毁程序
notifyDestroyed();//通知程序服务管理销毁
}
}
public void run()//主循环
{
while (running)
{
myCanvas.repaint();//画布重绘
myCanvas.serviceRepaints();//使用强制刷屏
}
}
private int rnd(int bound)
{
return Math.abs(random.nextInt() % bound);//取bound范围内的一个随机正数(绝对值)
}
}