Java 游戏编程基础 做个碰撞的小球

来源:互联网 发布:windows 计划任务工具 编辑:程序博客网 时间:2024/06/05 19:45

package myball;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.net.*;
import java.util.*;
import java.math.*;

/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2007</p>
 *
 * <p>Company: </p>
 *
 * 
@author not attributable
 * 
@version 1.0
 
*/

public class Ball {
     
int x_pos;
     
int y_pos;
     
int x_speed;
     
int y_speed;
     
int radius;
     Color c;
     Random rnd;
    
public Ball(int x,int y,int mvx,int mvy,int mr,Color mcolor) {
        x_pos
=x;
        y_pos
=y;
        x_speed
=mvx;
        y_speed
=mvy;
        radius
=mr;
        c
=mcolor;

    }

    
public Ball() {
    rnd
=new Random();
    x_pos
=((rnd.nextInt()))%(int)99+10;
    y_pos
=(rnd.nextInt())%(int)99+10;
    x_speed
=(rnd.nextInt())%(int)5+5;
    y_speed
=(rnd.nextInt())%(int)5+5;
    radius
=5+(rnd.nextInt())%(int)5;
    c
=Color.red;
    }

    
public  void move(){
        x_pos
=x_pos+x_speed;
        y_pos
=y_pos+y_speed;
    }

   
public void drawball(Graphics g){
    g.setColor(c);
    g.fillOval(x_pos
-radius,y_pos-radius,2*radius,2*radius);

    }

  
public void setVX(int mvx){
      x_speed
=mvx;
  }

  
public void setVY(int mvy){
      y_speed
=mvy;
  }

  
public void setXPos(int x){
      x_pos
=x;
  }

  
public void setYPos(int y){
      y_pos
=y;
  }


}

package myball;

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.net.*;
import java.util.*;

public class BallApplet extends Applet implements Runnable {
    
int x_pos=50;
    
int y_pos=50;
    
int x_speed=0;
    
int y_speed=0;
    
int radius=10;
    
int maxspeed=5;
    
int appletsize_x=300;
    
int appletsize_y=300;
    Random rnd;
    
private Image dbImage;
    
private Graphics dbg;
    AudioClip bounce;
    AudioClip hit;
    Image backImage;
    ArrayList ball
=new ArrayList();
    
public void init(){
    rnd
=new Random();
    x_speed
=(rnd.nextInt())%maxspeed;
    y_speed
=(rnd.nextInt())%maxspeed;
    appletsize_x
=this.getWidth();
    appletsize_y
=this.getHeight();
    bounce
=getAudioClip(getCodeBase(),"chimes.au");
    hit
=getAudioClip(getCodeBase(),"gun.au");
    backImage
=getImage(getCodeBase(),"ok.gif");
    
//ballA=new Ball(200,200,-3,5,10,Color.cyan);
    
//ballB=new Ball(x_pos,y_pos,x_speed,y_speed,radius,Color.yellow);
    
//ballC=new Ball(90,90,4,3,10,Color.red);
   ball.add(new Ball(200,200,-3,5,10,Color.white));
   ball.add(
new Ball(90,90,4,3,10,Color.white));
}

    
public boolean ballHit(Ball a,Ball b){
        
double  distance=0;
        
double  x=0;
        
double  y=0;
        
double radius=0;
        
int speed=0,space=0;
        radius
=a.radius+b.radius;
        x
=a.x_pos-b.x_pos;
        y
=a.y_pos-b.y_pos;
        
if(x<radius && y<radius){
           distance
=Math.sqrt((x*x)+(y*y));
          
if(distance>radius){
            
return false;
            }

          
else
          
{
                speed
=a.x_speed;
                a.setVX(b.x_speed);
                b.setVX(speed);
                
if(x<0){
                    space
=a.x_pos +(int) radius;
                    b.setXPos(space);
                }

                
else
                
{
                    space
=b.x_pos+(int)radius;
                    a.setXPos((space));
                }


                speed
=a.y_speed;
                a.setVY(b.y_speed);
                b.setVY(speed);
                
if(y>0){
                    space
=a.y_pos+(int)radius;
                    b.setYPos(space);
                }

                
else
                
{
                    space
=b.y_pos+(int)radius;
                    a.setYPos(space);
                }

               
return true;
          }

       }

        
else
        
{
             
return false;
        }


    }

    
public boolean ballOut(Ball b){
        
if(b.x_pos>appletsize_x-b.radius){
          x_speed
=-(b.x_speed);
          b.setVX(x_speed);
          b.setXPos(appletsize_x
-b.radius);
          
return true;
          }

      
else if(b.x_pos<b.radius)
      
{
          x_speed
=-(b.x_speed);
          b.setXPos(b.radius);
          b.setVX(x_speed);
          
return true;
      }

      
if(b.y_pos>appletsize_y-b.radius){
          b.setYPos(appletsize_y
-b.radius);
          b.setVY(
-(b.y_speed));
          
return true;
      }

      
else if(b.y_pos<b.radius){
         b.setYPos(b.radius);
         y_speed
=-(y_speed);
         b.setVY(
-(b.y_speed));
         
return true;
      }

        
return false;
    }

    
public boolean mouseDown(Event e,int x,int y) {

        
return true;
    }

    
public boolean keyDown(Event e,int key){

        
return true;
    }

    
void newBall(){
        ball.add(
new Ball());
    }

    
void eatBall(Ball b){
        ball.remove(b);
    }

    
public void start(){
    Thread th
=new Thread(this);
    th.start();
    }

    
public void stop(){}
    
public void destory(){}
    
public void run(){
    Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
    
while(true){

       
/* if(ballHit(ballA,ballB)){
            hit.play();
        }
        if(ballHit(ballA,ballC )){
            hit.play();
        }
        if(ballHit(ballB,ballC)){
            hit.play();
        }
        if(ballOut(ballA)){
           bounce.play();
       }
       ballA.move();
       if(ballOut(ballB)){
           bounce.play();
       }
       ballB.move();
       if(ballOut(ballC)){
           bounce.play();
       }
       ballC.move(); 
*/

       
int i=0,j=0;
       
int size=0;
       Ball ballA,ballB,ballEat;
       ballEat
=null;
       size
=ball.size();
       
for(i=0;i<size;i++)
       
{  ballA=(Ball)(ball.get(i));
           
for(j=i+1;j<size;j++)
           
{  ballB=(Ball)(ball.get(j));
               
if(ballHit(ballA,ballB)){
                   hit.play();
                   
//add a new ball
                   if (ballA.radius == ballB.radius) {
                       newBall();
                   }

                   
else if(ballA.radius > ballB.radius){
                       ballEat
=ballB;
                   }

                   
else {
                       ballEat
=ballA;
                   }

               }

       }

       }

       
if(ballEat!=null){
           eatBall(ballEat);
       }

       
for(i=0;i<ball.size();i++){
           ballA
=(Ball)ball.get(i);
           
if(ballOut(ballA)){
               bounce.play();
           }

           ballA.move();
       }

       repaint();
        
try {
            Thread.sleep(
20);
        }

        
catch(InterruptedException ex){

        }

        Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
    }

    }

    
public void paint(Graphics g){
    g.drawImage(backImage,
0,0,this);
   
/* ballA.drawball(g);
    ballB.drawball(g);
    ballC.drawball(g); 
*/

   Ball ballA;
   
for(int i=0;i<ball.size();i++)
   
{
       ballA
=(Ball)ball.get(i);
       ballA.drawball(g);
   }


    }

    
public void update(Graphics g){
        
if(dbImage==null)
        
{
            dbImage
=createImage(this.getSize().width,this.getSize().height);
            dbg
=dbImage.getGraphics();
        }

        dbg.setColor(getBackground());
        dbg.fillRect(
0,0,this.getWidth(),this.getHeight());
        dbg.setColor(getForeground());
        paint(dbg);
        g.drawImage(dbImage,
0,0,this);
    }

}

这个问题其实很复杂,因为小球之间的球心不在一条直线上。我只是为了编游戏,就省事些。

根据动量守恒原理。如果一个运动的小球碰上一个静止的小球,则原来的静止的小球运动。

小球相碰的时候有两个力,一个是产成的弹力,另一个是对方小球给额外施加的力。

也就是说,在完全弹性碰撞的时候发生了速度的交换。

例如:用子弹打同样重量的迎面飞来的石头,在完全弹性碰撞的时候,子弹把石头打飞了,子弹的速度成了石头的速度,反弹回来了。如果子弹追着石头打会如何呢?则,子弹停止了,石头飞的更快了。

就根据这个道理,把小球的速度分解成x轴速度和y轴速度。分别计算,最后合成。看看是否符合常规印象。

=========================================================================

经过编程实验成功了。实现起来很简单,当两个小球相撞的时候 x轴速度交换,y轴速度交换,就实现了两个小球的弹性碰撞。也就是说当一个小球飞撞上另一个静止的小球后,原来静止的小球开始运动,原来运动的小球静止。

编程还解决了两个小问题:

当两个小球相碰的时候,由于运动不是连续的,而是根据步长来的,因此碰撞时要重置两个小球球心

 编程的基本步骤:

1. 主要是开一个线程,在线程中不断的更改小球的位置,然后调用applet 的repaint() 方法,实现动画效果。

2.为了让画面不闪烁,准备两幅画,后台画好了以后,前台再展示。