本篇博客主要利用java實作了一個簡易版的飛機大戰,適合初學者練手,所涉及到的知識主要有以下幾點:
1,面向物件,飛機大戰的功能是針對每個英雄機、子彈和敵機物件實作的,
2,陣列,由于敵機和子彈物件有多個,創建一個List陣列用來存盤相應物件,之后針對陣列中的物件進行操作,
3,圖片,站在用戶的角度,我們看到的是一張張飛機、子彈的圖片,對物件的操作要和相應的圖片聯系起來,
4,執行緒,利用sleep()函式使執行緒休眠,讓游戲效果可以用視覺捕捉,
一,游戲規則:
當英雄機發射的子彈擊中敵機,敵機產生爆炸效果并消失,每擊中一架敵機分數+10,
二,游戲效果:

三,游戲制作
1,視窗的實作
package PlaneGame;
import java.awt.Graphics;
import javax.swing.JFrame;
public class GameMain {
//視窗寬高
static int width=550;
static int heigh=700;
public void UI() {
//創建一個表單
JFrame frame = new JFrame();
frame.setTitle("飛機大戰");//設定標題
frame.setSize(width, heigh);//設定表單大小
frame.setLocationRelativeTo(null);//使表單顯示在螢屏中央
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//退出時關閉視窗
frame.setVisible(true);//顯示表單可見
}
//主函式 程式入口
public static void main(String[] args) {
GameMain gamemain= new GameMain();
gamemain.UI();
}
}
效果如下:

2,英雄機的顯示與移動
<1>創建一個GamePanel類繼承JPanel,JFrame是最頂層組件,每一個視窗都是JFrame,其他組件都要放在視窗里面,視窗里面可以有好幾個區域,每個區域都可以稱做一個面板,這個面板可以叫做JPanel(別的容器也可以),JPanel是Java的一個輕量級容器,JPanel可以添加到JFrame中,反之則不行,本次游戲制作我們將主要功能全部放在GamePanel中,因為JPanel默認使用了雙緩沖繪圖,可以解決閃頻問題,
package PlaneGame;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class GamePanel extends JPanel{
}
<2>在主視窗類GameMain中創建一個GamePanel物件并添加到視窗物件中,
//創建JPanel 添加到表單上 監聽在JPanel中
GamePanel panel = new GamePanel();
frame.add(panel);
<3>展示英雄機的圖片,這里我們將游戲的圖片全部放在Eclipse的一個img圖片包中,這樣只需要從img包中獲取圖片就可以了,

//英雄機左上角坐標 初始位置 之后根據滑鼠拖拽改變位置
int heroX=300;
int heroY=400;
//英雄機圖片 圖片路徑
ImageIcon heroImage = new ImageIcon("img/hero.png");
//paint方法視窗物件自動呼叫 不需手動呼叫 繪制圖片
public void paint(Graphics g) {
super.paint(g);
//繪制英雄機
g.drawImage(heroImage.getImage(), heroX, heroY,null);
}
得到效果如下:

<4>創建滑鼠拖拽監聽器,使英雄機位置隨滑鼠拖拽移動,
public class GamePanel extends JPanel implements MouseMotionListener{
//重寫滑鼠拖拽方法
public void mouseDragged(MouseEvent e) {
//滑鼠的x、y
int x=e.getX();
int y=e.getY();
//將滑鼠拖拽位置賦給英雄機坐標
heroX=x;
heroY=y;
}
//重寫滑鼠移動方法
public void mouseMoved(MouseEvent e) {
//System.out.println("滑鼠移動");
}
}
- 在paint()方法中添加repaint()方法,這樣英雄機坐標改變后自動重新繪制,達到移動效果,
//重新繪制自動呼叫paint方法 更新圖片 否則實作不了影片效果
repaint();
- 在GameMain類的UI方法中給視窗添加滑鼠監聽器,
//添加滑鼠移動監聽器
frame.addMouseMotionListener(panel);
效果如下:

<5>使滑鼠位置處于圖片中央,按照上述移動圖片發現滑鼠位置始終處于圖片的左上角,這是因為英雄機圖片是一張去除背景的矩形圖片,滑鼠位置就是矩形圖片的左上角,為了更好地控制英雄機,我們要讓滑鼠位置出現在圖片中央,就是對英雄機的左上角位置進行處理,使英雄機左上角位置不再是滑鼠位置,而變為滑鼠坐標減去圖片大小的1/2,這樣滑鼠就能出現在圖片中央了,
heroX=x-(heroImage.getIconWidth()/2);//使滑鼠在英雄機圖片的中央
heroY=y-(heroImage.getIconHeight()/2);
效果如下:

<6>限制英雄機位置,使英雄機的移動不超過表單,在上面的效果中我們發現英雄機會隨著滑鼠的拖拽移除表單邊界,但在游戲中我們不希望這樣的效果發生,因此當英雄機的圖片邊緣移動到表單邊緣時,將英雄機圖片位置限定為表單邊界,這樣英雄機的移動就不會超過表單,
public void mouseDragged(MouseEvent e) {
//滑鼠的x、y
int x=e.getX();
int y=e.getY();
//將滑鼠拖拽位置賦給英雄機坐標
heroX=x-(heroImage.getIconWidth()/2);//使滑鼠在英雄機圖片的中央
heroY=y-(heroImage.getIconHeight()/2);
//使英雄機不超出邊界
//右邊界
if((x+heroImage.getIconWidth())>GameMain.width) {
heroX=GameMain.width-heroImage.getIconWidth()-20;
}
//左邊界
if((x)<80) {
heroX=0;
}
//下邊界
if((y+heroImage.getIconHeight())>GameMain.heigh) {
heroY=GameMain.heigh-heroImage.getIconHeight()-20;
}
//上邊界
if(y<80) {
heroY=0;
}
//System.out.println(heroX+" "+heroY);
}
效果如下:

3,敵機效果
<1>創建敵機類,每一個敵機都是一個敵機物件,在敵機類中得到敵機的圖片,定義敵機的各種屬性和方法,同時定義敵機類的構造方法,這樣在之后創建敵機物件的同時就能初始化敵機的位置和寬高,
package PlaneGame;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.ImageIcon;
//敵機物件
public class Enemy {
//敵機寬高
private int width;
private int heigth;
//敵機坐標
private int x;
private int y;
//敵機圖片
private ImageIcon enemyImageIcon = new ImageIcon("img/enemy.png");
//構造方法 獲取敵機寬高 敵機x、y位置隨機出現
//敵機物件有多個 每次創建物件的時候立刻得到該物件的寬高和位置
public Enemy() {
this.width=enemyImageIcon.getIconWidth();
this.heigth=enemyImageIcon.getIconHeight();
//隨機產生敵機位置
Random random = new Random();
//不超出表單范圍 且在英雄機能擊中的范圍內
this.x=random.nextInt(GameMain.width-width-25);//-width-25是為了使敵機位置不超出左邊界且不太偏使子彈無法擊中
this.y=-random.nextInt(GameMain.heigh-heigth);//敵機從上往下飛 默認初始化在表單外 表單上方(-heigth)
}
//私有屬性 寬的get方法
public int getWidth() {
return width;
}
//私有屬性 寬的set方法
public void setWidth(int width) {
this.width = width;
}
//私有屬性 高的get方法
public int getHeigth() {
return heigth;
}
//私有屬性 高的set方法
public void setHeigth(int heigth) {
this.heigth = heigth;
}
//私有屬性 敵機x坐標的get方法
public int getX() {
return x;
}
//私有屬性 敵機x坐標的set方法
public void setX(int x) {
this.x = x;
}
//私有屬性 敵機y坐標的get方法
public int getY() {
return y;
}
//私有屬性 敵機y坐標的set方法
public void setY(int y) {
this.y = y;
}
}
<2>在創建容器物件時創建敵機物件,
- 創建一個List陣列用來保存敵機物件,
//存盤敵機的陣列
List<Enemy> enemys = new ArrayList<Enemy>();
- 在GamePanel中增加一個構造方法,在創建GamePanel物件時就創建敵機物件,使得敵機物件一開始就出現在面板中,
//構造方法 在創建GamePanel物件時就創建敵機物件 使得敵機物件一開始就出現在面板中
public GamePanel() {
//創建10個敵機 加入陣列中
for(int i=0;i<10;i++) {
enemys.add(new Enemy());
}
}
<3>init()方法
- GamePanel定義init()方法初始化容器,在該方法中實作整個游戲的具體邏輯,
// //初始化使用 邏輯操作
public void init() {
}
- 在GameMain類的UI()方法中呼叫init()方法,
public void UI() {
//創建一個表單
JFrame frame = new JFrame();
frame.setTitle("飛機大戰");//設定標題
frame.setSize(width, heigh);//設定表單大小
frame.setLocationRelativeTo(null);//使表單顯示在螢屏中央
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//退出時關閉視窗
//創建JPanel 添加到表單上 監聽在JPanel中
GamePanel panel = new GamePanel();
frame.add(panel);
//添加滑鼠移動監聽器
frame.addMouseMotionListener(panel);
frame.setVisible(true);//顯示表單可見
//呼叫初始化方法 游戲邏輯操作
panel.init();
}
<4>讓敵機動起來
- 在Enemy類中定義移動方法,敵機往下移動即增加敵機的y坐標,
//敵機移動方法 往下移 可視為敵機的移動速度
public void move() {
this.y+=1;
}
- 在init()方法中呼叫move方法,使所有敵機都移動起來,
public void init() {
// //讓所有敵機往下移動
for(int i=0;i<enemys.size();i++) {
Enemy enemy =enemys.get(i);
enemy.move();//移動敵機 使敵機往下移 改變敵機y值
}
}
<5>繪制敵機
- 在Enemy類中定義繪制敵機的方法,
//畫敵機的方法
public void drawImage(Graphics g) {
g.drawImage(enemyImageIcon.getImage(), x, y,null);
}
- 在paint()方法中呼叫,將全部敵機繪制出來,
//視窗物件自動呼叫 不需手動呼叫 繪制圖片
public void paint(Graphics g) {
super.paint(g);
//繪制英雄機
g.drawImage(heroImage.getImage(), heroX, heroY,null);
//繪制全部敵機
for(int i=0;i<enemys.size();i++) {
Enemy enemy = enemys.get(i);
enemy.drawImage(g);
}
// //重新繪制自動呼叫paint方法 更新圖片 否則實作不了影片效果
// repaint();
}
- 讓敵機位置不斷改變,上述只實作了敵機的一次移動,要實作敵機的不斷移動就要增加while(true)模塊,
while(true) {
// //讓所有敵機往下移動
for(int i=0;i<enemys.size();i++) {
Enemy enemy =enemys.get(i);
enemy.move();//移動敵機 使敵機往下移 改變敵機y值
}
- 增加休眠,否則敵機移動太快,視覺無法捕捉,
while(true) {
// //讓所有敵機往下移動
for(int i=0;i<enemys.size();i++) {
Enemy enemy =enemys.get(i);
enemy.move();//移動敵機 使敵機往下移 改變敵機y值
}
//休息5ms 否則敵機移動太快 視覺無法捕捉
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
實作效果如下:

<6>洗掉超過邊界的敵機,增加新的敵機,
在上面的效果中我們發現10架敵機移動完之后界面中就沒有敵機了,因此我們要向敵機串列中不斷加敵機,但這樣做會導致敵機串列中存盤的敵機越來越多,從用戶角度來看,移出界面的敵機就相當與無效,因此我們可以把移動到界面外的敵機洗掉,然后再添加新的敵機,這樣敵機陣列中的敵機一直只有10架,
// //讓所有敵機往下移動
for(int i=0;i<enemys.size();i++) {
Enemy enemy =enemys.get(i);
enemy.move();//移動敵機 使敵機往下移 改變敵機y值
//判斷敵機是否飄出下界 敵機y坐標是否超過表單 超過則將該架敵機移除釋放記憶體 重新添加一架敵機否則敵機移除完就沒有了
if(enemy.getY()>GameMain.heigh) {
enemys.remove(enemy);
enemys.add(new Enemy());
}
}
效果如下:

4,子彈效果
<1>創建子彈類Bullet,
- 每個子彈都是一個物件,在子彈類中得到子彈圖片定義子彈類的屬性和方法,
package PlaneGame;
import java.awt.Graphics;
import javax.swing.ImageIcon;
//子彈類
public class Bullet {
//子彈寬高
private int width;
private int heigth;
//子彈位置
private int x;
private int y;
//子彈圖片
private ImageIcon bulletImageIcon = new ImageIcon("img/bullet.png");
//私有屬性 子彈寬度width的get方法
public int getWidth() {
return width;
}
//私有屬性 子彈寬度width的set方法
public void setWidth(int width) {
this.width = width;
}
//私有屬性 子彈高度heigth的get方法
public int getHeigth() {
return heigth;
}
//私有屬性 子彈高度heigth的set方法
public void setHeigth(int heigth) {
this.heigth = heigth;
}
//私有屬性 子彈坐標x的get方法
public int getX() {
return x;
}
//私有屬性 子彈坐標x的set方法
public void setX(int x) {
this.x = x;
}
//私有屬性 子彈坐標y的get方法
public int getY() {
return y;
}
//私有屬性 子彈坐標y的set方法
public void setY(int y) {
this.y = y;
}
}
- 在構造器中初始化子彈位置,
//構造方法 初始化子彈 子彈的位置x、y跟隨滑鼠位置 通過構造方法將滑鼠位置傳入
public Bullet(int x,int y) {
this.x=x;
this.y=y;
this.width=bulletImageIcon.getIconWidth();
this.heigth=bulletImageIcon.getIconHeight();
}
<2>創建子彈物件
- 創建一個用來保存子彈物件的陣列,
//存盤敵機的陣列
List<Enemy> enemys = new ArrayList<Enemy>();
//創建子彈的陣列
List<Bullet> bullets = new ArrayList<Bullet>();
- 創建子彈物件,將英雄機上方中間位置傳入子彈物件中,將子彈物件添加到子彈陣列中,
while(true) {
//創建一些子彈 修改子彈位置 使子彈位置在飛機正中間
Bullet bullet = new Bullet(heroX+(heroImage.getIconWidth()/2)-2,heroY-15);
//添加到子彈陣列中
bullets.add(bullet);
//讓所有敵機往下移動
for(int i=0;i<enemys.size();i++) {
Enemy enemy =enemys.get(i);
enemy.move();//移動敵機 使敵機往下移 改變敵機y值
}
//休息5ms 否則敵機移動太快 視覺無法捕捉
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
<3>讓子彈移動起來
- 在Bullet類中定義移動方法,
//子彈移動方法 子彈向上移 可視為子彈移動速度
public void move() {
this.y-=3;
}
- 在init()方法中呼叫移動方法,讓所有子彈移動起來,
//創建一些子彈 修改子彈位置 使子彈位置在飛機正中間
Bullet bullet = new Bullet(heroX+(heroImage.getIconWidth()/2)-2,heroY-15);
//添加到子彈陣列中
bullets.add(bullet);
//讓子彈移動起來
for(int i=0;i<bullets.size();i++) {
Bullet tempBullet =bullets.get(i);
tempBullet.move();
}
<4>繪制子彈
- 在Bullet類中定義繪制方法,
//子彈繪制方法
public void drawImage(Graphics g) {
g.drawImage(bulletImageIcon.getImage(), x, y, null);
}
- 在paint()方法中呼叫,將所有子彈繪制出來,
//繪制英雄機
g.drawImage(heroImage.getImage(), heroX, heroY,null);
//繪制全部敵機
for(int i=0;i<enemys.size();i++) {
Enemy enemy = enemys.get(i);
enemy.drawImage(g);
}
//英雄機只有一架 而敵機子彈等有多架 因此定義繪制函式 每個物件都呼叫自己的繪制繪制函式
//繪制全部子彈
for(int i=0;i<bullets.size();i++) {
Bullet bullet = bullets.get(i);
bullet.drawImage(g);
}
得到的效果圖如下:

<5>降低子彈增加頻率,
在上面的效果中我們發現子彈過密影響游戲效果,因此我們利用flag計數來控制子彈的添加,將添加代碼修改如下:
// //初始化使用 邏輯操作
public void init() {
int flag=0;//用來使子彈的創建不過密
//一直進行添加、洗掉、判斷是否碰撞等操作
while(true) {
flag++;
//創建子彈 使子彈的創建不過密
if(flag%20==0) {
//創建一些子彈 修改子彈位置 使子彈位置在飛機正中間
Bullet bullet = new Bullet(heroX+(heroImage.getIconWidth()/2)-2,heroY-15);
//添加到子彈陣列中
bullets.add(bullet);
}
//讓子彈移動起來
for(int i=0;i<bullets.size();i++) {
Bullet tempBullet =bullets.get(i);
tempBullet.move();
}
...//省略其他代碼
...
}
}

<6>洗掉越界的子彈
和敵機一樣,當子彈飄出界面時,我們將其洗掉,可以有效控制子彈陣列的長度,這時洗掉完越界的子彈后不用添加新的子彈,因為之前的flag計數部分一直在添加新的子彈,
//讓子彈移動起來
for(int i=0;i<bullets.size();i++) {
Bullet tempBullet =bullets.get(i);
tempBullet.move();
}
// //System.out.println(bullets.size());
//洗掉越界的子彈 否則子彈一直在增加 不利于記憶體
for(int i=0;i<bullets.size();i++) {
Bullet bullet = bullets.get(i);
if(bullet.getY()<0) {//子彈越界了
bullets.remove(bullet);
}
}
5,爆炸效果
<1>碰撞方法,即子彈是否運動到敵機圖片范圍,在GamePanel中定義碰撞方法:
//碰撞方法 判斷子彈是否打中敵機 即子彈是否運動到敵機所處區域
public boolean isHit(Enemy enemy,Bullet bullet) {
//指定一個區域 即敵機圖片所處區域
Rectangle rect = new Rectangle(enemy.getX(),enemy.getY(),enemy.getWidth(),enemy.getHeigth());
//表示(x,y)坐標空間中的位置的點 即子彈的中心位置
Point p = new Point(bullet.getX()+bullet.getWidth()/2,bullet.getY()+bullet.getHeigth());
//如果子彈處在敵機的區域 則認為子彈擊中了敵機 回傳true
return rect.contains(p);
}
<2>碰撞后洗掉該敵機和子彈,同時添加新的敵機和子彈,使得不會因為在界面內全部被擊中后界面中沒有敵機和子彈(上文中是在敵機和子彈飄出邊界后才洗掉和添加),
// //讓所有敵機往下移動
for(int i=0;i<enemys.size();i++) {
Enemy enemy =enemys.get(i);
enemy.move();//移動敵機 使敵機往下移 改變敵機y值
//判斷敵機是否飄出下界 敵機y坐標是否超過表單 超過則將該架敵機移除釋放記憶體 重新添加一架敵機否則敵機移除完就沒有了
if(enemy.getY()>GameMain.heigh) {
enemys.remove(enemy);
enemys.add(new Enemy());
}
}
//判斷是否發生碰撞 子彈打到敵機 獲取當前所有敵機和子彈 任意兩個相撞都是碰撞了
for(int i=0;i<enemys.size();i++) {
Enemy enemy = enemys.get(i);//敵機
for(int j=0;j<bullets.size();j++) {
Bullet bullet = bullets.get(j);//子彈
//判斷是否擊中
if(isHit(enemy,bullet)) {
敵機消失 將敵機洗掉移除敵機串列
enemys.remove(enemy);
//再新加入一個敵機 否則如果所有敵機打完全部刪光 沒有敵機了
enemys.add(new Enemy());
//洗掉該子彈
bullets.remove(bullet);
//添加新的子彈進去
//bullets.add(new Bullet(heroX+(heroImage.getIconWidth()/2)-2,heroY-15));
}
}
}

<3>定義爆炸圖片類Bomb,
- 在Bomb類中得到爆炸圖片,定義爆炸圖片的屬性和方法,
package PlaneGame;
import java.awt.Graphics;
import javax.swing.ImageIcon;
//碰撞類
public class Bomb {
//碰撞圖片的坐標 左上角
private int x;
private int y;
//碰撞圖片的寬高
private int width;
private int heigth;
//碰撞圖片
private ImageIcon bombImageIcon = new ImageIcon("img/bomb.png");
//私有屬性 爆炸圖片x坐標的get方法
public int getX() {
return x;
}
//私有屬性 爆炸圖片x坐標的set方法
public void setX(int x) {
this.x = x;
}
//私有屬性 爆炸圖片y坐標的get方法
public int getY() {
return y;
}
//私有屬性 爆炸圖片y坐標的set方法
public void setY(int y) {
this.y = y;
}
//私有屬性 爆炸圖片寬度的get方法
public int getWidth() {
return width;
}
//私有屬性 爆炸圖片寬度的set方法
public void setWidth(int width) {
this.width = width;
}
//私有屬性 爆炸圖片高度的get方法
public int getHeigth() {
return heigth;
}
//私有屬性 爆炸圖片高度的set方法
public void setHeigth(int heigth) {
this.heigth = heigth;
}
}
- 定義構造方法,使得創建物件時能夠初始化爆炸圖片的位置,
//構造方法 初始化爆炸圖片 爆炸圖片顯示再敵機位置 視覺效果為敵機被子彈擊中敵機爆炸 通過創建物件時將敵機位置傳入
public Bomb(int x,int y) {
this.x=x;
this.y=y;
this.width=bombImageIcon.getIconWidth();
this.heigth=bombImageIcon.getIconHeight();
}
<4>當發生碰撞時展示爆炸圖片,
- 創建一個保存爆炸圖片的陣列,
//存盤敵機的陣列
List<Enemy> enemys = new ArrayList<Enemy>();
//創建子彈的陣列
List<Bullet> bullets = new ArrayList<Bullet>();
//創建保存碰撞圖片的陣列
List<Bomb> bombs = new ArrayList<Bomb>();
- 發生爆炸時創建爆炸圖片物件,將爆炸圖片物件添加到爆炸圖片陣列中,
if(isHit(enemy,bullet)) {
//如果擊中 則敵機消失 將敵機洗掉移除敵機串列
enemys.remove(enemy);
//再新加入一個敵機 否則如果所有敵機打完全部刪光 沒有敵機了
enemys.add(new Enemy());
//洗掉該子彈
bullets.remove(bullet);
//添加新的子彈進去
bullets.add(new Bullet(heroX+(heroImage.getIconWidth()/2)-2,heroY-15));
//創建一個爆炸圖片的物件 爆炸圖片的位置就是被擊中敵機的位置
Bomb bomb = new Bomb(enemy.getX(),enemy.getY());
//添加到爆炸圖片集合中
bombs.add(bomb);
}
- 在Bomb類中定義展示爆炸圖片的方法,
//繪制爆炸圖片方法
public void drawImage(Graphics g) {
g.drawImage(bombImageIcon.getImage(), x, y, null);
}
- 在paint()方法中繪制全部爆炸圖片,
//繪制全部子彈
for(int i=0;i<bullets.size();i++) {
Bullet bullet = bullets.get(i);
bullet.drawImage(g);
}
//繪制全部爆炸圖片
for(int i=0;i<bombs.size();i++) {
Bomb bomb = bombs.get(i);
bomb.drawImage(g);
}
展示效果如下:

<5>使爆炸圖片展示一段時間后消失,
在上一個效果中我們發現爆炸圖片展示后一直停留在界面中并沒有消失,這樣以來整個螢屏都會被爆炸圖片占滿,因此我們在展示完爆炸圖片后要使其消失,
- 洗掉爆炸圖片,我們的爆炸圖片都需要洗掉,在init中添加代碼:
// //洗掉爆炸圖片 否則爆炸圖片一直停留在界面上
for(int i=0;i<bombs.size();i++) {
Bomb bomb = bombs.get(i);
bombs.remove(bomb);
}
得到效果圖如下:

- 在上述效果中我們發現原本顯示的爆炸圖片消失了,這是因為爆炸圖片一畫出來就被洗掉了,速度太快肉眼無法捕捉,因此我們利用count計數,使爆炸效果展示一段時間后再消失,
在Bomb類中增加count屬性,同時定義其get和set方法
//洗掉的次數
private int count;
...
...
//私有屬性 爆炸圖片次數的get方法
public int getCount() {
return count;
}
//私有屬性 爆炸圖片次數的set方法
public void setCount(int count) {
this.count = count;
}
在Bomb類中定義move方法,對count進行增加,
//多次呼叫move方法爆炸圖片并不移動 只拖延時間 count達到一定次數之后再洗掉爆炸圖片
public void move() {
count++;
}
多次呼叫move方法 當同一個爆炸圖片物件的count次數超過8之后才洗掉該爆炸圖片,
//洗掉爆炸圖片 否則爆炸圖片一直停留在界面上
for(int i=0;i<bombs.size();i++) {
Bomb bomb = bombs.get(i);
bomb.move();
//多次呼叫move方法 當同一個爆炸圖片物件的 count次數超過8之后才洗掉該爆炸圖片 這樣不會使爆炸圖片轉瞬即逝 視覺無法捕捉
if(bomb.getCount()>8) {
bombs.remove(bomb);
}
}
得到的效果如下:

6,分數的展示
<1>在GamePanel類中定義一個socre屬性,每碰撞一次score+10.
//英雄機左上角坐標 初始位置 之后根據滑鼠拖拽改變位置
int heroX=300;
int heroY=400;
int score=0;//記錄分數 當子彈擊中敵機則+10分
//判斷是否擊中
if(isHit(enemy,bullet)) {
//擊中 +10分
score=score+10;
//如果擊中 則敵機消失 將敵機洗掉移除敵機串列
enemys.remove(enemy);
//再新加入一個敵機 否則如果所有敵機打完全部刪光 沒有敵機了
enemys.add(new Enemy());
//洗掉該子彈
bullets.remove(bullet);
//添加新的子彈進去
bullets.add(new Bullet(heroX+(heroImage.getIconWidth()/2)-2,heroY-15));
//創建一個爆炸圖片的物件 爆炸圖片的位置就是被擊中敵機的位置
Bomb bomb = new Bomb(enemy.getX(),enemy.getY());
//添加到爆炸圖片集合中
bombs.add(bomb);
}
<2>在paint()函式中顯示分數,
//視窗物件自動呼叫 不需手動呼叫 繪制圖片
public void paint(Graphics g) {
super.paint(g);
//設定字體
g.setFont(new Font("",Font.BOLD,30));//字體、字體樣式、字體大小
//在表單上展示一個字串 即得分情況
g.drawString("當前得分:"+score, 10, 30);
//繪制英雄機
g.drawImage(heroImage.getImage(), heroX, heroY,null);
...
...
}
得到效果圖如下:

7,背景圖片
<1>得到背景圖片
//英雄機圖片 圖片路徑
ImageIcon heroImage = new ImageIcon("img/hero.png");
//背景圖片
ImageIcon bgImage = new ImageIcon("img/background.png");
<2>在paint()方法中繪制背景圖片
//視窗物件自動呼叫 不需手動呼叫 繪制圖片
public void paint(Graphics g) {
super.paint(g);
//展示背景圖片 注意與字體的順序 若在字體后可能會掩蓋字體
g.drawImage(bgImage.getImage(), 0, 0, null);
//設定字體
g.setFont(new Font("",Font.BOLD,30));//字體、字體樣式、字體大小
//設定字體顏色
g.setColor(Color.WHITE);
//在表單上展示一個字串 即得分情況
g.drawString("當前得分:"+score, 10, 30);
//繪制英雄機
g.drawImage(heroImage.getImage(), heroX, heroY,null);
}
基于以上我們就能得到博文開始的游戲效果啦!
完整代碼如下:
百度網盤鏈接
提取碼:0z7h
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/266008.html
標籤:其他
