JAVA中的多线程与运动仿真(1)——用JAVA来放一场烟花

JAVA中的多线程与运动仿真(1)——用JAVA来放一场烟花

一.实现效果的简单展示:
初级实现的烟花特效
初步实现的动态效果为在鼠标点击之后,点击之处出现一簇小球,然后向不同方向散开变大。
利用这一效果,再在后续增加颜色渐变的效果,增加小球的数量,降低大小即可实现逼真的烟花特效。

二.代码实现的简单分析

1.创建窗体
由于画笔对象需要在窗体上获取,并且后续的小球等图像的绘制也需要在窗体上进行,所以在整个项目的开始阶段应当首先利用例如JFrame类来创建,调试好窗体。

2.绘制与移动小球
在导入java.awt.Graphics包后,从窗体上获取到画笔(Graphics)对象即可开始调用相关方法。
假设我已经获取到了画笔对象:g
在使用g调用setcolor方法设置颜色后即可调用fillOval方法来绘制一个特定位置与大小的圆形:
例如:g.fillOval(100,200,60,70)便是绘制一个左上顶点坐标为(100,200)长60,高70的长方形的内切圆
绘制好圆形后,再次使用g调用fillOval方法,但是改变绘制的坐标即可实现小球平面位置的移动。
但是,由于移动前后的小球位于同一个图层上,从视觉的直观感受上我们只会感觉一下绘制了多个小球,或者绘制了一个不断增长的柱形。
因此,在绘制新的位置的小球时,应重新设置颜色,再调用fillRect方法绘制实心矩形来实现对上一个图层的擦除
同时,即便如此,小球的绘制速度也太快了,呈现出来的是小球一闪而过,因此要调用Thread.sleep(x)函数[其中x为线程暂停的时间,单位为毫秒ms]来使得人眼能够捕捉到小球的运动。
此时,单个小球的简单运动就完成了。

3.利用线程解决小球频闪问题
在第二步完成之后,当小球数量较多,甚至仅仅是两个时,小球的显示就不会像原来只有一个小球时的那样清楚连贯,而是出现间歇性闪烁,这是因为在小球创建多了之后,有多个线程,但是却仅有一个窗体,此时多个线程在操作一个窗体对象,各个线程在不断的在执行擦除操作,因而导致了小球的闪烁现象。
解决这一问题最好的办法便是防止同时启动多个线程,而是将新创建的小球放入队列中,由一个线程来同时进行操作。

三.代码实现部分

①.Ball.java

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

public class Ball implements Mover{
	
	Color color1 = new Color(250,220,74);
	
	Random Ran = new Random();
	//小球运动步长
	float x_length = 5;
	float y_length = 5;
	int size = 10;
	int i=1;
	//小球初始速度的方向
	float vx = (2*Ran.nextFloat()-1)*x_length;
	float vy = (2*Ran.nextFloat()-1)*y_length;
	//小球加速度
	float acce = (float) 1.1;
	
	//小球初始误差中心坐标
	public float x,y;
	
	public Ball(int x, int y){
		
		this.x=x;
		this.y=y;
		
	}
	
	public void move() {
	   
		vx *= acce;
		vy *= acce;
		
		x += vx;
		y += vy;
		
		size += 3;
		i=i+1;
	}

	
	public void draw(Graphics g) {

		g.setColor(Color.ORANGE);
		g.fillOval((int) x,(int) y, size, size);
		
	}

}

②.drawboard.java

import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JLabel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.*;
import java.util.ArrayList;
import java.util.Random;

class drawboard{

	
	
	public static void main(String[] args){
		
		drawboard itUI = new drawboard();
		itUI.ShowUI();
	}
	
	
	public ArrayList<Mover> MoverList = new ArrayList<>();
	
	public void ShowUI(){
		JFrame DrawBoard = new JFrame();
		//窗体基本配置
		DrawBoard.setTitle("烟花特效");
		DrawBoard.setSize(1600,1000);
		DrawBoard.setLocationRelativeTo(null);
		DrawBoard.setDefaultCloseOperation(3);
		DrawBoard.setLayout(new FlowLayout());
		
		//添加鼠标监听器
		drawmouse Mouse = new drawmouse(MoverList);
		DrawBoard.addMouseListener(Mouse);
		
		DrawBoard.setVisible(true);
		
	
		
		Graphics g = DrawBoard.getGraphics();
		
		
		//运行线程
		drawthread dt = new drawthread(MoverList,g);
		dt.start();
		
		System.out.println("启动");
//		Mouse.g = g;
	}
}

③.drawmouse.java

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

public class drawmouse extends MouseAdapter{

	public int x,y;
	public ArrayList<Mover> MoverList;
	public drawmouse(ArrayList<Mover> MoverList){
		
		this.MoverList = MoverList;
		
	}
	//鼠标点击一下,放一个飞机进入队列
	public void mouseClicked(MouseEvent e){
		
		x=e.getX();
		y=e.getY();
		
		for(int i=0;i<=20;i++){
		
			Ball nBall = new Ball(x,y);
			MoverList.add(nBall);
			
		}
		
	}
}

④.drawthread.java

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

public class drawthread extends Thread{

	public Graphics g;
	Random ran = new Random();
	
	public ArrayList<Mover> MoverList;

	public drawthread(ArrayList<Mover> MoverList,Graphics g){
		this.MoverList = MoverList;
		this.g = g;
	}
	
	public void run(){
	
		while(true){
		//休眠50秒
		try {
			Thread.sleep(50);
		} catch (Exception ef) {
			
		}
         
		//刷新背景
		g.setColor(Color.WHITE);
			g.fillRect(0, 0, 1800, 1200);
			
		//移动一下队列中所有球,再画一下队列中所有小球
	    	System.out.println("T----线程把队列中所有小球画移了一次");

			for(int i=0;i<MoverList.size();i++) {
			//得到队列中的一个小球
				
			Mover Mover=MoverList.get(i); 
                  Mover.move();
			      Mover.draw(g); 
		}
		
	}
 }
}

⑤.Mover.java

import java.awt.Graphics;

public interface Mover {

	public void move();
	
	public void draw(Graphics g);
	
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值