這是飛機大戰遊戲的基礎工具類代碼及解釋,其他的也在博客中
遊戲中上層的主要類,統一放在包com.airbattle.game下
遊戲的主要邏輯在這個包裏實現
類名 | 用途 |
Drawer | 畫圖,用畫筆Graphics,在畫板上指定位置處畫出img圖像,這是靜態方法 |
Property | 關於遊戲配置的所有常量,包括:設置背景、各個角色的圖片,飛機移動速度、飛機開火速度、飛機最大生命值、遊戲幀率、遊戲的其他配置信息。這裏還有變量frame,用於記錄遊戲幀數 |
Heroplane | 英雄機,即遊戲主角 |
BulletArray | 子彈陣列類,遊戲產生的所有子彈,放在這個類中。類中是一個類似堆的數據結構,有兩個堆,一個存儲英雄機的子彈對象,一個存儲敵機的子彈對象,還有兩個指針,表示每個堆中有多少個子彈對象,指向堆頂 |
HostileArray. | 敵機陣列類,所有的敵機對象存儲在這個類中 |
PlaneController | 按鍵事件處理器,繼承了Java類庫的KeyAdapter類,用於處理鍵盤事件 |
Game | 主程序及畫圖類的繼承與實現 |
下面是源代碼,命名很清晰,有註釋
Drawer類
package com.airbattle.game;
import java.awt.Graphics;
import com.airbattle.gameproperty.Image;
import com.airbattle.gameproperty.Position;
public class Drawer {
//用畫筆Graphics,在畫板上位置pos處畫出img圖像
static public void draw(Graphics g, Image img, Position pos) {
g.drawImage(img.img, pos.y, pos.x, null);
}
}
Property類
package com.airbattle.game;
public class Property {
public static final int FRAME_RATE = 100; //幀率,FPS
public static final int SPACE = (int)(1000.0 / FRAME_RATE); //每幀之間的延遲時間,ms
public static final int HERO_FIRE_TIMESPACE = 400; //英雄開火間隔,ms
public static final int HERO_FIRE_FRAME = //英雄機開火間隔的幀數
(int)((double)HERO_FIRE_TIMESPACE / SPACE);
public static final int HERO_MOVE_SPEED = 5; //英雄移動速度
public static final int ENEMY_FIRE_TIMESPACE = 300; //敵軍開火間隔,ms
public static final int ENEMY_FIRE_FRAME = //敵軍開火間隔的幀數
(int)((double)ENEMY_FIRE_TIMESPACE / SPACE);
public static final int ENEMY_MOVE_SPEED = 1; //敵軍移動速度
public static final int ENEMY_MOVE_SPACE = 20; //敵人移動的時間間隔
public static final int ENEMY_MOVE_FRAME = //敵人移動的幀數間隔
(int)((double)ENEMY_MOVE_SPACE / SPACE);
public static final int BULLET_MOVE_SPEED = 2; //子彈移動速度
public static final int BULLET_MOVE_SPACE = 10;//子彈移動的時間間隔
public static final int BULLET_MOVE_FRAME = //敵人移動的幀數間隔
(int)((double)BULLET_MOVE_SPACE / SPACE);
public static final int ENEMY_ARRAY_COL = 20; //敵軍陣列的列數
public static final int ENEMY_ARRAY_ROW = 6; //敵軍陣列的行數
public static final String HERO_IMAGE_FILEPATH =
"D:\\workspace\\AirBattle\\src\\plane.jpg"; //英雄機圖片文件
public static final int HERO_IMAGE_WIDTH = 40;
public static final int HERO_IMAGE_HEIGHT = 40;
public static final String ENEMY_IMAGE_FILEPATH =
"D:\\workspace\\AirBattle\\src\\hostile.jpg"; //敵機圖片文件
public static final int ENEMY_IMAGE_WIDTH = 15;
public static final int ENEMY_IMAGE_HEIGHT = 15;
public static final String BACKGROUND_IMAGE_FILEPATH =
"D:\\workspace\\AirBattle\\src\\stars.jpg"; //背景圖片文件
public static final int BACKGROUND_IMAGE_WIDTH = 480;
public static final int BACKGROUND_IMAGE_HEIGHT = 640;
public static final String HEROBULLET_IMAGE_FILEPATH =
"D:\\workspace\\AirBattle\\src\\herobullet2.jpg"; //英雄機子彈圖片文件
public static final int HEROBULLET_IMAGE_WIDTH = 10;
public static final int HEROBULLET_IMAGE_HEIGHT = 20;
public static final String ENEMYBULLET_IMAGE_FILEPATH =
"D:\\workspace\\AirBattle\\src\\enemybullet.jpg"; //敵軍子彈圖片文件
public static final int ENEMYBULLET_IMAGE_WIDTH = 5;
public static final int ENEMYBULLET_IMAGE_HEIGHT = 10;
public static final int ENEMYARRAY_SPACE_X = 30; //敵軍陣列的x,y間距
public static final int ENEMYARRAY_SPACE_Y = 5;
public static final int BULLET_BUFFER_SIZE = 10000; //子彈緩衝區大小,太小會發生溢出
public static final int MAX_HERO_HEALTH = 10; //英雄機的最大生命值
public static int frame = 0; //總幀數
public Property() {
}
}
Heroplane類
package com.airbattle.game;
import com.airbattle.gameinterface.HeroplaneInterface;
import com.airbattle.gameobject.Aircraft;
import com.airbattle.gameobject.Bullet;
import com.airbattle.gameproperty.Image;
import com.airbattle.gameproperty.Position;
import com.airbattle.gameproperty.Rect;
public class Heroplane extends Aircraft implements HeroplaneInterface{
//英雄機形態,沒有實現相關功能
int form;
//有僚機時的圖像,沒有實現相關功能
Image wingmanImg;
//是否無敵,沒有實現相關功能
boolean matchless;
//攻擊力,沒有實現相關功能
int damage;
//生命值
int health;
//得分
int score;
//飛機的寬和高
public static final int width = Property.HERO_IMAGE_WIDTH;
public static final int height = Property.HERO_IMAGE_HEIGHT;
public Heroplane() {
this.form = 0;
this.matchless = false;
this.damage = 1;
this.health = Property.MAX_HERO_HEALTH;
this.score = 0;
//System.out.println("英雄機初始化完成,圖像已加載到內存");
}
//設置飛機位置,因爲鍵盤事件處理程序在圖像類中,所以需要從圖像類中更新飛機的位置信息
public void setPos(Position pos) {
this.pos = pos;
}
//開火,從英雄機當前位置生成一顆飛向敵機陣列的子彈
public Bullet fire() {
return new Bullet(1, new Position(this.pos.x, this.pos.y + Property.HERO_IMAGE_WIDTH/2));
};
//獲取飛機的外接矩形框,用於判斷飛機是否和敵人子彈的矩形框接觸
public Rect getRect() {
return new Rect(this.pos.x, this.pos.y,
height, width);
}
//被子彈打中,減生命值
public void onHit(int numHit) {
this.health -= numHit;
//System.out.println("英雄生命值已扣除");
};
//變形,未實現
public void transform() {
};
public int getHealth() {
return this.health;
};
public int getScore() {
return this.score;
};
public void moveStep() {
}
}
BulletArray類
package com.airbattle.game;
import com.airbattle.gameinterface.GameObjectInterface;
import com.airbattle.gameobject.Bullet;
import com.airbattle.gameproperty.Rect;
/**
*
* @author William
*子彈陣列類,遊戲產生的所有子彈,放在這個類中。
*類中是一個類似堆的數據結構,有兩個堆,
*一個存儲英雄機的子彈對象,一個存儲敵機的子彈對象,
*還有兩個指針,表示每個堆中有多少個子彈對象,指向堆頂
*/
public class BulletArray implements GameObjectInterface{
Bullet[] enemyBullet = new Bullet[Property.BULLET_BUFFER_SIZE];
Bullet[] heroBullet = new Bullet[Property.BULLET_BUFFER_SIZE];
public int pointerEnemy = 0;
public int pointerHero = 0;
//構造器,剛開始沒有子彈,指針全都指向null
public BulletArray() {
for (int i = 0; i < enemyBullet.length; i++) {
enemyBullet[i] = null;
}
for (int i = 0; i < heroBullet.length; i++) {
heroBullet[i] = null;
}
//System.out.println("子彈圖像已加載到內存");
//System.out.println("子彈初始化完畢");
}
//敵軍開火時,添加敵軍子彈
public void addEnemyBullet(Bullet bullet) {
enemyBullet[pointerEnemy++] = bullet;
//System.out.println("新增的子彈已經加入敵人子彈陣列 ");
}
//英雄機開火時,添加敵軍子彈
public void addHeroBullet(Bullet bullet) {
heroBullet[pointerHero++] = bullet;
//System.out.println("新增的子彈已經加入英雄子彈陣列");
}
//子彈移動
public void bulletMove() {
//System.out.println("英雄子彈移動...");
for (int i = 0; i < pointerHero; i++) {
heroBullet[i].moveStep(-Property.BULLET_MOVE_SPEED);
}
//System.out.println("敵人子彈移動...");
for (int i = 0; i < pointerEnemy; i++) {
enemyBullet[i].moveStep(Property.BULLET_MOVE_SPEED);
}
}
//刪除已經出界的子彈,清理內存空間
public void deleteInvalidBullet() {
for (int i = 0; i < pointerHero; i++) {
if (heroBullet[i].pos.x < 0 || heroBullet[i].pos.x > 640) {
deleteHeroBullet(i);
}
}
for (int i = 0; i < pointerEnemy; i++) {
if (enemyBullet[i].pos.x < 0 || enemyBullet[i].pos.x > 640) {
deleteEnemyBullet(i);
//System.out.println("Actually deleted!");
}
}
//System.out.println("無效子彈已刪除");
}
//刪除堆中特定的子彈
public void deleteHeroBullet(int i) {
heroBullet[i] = null;
for (int j = i; j < pointerHero-1; j++) {
heroBullet[j] = heroBullet[j+1];
heroBullet[j+1] = null;
}
pointerHero--;
}
public void deleteEnemyBullet(int i) {
enemyBullet[i] = null;
for (int j = i; j < pointerEnemy-1; j++) {
enemyBullet[j] = enemyBullet[j+1];
enemyBullet[j+1] = null;
}
pointerEnemy--;
}
public void moveStep() {
}
//根據給定的英雄機的外界矩形,判斷有幾個敵軍子彈打到了英雄機
//打到之後進行計數,然後將敵軍子彈刪除
public int heroInRange(Rect rect) {
int hitCnt = 0;
for (int i = 0; i < pointerEnemy; i++) {
Rect bulletRect = new Rect(enemyBullet[i].pos.x,
enemyBullet[i].pos.y,
Property.ENEMYBULLET_IMAGE_HEIGHT,
Property.ENEMYBULLET_IMAGE_WIDTH);
if (rect.hit(bulletRect) == true) {
hitCnt++;
deleteEnemyBullet(i);
}
}
return hitCnt;
}
//根據給定的敵機的外界矩形,判斷有幾個英雄機子彈打到了英雄機
//打到之後返回非0值,並將英雄機子彈刪除
public int enemyInRange(Rect rect) {
int hitCnt = 0;
for (int i = 0; i < pointerHero; i++) {
Rect bulletRect = new Rect(heroBullet[i].pos.x,
heroBullet[i].pos.y,
Property.HEROBULLET_IMAGE_HEIGHT,
Property.HEROBULLET_IMAGE_WIDTH);
if (rect.hit(bulletRect) == true) {
hitCnt++;
deleteHeroBullet(i);
}
}
return hitCnt;
}
}
HostileArray類
package com.airbattle.game;
import java.util.Random;
import com.airbattle.gameinterface.GameObjectInterface;
import com.airbattle.gameobject.Bullet;
import com.airbattle.gameobject.HostilePlane;
import com.airbattle.gameproperty.Image;
import com.airbattle.gameproperty.Position;
/**
*
* @author William
* 敵軍陣列類
* 陣列大小在配置文件中指定
* 陣列的樣式在主函數中傳入一個和陣列相同形狀的矩陣
* 非0值代表該位置有敵機,0代表沒有敵機
*/
public class HostileArray implements GameObjectInterface{
//敵機陣列數組
HostilePlane[][] planes = new HostilePlane[Property.ENEMY_ARRAY_ROW][Property.ENEMY_ARRAY_COL];
//陣列的位置(左上角座標)
Position pos = new Position(0, 0);
//移動速度(負代表向左,正代表向右)
public int moveDir = Property.ENEMY_MOVE_SPEED;
public HostileArray(short[][] array) {
int cnt = 0;
for (int i = 0; i < planes.length; i++)
for (int j = 0; j < planes[i].length; j++) {
if (array[i][j] != 0) {
planes[i][j] = new HostilePlane(
new Position(i*Property.ENEMYARRAY_SPACE_X, 20)
);
cnt++;
}
else
planes[i][j] = null;
}
//System.out.println("敵機圖像已加載到內存");
//System.out.println("敵機陣列初始化完畢,共初始化 " + cnt +" 臺敵機");
}
//實例化敵軍陣列對象,
//按照arrayDefine數組提供的規則初始化敵軍陣列
public Bullet randomFire() {
Random rand = new Random();
int firingMark = -1;
int col = -1, row = -1;
while (firingMark == -1) {
int random_fire = rand.nextInt(Property.ENEMY_ARRAY_ROW * Property.ENEMY_ARRAY_COL);
row = random_fire/Property.ENEMY_ARRAY_COL;
col = random_fire%Property.ENEMY_ARRAY_COL;
if (planes[row][col] != null)
firingMark = random_fire;
}
return new Bullet(1, new Position(row, planes[row][col].pos.y));
}
//判斷陣列是否碰到了窗體邊界,如果碰到了返回true
private boolean isCollide() {
if (this.pos.y + this.moveDir <= 0 ||
this.pos.y + this.moveDir +
Property.ENEMY_ARRAY_COL*Property.ENEMY_IMAGE_WIDTH
+ Property.ENEMYARRAY_SPACE_Y * (Property.ENEMY_ARRAY_COL + 1)
>= Property.BACKGROUND_IMAGE_WIDTH
)
return true;
return false;
}
//移動到下一個位置
//先判斷敵軍陣列下次移動會不會移出窗體,如果能,向相反方向運動
public void nextPos() {
if (this.isCollide())
moveDir *= -1;
this.pos.y += moveDir;
//System.out.println("敵軍陣列移動完成,當前位置:"+ pos.x + ", " + pos.y + ")");
}
public void moveStep() {
}
//因爲更新敵軍位置時都是更新陣列左上角的座標
//想要獲取每個敵機的具體位置時,需要進行計算
public void refreshPos() {
for (int i=0; i<Property.ENEMY_ARRAY_ROW; i++)
for (int j=0; j<Property.ENEMY_ARRAY_COL; j++)
if (planes[i][j] != null) {
Position pos = planes[i][j].pos;
pos.y = this.pos.y + j*(Property.ENEMY_IMAGE_WIDTH + Property.ENEMYARRAY_SPACE_Y);
}
}
}
PlaneController類
package com.airbattle.game;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class PlaneController extends KeyAdapter{
public MyJPanel jpanel;
public PlaneController(MyJPanel jpanel) {
this.jpanel = jpanel;
}
//重寫這個函數,定義按下左鍵、右鍵時英雄機移動
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
//System.out.println("按鍵按下,鍵值:" + code);
switch(code) {
case 37:
if (jpanel.heroPos.y > 0)
jpanel.heroPos.y-=Property.HERO_MOVE_SPEED;
break;
case 39:
if (jpanel.heroPos.y + Property.HERO_MOVE_SPEED + Property.HERO_IMAGE_WIDTH
< Property.BACKGROUND_IMAGE_WIDTH)
jpanel.heroPos.y+=5;
else jpanel.heroPos.y = Property.BACKGROUND_IMAGE_WIDTH - Property.HERO_IMAGE_WIDTH;
break;
}
}
}
Game類
package com.airbattle.game;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Scanner;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import com.airbattle.gameobject.Bullet;
import com.airbattle.gameproperty.Image;
import com.airbattle.gameproperty.Position;
import com.airbattle.gameproperty.Rect;
import com.airbattle.game.Property;
public class Game {
static public void main(String[] argv) throws InterruptedException {
//System.out.println("遊戲開始——————————————");
//實例化英雄機對象
Heroplane hero = new Heroplane();
//定義一個數組,用於確定敵軍陣列的陣型
//數組中數字不爲0,代表該點有敵軍,在構造函數中將新建一個敵軍對象放在該位置
//如果是0,則該位置沒有敵軍,初始化爲null
short[][] arrayDefine = new short[Property.ENEMY_ARRAY_ROW][Property.ENEMY_ARRAY_COL];
//將數組全部設置爲1,如果需要設置敵軍陣型,只需要修改這個數組
for (int i=0; i<Property.ENEMY_ARRAY_ROW; i++)
for (int j=0; j<Property.ENEMY_ARRAY_COL; j++) {
arrayDefine[i][j] = 1;
}
//實例化敵軍陣列對象,其中包含一個敵機數組,按照arrayDefine數組提供的規則初始化敵軍陣列
HostileArray hostile = new HostileArray(
arrayDefine);
//System.out.println("-------------- 敵機陣列初始化 --------------");
//實例化子彈陣列對象,其中是一個類似堆的數據結構
//有兩個堆,一個存儲英雄機的子彈對象,一個存儲敵機的子彈對象
//還有兩個指針,表示每個堆中有多少個子彈對象
BulletArray bullet = new BulletArray();
//System.out.println("-------------- 子彈陣列初始化 --------------");
//定義窗口對象
JFrame jFrame = new JFrame();
//定義畫板對象,在該對象的paint函數中實現繪圖
MyJPanel jpanel = new MyJPanel(hostile, bullet);
//設置窗口標題
jFrame.setTitle("飛機大戰-WilliamCode");
//將畫板對象加入窗體中
jFrame.add(jpanel);
// 設置畫框大小(寬度,高度),默認都爲0
//這裏設置爲背景圖片的寬和高
jFrame.setSize(Property.BACKGROUND_IMAGE_WIDTH, Property.BACKGROUND_IMAGE_HEIGHT);
// 將畫框展示出來。true設置可見
jFrame.setVisible(true);
//向窗體加入按鍵事件監聽器
//PlaneController是一個監聽器,繼承了java類庫中的KeyAdapter
//需要重寫其中的KeyPressed方法,在其中定義按鍵按下時的操作
jFrame.addKeyListener(new PlaneController(jpanel));
//主循環開始
while(true) {
//遊戲幀數計數器,提供遊戲從開始運行一共渲染了多少幀
Property.frame ++;
//System.out.println("\n\n-------------- 遊戲幀開始 --------------");
//System.out.println("正在檢測敵軍是否被英雄子彈擊中,擊中減生命值,到0則銷燬對象");
//刷新敵機陣列的位置信息
hostile.refreshPos();
//遍歷敵軍陣列,判斷敵軍是否被子彈打中
//如果打中,將該敵機銷燬
for (int i=0; i<Property.ENEMY_ARRAY_ROW; i++)
for (int j=0; j<Property.ENEMY_ARRAY_COL; j++){
if (hostile.planes[i][j] != null) {
Rect r = hostile.planes[i][j].getRect();
//System.out.println(r.x1 + " " + r.x2 + " " + r.y1 + " " + r.y2);
int numHit = bullet.enemyInRange(hostile.planes[i][j].getRect());
if (numHit != 0) {
hostile.planes[i][j] = null;
jpanel.score++;
}
}
}
//判斷敵軍子彈是否機中英雄機,返回擊中的子彈數目
int numHit = bullet.heroInRange(hero.getRect());
//System.out.println("正在檢測英雄機是否被敵軍子彈擊中,擊中減生命值,到0則遊戲結束");
//英雄機被擊中,扣除生命值,並更新到窗體中
//System.out.println("擊中英雄機的子彈數量:" + numHit);
hero.onHit(numHit);
jpanel.health = hero.health;
//System.out.println("正在佈置敵軍開火");
//判斷是否到達幀數,到達一定幀數時,敵機開火
if (Property.frame % Property.ENEMY_FIRE_FRAME == 0) {
//任選一個敵機開火,返回子彈文件
Bullet newBullet = hostile.randomFire();
//將子彈加入子彈陣列中
bullet.addEnemyBullet(newBullet);
}
//判斷是否到達幀數,到達一定幀數時,敵軍移動
if (Property.frame % Property.ENEMY_MOVE_FRAME == 0) {
//System.out.println("正在更新敵軍移動");
//這裏只需要更改敵軍的左上角的x,y座標,敵機陣列作爲一個整體移動
//因爲每個敵機的具體座標在使用前,都會使用refreshPos函數進行計算
hostile.nextPos();
}
//System.out.println("正在佈置友軍開火");
//判斷是否到達幀數,到達一定幀數時,友軍開火
if (Property.frame % Property.HERO_FIRE_FRAME == 0) {
//友軍開火,返回一個子彈對象,該子彈從英雄機所在位置發出,垂直打向敵機陣列
Bullet newBullet = hero.fire();
//將子彈加入子彈陣列
bullet.addHeroBullet(newBullet);
}
//System.out.println("正在更新友軍移動");
//按鍵監聽器存儲在JPanel對象中,所以英雄機的位置信息暫存在JPanel中
//使用前需要把位置信息更新到英雄機對象
hero.setPos(jpanel.heroPos);
//System.out.println("正在佈置背景移動");
//System.out.println("背景暫時不用移動");
//判斷是否到達幀數,到達一定幀數時,進行子彈的移動和刪除
if (Property.frame % Property.BULLET_MOVE_FRAME == 0) {
//System.out.println("正在更新子彈移動");
//子彈的移動,敵軍子彈向英雄機移動,英雄機子彈向敵軍移動
bullet.bulletMove();
//System.out.println("出界子彈處理");
//處理出界的子彈,直接從子彈的堆中刪除,防止內存溢出和泄露
bullet.deleteInvalidBullet();
}
//System.out.println("遊戲幀結束,準備渲染下一幀(按Enter繼續)");
//System.out.println("+++++++++++");
//System.out.println("英雄機血量" + hero.health);
//System.out.println("敵機子彈數量" + bullet.pointerEnemy);
//System.out.println("英雄機子彈數量" + bullet.pointerHero);
//等待一定時間
Thread.sleep(Property.SPACE);
}
}
}
//繼承的JPanel對象
//在創建對象時,自動調用一次paint方法
//我們在paint方法結束時,新啓動了一個進程
//在改進程中重新啓動了畫圖,即調用了repaint方法
//repaint方法會調用一系列方法,確保畫圖時不會發生窗口閃爍等問題
//最後,repaint方法會自動調用paint方法,重新畫圖
//我們只需要修改paint方法中畫圖時用到的對象即可,畫圖會自己進行
class MyJPanel extends JPanel{
//需要顯示的英雄機生命值、得分
public int health = 0;
public int score = 0;
//因爲鍵盤事件監聽器放在對象中,所以這裏存放了英雄機的位置信息
Position heroPos = new Position((int)((Property.BACKGROUND_IMAGE_HEIGHT+0.1)*0.8), Property.BACKGROUND_IMAGE_WIDTH/2-Property.HERO_IMAGE_WIDTH/2);
//各種遊戲元素的圖片文件
static Image heroImage = new Image(Property.HERO_IMAGE_FILEPATH, Property.HERO_IMAGE_WIDTH, Property.HERO_IMAGE_HEIGHT);
static Image hostileImage = new Image(Property.ENEMY_IMAGE_FILEPATH, Property.ENEMY_IMAGE_WIDTH, Property.ENEMY_IMAGE_HEIGHT);
static Image backgroundImage = new Image(Property.BACKGROUND_IMAGE_FILEPATH, Property.BACKGROUND_IMAGE_WIDTH, Property.BACKGROUND_IMAGE_HEIGHT);
static Image enemyBulletImage = new Image(Property.ENEMYBULLET_IMAGE_FILEPATH, Property.ENEMYBULLET_IMAGE_WIDTH, Property.ENEMYBULLET_IMAGE_HEIGHT);
static Image heroBulletImage = new Image(Property.HEROBULLET_IMAGE_FILEPATH, Property.HEROBULLET_IMAGE_WIDTH, Property.HEROBULLET_IMAGE_HEIGHT);
//定義敵軍陣列、子彈陣列的引用,和主函數中引用同一對象
HostileArray hostile;
BulletArray bullet;
//構造函數,將上述兩個引用在構造對象時賦值
public MyJPanel(HostileArray hostile, BulletArray bullet) {
super();
this.hostile = hostile;
this.bullet = bullet;
}
//畫圖函數,這是JPanel對象規定的方法,每次在畫圖時,這個函數將會被調用
public void paint(Graphics graphics) {
// 必須先調用父類的paint方法
super.paint(graphics);
//畫背景圖片
//Drawer是自己實現的一個類
//使用畫筆graphics在畫板上畫圖,draw是靜態方法
Drawer.draw(graphics, backgroundImage, new Position(0,0));
//畫英雄機
Drawer.draw(graphics, heroImage, heroPos);
//遍歷敵軍子彈陣列,畫子彈
for (int i=0; i<bullet.pointerEnemy; i++) {
Drawer.draw(graphics, enemyBulletImage, bullet.enemyBullet[i].pos);
}
//遍歷友軍子彈陣列,畫子彈
for (int i=0; i<bullet.pointerHero; i++) {
Drawer.draw(graphics, heroBulletImage, bullet.heroBullet[i].pos);
}
//更新敵軍陣列的所有敵機的位置信息
hostile.refreshPos();
//遍歷敵軍陣列,畫敵軍
for (int i=0; i<Property.ENEMY_ARRAY_ROW; i++)
for (int j=0; j<Property.ENEMY_ARRAY_COL; j++) {
if(hostile.planes[i][j] != null) {
Drawer.draw(graphics, hostileImage, hostile.planes[i][j].pos);
}
}
//java.awt.Image image = new ImageIcon(file).getImage();
// 用畫筆Graphics,在畫板JPanel上畫一個小人
//graphics.drawImage(heroImage.img,x++,y++,this);// 頭部(畫圓形)
//顯示生命值和得分
graphics.setFont(new Font("微軟雅黑", Font.BOLD, 20));
graphics.setColor(Color.white);
graphics.drawString("HP:" + health, 10, Property.BACKGROUND_IMAGE_HEIGHT-50);
graphics.drawString("Score:" + score, 10, Property.BACKGROUND_IMAGE_HEIGHT-70);
new updateClass().start();
}
//這個進程用於重畫圖像
//這個內部類在paint方法調用完成時進行了run方法的調用
class updateClass extends Thread{
public void run() {
repaint();
}
}
}