碰撞检测示例:CollisionDetection



 
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范围内的一个随机正数(绝对值)
 }

}

原文地址:https://www.cnblogs.com/bluespot/p/876795.html