多线程之小球的运动

多线程的学习如今做出了成果,便展示给大家
首先我们看一下效果图吧
小球运动,背景可以替换自己喜欢的图片,还有背景音乐,小球用图片来替换都很有趣!
听起来是不是有点花里胡哨,不过都只是看个人兴趣,选择自己喜欢的就是最好的。
在这里插入图片描述
再来看一下效果的实现
在这里插入图片描述
多线程是指多个线程并发执行的技术。
我们这里利用的是建立一个小球即为建立一个线程,然后多个线程共同执行便可以呈现共同的效果。

在代码编写过程中可能会遇到的问题与解决办法

  1. 图片与小球同时出现时有闪动现象
    解决办法:采用双缓冲技术,将图片与小球先画在缓冲画布上,然后再在画布上画出

  2. 按钮被涂抹掉
    解决办法:调整图片的位置和小球的运动位置,使其不会涂抹在画布上

  3. 传值问题
    这个点是我经常的错误,不易发现,大家可以检查一下自己是否也犯了这样的错误,一定要确定好自己每一步的传值

这里的代码在运行的时候,小球的颜色会发生变化,很有趣,因为颜色是随机数决定的,所以会产生这种现象
代码的编写用了四个类

一 窗体类
二 监听器类
三 小球类
四 音乐类

窗体类

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;


public class BallUI extends JFrame {
	// 画笔
	Graphics g;
	// 获取缓冲图片
	BufferedImage buffimage = new BufferedImage(900, 900, BufferedImage.TYPE_INT_ARGB);
	// 从缓冲图片上获取画笔
	Graphics buffg = buffimage.getGraphics();
	public static void main(String[] args){
		BallUI ball = new BallUI();
		ball.showUI();	
	}
	public void showUI() {
		this.setTitle("Ball");
		this.setSize(900, 900);
//		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//		this.setResizable(false);
//		this.setDefaultCloseOperation(3);
		//设置背景颜色
//		this.getContentPane().setBackground(new Color(200,255,255));
		this.setLayout(new FlowLayout());
		this.setLocationRelativeTo(null);
		JButton add = new JButton("创建");
		JButton start = new JButton("启动");
		JButton stop = new JButton("停止");
		JButton play = new JButton("播放音乐");


		this.add(add);
		this.add(start);
		this.add(stop);
		this.add(play);
		
		Ballistener blis = new Ballistener(this);
		blis.g = g;
		add.addActionListener(blis);
		start.addActionListener(blis);
		stop.addActionListener(blis);
		play.addActionListener(blis);


		add.setFocusable(false);
		start.setFocusable(false);
		stop.setFocusable(false);
		play.setFocusable(false);

		this.addMouseListener(blis);
		this.setVisible(true);
		
		g = this.getGraphics();
		
		Image image = new ImageIcon("bj1.jpg").getImage();
		buffg.drawImage(image, 0, 40, null);
		// 画笔绘制缓冲图片
		g.drawImage(buffimage, 0, 40, null);
		
		
	}
	
}

监听器类

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Random;

public class Ballistener extends MouseAdapter implements ActionListener {
	BallUI bu;
	int x,y;
	MyArrayList<BallThread> al = new MyArrayList<BallThread>();
	public Ballistener(BallUI bu) {
		this.bu = bu;
	}

	private Random r = new Random();
	public Graphics g;
	public void actionPerformed(ActionEvent e) {
		String str = e.getActionCommand();
		Music music = new Music("C:\\Users\\89655\\Desktop\\月夜 - 双笙.mp3");
		if(str.equals("创建")){
			BallThread ball = new BallThread(r.nextInt(900),
					r.nextInt(900),20,4,4,bu,al);
			al.add(ball);
			ball.start();			
		}else if(str.equals("启动")){
			for(int i=0;i<al.size();i++){
				BallThread ball =al.get(i);
				ball.stateFlag=false;
			}
		}else if(str.equals("停止")){
			for(int i=0;i<al.size();i++){
				BallThread ball =al.get(i);
				ball.stateFlag=true;
			}
		}else if(str.equals("播放音乐")){
			new Music("C:\\Users\\89655\\Desktop\\月夜 - 双笙.mp3").start();
		}
		};
}

小球类

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.Random;

import javax.swing.ImageIcon;

public class BallThread extends Thread {
	int x, y, size, movex, movey;
	private Random r = new Random();
	// 获取缓冲图片
	BufferedImage buffimage = new BufferedImage(900, 900, BufferedImage.TYPE_INT_ARGB);
	// 从缓冲图片上获取画笔
	Graphics buffg = buffimage.getGraphics();
	BallUI bu;
	Graphics g;
	boolean stateFlag = false;
	boolean flag = false;
	MyArrayList<BallThread> al;
	BallThread ball;

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public int getSize() {
		return size;
	}

	public void setSize(int size) {
		this.size = size;
	}

	Color color = new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255));

	public BallThread(int x, int y, int size, int movex, int movey, BallUI bu, MyArrayList al) {
		this.x = x;
		this.y = y;
		this.size = size;
		this.movex = movex;
		this.movey = movey;
		this.bu = bu;
		g = this.bu.getGraphics();
		this.al = al;
	}

	public void run() {
		while (!flag) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			// 缓冲画笔 绘制背景图片
			Image image = new ImageIcon("bj1.jpg").getImage();
			buffg.drawImage(image, 0, 40, null);
			// 缓冲画笔 绘制小球 移动小球
			for (int i = 0; i < al.size(); i++) {
					BallThread ball = al.get(i);
					ball.draw(buffg);
			}
			 if (stateFlag) {
			 continue;
			}
			// 画笔绘制缓冲图片
			g.drawImage(buffimage, 0, 40, null);
		}
	}
	public void draw(Graphics g){		
		// 遍历小球的数据,画出所有小球	
		x += movex;
		y += movey;
		Random random = new Random();
		//颜色进行随机设置
		int r = random.nextInt(256);
		int gc = random.nextInt(256);
		int b = random.nextInt(256);
		
	//						这一步为选取r,g,b中的最大值,进行一系列变换使r,g,b得到的color最亮
		int max = r > gc ? r : gc;
		max = max > b ? max : b;
		
		double brighter = 255.0 / max;
		r = (int) (r * brighter);
		gc = (int) (gc * brighter);
		b = (int) (b * brighter);
		color = new Color(r, gc, b);
		g.setColor(color);
		g.fillOval(x, y, size, size);
//		Image image = new ImageIcon("guang1.png").getImage();
//		g.drawImage(image, x, y, null);
		bound();
		collide();	
	}
	public void bound(){
		// 当碰到边界时进行反弹处理
		if (x > (900 - size) && movex > 0) {
			movex = -movex;
		}
		if (y > (850 - size) && movey > 0) {
			movey = -movey;
		}
		if (movex < 0 && x < 2) {
			movex = -movex;
		}
		if (movey < 0 && y < 120) {
			movey = -movey;
		}
	}
	public void collide(){
		// 当小球之间进行碰撞
		for (int i = 0; i < al.size(); i++) {
			ball = al.get(i);
			if (this == ball) {
				continue;
			}
			int xx = Math.abs(this.x - ball.x);
			int yy = Math.abs(this.y - ball.y);
			int xy = (int) Math.sqrt(xx * xx + yy * yy);
			int tempx = 0;
			int tempy = 0;
			
			if (xy <= (this.size / 2 + ball.size / 2)) {
				tempx = this.movex;
				tempy = this.movey;
				this.movex = ball.movex;
				this.movey = ball.movey;
				ball.movex = tempx;
				ball.movey = tempy;
			}
		}
	}
}

音乐类

import java.io.BufferedInputStream;
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import javazoom.jl.decoder.JavaLayerException; 
import javazoom.jl.player.*;  
public class Music extends Thread {
		Player player;    
		String music;    
		public Music(String file) {        
			this.music = file;    
			}     
		public void run() {        
			try {            
				play();             
				} 
			catch (FileNotFoundException | JavaLayerException e)
			{             
				e.printStackTrace();        
				}    
		}   
		public void play() throws FileNotFoundException, JavaLayerException { 
			BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(music));         
			player = new Player(buffer);         
			player.play();     
		} 
	}

在这里需要添加额外的包,否则会产生错误,这个包帮助音乐播放,如果不需要音乐也没关系
包的下载地址在下方的链接里
链接:https://pan.baidu.com/s/1GG5Lefd0VxcSgmSGCpaILQ
提取码:xp4o

在多线程的学习中,对于代码还有很多创新点,多思考,会产生意想不到的效果

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值