掃雷遊戲製作全過程 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");
		}
	}

您可以在源代碼中註釋掉上面的正確的方法,把原來註釋掉的有問題的方法還原,看看效果如何。

當然,有問題的這個方法運行起來並不是每一次都有問題,多試幾次,或者增加圖片的個數效果就比較明顯了。

在這裏,我將兩個方法分別運行的效果圖傳上來了:

                 


 我們接下來說如何來實現時間爲動畫的。首先我們將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的時間片段的長短來實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章