`
hmeng
  • 浏览: 15842 次
  • 性别: 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
分享到:
评论

相关推荐

    vb.net制作启动画面

    为了使GIF动起来,需要将PictureBox的SizeMode设置为StretchImage,并启用它的AutoSize属性。 ```vbnet Public Class SplashScreenForm Private Sub SplashScreenForm_Load(sender As Object, e As EventArgs) ...

    让应用程序有启动画面2.rar_visual c_启动 画面_启动画面

    在开发Windows应用程序时,添加一个启动画面可以提升用户体验,使其看起来更加专业。本文将详细讲解如何在Visual C++环境中为应用程序添加启动画面,主要涉及的知识点包括:Visual C++编程基础、资源编辑器的使用、...

    JAVA将连续图像制作成动画

    当一系列连续的静态图像以一定速度连续播放时,人眼会感知到这些图像在“动起来”。为了创建动画效果,需要不断更新显示的图像,并控制每张图像显示的时间间隔(帧率)。 #### 三、线程的应用 - **概念**: 线程是...

    SurfaceView-Sample-master.zip_android_surfaceview

    总结起来,SurfaceView是Android系统为高性能图形处理设计的一个强大工具,它允许开发者在后台线程中进行高效且无闪烁的绘图操作,从而优化应用性能,提高用户体验。通过实践"SurfaceView-Sample-master.zip"中的...

    高仿墨迹天气背景动画效果-云,风,雪等.zip

    7. **随机数生成**:为了让动画看起来更加自然,云朵的形状、大小、速度以及雪花的落点等可能都加入了随机因素,这需要使用`Random`类。 8. **多线程处理**:如果动画计算复杂度较高,可能使用了`AsyncTask`或者...

    VB.net 窗口启动 收藏的很多动画

    它可以在应用程序启动时展示,增加视觉效果,使程序看起来更加专业和动态。以下是对VB.NET窗口启动动画的一些详细解释和相关知识点: 1. **VB.NET窗口生命周期**: - 窗口在启动时经历一系列的生命周期事件,包括`...

    java程序设计实践教程

    - 学习如何使用定时器来更新画面。 - **日历:** - 实现日历功能,能够显示指定月份的日历视图。 - 学习如何处理日期相关的逻辑。 - **网上购物结算模拟:** - 模拟网上购物的结算过程。 - 学习如何管理...

    c#制作的启动时显示窗体动画

    在C#编程环境中,开发一款应用时,提升用户体验的一个重要方面是创建吸引人的启动画面和动态效果。"启动时显示窗体动画"就是一个这样的功能,它可以在程序启动时为用户提供视觉上的吸引力,使得应用程序看起来更加...

    可编程控制器原理与实践三菱FXN系列组态技术介绍PPT学习教案.pptx

    - **让画面运动起来**:通过动画连接,使画面随数据库变量变化而变化。 - **实时趋势曲线与实时报警窗口**:展示实时数据变化趋势,及时发出设备状态警告。 - **查阅历史数据**:提供历史数据查询功能,便于分析和...

    一个高级的启动Android画面

    总结起来,创建一个高级的启动Android画面涉及设计和编程两个方面。设计上,需要考虑品牌形象、视觉吸引力和加载速度;编程上,要确保流畅性、效率,并正确处理界面切换。通过合理的布局、动画效果以及高效的编程...

    winform画面切换特效

    本示例项目专注于Winform应用中的画面切换效果,旨在为开发者提供一种方法来使应用程序看起来更加专业和吸引人。下面我们将深入探讨Winform画面切换特效的实现原理和相关技术。 首先,Winform本身并不直接支持内置...

    image-vector-master.zip

    "image-vector-master"项目中可能就包含了利用Canvas进行游戏画面绘制的示例。Canvas的灵活性和高性能,使得它成为开发各种类型游戏的基础,如休闲游戏、策略游戏甚至动作游戏。 此外,WebGL的出现为HTML5带来了3D...

    Flappy-bird-cocos2d.rar_Project X_bird_cocos2d_cocos2d flappy bi

    1. **渲染引擎**:Cocos2d-x使用了基于OpenGL的渲染引擎,能高效地处理2D图形,使得游戏画面流畅。 2. **物理引擎**:虽然Flappy Bird没有复杂的物理效果,但Cocos2d-x支持Box2D物理引擎,可以用于创建更复杂的游戏...

    android-java-splashscreenloadingbar:带有加载栏的Android启动画面

    在Android应用开发中,启动画面(Splash Screen)通常用于提供用户友好的体验,尤其是在应用程序初始化...通过分析这个项目,开发者可以学习到如何将复杂的加载逻辑与用户友好的启动界面结合起来,提高应用的启动体验。

    secondlife源码分析(pdf版)

    - 分析了如何将不同的人物模型、纹理等元素组合起来,形成完整的角色。 20. **显示人物名称** - 介绍了解决方案,使得游戏中能够准确地显示每个角色的名字。 21. **显示人物名称的字体** - 讨论了如何选择合适...

    基于对话框的应用加启动画面

    2. **创建启动对话框类**:在MFC(Microsoft Foundation Classes)环境中,你可以通过Visual Studio的资源编辑器创建一个新的对话框资源,并设置其属性,使其无边框、无标题栏,这样看起来更像启动画面。然后,创建...

    CitectSCADA7.20TechnicalReference

    - 需要注意线程安全问题,尤其是在多线程环境中使用CtAPI函数。 #### 图形编辑器的使用 CitectSCADA 7.20提供了一个直观易用的图形编辑器,允许用户创建复杂的监控界面。通过这个编辑器,用户可以轻松地设计和...

    C# 启动欢迎画面

    首先,让我们理解C#中的类库。类库是一种包含可重用代码的程序集,它可以被其他项目引用,以便在多个应用程序之间共享功能。在这里,我们有一个已经封装好的启动界面类库,这意味着它已经包含了所有必要的代码,以便...

Global site tag (gtag.js) - Google Analytics