`
海王子1994
  • 浏览: 43902 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

线程小动画之屏保--模仿小球碰撞反弹(二)

 
阅读更多

之前已经能产生许多小球,但是会发现小球和小球接触后,其中一个球的形状就消失了一部分,没有起到碰撞的效果,所以接下来就继续完成操作。



 

考虑到碰撞情况,无法就是考虑两球球心间距离与它们半径之和的比较关系,前者小于后者就发生碰撞,反之则没有发生。当然如果只有一个球,自然不会发生碰撞的哈!

//分析碰撞情况
			for(int i=0;i<al.size();i++)
			{
				Ball ball=al.get(i);//获取小球
				if(ball==this)
				{
					continue;//重新开始循环,考虑下一个球
				}
				int xx=Math.abs((x+radius)-(ball.x+ball.radius));//两个球心所在纵线的距离
				int yy=Math.abs((y-radius)-(ball.y-ball.radius));//两个球心所在水平线的距离
				int len=(int)Math.sqrt(xx*xx+yy*yy);//球心之间的距离
				if(len<radius+ball.radius)
				{
					int temp=vx;
					vx=ball.vx;
					ball.vx=temp;
					
					int temp1=vy;
					vy=ball.vy;
					ball.vy=temp1;
					
				}
				
			}

 

 

这样就能实现小球碰撞的效果,只是还想球能够停止,然后又能动起来,或者是沿着窗体滚动,怎样弄呢?

不妨设置三个标记,分别是暂停,停止,绕行标记,当符合标记,则按相应标记进行。此外补充说明,在测试类中要创建一个ArrayList类对象,保存所有出现的球,然后就可以随意地取出。

 

下面是改进后的球的线程类代码;

 

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.JPanel;


public class Ball extends Thread{

	private int x,y;//小球所在最小正方形的左上角坐标
	private int vx,vy;//小球的各分向速度
	private int radius;//小球的半径
	private Color color;
	private JPanel jpa;//画布所在面板
	private ArrayList<Ball>al;//存储球的队列
	private boolean PauseFlag;//暂停标志
	private boolean StopFlag;//停止标志
	private boolean RoundFlag;
	/////////////////////////
	private static final int FORWARD = 0;

	 private static final int BACKWARD = 1;

	 private static final int DOWN = 2;

	 private static final int UP = 3;

	 private int direction = FORWARD;
	
	//构造函数,传入放置画布的面板和存储所有球队列,而且设置球的参数
	public Ball(JPanel jpa,ArrayList al)
	{
		this.jpa=jpa;
		this.al=al;
		Random rad=new Random();
		vx=rad.nextInt(20)+2;
		vy=rad.nextInt(25)+3;
		radius=rad.nextInt(30)+10;
		color=new Color(rad.nextInt(256),rad.nextInt(256),rad.nextInt(256));
	}
	
	//添加暂停的方法
	public void setPause(boolean flag)
	{
		PauseFlag=flag;
	}
	//添加环绕的方法
	public void setRound(boolean flag)
	{
		RoundFlag=flag;
	}
	
	public void run()
	{
		Graphics g=jpa.getGraphics();//获取画布
		while(true)
		{
			try{
				Thread.sleep(50);
			}catch(InterruptedException e)
			{
				e.printStackTrace();
			}
		
			//如果暂停标志为true,则循环在此处结尾,从头重新开始
			if(PauseFlag)
			{
				continue;
			}
			
			
			//清屏操作
			g.setColor(jpa.getBackground());
			g.fillOval(x, y, radius*2, radius*2);
			
			
			if(RoundFlag)
			{
				if (x+radius*2>jpa.getWidth() && direction == FORWARD)
				    direction = DOWN;
				   if (y+radius*2>jpa.getHeight() && direction == DOWN)
				    direction = BACKWARD;
				   if (x - radius * 2 <= 10 && direction == BACKWARD)
				    direction = UP;
				   if (y -radius*2 <=10&& direction == UP)
				    direction = FORWARD;

				   // compute angle start & extent
				   if (direction == FORWARD) {
				    x += 1;
				    y = 0;
				   }
				   if (direction == DOWN) {
				    x = jpa.getWidth() - 2*radius;
				    y += 1;
				   }
				   if (direction == BACKWARD) {
				    x -= 1;
				    y = jpa.getHeight() - radius * 2+1;
				   }
				   if (direction == UP) {
				    x = 0;
				    y -= 1;
				   }
			}
			
			
			
			
			//如果重置标志为true,则跳出循环
			if(StopFlag)
			{
				return;
			}			
			
			
			//分析碰撞情况
			for(int i=0;i<al.size();i++)
			{
				Ball ball=al.get(i);//获取小球
				if(ball==this)
				{
					continue;//重新开始循环,考虑下一个球
				}
				int xx=Math.abs((x+radius)-(ball.x+ball.radius));//两个球心所在纵线的距离
				int yy=Math.abs((y-radius)-(ball.y-ball.radius));//两个球心所在水平线的距离
				int len=(int)Math.sqrt(xx*xx+yy*yy);//球心之间的距离
				if(len<radius+ball.radius)
				{
					int temp=vx;
					vx=ball.vx;
					ball.vx=temp;
					
					int temp1=vy;
					vy=ball.vy;
					ball.vy=temp1;
					
				}
				
			}
			//更改坐标情况 
			x+=vx;
			y+=vy;
			
			//小球出界反弹
			if(x+radius*2>jpa.getWidth()||x<0)
			{
				vx=vx*(-1);
			}
			if(y+radius*2>jpa.getHeight()||y<0)
			{
				vy=vy*(-1);
			}
			
			g.setColor(color);
			g.fillOval(x, y, 2*radius, 2*radius);
		}
	}
}

 

 

然后是主界面类:

 

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class BallJFrame {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		BallJFrame bj=new BallJFrame();
		bj.init();

	}
	
	public void init()
	{
		final JFrame jf=new JFrame();
		jf.setTitle("小球碰撞");
		jf.setSize(500, 500);
		jf.setDefaultCloseOperation(3);
		jf.setLayout(new BorderLayout());
		jf.setResizable(false);
		
		final ArrayList<Ball> arraylist=new ArrayList<Ball>();
		
		final JPanel jpa=new JPanel();
		jpa.setBounds(0,30,500,450);
		jpa.setBackground(Color.BLACK);//设置面板背景色为黑色
		jf.add(jpa,BorderLayout.CENTER);
		
		ActionListener al=new ActionListener(){
               						
			public void actionPerformed(ActionEvent e) {
				String str=e.getActionCommand();
				
				   if(str.equals("Add"))
				   {
					   Ball ball=new Ball(jpa,arraylist);
					   ball.start();
					   arraylist.add(ball);
				   }
				   if(str.equals("Stop"))
				   {
					   for(int i=0;i<arraylist.size();i++)
					   {
						   Ball ball=arraylist.get(i);
						   ball.setPause(true);
					   }
				   }
				   
				   if(str.equals("Resume"))
				   {
					   for(int i=0;i<arraylist.size();i++)
					   {
						   Ball ball=arraylist.get(i);
						   ball.setPause(false);
					   }
				   }
				   
				   if(str.equals("Round"))
				   {
					   for(int i=0;i<arraylist.size();i++)
					   {
						   Ball ball=arraylist.get(i);
						   ball.setRound(true);
					   }
				   }
			}
			
		};
		
		JPanel jpa2=new JPanel(new FlowLayout());
		jpa2.setBounds(0,0,500,80);
		
		JButton jbu_add=new JButton("Add");
		jbu_add.addActionListener(al);
		jpa2.add(jbu_add);
		
		JButton jbu_stop=new JButton("Stop");
		jbu_stop.addActionListener(al);
		jpa2.add(jbu_stop);
		
		JButton jbu_resume=new JButton("Resume");
		jbu_resume.addActionListener(al);
		jpa2.add(jbu_resume);
		
		JButton jbu_round=new JButton("Round");
		jbu_round.addActionListener(al);
		jpa2.add(jbu_round);
		
		
		jf.add(jpa2,BorderLayout.NORTH);
		jf.setVisible(true);
	}

}

 这样就既能实现小球碰撞的效果,然后又能让它们暂停,重新动起来,或者绕着滚·····你可以尝试弄出更多的效果,继而超越屏保的视觉效果!

 



 

 

 

 

  • 大小: 16.3 KB
  • 大小: 15.4 KB
1
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics