Java學習二(飛機大戰項目)day09
阿新 • • 發佈:2018-03-29
h+ remove color 匿名 ktr day graphic score ride
day09 1.子彈與敵人的碰撞 1)在超類中FlyingObject設計hit()實現敵人與子彈/英雄機得碰撞 /** 成員方法:檢測敵人與子彈/英雄機的碰撞 * this:敵人 other:子彈 */ public boolean hit(FlyingObject other) { int x1 = this.x - other.width; int x2 = this.x + this.width; int y1 = this.y - other.height; int y2 = this.y + this.height; int x = other.x; int y = other.y; return x>=x1 && x<=x2 && y>=y1 && y<=y2; } 在超類中FlyingObject設計goDead()實現飛行物去死的 /** 成員方法:飛行物去死 */ public void goDead() { state = DEAD; //將當前狀態修改為DEAD }
import java.util.Random;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.awt.Graphics;
/**
* 飛行物--超類
* @author soft01
*/
public abstract class FlyingObject {
/** 常量: 三種狀態(活著的、死了的、刪除的) */
public static final int LIFE = 0;
public static final int DEAD = 1;
public static final int REMOVE = 2;
/** 成員變量:當前狀態(默認為活著的) */
protected int state = LIFE;
/** 成員變量:寬、高、x軸、y軸 */
protected int width;
protected int height;
protected int x;
protected int y;
/** 構造方法:專門給英雄機、天空、子彈用 */
public FlyingObject(int width,int height,int x,int y) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;
}
/** 構造方法:專門給小敵機、大敵機、小蜜蜂用 */
public FlyingObject(int width,int height) {
this.width = width;
this.height = height;
Random rand = new Random();
x = rand.nextInt(World.WIDTH-width);
y = -height;
}
/** 抽象方法:飛行物移動 */
public abstract void step();
/** 抽象方法:獲取圖片 */
public abstract BufferedImage getImage();
/** 抽象方法:檢查飛行物是否越界 */
public abstract boolean outOfBounds();
/** 靜態方法:讀取圖片 */
public static BufferedImage loadImage(String fileName) {
try {
BufferedImage img = ImageIO.read(FlyingObject.class.getResource(fileName)); //同包中讀圖片
return img;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
/** 成員方法:判斷狀態(活著的、死了的、刪除的) */
public boolean isLife() {
return state == LIFE;
}
public boolean isDead() {
return state == DEAD;
}
public boolean isRemove() {
return state == REMOVE;
}
/** 成員方法:畫對象的 g:畫筆 */
public void paintObject(Graphics g) {
g.drawImage(getImage(),x,y,null);
}
/** 成員方法:檢測敵人與子彈/英雄機的碰撞
* this:敵人 other:子彈 */
public boolean hit(FlyingObject other) {
int x1 = this.x - other.width; //敵人的x - 子彈/英雄機的寬
int x2 = this.x + this.width; //敵人的x + 敵人的寬
int y1 = this.y - other.height; //敵人的y - 子彈/英雄機的高
int y2 = this.y + this.height; //敵人的y + 敵人的高
int x = other.x; //子彈/英雄機的x
int y = other.y; //子彈/英雄機的y
return x>=x1 && x<=x2 && y>=y1 && y<=y2; //x在x1和x2之間,y在y1和y2之間
}
/** 成員方法:飛行物去死 */
public void goDead() {
state = DEAD; //將當前狀態修改為DEAD
}
}
在Hero類中設計addLife()增命、addDoubleFire()增火力
/** 成員方法:命數增加 */
public void addLife() {
life++; //命數增1
}
/** 成員方法:火力值增加 */
public void addDoubleFire() {
doubleFire += 40; //火力值增40
}
import java.awt.image.BufferedImage;
/**
* 英雄機
* @author soft01
*/
public class Hero extends FlyingObject{
/** 靜態變量:英雄機圖片 */
private static BufferedImage[] images;
static {
images = new BufferedImage[2];
for (int i = 0; i < images.length; i++) {
images[i] = loadImage("hero" + i + ".png");
}
}
/** 成員變量:生命、火力值 */
private int life; //生命
private int doubleFire; //火力值
/** 構造方法 */
public Hero(){
super(97,124,140,400);
life = 3;
doubleFire = 0;
}
/** 成員方法:命數增加 */
public void addLife() {
life++; //命數增1
}
/** 成員方法:獲取命數 */
public int getLife() {
return life; //返回命
}
/** 成員方法:火力值增加 */
public void addDoubleFire() {
doubleFire += 40; //火力值增40
}
/** 成員方法:英雄機移動 */
public void step() {}
/** 成員方法:英雄機隨鼠標移動x,y */
public void moveTo(int x,int y) {
this.x = x - this.width/2; //英雄機的x=鼠標的x-1/2英雄機的寬
this.y = y - this.height/2; //英雄機的y=鼠標的y-1/2英雄機的高
}
/** 成員方法:獲取圖片 */
int index = 0;
@Override
public BufferedImage getImage() {
if(isLife()) {
return images[index++%2]; //(index++%2)余數為0或1
}
return null;
}
/** 成員方法:英雄機發射子彈(創建子彈對象) */
public Bullet[] shoot() {
int xStep = this.width/4; //xStep:1/4英雄機的寬
int yStep = 20; //yStep:固定的20
if (doubleFire > 0) { //雙
Bullet[] bs = new Bullet[2]; //2發子彈
//英雄機的x坐標加1/4英雄機的寬
bs[0] = new Bullet(this.x + 1 * xStep,y-yStep);
//英雄機的x坐標加3/4英雄機的寬
bs[1] = new Bullet(this.x + 3 * xStep, y-yStep);
doubleFire -= 2; //發射一次雙倍火力,火力值減2
return bs;
} else { //單
Bullet[] bs = new Bullet[1]; //1發子彈
//英雄機的x坐標加2/4英雄機的寬
bs[0] = new Bullet(this.x + 2 * xStep, y-yStep);
return bs;
}
}
/** 成員方法:英雄機永不越界 */
@Override
public boolean outOfBounds() {
return false;
}
}
2)子彈與敵人的碰撞為定時發生的,所以在run()中調用BulletBangAction()方法
在BulletBangAction()中:
遍歷所有子彈,獲取每一個子彈,遍歷所有敵人,獲取每個敵人
判斷是否撞上了,若撞上了:
1)子彈去死,敵人去死
2)小敵機和大敵機 ----------得分
小蜜蜂 ----------------英雄機得命或雙倍火力
/** 成員方法:子彈與敵人的碰撞 */
int score = 0;
public void bulletBangAction() { //每10個毫秒走一次
//遍歷子彈數組
for (int i = 0; i < bullets.length; i++) {
Bullet b = bullets[i];//得到每一個子彈
//遍歷敵人數組
for (int j = 0; j < enemies.length; j++) {
FlyingObject f = enemies[j]; //得到每一個敵人
//如果活著的子彈和活著的敵人撞上了
if(b.isLife() && f.isLife() && f.hit(b)) {
b.goDead(); //子彈去死
f.goDead(); //敵人去死
if (f instanceof Enemy) {//若被撞對象是敵人
Enemy e = (Enemy)f;//強轉為得分接口
score += e.getScore();//玩家得分
}
if (f instanceof Award) {//若被撞對象是獎勵
Award a = (Award)f;// 強轉為獎勵接口
int type = a.getType();//獲取獎勵類型 //基於不同的類型來得到不同的獎勵
switch (type) {
//若獎勵為火力值
case Award.DOUBLE_FIRE:
hero.addDoubleFire(); //則增加火力值
break;
case Award.LIFE: //若獎勵為命
hero.addLife(); //則增加命
break; }
}
}
}
}
}
2.畫分和畫命
1)在Hero類中設計getLife()獲取命
/** 成員方法:獲取命數 */
public int getLife() {
return life; //返回命
}
2)在paint()方法中,畫分和畫命
g.drawString("SCORE:" + score,10,25);
g.drawString("LIFE:" + hero.getLife(), 10, 45);
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Random;
import java.util.Arrays;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;;
/**
* 整個世界
* @author soft01
*/
public class World extends JPanel{
/** 常量:窗口寬、窗口高 */
public static final int WIDTH = 400;
public static final int HEIGHT = 700;
/** 成員變量:天空、英雄機、飛行物敵人數組、子彈數組 */
private Sky sky = new Sky();
private Hero hero = new Hero();
private FlyingObject[] enemies = {};
private Bullet[] bullets = {};
/** 啟動程序的執行 */
public void action() {
Timer timer = new Timer(); //創建定時器對象
int interval = 10; //定時間隔(以毫秒為單位)
timer.schedule(new TimerTask() { //匿名內部類
@Override
public void run() { //定時幹的事(每10個毫秒走一次)
enterAction(); //敵人入場,子彈入場,飛行物移動
shootAction(); //子彈入場,英雄機發射子彈
stepAction(); //飛行物入場
outOfBoundsAction(); //刪除越界
bulletBangAction(); //子彈與敵人的碰撞
repaint(); //重畫(重新調用paint()方法)
}
},interval,interval); //定時計劃
/** 鼠標偵聽器 */
MouseAdapter l = new MouseAdapter() {
/** 重寫mouseMoved()鼠標移動 */
public void mouseMoved(MouseEvent e) {
int x = e.getX(); //獲取鼠標的x坐標
int y = e.getY(); //獲取鼠標的y坐標
hero.moveTo(x, y); //英雄機隨著鼠標移動
}
};
this.addMouseListener(l); //處理鼠標操作事件
this.addMouseMotionListener(l); //處理鼠標滑動事件
}
/** 成員方法:生成敵人(小敵機、大敵機、小蜜蜂)對象 */
public FlyingObject nextOne() {
Random rand = new Random(); //隨機數對象
int type = rand.nextInt(20); //0~19之間的數
if (type < 11) { //0~7返回小敵機
return new Airplane();
} else if(type < 17){ //8~15返回小敵機
return new BigAirplane();
} else { //16~19返回小敵機
return new Bee();
}
}
/** 成員方法:敵人(小敵機、大敵機、小蜜蜂)入場 */
int enterIndex = 0; //敵人入場計數
public void enterAction() { //每10個毫秒走一次
enterIndex++; //每10毫秒增1
if(enterIndex%40 == 0) { //每400(10*40)毫秒走一次
FlyingObject obj = nextOne();
enemies = Arrays.copyOf(enemies, enemies.length+1); //數組擴容
enemies[enemies.length-1] = obj; //將敵人對象填充到enemies數組的最後一個元素上
}
}
/** 成員方法:子彈入場,英雄機發射子彈 */
int shootIndex = 0; //子彈入場計數
public void shootAction() { //每10個毫秒走一次
shootIndex++; //每10毫秒增1
if(shootIndex%20 == 0) { //每300(10*30)毫秒走一次
Bullet[] bs = hero.shoot(); //獲取英雄機發射出來的子彈對象
bullets = Arrays.copyOf(bullets, bullets.length+bs.length); //擴容(bs有幾個元素就擴大幾個)
System.arraycopy(bs, 0, bullets, bullets.length - bs.length, bs.length); //數組的追加
}
}
/** 成員方法:飛行物入場 */
public void stepAction() {
sky.step(); //天空移動
for (int i = 0; i < enemies.length; i++) {
enemies[i].step(); //飛行物移動
}
for (int i = 0; i < bullets.length; i++) {
bullets[i].step(); //子彈移動
}
}
/** 成員方法:刪除越界 */
public void outOfBoundsAction() { //每10個毫秒走一次
int index = 0; //1)不越界敵人下標 2)不越界敵人個數
FlyingObject[] enemyLives = new FlyingObject[enemies.length]; //不越界敵人數組
for (int i = 0; i < enemies.length; i++) { //獲取敵人數組
FlyingObject f = enemies[i]; //獲取每一個敵人
if(!f.outOfBounds()) { //不越界
enemyLives[index] = f; //將不越界敵人放到不越界數組中
index++; //1)不越界敵人數組下標增一 2)不越界敵人個數增1
}
}
enemies = Arrays.copyOf(enemyLives, index); //將不越界數組中的元素復制到敵人數組之中,數組的長度為index
index = 0;
Bullet[] bulletLives = new Bullet[bullets.length];
for (int i = 0; i < bullets.length; i++) {
Bullet b = bullets[i];
if(!b.outOfBounds()) {
bulletLives[index] = b;
index++;
}
}
bullets = Arrays.copyOf(bulletLives, index);
}
/** 成員方法:子彈與敵人的碰撞 */
int score = 0;
public void bulletBangAction() { //每10個毫秒走一次
for (int i = 0; i < bullets.length; i++) { //遍歷子彈數組
Bullet b = bullets[i]; //得到每一個子彈
for (int j = 0; j < enemies.length; j++) { //遍歷敵人數組
FlyingObject f = enemies[j]; //得到每一個敵人
if(b.isLife() && f.isLife() && f.hit(b)) { //如果活著的子彈和活著的敵人撞上了
b.goDead(); //子彈去死
f.goDead(); //敵人去死
if (f instanceof Enemy) { //若被撞對象是敵人
Enemy e = (Enemy)f; //強轉為得分接口
score += e.getScore(); //玩家得分
}
if (f instanceof Award) { // 若被撞對象是獎勵
Award a = (Award)f; // 強轉為獎勵接口
int type = a.getType(); //獲取獎勵類型
switch (type) { //基於不同的類型來得到不同的獎勵
case Award.DOUBLE_FIRE: //若獎勵為火力值
hero.addDoubleFire(); //則增加火力值
break;
case Award.LIFE: //若獎勵為命
hero.addLife(); //則增加命
break;
}
}
}
}
}
}
/** 成員方法:paint()方法 */
@Override
public void paint(Graphics g) {
sky.paintObject(g); //畫天空
hero.paintObject(g); //畫英雄機
for (int i = 0; i < enemies.length; i++) { //遍歷所有敵人
enemies[i].paintObject(g); //畫敵對飛行物
}
for (int i = 0; i < bullets.length; i++) { //遍歷子彈
bullets[i].paintObject(g); //畫子彈
}
g.drawString("SCORE:" + score,10,25);
g.drawString("LIFE:" + hero.getLife(), 10, 45);
}
/** main主方法 */
public static void main(String[] args) {
JFrame frame = new JFrame(); //創建窗口
World world = new World(); //創建面板
frame.add(world); //將面板添加到窗口
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //設置關閉窗口即停止運行程序
frame.setSize(WIDTH,HEIGHT); //設置窗口大小
frame.setLocationRelativeTo(null); //設置窗口居中顯示
frame.setVisible(true); //1)設置窗口可見 2)盡快調用paint()方法
world.action(); //啟動程序
}
}
Java學習二(飛機大戰項目)day09