`
hmeng
  • 浏览: 15203 次
  • 性别: Icon_minigender_2
社区版块
存档分类
最新评论

线程------让画面动起来

阅读更多
    线程是大部分游戏的基础,这几天学习了线程,掌握了游戏的框架,恍然发现自己也能做出那些曾经觉得高大上的东西了。
    线程:我觉得就是流水线,把一件事情交给一个或多个对象去做,而主线的控制继续。
    创建线程的方法,主要有如下两种:
    实现Runnable接口和继承Thread类
    第一种方法实例如下   
public class MyRunnable implements Runnable{  
        public void run(){  
            System.out.println(Thread.currentThread().getName());  
        }  
        public static void main(String args[]){  
            MyRunnable r1 = new MyRunnable();  
            MyRunnable r2 = new MyRunnable();  
            MyRunnable r3 = new MyRunnable();  
            Thread thread1 = new Thread(r1,"MyThread1");  
           Thread thread2 = new Thread(r2);  
           thread2.setName("MyThread2");  
           Thread thread3 = new Thread(r3);  
           thread1.start();  
           thread2.start();  
           thread3.start();  
       }  
   }

    第二种方法的实现,若把线程单独写一个类时,主要的格式,代码示例:线程弹球
public class Ball extends Thread {
public void run(){
		while(true){
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {			
				e.printStackTrace();
			} 
             //是否暂停
			if(pauseFlag)
		          continue;			
			//清除小球
			clearBall();		
			//是否结束
			if(endFlag)
		         return;				
			//移动			
			move();	
			//画出小球			
			drawBall();			
		}		
	}
	
}

   调用时,实例化一个线程对象,调用start()方法即可。
   也可以不单独写一个类,在初始化窗体的方法中用while(true)无限循环处理,达到线程的效果。
    双缓冲:利用双缓冲,可消除闪屏的动图,方法是先创建缓存图片,取出缓存图片的画布,在该画布上把所有要显示的图片画出,然后将缓存图片画到窗体上。代码示例:
   
//重力小球
  public class Game extends JFrame{	
	public static void main(String[] args){
		new Game().unitUI();
	}
    //初始化窗体
	private void unitUI() {
		this.setTitle("ball");
		this.setSize(new Dimension(500,500));
		this.setDefaultCloseOperation(3);
		this.setLocationRelativeTo(null);
		this.setVisible(true);
		//获取窗体画布
		Graphics g=this.getGraphics();
		//初始坐标位置
		int x=200,y=0;
		//速度
		int vy=0;
		//速度增量
		int addVy=1;
		//重力小球线程
		while(true){
			try {//休眠时间
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			//---画出缓存图片
			BufferedImage buffer= new BufferedImage(this.getWidth(),
					this.getHeight(),BufferedImage.TYPE_INT_BGR);
			//获取画布
			Graphics gh=buffer.getGraphics();
			//设置颜色
			gh.setColor(Color.RED);
			//画出小球大小
			gh.fillOval(x, y,40, 40);
			//改变小球位置和速度
			y+=vy;
			vy+=addVy;
			//判断出界
			if(y>=this.getHeight()-20){
				vy=-vy;
				vy+=addVy;	
			}
			//画到窗体上
			g.drawImage(buffer, 0, 0, null);
		}
		
		
	}

}


   实践:加入动态背景的弹球
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayList;

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

public class BallGame extends JFrame{
	private static BallGame bg=new BallGame();
	private ArrayList<Ball> blist=new ArrayList<Ball>();
	private Ball ball;	
	public JPanel panel;
	
	public static void main(String[] args){
		bg.unit();
	}
	
	public void unit(){
		//初始化窗体
		this.setTitle("Ball");
		this.setSize(new Dimension(600,600));
		this.setLocationRelativeTo(null);
		this.setDefaultCloseOperation(3);
		//添加组件
		JPanel jp=new JPanel();
		jp.setPreferredSize(new Dimension(0,40));
		jp.setBackground(new Color(9,2,180));
		//在北边的面板上添加按钮
		String[] array={"ADD","PAUSE","RESUME","END"};
		for(int i=0;i<array.length;i++){
			JButton jb=new JButton(array[i]);			
			jb.addActionListener(l);
			jp.add(jb);
			
		}		
		this.add(jp,BorderLayout.NORTH);
		
		panel=new JPanel();
		this.add(panel,BorderLayout.CENTER);
		
		//添加音乐!!!!
		AudioClip clip=null;
		try{
			clip = Applet.newAudioClip((new File("images/有你的快乐。mp3")).toURI().toURL());
		}catch(MalformedURLException el){
			el.printStackTrace();
		}
		clip.play();
		//显示窗体
		this.setVisible(true);
		//实现线程的另一种方法
//		Runnable r=new Runnanle(){
//		public void run(){
//		 while (true{
//			 }
//		}
//	    };
//		Thread t=new Thread(r);
//		t.start();
		
		//取画笔
		Graphics g=panel.getGraphics();
		ImageIcon icon=new ImageIcon("images/b.jpg");
		ImageIcon icon2=new ImageIcon("images/dxsx.gif");
		int x=0,y=0;				
		//画图线程
		while(true){
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
		    //------画出缓存图片------
			
			//创建缓存图片
			BufferedImage buffer=new BufferedImage(
					panel.getWidth(),panel.getHeight(),
					BufferedImage.TYPE_INT_RGB); 
			//得到画布对象
			Graphics gh=buffer.getGraphics();
			//画出两张背景			
			gh.drawImage(icon.getImage(), x, 0, null);
			gh.drawImage(icon.getImage(), x+icon.getIconWidth(), 0, null);
			x-=5;
			//当第一张图片完全移动到窗体外,重新接到第二章图片之后
			while(x+icon.getIconWidth()<=0){
				x=0;
			}
			//遍历画出所有小球
			for(int i=0;i<blist.size();i++){
				Ball ball=blist.get(i);
				ball.drawBall(gh);
			}
			
			gh.drawImage(icon2.getImage(), 250, 200, null);
			//---在面板上画出缓存图片---
			g.drawImage(buffer,0,0,null);
			
		
		}
	}
	
	private ActionListener l=new ActionListener(){

		public void actionPerformed(ActionEvent e) {
			String s=e.getActionCommand();
			if(s.equals("ADD")){
				//添加到队列中,并启动线程
				ball=new Ball(panel,blist);
				blist.add(ball);
				ball.start();
				
			}
            if(s.equals("PAUSE")){
				for(int i=0;i<blist.size();i++){
					ball=blist.get(i);
					ball.setPauseFlag(true);
				}
					
			}
            if(s.equals("RESUME")){
            	for(int i=0;i<blist.size();i++){
					ball=blist.get(i);
					ball.setPauseFlag(false);
					
				}
            }
            if(s.equals("END")){
            	//取出对象后停止线程然后删除
            	while(blist.size()>0){
            		Ball ball=blist.get(0);
            		ball.setEndFlag(false);
					blist.remove(0);
					
				}
	
            }
			
		}
		
	};
	

}

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

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

public class Ball extends Thread {
	private Graphics2D g;
	private JPanel jp;
	private int radius;
	private int x=radius,y=radius;
	private int oldX=x,oldY=y;
	private Color color;
	private int c1,c2,c3;
	private int vx;
	private int vy;
	private Random ran=new Random();

	private Boolean pauseFlag=false;
	private Boolean endFlag=false;
	
	private ArrayList<Ball> list=new ArrayList<Ball>();
	
	public Boolean getPauseFlag() {
		return pauseFlag;
	}
	public void setPauseFlag(Boolean pauseFlag) {
		this.pauseFlag = pauseFlag;
	}
	public Boolean getEndFlag() {
		return endFlag;
	}
	public void setEndFlag(Boolean endFlag) {
		this.endFlag = endFlag;
	}
	
	//构造函数
	public Ball(JPanel jp,ArrayList<Ball> list){
		//System.out.println("get Graphics!");
		this.jp=jp;
		this.list=list;
		//初始化属性
		unit();
	}
	public void run(){
		while(true){
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {			
				e.printStackTrace();
			}
			//是否暂停
			if(pauseFlag)
				continue;			
			//清除小球
			//clearBall();		
			//是否结束
			if(endFlag)				
				return;				
			//移动			
			move();	
			//画出小球			
			//drawBall();			
		}		
	}
	//初始化属性的方法
	private void unit(){
		radius=ran.nextInt(20)+20;
		vx=ran.nextInt(10)+1;
		vy=ran.nextInt(10)+1;
		color=new Color(ran.nextInt(256),ran.nextInt(256),ran.nextInt(256));
		
	}
	//检查碰撞
	private void check(int m){
		//遍历队列
		for(int i=0;i<list.size();i++){	
		    Ball b=list.get(i);
		    if(b==this)
		    	continue;
		    //判断圆心距是否大于两半径之和
		    int lenX=Math.abs(this.x-b.x);
		    int lenY=Math.abs(this.y-b.y);
		    int len=(int)Math.sqrt(lenX*lenX+lenY*lenY);
		    if(len<=this.radius+b.radius){
		    	//横向
		    	if(m==1){
		    		//回到上一个位置,避免两球黏在一起
		    	    x=oldX;
		    	    y=oldY;
		    	    this.vx=-vx;	    	
		    	}
		    	//纵向
		    	if(m==2){
		    		x=oldX;
		    		y=oldY;
		    		this.vy=-vy;
		    	}
		    }		    
		}

	}
	
	public void drawBall(Graphics gh){
		g=(Graphics2D) gh;

		//消除锯齿
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
				RenderingHints.VALUE_ANTIALIAS_ON);
		
		 //取出三基色处理
	    int red=color.getRed();
	    int green=color.getGreen();
	    int blue=color.getBlue();
	    
		//取出当前半径
		int r=radius;
		int xx=x;
		int yy=y;
	    //循环画出小球成立体效果
		for(int i=0;i<20;i++){	
		    red +=7;
		    green +=7;
		    blue +=7;		
		    //判断范围
		    if(red>255)
			    red=255;
		    if(green>255)
		    	green=255;
		    if(blue>255)
			    blue=255;			
		    Color c=new Color(red,green,blue);
			g.setColor(c);
		    g.fillOval(xx-r, yy-r, r*2, r*2);
		    r-=2;
		    //圆心向左偏移
		    xx-=1;
		}
		
	}
	
	
	private void move(){
		oldX=x;
		x += vx;			
		check(1);		
		oldY=y;
		y += vy;	
		check(2);
		//判断出界否
		if(x-radius<0){
			vx=Math.abs(vx);
		}
		if(x+radius>jp.getWidth()){
			vx=-Math.abs(vx);
		}
		if(y-radius<0)
			vy=Math.abs(vy);
		if(y+radius>jp.getHeight()){
			vy=-Math.abs(vy);
		}
		
	}
}

   效果截图


   这是做的一个小练习,还有很多不足,在其他的应用中仍需继续学习和完善。
  • 大小: 211.9 KB
  • 大小: 16.1 KB
  • 大小: 291.6 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics