扫雷游戏制作全过程 03 时间伪动画

现在把地雷模块先放一下,开始设计时间模块。可以用JLabel来显示数字,也可以用其来显示表示数字的图片。我选择了后者。其实最开始想做成时间翻页的效果,其实也能实现,但是如果使用下面的方法真的过于麻烦了。

有一点要注意的是:

我们显示图片时应该等到 图片被下载完成后才启动装载过程,然后显示完整的图像。但是getImage可以在没有载入全部的图像的情况下立即返回。如果创建一个显示多幅图片的动画,可以使用getImage来将所有的图片载入一个数组,以便JLabel有序的显示,但是动画的第一次运行不一定是有效的,因为JLabel类要等到整个图像被装载后才显示它。

为了避免这个问题,Java提供了MedioTracker类。

MedioTracker能自动追踪一个或多个图片的装载进度。我们可以使用它阻塞其他的操作直到一个或多个图像(相关连的)被完全载入。

我把它实现的全过程写到了loadPicture方法中:(这个是可用的)

	public void loadPicture()
	{
		MediaTracker tracker = new MediaTracker(this);
		for(int i=0;i<images.length ;i++)
		{
			images[i] = getToolkit().getImage("image/Time/"+i+"t.png");
			tracker.addImage(images[i], i);
		}
		try
		{
			tracker.waitForAll();
		}
		catch(InterruptedException ie){}
	}
代替了最初可能各种显示有误的(这个是有问题的):

    	
        public void loadPicture()
	{
		for(int i=0;i<images.length ;i++)
		{
			images[i] = getToolkit().getImage("image/Time/"+i+"t.png");
		}
	}

您可以在源代码中注释掉上面的正确的方法,把原来注释掉的有问题的方法还原,看看效果如何。

当然,有问题的这个方法运行起来并不是每一次都有问题,多试几次,或者增加图片的个数效果就比较明显了。

在这里,我将两个方法分别运行的效果图传上来了:

扫雷游戏制作全过程 03 时间伪动画_第1张图片                 


 我们接下来说如何来实现时间为动画的。首先我们将0-9十张图片加载到了images数组中,

然后启动一个线程,添加一个计数器,每隔1秒自加1.(根据具体情况,也可以0.1s。。。)

我设定了分钟和秒两个大块,而又细分为四个动态改变的小块。其改变的时间和范围由左到右分别是:

0-5*600s

0-9*60s

0-5*10s

0-9*1s

其实仅仅通过时间刷新来判断是否达到图片的刷新条件就OK了。具体实现的代码如下:

好像这段代码有点太繁琐了,大部分都是在修饰界面。关键的代码就是上面的loadPicture,还有下面的那个重写的paintComponent的图片与时间的对应函数关系。

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.BevelBorder;
import javax.swing.border.SoftBevelBorder;

class TimePanel extends JPanel
{
	private JPanel panel0 = new JPanel();
	private JPanel panel1 = new JPanel();
	private JPanel panel2 = new JPanel();
	private MicPanel micpanel[] = new MicPanel[4];
	/*********************************************/
	private Image images[] = new Image[10];
	private long current = 0;
	/**初始化的时候默认不显示跑*/
	private boolean stop = true;

	public static void main(String[] args)
	{
		JFrame frame = new JFrame();
		TimePanel tpanel = new TimePanel();
		frame.add(tpanel);
		frame.pack();
		frame.setVisible(true);
    }


	public TimePanel()
	{
		loadPicture();
		initOther();
		panel1.add(micpanel[2] = new MicPanel(10,6),BorderLayout.WEST);
		panel1.add(micpanel[3] = new MicPanel(1,10),BorderLayout.EAST);
		panel2.add(micpanel[0] = new MicPanel(600,6),BorderLayout.WEST);
		panel2.add(micpanel[1] = new MicPanel(60,10),BorderLayout.EAST);
		startTime();
		reStarted();
	}

	public void loadPicture()
	{
		MediaTracker tracker = new MediaTracker(this);
		for(int i=0;i<images.length ;i++)
		{
			images[i] = getToolkit().getImage(i+"t.png");
			tracker.addImage(images[i], i);
		}
		try
		{
			tracker.waitForAll();
		}
		catch(InterruptedException ie){}
	}


    /*
    	public void loadPicture()
		{

			for(int i=0;i<images.length ;i++)
			{
				images[i] = getToolkit().getImage(+i+"t.png");
			}
	    }
     */

	public void startTime()
	{
		stop = true;
		MyRunnable myrun = new MyRunnable();
		Thread thread = new Thread(myrun);
		thread.start();
	}

	public void initOther()
	{
		panel0.setLayout(new BorderLayout());
		panel1.setLayout(new BorderLayout());
		panel2.setLayout(new BorderLayout());
		/*panel1放分钟,panel2放秒*/

		panel0.add(panel1,BorderLayout.EAST);
		panel0.add(panel2,BorderLayout.WEST);
		/*不透明的话就不美观了*/
		panel0.setOpaque(false);
		panel1.setOpaque(false);
		panel2.setOpaque(false);
		this.setOpaque(false);
		/*设置突出的边框*/
		panel1.setBorder(new SoftBevelBorder(BevelBorder.RAISED));
		panel2.setBorder(new SoftBevelBorder(BevelBorder.RAISED));
		panel0.setBorder(new SoftBevelBorder(BevelBorder.RAISED));//(BevelBorder.LOWERED));
		add(panel0);
		try
		{
		  UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
		  SwingUtilities.updateComponentTreeUI(this);
		}
		catch(Exception e) { e.printStackTrace(); }
	}

	class MicPanel extends JPanel
	{
		private int cut_time;
		private int limit_time;

		public MicPanel(int copy_cut,int copy_limit)
		{
			//super();
			cut_time = copy_cut;
			limit_time = copy_limit;
			repaint();
		}
		/*原来这是非常有用的,要重写这个方法*/
		public Dimension getPreferredSize()
		{
			return new Dimension(images[0].getWidth(this),images[0].getHeight(this));
		}

		public void paintComponent(Graphics g)
		{
			super.paintComponent(g);
			g.drawImage(images[(int)(current/cut_time)%limit_time],0,0,this);
		}
	}

	public void reStarted()
	{
		current = 0;
		stop = false;
	}

	public void stoped()
	{
		stop = true;
	}

	class MyRunnable implements Runnable
	{
		public void run()
		{
			while(true)
			{
				if(!stop)
				{
					try{
						current++;
						Thread.sleep(1000);
						micpanel[0].repaint();
						micpanel[1].repaint();
						micpanel[2].repaint();
						micpanel[3].repaint();
					}catch(InterruptedException ie){}
				}
			}
		}
	}
}

图片和源代码已经上传。(关于MediaTracker的部分,我是参考的《java程序设计进阶教程》(清华大学出版社))。

看完了这个例子,我想您应该也能想到如何很麻烦的制作出时间在纸上翻页的效果来,简单的伪动画也可以通过修改sleep的时间片段的长短来实现。

你可能感兴趣的:(java,thread,游戏,exception,image,Class)