Ch09 繪圖與多媒體 物件導向系統實務
大綱 繪圖的基礎 Graphics類別的色彩、文字與繪圖 圖片的載入與顯示 動畫效果 Java Applet的圖片載入 音樂的播放 2017/3/22
Graphics繪圖類別-取得Graphics繪圖類別 在Java Applet程式範例已經說明過paint()方法繪出文字和簡單圖形,使用的是Graphics類別的方法。 在Java執行繪圖功能需要使用「圖形內容」(Graphics Contexts)的Graphics物件,繪製的文字、影像和圖形都是繪製在此畫布物件上,如同將GUI元件新增到JFrame物件的ContentPane物件一般。 2017/3/22
範例1:使用Applet呈現圖 Ch11_10.html <HTML> <head> Ch11_10.java <title>Ch11_10.html</title> </head> <body> <hr> <center> <applet code = Ch11_10.class width = 200 height = 200 > </applet> </center> </body> </html> Ch11_10.java import java.applet.Applet; import java.awt.*; public class Ch11_10 extends Applet { public void paint(Graphics g) setBackground(Color.lightGray); g.setColor(Color.red); g.fillRect(10,10,100, 100); } 2017/3/22
Graphics繪圖類別-paint()方法 繼承自Component元件的paint()方法在呼叫時,其傳入參數就是Graphics物件,如下所示: public void paint(Graphics g) { ……… } 在上述的paint()方法呼叫繪圖方法,就可以在元件上繪出圖形。 2017/3/22
範例2:使用JFrame類別的畫布 import javax.swing.*; import java.awt.*; import java.awt.event.*; class Ch11_11 extends JFrame { Ch11_11() super("JFrame畫布"); Container c = getContentPane(); c.setBackground(Color.lightGray); } public void paint(Graphics g) g.setColor(Color.red); g.fillRect(10, 10, 100, 100); public static void main(String [] args) { // 建立Swing應用程式 Ch11_11 app = new Ch11_11(); // 關閉視窗事件, 結束程式的執行 app.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) { System.exit(0); } }); app.setSize(300,200); // 設定尺寸 app.setVisible(true); // 顯示視窗 } 2017/3/22
Graphics繪圖類別-getGraphics()方法 在paint()方法之外的其它方法執行繪圖,可以使用getGraphics()方法取得元件的Graphics物件,如下所示: Graphics g = app.getGraphics(); 上述程式碼取得app元件的Graphics物件,接著就可以呼叫繪圖方法在元件上繪出圖形。 2017/3/22
範例3:使用getGraphics() import javax.swing.*; import java.awt.*; import java.awt.event.*; class Ch11_12 extends JFrame { Ch11_12() super("JFrame畫布"); Container c = getContentPane(); c.setBackground(Color.lightGray); } public static void main(String [] args) { // 建立Swing應用程式 Ch11_12 app = new Ch11_12(); // 關閉視窗事件, 結束程式的執行 app.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) { System.exit(0); } }); app.setSize(300,200); // 設定尺寸 app.setVisible(true); // 顯示視窗 //利用getGraphics()取得Graphics Context Graphics g = app.getGraphics(); g.setColor(Color.red); g.fillRect(10, 10, 100, 100); } 2017/3/22
Graphics繪圖類別-Swing的paintComponent()方法 對於繼承自Swing元件的類別。例如:JPanel建立的畫布時,繪圖方法的程式碼是位於覆寫的paintComponent()方法,如下所示: class UserPanel extends JPanel { // 建構子 public UserPanel() { ……… } public void paintComponent(Graphics g) } 2017/3/22
範例4: JPanel類別的畫布 2017/3/22 import javax.swing.*; import java.awt.*; import java.awt.event.*; class Ch11_13 extends JFrame { GraphicPanel gPanel = new GraphicPanel(); Ch11_13() super("JPanel畫布"); Container c = getContentPane(); c.setLayout(new FlowLayout()); c.setBackground(Color.lightGray); c.add(gPanel); Graphics g = gPanel.getGraphics(); repaint(); } class GraphicPanel extends JPanel GraphicPanel() setPreferredSize(new Dimension(200,150)); public void painComponent(Graphics g) super.paintComponent(g); g.setColor(Color.red); g.fillRect(10, 10, 100, 100); public static void main(String [] args) { // 建立Swing應用程式 Ch11_13 app = new Ch11_13(); // 關閉視窗事件, 結束程式的執行 app.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) { System.exit(0); } }); app.setSize(300,200); // 設定尺寸 app.setVisible(true); // 顯示視窗 } 2017/3/22
Graphics繪圖類別-再談paint()和repaint()方法 Swing元件屬於JComponent的子類別,同時繼承Component的paint()和repaint()方法,因為元件繪圖操作大都是呼叫paint()方法完成,paint()方法非常總明,能夠在使用者調整視窗尺寸(例如:縮小和放大元件的視窗)等操作後,或是執行setText()等方法改變元件內容時,自動重新呼叫repaint()方法重繪調整後的圖形和元件。 2017/3/22
座標系統與JComponent元件-說明 電腦螢幕的座標系統是使用「像素」(Pixels)為單位,Graphics物件的畫布是一張長方形區域,左上角為原點,其座標是(0, 0),X軸從左到右,Y軸由上到下,如下圖所示: 2017/3/22
座標系統與JComponent元件-取得尺寸 座標系統可以使用JComponent元件的getWidth()、getHeight()方法取得元件的寬和高,因為元件的四周預設有邊線,所以需要使用getInsets()取得邊線left、right、top和bottom的尺寸,如下所示: Insets ins = getInsets(); int width = getWidth() - (ins.left + ins.right); int height = getHeight() - (ins.top + ins.bottom); 2017/3/22
JFrame類別的畫布-說明 Java應用程式可以將整個JFrame視窗或某個Swing元件作為畫布,如果是JFrame畫布,只需在paint()方法撰寫繪圖方法的程式碼,就可以在視窗繪出所需圖形。 2017/3/22
JFrame類別的畫布-繪圖 如果不是在paint()方法,Java程式碼需要使用getGraphics()方法取得Grphics物件後,在Graphics物件繪出所需圖形,如下所示: Graphics g = app.getGraphics(); g.setColor(Color.green); g.fillOval(100, 100, 40, 40); 2017/3/22
JPanel類別的畫布 Swing的JPanel元件可以取代AWT的Canvas類別畫布,JPanel預設提供「雙緩衝區」(Double Buffering)繪圖功能,所有元件的繪圖都是在幕後完成後,才會一次顯示到螢幕上,所以可以加速圖形的顯示。 2017/3/22
指定色彩-建立Color物件 Java色彩是java.awt.Color的Color物件,這是使用RGB色彩以不同程度的紅、綠和藍3原色混合出的Color色彩物件,如下所示: Color myColor = new Color(r, g, b); 上述參數r、g和b如為int整數,其範圍是0~255,如為float是0.0~1.0。 2017/3/22
指定色彩-指定色彩方法 在建立好Color物件後,可以使用Graphics類別的方法指定色彩,相關方法如下表所示: 2017/3/22
指定字型-建立Font物件 Java的字型是java.awt.Font的Font物件,這是代表指定尺寸和樣式的字型,如下所示: Folot myFont = new Font("新細明體", Font.PLAIN, 30); 上述參數分別是字型名稱、樣式和尺寸。 2017/3/22
指定字型-指定字型方法 在建立好Font物件後,可以使用Graphics類別的方法指定字型,相關方法如下表所示: 2017/3/22
字型定位尺寸FontMetrics-說明 2017/3/22
字型定位尺寸FontMetrics-相關方法 2017/3/22
圖形和字串的繪圖方法-1 Graphics類別提供多種方法可以繪出線條、長方形、圓邊長方形、圓形或橢圓形,如下表所示: 2017/3/22
圖形和字串的繪圖方法-2 2017/3/22
圖形和字串的繪圖方法-3 2017/3/22
填滿圖形的繪圖方法-1 Graphics類別還提供繪出填滿圖形的相關方法,如下表所示: 2017/3/22
填滿圖形的繪圖方法-2 2017/3/22
填滿圖形的繪圖方法-3 2017/3/22
圖片的載入與顯示-說明 Java程式是使用Image物件來載入圖片,Image是抽象類別,其繼承的子類別可以儲存多種格式的圖片檔案。 在使用上是以Toolkit抽象類別(Abstract Window Toolkit實作的抽象類別)的方法將圖檔載入成為Image物件。 2017/3/22
圖片的載入與顯示-載入 首先使用getDefaultToolkit()取得Toolkit物件,如下所示: Toolkit toolkit = Toolkit.getDefaultToolkit(); 程式碼在取得Toolkit物件toolkit後,使用getImage()方法載入圖檔,例如:取得JPG圖檔sample.jpg的Image物件,其程式碼如下所示: Image image = toolkit.getImage("sample.jpg"); 2017/3/22
圖片的載入與顯示-顯示 在paint()或paintComponent()方法使用drawImage()顯示圖檔的Image物件,如下所示: g.drawImage(image, 5, 5, this); 程式碼是在座標(5, 5)顯示名為image的Image物件,實作ImageObserver介面的物件是元件本身this,因為繼承自Component類別的Swing元件都已經實作ImageObserver介面,所以使用元件本身即可。 2017/3/22
範例5:讀取圖片 2017/3/22 import javax.swing.*; import java.awt.*; import java.awt.event.*; class Ch11_15 extends JFrame { //建構子 Ch11_15() super("載入與顯示圖片"); Container c = getContentPane(); Toolkit toolkit = Toolkit.getDefaultToolkit(); Image image = toolkit.getImage("MickeyChristmas.jpg"); ImagePanel imagePane = new ImagePanel(image); c.add(imagePane); } class ImagePanel extends JPanel private Image image; ImagePanel(Image image) this.image = image; public void paintComponent(Graphics g) super.paintComponent(g); g.drawImage(image, 5, 5, this); public static void main(String [] args) { Ch11_15 app = new Ch11_15(); // 關閉視窗事件, 結束程式的執行 app.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) { System.exit(0); } }); app.setSize(370,320); // 設定尺寸 app.setVisible(true); // 顯示視窗 } 2017/3/22
圖片的載入與顯示-圖例 2017/3/22
調整圖片尺寸-圖片的放大與縮小 drawImage()方法新增參數width和height,分別是圖片的寬和高,如果設定的尺寸比原圖形小是縮小圖片,反之就是放大圖片。 boolean drawImage(Image image, int x, int y, int width, int height, ImageObserver observer) 2017/3/22
調整圖片尺寸-圖片的翻轉與剪裁 boolean drawImage(Image image, int x1, int y1, int x2, int y2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) drawImage()方法參數的4個座標分成2組,其說明如下表所示: 2017/3/22
調整圖片尺寸-圖片翻轉 首先來看翻轉圖片情況:如果sample.gif原始圖片尺寸的寬是width,高是height,原始圖片的左上角座標是(0, 0),右下角座標為(width, height),翻轉操作如下: 原尺寸上下翻轉:原始圖片座標分別為(0, height)和(width, 0),換句話說,原始圖片的左下角成為顯示圖片的左上角,而右上角成為右下角。 原尺寸左右翻轉:原始圖片座標分別為(width, 0)和(0, height),換句話說,原始圖片的右上角成為顯示圖片的左上角,而左下角成為右下角。 2017/3/22
調整圖片尺寸-圖片的剪裁 翻轉與剪裁圖片是使用第2組座標,如果第2組座標的尺寸只有部分的圖片,就會剪裁圖片。 2017/3/22
範例6:圖片放大,縮小, 旋轉 class ImagePanel extends JPanel { private Image image; //建構子 ImagePanel(Image image) setPreferredSize(new Dimension(900, 620)); this.image = image; } public void paintComponent(Graphics g) int x, y, width, height; width = image.getWidth(this); height = image.getHeight(this); super.paintComponent(g); x = 0; y = 5; g.drawImage(image, x, y, this); //縮小1/2 x += width; // 設定第二張圖的起始位置 g.drawImage(image, x, y, width/2, height/2, this); //上下旋轉 x += width/2; g.drawImage(image, x, y, x+width, y+height, 0, height, width, 0, this); //左右旋轉 x = 0; y += height +5; g.drawImage(image, x, y, x+height/2, y+width/2, width, 0,0,height, this); //放大並剪裁(取原圖的1/4並放大到原圖大小) x += height/2; g.drawImage(image, x, y, x+width, y+height, 0,0,width/2, height/2, this); } 2017/3/22
動畫效果 動畫效果是使用卡通片的製作原理,快速顯示一張張靜態圖片,因為每張圖片擁有少許改變。例如:位移或尺寸,或定時在不同位置繪出圖形,在人類視覺殘留的情況下,就會產生動畫效果。 2017/3/22
Timer類別的時間控制-說明 在Java程式建立動畫效果是使用Timer計時器類別控制繪圖或圖片顯示,Timer類別可以在間隔時間自動產生事件,以便指定傾聽者物件進行處理。Timer類別的建構子,如下表所示: 2017/3/22
Timer類別的時間控制-使用 Timer類別的使用十分的簡單,只需先建立好Timer物件,如下所示: Timer timer = new Timer(300, this); 上述程式碼建立Timer物件且設定300毫秒間隔時間產生事件,傾聽者物件是本身,接著就可以呼叫下表Timer類別的方法啟動、重新啟動和停止計時器。 2017/3/22
Timer類別的時間控制-方法1 呼叫下表Timer類別的方法啟動、重新啟動和停止計時器,如下表所示: 2017/3/22
Timer類別的時間控制-方法2 Timer類別的其它相關方法,如下表所示: 2017/3/22
圖片移動的動畫效果 在Java程式只需使用Timer類別配合圖片載入與顯示,就可以建立圖片移動橫跨螢幕的動畫效果。 2017/3/22
範例7:動畫 2017/3/22 // 顯示動畫的JPanel class AnimationPane extends JPanel { Image image; // 建構子 public AnimationPane(Image image) { setPreferredSize(new Dimension(250, 100)); setBackground(Color.lightGray); this.image = image; } public void paintComponent(Graphics g) { super.paintComponent(g); int width = getWidth(); int height = getHeight(); // 計算圖片的尺寸 int imgWidth = image.getWidth(this); int imgHeight = image.getHeight(this); g.drawImage(image,((offset*5)%(imgWidth+width)) - imgWidth, (height-imgHeight)/2, this); // 實作事件處理方法 public void actionPerformed(ActionEvent evt) { offset++; animationPane.repaint(); // 重繪 // 主程式 public static void main(String[] args) { // 建立Swing應用程式 Ch11_08 app = new Ch11_08(); // 關閉視窗事件, 結束程式的執行 app.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) { System.exit(0); } }); import javax.swing.*; import java.awt.*; import java.awt.event.*; // 繼承JFrame類別, 實作ActionListener介面 public class Ch11_08 extends JFrame implements ActionListener { private int offset = -10; private Image im; private Timer timer; private AnimationPane animationPane; // 建構子 public Ch11_08() { super("動畫功能的顯示範例"); int delay = 100; timer = new Timer(delay, this); timer.setInitialDelay(0); Container c = getContentPane(); c.setLayout(new FlowLayout()); c.setBackground(Color.gray); Toolkit toolkit = Toolkit.getDefaultToolkit(); im = toolkit.getImage("023.gif"); animationPane = new AnimationPane(im); c.add(animationPane); timer.start(); } app.setSize(300, 150); // 設定尺寸 app.setVisible(true); // 顯示視窗 2017/3/22
範例8:動畫(會更換圖片) 2017/3/22 import java.awt.*; import java.applet.*; public class Ch11_09 extends Applet implements Runnable { Thread fly; int x, y, dx, dy, flag, num, i; Image [] Img; public void init() x = getWidth(); y = 50; dx = -5; dy = 0; Img = new Image[4]; num = 1; Img[0] = getImage(getDocumentBase(), "013.gif"); Img[1] = getImage(getDocumentBase(), "023.gif"); Img[2] = getImage(getDocumentBase(), "024.gif"); Img[3] = getImage(getDocumentBase(), "001.gif"); } public void start() { fly = new Thread(this); fly.start(); } public void run() while(true) x = x + dx; y = y + dy; flag = num % 4; repaint(); num = num + 1; if(x<0) x = getWidth(); try { Thread.sleep(1500); } catch (InterruptedException e) {} public void paint(Graphics g) g.drawImage(Img[flag], x, y, x+10, y+25, this); 2017/3/22
Java Applet的圖片載入-Applet 在Java Applet程式載入和顯示圖片是使用getImage()方法將圖片載入成為Image物件,例如:建立URL物件來載入圖片,如下所示: Image image = getImage( new URL("http://www.company.com/sample.gif")); 使用getDocumentBase()或getCodeBase()方法取得檔案的URL位置,如下圖所示: Image image = getImage(getDocumentBase(),"sample.gif"); 2017/3/22
Java Applet的圖片載入-JApplet Java Applet繼承自JApplet可以使用Swing的ImageIcon物件來載入和顯示圖片。例如:使用ImageIcon載入Baby.jpg圖檔的程式碼,如下所示: ImageIcon image1 = new ImageIcon("Baby.jpg"); 在載入圖片成為ImageIcon物件後,就可以使用paintIcon()方法顯示圖片,如下所示: image1.paintIcon(this, g, 5, 5); 2017/3/22
音樂的播放-說明 在Java Applet不只可以顯示圖片,還可以播放音樂檔案,目前支援的音樂檔案格式有au、aiff、wav、mid和rmf。 2017/3/22
音樂的播放-載入 在Java API的java.applet.*套件的Applet類別提供getAudioClip()方法建立AudioClip物件載入音樂檔案,如下所示: AudioClip audio = getAudioClip(getDocumentBase(),"Microsoft.wav"); 程式碼建立AudioClip物件,參數為URL物件和音樂檔案名稱。 2017/3/22
音樂的播放-播放 在建立好AudioClip物件後,就可以使用AudioClip介面的3個方法控制音樂的播放,如下表所示: 2017/3/22
範例8:播放音樂(使用Applet) play = new JButton("播放"); import java.awt.*; play.addActionListener(this); c.add(play); loop = new JButton("循環播放"); loop.addActionListener(this); c.add(loop); stop = new JButton("停止"); stop.addActionListener(this); c.add(stop); } // 實作事件處理方法 public void actionPerformed(ActionEvent evt) { if (evt.getSource()==play) audio.play(); else if (evt.getSource()==loop) audio.loop(); else if (evt.getSource()==stop) audio.stop(); import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.applet.*; // 繼承JApplet類別, 實作ActionListener介面 public class Ch11_07 extends JApplet implements ActionListener { private AudioClip audio; private JButton play, loop, stop; // 初始方法 public void init() { // 取得參數 String file = getParameter("FILE"); Container c = getContentPane(); c.setBackground(Color.gray); c.setLayout(new FlowLayout(FlowLayout.CENTER)); audio = getAudioClip(getDocumentBase(), file); 2017/3/22
範例8:播放音樂(使用Applet)-續 <html> <head><title>Ch11_07.htm</title></head> <body> <applet code="Ch11_07.class" width=350 height=50> <param name="File" value="FIR_YueYaWan_F.mid"> </applet> </body> </html> 2017/3/22
範例9:播放音樂(使用Sound) import java.io.*; import javax.sound.sampled.*; public class Ch11_07_02 { public static void main(String args []) try System.out.println("播放聲音檔案: " + "jay1.wav"); File sf = new File("jay1.wav"); //取得聲音輸入串流 AudioInputStream astr = AudioSystem.getAudioInputStream(sf); //取得聲音形式 AudioFormat afmt = astr.getFormat(); //建立訊號線資訊物件 DataLine.Info inf = new DataLine.Info(SourceDataLine.class, afmt); //取得符合指定訊號線資訊的訊號線 SourceDataLine l = (SourceDataLine) AudioSystem.getLine(inf); //以指定形式開啟訊號線 l.open(afmt); //開始訊號線的讀寫 l.start(); //讀寫緩寫區 byte [] buf = new byte[65536]; //從聲音串流讀入資料寫入混音器 for(int n = 0; (n=astr.read(buf, 0, buf.length))>0; ) { l.write(buf, 0, n); } //清掉混音器內的資料 l.drain(); //關閉 l.close(); } catch (Exception e) e.printStackTrace(); System.exit(0); 2017/3/22
範例10:滑鼠控制圖像移動 public boolean mouseDown(Event evt, int mx, int my) { if((mx >= 400) && (mx <= 410) && (my >= 400) && (my <= 410)) dx = 0; dy = -5; } if((mx >= 400) && (mx <= 410) && (my >= 440) && (my <= 450)) dy = 5; if((mx >= 380) && (mx <= 390) && (my >= 420) && (my <= 430)) dx = -5; dy = 0; if((mx >= 420) && (mx <= 430) && (my >= 420) && (my <= 430)) dx = 5; clickPoint = new Point(mx, my); message = "Mouse_click_Position: )" + mx + ", " + my + " )"; repaint(); return true; import java.awt.*; import java.applet.*; public class Ch11_21 extends Applet implements Runnable { Thread flag; int x, y, dx, dy; Image Img; Point clickPoint; String message = ""; public void init() x = y = 50; dx = 5; dy = 0; Img = getImage(getDocumentBase(), "010.gif"); } 2017/3/22
範例10:滑鼠控制圖像移動(續) 2017/3/22 public void start() { flag = new Thread(this); flag.start(); } public void run() while(true) x = x + dx; y = y + dy; repaint(); if ( x <= 0) dx = 5; else if( x+70 >= getWidth()) dx = -5; else if( y+70 >= getHeight()) dy = -5; try { Thread.sleep(250); } catch(InterruptedException e) {} public void paint(Graphics g) { g.drawString(message, 5, 15); g.drawRect(400, 400, 10, 10); g.drawRect(400, 440, 10, 10); g.drawRect(380, 420, 10, 10); g.drawRect(420, 420, 10, 10); g.drawImage(Img, x, y, this); } 2017/3/22
範例11:方向鍵控制圖像移動 2017/3/22 import java.awt.*; import java.applet.*; public class Ch11_22 extends Applet implements Runnable { Thread flag; int x, y, dx, dy; Image Img; public void init() x = y = 50; dx = 5; dy = 0; Img = getImage(getDocumentBase(), "010.gif"); } public boolean keyDown(Event evt, int key) { switch (key) case Event.UP: dx = 0; dy = -5; break; case Event.DOWN: dy = 5; case Event.LEFT: dx = -5; dy = 0; case Event.RIGHT: dx = 5; } return true; public void start() flag = new Thread(this); flag.start(); 2017/3/22
範例11:方向鍵控制圖像移動(續) public void run() { while(true) x = x + dx; y = y + dy; repaint(); if ( x <= 0) dx = 5; else if( x+70 >= getWidth()) dx = -5; else if( y+70 >= getHeight()) dy = -5; try { Thread.sleep(250); } catch(InterruptedException e) {} } public void paint(Graphics g) { g.drawImage(Img, x, y, this); } 2017/3/22
研究:用球擊中靶塊 2017/3/22 import java.awt.*; import java.lang.*; import java.applet.*; public class BlockHit extends Applet implements Runnable { int fieldx1 = 0; int fieldy1 = 0; int fieldx2 = 256; int fieldy2 = 306; int block_xnum = 10; int block_ynum = 8; int block_width = 15; int block_height = 5; int block_left_board = 6; int block_up_board = 46; int block_lower_board = 116; int pad_width = 20; Graphics g; Thread theBall; int blockState[][] = new int[block_xnum][block_ynum]; int padx; int ballX, ballY; int ballDX,ballDY; int speed; int eraseCount; int padHitCount; int score; int left; boolean onGame; boolean onFireBall; Panel pControl; Label lScore, lLeft; Button bControl; int threadProcessing; public void init() { setLayout(new BorderLayout()); setBackground(Color.green); g = getGraphics(); pControl = new Panel(); pControl.setBackground(Color.gray); pControl.setLayout(new FlowLayout()); bControl = new Button(" START "); lScore = new Label("SCORE:0 "); lLeft = new Label("LEFT:5"); pControl.add(bControl); pControl.add(lScore); pControl.add(lLeft); add("South", pControl); } public void start() gameInit(); onGame = false; onFireBall = false; 2017/3/22
2017/3/22 public void remakeBlock() { g.setColor(Color.blue); for (int x = 0 ; x < block_xnum ; x++) for (int y = 0 ; y < block_ynum ; y++) blockState[x][y] = 1; g.fillRect(block_left_board + x * (block_width + 10) , block_up_board + y * (block_height +5) , block_width, block_height); } public boolean action(Event e, Object o) if (e.target instanceof Button) if (" START " .equals(o)) if (onGame == false) gameInit(); bControl.setLabel("STOP"); onGame = true; else if ("STOP" .equals(o)) stop(); bControl.setLabel(" START "); onGame = false; onFireBall = false; return true; return false; void gameInit() { for (int x = 0 ; x < block_xnum ; x++) for (int y = 0 ; y < block_ynum ; y++) blockState[x][y] = 1; padx = fieldx2 / 2; score = 0; addScore(0); left = 5; subLeft(0); eraseCount = 0; bControl.setLabel(" START "); threadProcessing = 0; repaint(); } public void paint(Graphics g) g.drawRect(fieldx1, fieldy1, fieldx2, fieldy2); g.setColor(Color.blue); if (blockState[x][y] == 1) g.fillRect(block_left_board + x * (block_width + 10) , block_up_board + y * (block_height +5) , block_width, block_height); 2017/3/22
2017/3/22 public boolean mouseDown(java.awt.Event e, int x, int y) { if (onGame == true) if (onFireBall == false) ballX = (padx / 10) * 10 + 1; if (ballX > block_xnum*(block_width+10)-5) ballX = block_xnum*(block_width+10)-5; else if (ballX < block_left_board) ballX = block_left_board; if (padx < fieldx2 / 2) ballDX = -5; else ballDX = 5; ballY = fieldy2 - 25; ballDY = -10; speed = 150; padHitCount = 0; subLeft(1); threadProcessing = 0; onFireBall = true; if (theBall != null) theBall = null; } if (theBall == null) theBall = new Thread(this); theBall.start(); return true; public boolean mouseMove(java.awt.Event e, int x, int y) { padx = x - 7; if (padx < 1) padx = 1; if (padx > fieldx2 - pad_width) padx = fieldx2 - pad_width; while (threadProcessing == 1) {} g.setColor(Color.green); g.fillRect(1, (fieldy2 - 20), (fieldx2-1) , 5); g.setColor(Color.black); g.fillRect(padx, (fieldy2 - 20), pad_width , 5); return true; } public void stop() if (theBall != null) theBall.stop(); theBall = null; 2017/3/22
2017/3/22 public void run() { int ballPX,ballPY; while(true) ballPX = ballX; ballPY = ballY; ballX = ballX + ballDX; ballY = ballY + ballDY; if ((ballY == (fieldy2 - 25)) && (ballX >= padx - 5) && (ballX <= padx + pad_width)) ballDY = -ballDY; if ((ballX >= (fieldx2-5)) || (ballX <= 1)) ballDX = -ballDX; if (ballY <= 1) if (ballY >= fieldy2-10) if (left == 0) onGame = false; bControl.setLabel(" START "); } g.setColor(Color.green); g.fillRect(ballPX, ballPY, 5 , 5); onFireBall = false; theBall.stop(); if (ballDY > 0) { if ((ballY >= block_up_board - 5) && (ballY <= block_lower_board - 5)) int blockX = ballX / 25; if ((ballX - blockX * 25) >= 5) int blockY = (ballY - (block_up_board - 5)) / 10; if (blockState[blockX][blockY] == 1) blockState[blockX][blockY] = 0; g.setColor(Color.green); g.fillRect(block_left_board + blockX * (block_width + 10) , block_up_board + blockY * (block_height +5), block_width, block_height); ballDY = -ballDY; eraseCount = eraseCount + 1; addScore(1); } else if ((ballY >= block_up_board + 5) && (ballY <= block_lower_board + 5)) 2017/3/22
2017/3/22 { int blockX = ballX / 25; { int blockX = ballX / 25; if ((ballX - blockX * 25) >= 5) { int blockY = (ballY - (block_up_board + 5)) / 10; if (blockState[blockX][blockY] == 1) blockState[blockX][blockY] = 0; g.setColor(Color.green); g.fillRect(block_left_board + blockX * (block_width + 10) , block_up_board + blockY * (block_height +5), block_width, block_height); ballDY = -ballDY; eraseCount = eraseCount + 1; addScore(1); } threadProcessing = 1; g.fillRect(ballPX, ballPY, 5 , 5); g.setColor(Color.red); g.fillRect(ballX, ballY, 5 , 5); threadProcessing = 0; if (eraseCount == 80) remakeBlock(); eraseCount = 0; try { Thread.sleep(speed); } catch(InterruptedException e) System.out.println("Catch Interrupt Exception"); void addScore(int delta) String str; score = score + delta; str = "SCORE:" + String.valueOf(score); lScore.setText(str); void subLeft(int delta) left = left - delta; str = "LEFT:" + String.valueOf(left); lLeft.setText(str); 2017/3/22