咱們須要畫出一個圓,那麼可使用fillOval方法ide
fillOval(int x,int y ,int width ,int height)
參數的X 和 Y是矩形框的左上角的座標,width和height是寬和高。this
而咱們重寫paint方法進行畫出坦克的圓spa
@Override public void paint(Graphics g) { //獲取默認的顏色Color Color c = g.getColor(); //將坦克顏色爲紅色 g.setColor(Color.red); //畫一個圓 g.fillOval(50,50,30,30); //將原顏色填充回 g.setColor(c); }
固然也能夠在lauchFrame方法裏添加背景填充色,顯得更外顯眼一些線程
//添加設置背景顏色 this.setBackground(Color.GREEN);
咱們使用fillOval方法畫出了圓的實現,那麼怎麼讓這個圓改變位置?code
//畫一個圓 g.fillOval(50,50,30,30);
咱們發現x和y的作標都是50,他們是固定的!圖片
若改變成變量的方式?是否是也是同樣能夠呢?get
int x = 50;//坦克的x座標 int y = 50;//坦克的y座標 @Override public void paint(Graphics g) { //獲取默認的顏色Color Color c = g.getColor(); //將坦克顏色爲紅色 g.setColor(Color.red); //畫一個圓 g.fillOval(x,y,30,30); //將原顏色填充回 g.setColor(c); }
若咱們每次原有的基礎上進行改動,是否是就動起來了?it
咱們採用repaint重繪方法,每隔多少毫秒刷新最新的圓點信息座標io
private class PaintThread implements Runnable { @Override public void run() { while (true) { repaint();//重繪方法 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }
//定義窗口方法 public void lauchFrame() { //省略其餘關鍵性代碼..... //添加設置背景顏色 this.setBackground(Color.GREEN); //使用線程重繪最新圓點信息座標 new Thread(new PaintThread()).start(); } @Override public void paint(Graphics g) { //省略其餘關鍵性代碼..... //刷新圓點位置 x += 5;//x座標 y += 5;//y座標 }
這時咱們在main方法運行起來就發現每一個100毫秒就會移動圓點位置了class
爲何使用線程重面,而不是每按下一個鍵進行一次重畫?
咱們的顯示器通常都是多少hz、多少hz的刷新率,而刷新速度太快,paint方法還沒完成,沒跟上致使會出現閃爍的問題
那麼怎麼解決呢?
1.逐條顯示
2.將全部東西畫在虛擬圖片上,一次性顯示出來
Image offScreenImage = null;//虛擬圖片 @Override public void update(Graphics g){ if(offScreenImage == null){ //若爲null,則建立一張圖片 offScreenImage = this.createImage(800,600); } //獲取到虛擬圖片的畫筆 Graphics gOffScreen = offScreenImage.getGraphics(); //使用虛擬圖片的畫筆畫圓 paint(gOffScreen); //將虛擬圖片畫下來 g.drawImage(offScreenImage,0,0,null); }
可是運行起來會發現,圓動起來後慢慢變成了一條線
這是怎麼回事呢?
由於當咱們不重寫update方法時,它會本身用背景顏色刷一遍,刷完再畫
而爲何會一條線呢,由於背景沒刷,以前畫出來的圓還在那
因此咱們用虛擬圖片的畫筆畫出一個方框出來代替以前的背景
@Override public void update(Graphics g){ if(offScreenImage == null){ //若爲null,則建立一張圖片 offScreenImage = this.createImage(800,600); } //獲取到虛擬圖片的畫筆 Graphics gOffScreen = offScreenImage.getGraphics(); //默認黑色,因此須要與效果背景一致獲取原色 Color c = gOffScreen.getColor(); gOffScreen.setColor(Color.green);//與原背景色一致 //使用畫筆畫出一個實現的方框代替原畫的背景效果 gOffScreen.fillRect(0,0,800,600); gOffScreen.setColor(c);//設置原回來 //使用虛擬圖片的畫筆畫圓 paint(gOffScreen); //將虛擬圖片畫下來 g.drawImage(offScreenImage,0,0,null); }
這時再運行就便可
因爲咱們的虛擬圖片、框框、以及一些尺寸大小都是固定的值,當須要修改變化的時候,若只有幾個地方,那還比較容易改動
如有幾百個地方、幾千個地方,這就改動的很繁瑣而且很雜亂
public class TankClient extends Frame { public static final int GAME_WINDTH = 800;//寬度常量 public static final int GAME_HEIGHT = 600;//高度常量 @Override public void update(Graphics g){ if(offScreenImage == null){ //若爲null,則建立一張圖片 offScreenImage = this.createImage(GAME_WINDTH,GAME_HEIGHT); } //省略其餘關鍵性代碼...... } //定義窗口方法 public void lauchFrame() { //設置窗口出現的位置 this.setLocation(400, 300); //設置窗口的寬度高度 this.setSize(GAME_WINDTH, GAME_HEIGHT); //省略其餘關鍵性代碼...... } }
✧將之後可能須要多處改變的量定義爲常量
✧Frame的寬度和高度
✧常量名通常大寫
尚學堂:坦克大戰(馬士兵老師)