slide1 n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Ch16 繪圖與多媒體 PowerPoint Presentation
Download Presentation
Ch16 繪圖與多媒體

Loading in 2 Seconds...

play fullscreen
1 / 63

Ch16 繪圖與多媒體 - PowerPoint PPT Presentation


  • 217 Views
  • Uploaded on

Ch16 繪圖與多媒體. JAVA 程式設計入門 (II). 大綱. 繪圖的基礎 Graphics 類別的色彩、文字與繪圖 圖片的載入與顯示 動畫效果 Java Applet 的圖片載入 音樂的播放. Graphics 繪圖類別 - 取得 Graphics 繪圖類別. 在 Java Applet 程式範例已經說明過 paint() 方法繪出文字和簡單圖形,使用的是 Graphics 類別的方法。

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Ch16 繪圖與多媒體' - jerry


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide1

Ch16 繪圖與多媒體

JAVA程式設計入門(II)

slide2
大綱
  • 繪圖的基礎
  • Graphics類別的色彩、文字與繪圖
  • 圖片的載入與顯示
  • 動畫效果
  • Java Applet的圖片載入
  • 音樂的播放
graphics graphics
Graphics繪圖類別-取得Graphics繪圖類別
  • 在Java Applet程式範例已經說明過paint()方法繪出文字和簡單圖形,使用的是Graphics類別的方法。
  • 在Java執行繪圖功能需要使用「圖形內容」(Graphics Contexts)的Graphics物件,繪製的文字、影像和圖形都是繪製在此畫布物件上,如同將GUI元件新增到JFrame物件的ContentPane物件一般。
1 applet
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);

}

}

Ch11_10.html

<HTML>

<head>

<title>Ch11_10.html</title>

</head>

<body>

<hr>

<center>

<applet

code = Ch11_10.class

width = 200

height = 200

>

</applet>

</center>

<hr>

</body>

</html>

範例1:使用Applet呈現圖
graphics paint
Graphics繪圖類別-paint()方法
  • 繼承自Component元件的paint()方法在呼叫時,其傳入參數就是Graphics物件,如下所示:

public void paint(Graphics g)

{ ……… }

  • 在上述的paint()方法呼叫繪圖方法,就可以在元件上繪出圖形。
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); // 顯示視窗

}

}

範例2:使用JFrame類別的畫布
graphics getgraphics
Graphics繪圖類別-getGraphics()方法
  • 在paint()方法之外的其它方法執行繪圖,可以使用getGraphics()方法取得元件的Graphics物件,如下所示:

Graphics g = app.getGraphics();

  • 上述程式碼取得app元件的Graphics物件,接著就可以呼叫繪圖方法在元件上繪出圖形。
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);

}

}

範例3:使用getGraphics()
graphics swing paintcomponent
Graphics繪圖類別-Swing的paintComponent()方法
  • 對於繼承自Swing元件的類別。例如:JPanel建立的畫布時,繪圖方法的程式碼是位於覆寫的paintComponent()方法,如下所示:

class UserPanel extends JPanel

{ // 建構子

public UserPanel()

{ ……… }

public void paintComponent(Graphics g)

{ ……… }

}

4 jpanel
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); // 顯示視窗

}

}

範例4: JPanel類別的畫布
graphics paint repaint
Graphics繪圖類別-再談paint()和repaint()方法
  • Swing元件屬於JComponent的子類別,同時繼承Component的paint()和repaint()方法,因為元件繪圖操作大都是呼叫paint()方法完成,paint()方法非常總明,能夠在使用者調整視窗尺寸(例如:縮小和放大元件的視窗)等操作後,或是執行setText()等方法改變元件內容時,自動重新呼叫repaint()方法重繪調整後的圖形和元件。
jcomponent
座標系統與JComponent元件-說明
  • 電腦螢幕的座標系統是使用「像素」(Pixels)為單位,Graphics物件的畫布是一張長方形區域,左上角為原點,其座標是(0, 0),X軸從左到右,Y軸由上到下,如下圖所示:
jcomponent1
座標系統與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);

jframe
JFrame類別的畫布-說明
  • Java應用程式可以將整個JFrame視窗或某個Swing元件作為畫布,如果是JFrame畫布,只需在paint()方法撰寫繪圖方法的程式碼,就可以在視窗繪出所需圖形。
jframe1
JFrame類別的畫布-繪圖
  • 如果不是在paint()方法,Java程式碼需要使用getGraphics()方法取得Grphics物件後,在Graphics物件繪出所需圖形,如下所示:

Graphics g = app.getGraphics();

g.setColor(Color.green);

g.fillOval(100, 100, 40, 40);

jpanel
JPanel類別的畫布
  • Swing的JPanel元件可以取代AWT的Canvas類別畫布,JPanel預設提供「雙緩衝區」(Double Buffering)繪圖功能,所有元件的繪圖都是在幕後完成後,才會一次顯示到螢幕上,所以可以加速圖形的顯示。
color
指定色彩-建立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。
slide18
指定色彩-指定色彩方法
  • 在建立好Color物件後,可以使用Graphics類別的方法指定色彩,相關方法如下表所示:
slide19
指定字型-建立Font物件
  • Java的字型是java.awt.Font的Font物件,這是代表指定尺寸和樣式的字型,如下所示:

Folot myFont = new Font("新細明體", Font.PLAIN, 30);

  • 上述參數分別是字型名稱、樣式和尺寸。
slide20
指定字型-指定字型方法
  • 在建立好Font物件後,可以使用Graphics類別的方法指定字型,相關方法如下表所示:
fontmetrics
字型定位尺寸FontMetrics-說明
  • FontMetrics物件可以取得字串和字型細部定位尺寸,以便在畫布上能夠準確編排文字內容,相關字型的細部尺寸,如下圖所示:
fontmetrics1
字型定位尺寸FontMetrics-相關方法
  • FontMetrics類別的相關方法,如下表所示:
slide23
圖形和字串的繪圖方法-1
  • Graphics類別提供多種方法可以繪出線條、長方形、圓邊長方形、圓形或橢圓形,如下表所示:
slide26
填滿圖形的繪圖方法-1
  • Graphics類別還提供繪出填滿圖形的相關方法,如下表所示:
slide29
圖片的載入與顯示-說明
  • Java程式是使用Image物件來載入圖片,Image是抽象類別,其繼承的子類別可以儲存多種格式的圖片檔案。
  • 在使用上是以Toolkit抽象類別(Abstract Window Toolkit實作的抽象類別)的方法將圖檔載入成為Image物件。
slide30
圖片的載入與顯示-載入
  • 首先使用getDefaultToolkit()取得Toolkit物件,如下所示:

Toolkit toolkit = Toolkit.getDefaultToolkit();

  • 程式碼在取得Toolkit物件toolkit後,使用getImage()方法載入圖檔,例如:取得JPG圖檔sample.jpg的Image物件,其程式碼如下所示:

Image image = toolkit.getImage("sample.jpg");

slide31
圖片的載入與顯示-顯示
  • 在paint()或paintComponent()方法使用drawImage()顯示圖檔的Image物件,如下所示:

g.drawImage(image, 5, 5, this);

  • 程式碼是在座標(5, 5)顯示名為image的Image物件,實作ImageObserver介面的物件是元件本身this,因為繼承自Component類別的Swing元件都已經實作ImageObserver介面,所以使用元件本身即可。
slide32
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); // 顯示視窗

}

}

範例5:讀取圖片
slide34
調整圖片尺寸-圖片的放大與縮小
  • drawImage()方法新增參數width和height,分別是圖片的寬和高,如果設定的尺寸比原圖形小是縮小圖片,反之就是放大圖片。

boolean drawImage(Image image, int x, int y, int width, int height, ImageObserver observer)

slide35
調整圖片尺寸-圖片的翻轉與剪裁

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組,其說明如下表所示:
slide36
調整圖片尺寸-圖片翻轉
  • 首先來看翻轉圖片情況:如果sample.gif原始圖片尺寸的寬是width,高是height,原始圖片的左上角座標是(0, 0),右下角座標為(width, height),翻轉操作如下:
    • 原尺寸上下翻轉:原始圖片座標分別為(0, height)和(width, 0),換句話說,原始圖片的左下角成為顯示圖片的左上角,而右上角成為右下角。
    • 原尺寸左右翻轉:原始圖片座標分別為(width, 0)和(0, height),換句話說,原始圖片的右上角成為顯示圖片的左上角,而左下角成為右下角。
slide37
調整圖片尺寸-圖片的剪裁
  • 翻轉與剪裁圖片是使用第2組座標,如果第2組座標的尺寸只有部分的圖片,就會剪裁圖片。
slide38
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);

}

}

範例6:圖片放大,縮小, 旋轉
slide39
動畫效果
  • 動畫效果是使用卡通片的製作原理,快速顯示一張張靜態圖片,因為每張圖片擁有少許改變。例如:位移或尺寸,或定時在不同位置繪出圖形,在人類視覺殘留的情況下,就會產生動畫效果。
timer
Timer類別的時間控制-說明
  • 在Java程式建立動畫效果是使用Timer計時器類別控制繪圖或圖片顯示,Timer類別可以在間隔時間自動產生事件,以便指定傾聽者物件進行處理。Timer類別的建構子,如下表所示:
timer1
Timer類別的時間控制-使用
  • Timer類別的使用十分的簡單,只需先建立好Timer物件,如下所示:

Timer timer = new Timer(300, this);

  • 上述程式碼建立Timer物件且設定300毫秒間隔時間產生事件,傾聽者物件是本身,接著就可以呼叫下表Timer類別的方法啟動、重新啟動和停止計時器。
timer 1
Timer類別的時間控制-方法1
  • 呼叫下表Timer類別的方法啟動、重新啟動和停止計時器,如下表所示:
timer 2
Timer類別的時間控制-方法2
  • Timer類別的其它相關方法,如下表所示:
slide44
圖片移動的動畫效果
  • 在Java程式只需使用Timer類別配合圖片載入與顯示,就可以建立圖片移動橫跨螢幕的動畫效果。
slide45
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); // 顯示視窗

}

}

// 顯示動畫的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); }

});

範例7:動畫
slide46
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);

}

}

範例8:動畫(會更換圖片)
java applet applet
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");

java applet japplet
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);

slide49
音樂的播放-說明
  • 在Java Applet不只可以顯示圖片,還可以播放音樂檔案,目前支援的音樂檔案格式有au、aiff、wav、mid和rmf。
slide50
音樂的播放-載入
  • 在Java API的java.applet.*套件的Applet類別提供getAudioClip()方法建立AudioClip物件載入音樂檔案,如下所示:

AudioClip audio = getAudioClip(getDocumentBase(),"Microsoft.wav");

  • 程式碼建立AudioClip物件,參數為URL物件和音樂檔案名稱。
slide51
音樂的播放-播放
  • 在建立好AudioClip物件後,就可以使用AudioClip介面的3個方法控制音樂的播放,如下表所示:
8 applet
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);

play = new JButton("播放");

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();

}

}

範例8:播放音樂(使用Applet)
8 applet1
範例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>
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);

}

}

範例9:播放音樂(使用Sound)
slide55
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");

}

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))

{

dx = 0;

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;

dy = 0;

}

clickPoint = new Point(mx, my);

message = "Mouse_click_Position: )" + mx + ", " + my + " )";

repaint();

return true;

}

範例10:滑鼠控制圖像移動
slide56
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);

}

}

範例10:滑鼠控制圖像移動(續)
slide57
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:

dx = 0;

dy = 5;

break;

case Event.LEFT:

dx = -5;

dy = 0;

break;

case Event.RIGHT:

dx = 5;

dy = 0;

}

return true;

}

public void start()

{

flag = new Thread(this);

flag.start();

}

範例11:方向鍵控制圖像移動
slide58
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);

}

}

範例11:方向鍵控制圖像移動(續)
slide59
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;

}

研究:用球擊中靶塊
slide60
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);

for (int y = 0 ; y < block_ynum ; y++)

{

for (int x = 0 ; x < block_xnum ; x++)

{

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);

}

}

}

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;

}

slide61
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);

g.setColor(Color.green);

return true;

}

public void stop()

{

if (theBall != null)

{

theBall.stop();

theBall = null;

}

}

slide62
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)

ballDY = -ballDY;

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))

slide63
{

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.setColor(Color.green);

g.fillRect(ballPX, ballPY, 5 , 5);

g.setColor(Color.red);

g.fillRect(ballX, ballY, 5 , 5);

g.setColor(Color.green);

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)

{

String str;

left = left - delta;

str = "LEFT:" + String.valueOf(left);

lLeft.setText(str);

}

}