Java小專案——飛機大戰(一、實現執行緒繪製背景和我方飛機,鍵盤控制飛機運動)
阿新 • • 發佈:2018-12-05
1 總體需求分析
1.1 類
1、主類
2、我方飛機類
3、執行緒類
2.2 效果圖
2 實現
2.1 飛機類 MyPlane
飛機類包括以下引數:
位置x、y
速度vx、vy
圖片圖示myicom:設定為飛機的圖片
飛機類包括以下方法:
有參構造方法:初始化x、y,保證第一次繪製飛機能夠有座標
public MyPlane(int x, int y) { this.x = x; this.y = y; }
繪製飛機方法:用引數畫筆g來繪製飛機,再更新vx和vy,
public void drawPlane(Graphics g) { g.drawImage(myicon.getImage(), x, y, null); x += vx; y += vy; }
程式碼:
package com.java8.planewarsV1; import javax.swing.*; import java.awt.*; public class MyPlane { private int x, y; private int vx, vy; private ImageIcon myicon = new ImageIcon(this.getClass().getResource("PaperPlane.png")); /** * 我方飛機的建構函式 * @param x:繪製座標x * @param y:繪製座標y */ public MyPlane(int x, int y) { this.x = x; this.y = y; } /** * 繪製飛機物件的函式,每次呼叫,則繪製一次飛機 * @param g:畫筆 */ public void drawPlane(Graphics g) { g.drawImage(myicon.getImage(), x, y, null); x += vx; y += vy; } /** * setVx * setVy * 用於在按鍵後,設定其每次移動的大小,並在釋放的時候清0 * @param vx */ public void setVx(int vx) { this.vx = vx; } public void setVy(int vy) { this.vy = vy; } }
2.2 主介面類 GameUI
介面類和監聽器類:兩個寫在一個類中,方便引數的傳入和傳出
介面類:主要實現一個面板JFrame jf,jf上新增鍵盤監聽器,jf上獲取畫筆g
監聽器類:KeyListener。按space空格開始遊戲,按上下左右控制飛機運動。
GameUI類的引數為:
private JFrame jf; private Graphics g; private MyPlane myPlane; private MyThread myThread; private ImageIcon bgicon = new ImageIcon(this.getClass().getResource("bg.jpeg")); private int speed = 5;
空格 VK_SPACE:
1.建立飛機物件,初始化飛機的x和y;2.若執行緒為null,則建立myThread執行緒,傳入mayplane飛機、g畫筆、jf物件; 3.使用Thread()方法,執行myThread執行緒,開始不斷繪製飛機類
// 按下空格,開啟執行緒 // 執行緒每隔0.02s就繪製背景圖、飛機 if(myThread == null){ //1.建立飛機物件 myPlane = new MyPlane((jf.getWidth() - 150) / 2, jf.getHeight() - 150); //2.建立myThread執行緒 myThread = new MyThread(myPlane,g,jf); //3.使用Thread()方法,執行myThread執行緒 new Thread(myThread).start(); }
左右上下 KeyEvent.VK_LEFT:
設定飛機類的x/y速度為+speed或者-speed
case KeyEvent.VK_LEFT: myPlane.setVx(-speed); break;
程式碼:
package com.java8.planewarsV1;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class GameUI implements KeyListener {
private JFrame jf;
private Graphics g;
private MyPlane myPlane;
private MyThread myThread;
private ImageIcon bgicon = new ImageIcon(this.getClass().getResource("bg.jpeg"));
private int speed = 5;
public static void main(String arg[]) {
GameUI gameUI = new GameUI();
gameUI.showUI();
}
private void showUI() {
jf = new JFrame();
jf.setTitle("飛機大戰1.0");
jf.setSize(800, 800);
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(3);
jf.setVisible(true);
g = jf.getGraphics();
g.drawImage(bgicon.getImage(),0,0,null);
jf.addKeyListener(this);
}
public void keyTyped(KeyEvent e) {
}
/***
* 按下對應按鈕,獲取按鈕的值e.getKeyCode(),進行不同操作
* 空格:開始遊戲;上下左右:對應移動
* @param e
*/
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_LEFT:
myPlane.setVx(-speed);
break;
case KeyEvent.VK_RIGHT:
myPlane.setVx(speed);
break;
case KeyEvent.VK_UP:
myPlane.setVy(-speed);
break;
case KeyEvent.VK_DOWN:
myPlane.setVy(speed);
break;
case KeyEvent.VK_SPACE:
// 按下空格,開啟執行緒
// 執行緒每隔0.02s就繪製背景圖、飛機
if(myThread == null){
//1.建立飛機物件
myPlane = new MyPlane((jf.getWidth() - 150) / 2,
jf.getHeight() - 150);
//2.建立myThread執行緒
myThread = new MyThread(myPlane,g,jf);
//3.使用Thread()方法,執行myThread執行緒
new Thread(myThread).start();
}
break;
}
}
/**
* 清空上一次操作的speed
* @param e
*/
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_LEFT:
myPlane.setVx(0);
break;
case KeyEvent.VK_RIGHT:
myPlane.setVx(0);
break;
case KeyEvent.VK_UP:
myPlane.setVy(0);
break;
case KeyEvent.VK_DOWN:
myPlane.setVy(0);
break;
}
}
}
2.3 MyThread
重寫執行緒run():
執行緒暫停0.02s繪製一次;在bufferedImage內繪製背景+繪製飛機(bg);將bufferedImage繪製到jf上(g)
繪製飛機執行緒建構函式:
需要傳入飛機、畫筆g、面板jf
/** * 繪製飛機執行緒建構函式 */ public MyThread(MyPlane myPlane, Graphics g,JFrame jf){ this.myPlane = myPlane; this.g = g; this.jf = jf; }
快取技術bufferedImage:
使用bufferedImage的畫筆bg,來繪製背景、繪製飛機。解決了畫面交替繪製閃爍問題。
/** * 使用快取技術bufferedImage,解決畫面交替繪製閃爍問題 * 1 首先將所有物體繪製於bufferedImage內 * 2 再將bufferedImage繪製於JFrame內 */ //1.建立bufferedImage物件:大小為jf大小,型別為RGB BufferedImage bufferedImage = new BufferedImage(jf.getWidth(),jf.getHeight(),BufferedImage.TYPE_INT_BGR); //2.獲取bufferedImage物件的畫筆:bg Graphics bg = bufferedImage.createGraphics(); //3.繪製背景和飛機,於bufferedImage物件上 bg.drawImage(bgicon.getImage(),0,0,null); myPlane.drawPlane(bg); //4.繪製bufferedImage,到JFrame上 g.drawImage(bufferedImage,0,0,null);
程式碼:
package com.java8.planewarsV1;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class MyThread implements Runnable{
private MyPlane myPlane;
private Graphics g;
private JFrame jf;
private ImageIcon bgicon = new ImageIcon(this.getClass().getResource("bg.jpeg"));
/**
* 繪製飛機執行緒建構函式
*/
public MyThread(MyPlane myPlane, Graphics g,JFrame jf){
this.myPlane = myPlane;
this.g = g;
this.jf = jf;
}
/**
* 不使用執行緒,每次繪製之間間隔過長;
* 使用執行緒,加速繪製飛機移動軌跡。
*/
public void run() {
while(true) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
/**
* 使用快取技術bufferedImage,解決畫面交替繪製閃爍問題
* 1 首先將所有物體繪製於bufferedImage內
* 2 再將bufferedImage繪製於JFrame內
*/
//1.建立bufferedImage物件:大小為jf大小,型別為RGB
BufferedImage bufferedImage = new BufferedImage(jf.getWidth(),jf.getHeight(),BufferedImage.TYPE_INT_BGR);
//2.獲取bufferedImage物件的畫筆:bg
Graphics bg = bufferedImage.createGraphics();
//繪製背景和飛機,於bufferedImage物件上
bg.drawImage(bgicon.getImage(),0,0,null);
myPlane.drawPlane(bg);
//繪製bufferedImage,到JFrame上
g.drawImage(bufferedImage,0,0,null);
}
}
}