Java學習二(飛機大戰項目)day07
阿新 • • 發佈:2018-03-27
strac pos rgs sched time ets 步驟 oca style
day07 功能實現的步驟: 1.先寫行為: 1)若是某個對象特有的行為,則將設計在派生類中 若是所有對象共有的行為,則將設計在超類中 1.1)所有派生類行為都一樣,設計為普通方法 1.2)所有派生類行為都不一樣,設計為抽象方法,而後派生類重寫 2.窗口調用: 1)定時觸發的,在run()中調用 2)事件觸發的,在監聽器中調用 3)畫出來的,在paint()中調用 項目功能: 1.敵人入場 ---------- 定時發生 1)創建敵人對象 敵人對象 --------------- 是由窗口創建出來的 ---創建敵人對象的行為 ----設計在窗口類World中設計nextOne() /** 成員方法:生成敵人(小敵機、大敵機、小蜜蜂)對象 */ public FlyingObject nextOne() { Random rand = new Random(); //隨機數對象 int type = rand.nextInt(20); //0~19之間的數 if (type < 8) { //0~7返回小敵機 return new Airplane(); } else if(type < 16){ //8~15返回小敵機 return new BigAirplane(); } else { //16~19返回小敵機 return new Bee(); } } 2)將對象添加到enemies數組中 敵人入場為定時發生的,在run()中調用enterAction()實現敵人入場,
在enterAction()中,每400毫秒調用nextOne()方法獲取敵人,enemies數組擴容,裝在最後一個元素上。 /** 成員方法:敵人(小敵機、大敵機、小蜜蜂)入場 */ 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[enemies.length-1] = obj; } }
2.子彈入場 ---------- 定時發生 1)創建子彈對象 子彈對象 --------------- 是由英雄機發射出來的 ---創建子彈對象的行為 ----設計在英雄機類Hero中 /** 成員方法:英雄機發射子彈(創建子彈對象) */ 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; } }
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 step() {}
/** 成員方法:英雄機隨鼠標移動 */
void moveTo(int x,int y) { }
/** 成員方法:獲取圖片 */
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;
}
}
}
2)將對象添加到bullets數組中
子彈入場為定時發生的,在run()中調用shootAction()實現敵人入場,
在shootAction()中,每300毫秒調用shoot()方法獲取子彈,bullets數組擴容,數組追加。
/** 成員方法:子彈入場,英雄機發射子彈 */
int shootIndex = 0; //子彈入場計數
public void shootAction() { //每10個毫秒走一次
shootIndex++; //每10毫秒增1
if(shootIndex%30 == 0) { //每300(10*30)毫秒走一次
//獲取英雄機發射出來的子彈對象
Bullet[] bs = hero.shoot();
//擴容(bs有幾個元素就擴大幾個)
bullets = Arrays.copyOf(bullets,bullets.length+bs.length);
//數組的追加
System.arraycopy(bs, 0, bullets,bullets.length - bs.length, bs.length);
}
}
3.飛行物移動 ---------- 定時發生
1)移動是所有對象所共有的行為,並且每個對象移動的行為都是不一樣的,
所以在超類FlyingObject中設計了抽象方法step(),
/** 抽象方法:飛行物移動 */
public abstract void step();
派生類重寫step()方法
/** 成員方法:英雄機移動 */
public void step() {}
/** 成員方法:小敵機移動 */
/** 成員方法:大敵機移動 */
public void step() {
y += speed; //y+(向下)
}
import java.awt.image.BufferedImage;
/**
* 小敵機
* @author soft01
*/
public class Airplane extends FlyingObject{
/** 靜態變量:小敵機圖片*/
private static BufferedImage[] images;
static {
images = new BufferedImage[5];
for (int i = 0; i < images.length; i++) {
images[i] = loadImage("airplane" + i + ".png");
}
}
/** 成員變量:移動速度 */
private int speed; //移動速度
/** 構造方法 */
public Airplane() {
super(49,36);
speed = 2;
}
/** 成員方法:小敵機移動 */
public void step() {
y += speed; //y+(向下)
}
/** 成員方法:獲取圖片 */
int index = 1; //輪換圖片的起始位置
@Override
public BufferedImage getImage() { //每10個毫秒輪換一次
if(isLife()) { //若活著的
return images[0]; //返回第一張圖
} else if(isDead()) { //若死了的
BufferedImage img = images[index++]; //從第2張圖片到最後一張圖片輪換
if (index == images.length) { //如果是最後一張圖片時
state = REMOVE; //狀態改為刪除
}
return img; //返回對應下標的圖片
}
return null; //死了的和刪除的,都返回null
}
}
/**
* 大敵機
* @author soft01
*/
public class BigAirplane extends FlyingObject{
/** 靜態變量:大敵機圖片*/
private static BufferedImage[] images;
static {
images = new BufferedImage[2];
for (int i = 0; i < images.length; i++) {
images[i] = loadImage("bigplane" + i + ".png");
}
}
/** 成員變量:移動速度 */
private int speed; //移動速度
/** 構造方法 */
public BigAirplane() {
super(69,99);
speed = 2;
}
/** 成員方法:大敵機移動 */
@Override
public void step() {
y += speed; //y+(向下)
}
/** 成員方法:獲取圖片 */
int index = 1; //輪換圖片的起始位置
@Override
public BufferedImage getImage() { //每10個毫秒輪換一次
if(isLife()) { //若活著的
return images[0]; //返回第一張圖
} else if(isDead()) { //若死了的
BufferedImage img = images[index++]; //從第2張圖片到最後一張圖片輪換
if (index == images.length) { //如果是最後一張圖片時
state = REMOVE; //狀態改為刪除
}
return img; //返回對應下標的圖片
}
return null; //死了的和刪除的,都返回null
}
}
/** 成員方法:子彈移動 */
@Override
public void step() {
y -= speed; //y-(向上)
}
import java.awt.image.BufferedImage;
/**
* 子彈
* @author soft01
*/
public class Bullet extends FlyingObject{
/** 靜態變量:子彈圖片*/
private static BufferedImage image;
static {
image = loadImage("bullet.png");
}
/** 成員變量:移動速度 */
private int speed; //移動速度
/** 構造方法 */
public Bullet(int x,int y) {
super(8,14,x,y);
speed = 3;
}
/** 成員方法:子彈移動 */
@Override
public void step() {
y -= speed; //y-(向上)
}
/** 成員方法:獲取圖片 */
@Override
public BufferedImage getImage() {
if(isLife()) { //若活著的
return image; //返回image
} else if(isDead()) { //若死了的
state= REMOVE; //狀態改為刪除
}
return null; //死了的和刪除的,都返回null
}
}
/** 成員方法:小蜜蜂移動 */
@Override
public void step() {
x += xSpeed;
y += ySpeed;
if(x <= 0 || x >= World.WIDTH-this.width) {
xSpeed *= -1;
}
}
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* 小蜜蜂
* @author soft01
*/
public class Bee extends FlyingObject{
/** 靜態變量:小蜜蜂圖片*/
private static BufferedImage[] images;
static {
images = new BufferedImage[2];
for (int i = 0; i < images.length; i++) {
images[i] = loadImage("bee" + i + ".png");
}
}
/** 成員變量:移動速度 */
private int xSpeed; //x坐標移動速度
private int ySpeed; //y坐標移動速度
private int awardType; //獎勵類型
/** 構造方法 */
public Bee() {
super(60,50);
xSpeed = 1;
ySpeed = 2;
Random rand = new Random();
awardType = rand.nextInt(2); //0~1之間的隨機數
}
/** 成員方法:小蜜蜂移動 */
@Override
public void step() {
x += xSpeed;
y += ySpeed;
if(x <= 0 || x >= World.WIDTH-this.width) {
xSpeed *= -1;
}
}
/** 成員方法:獲取圖片 */
int index = 1; //輪換圖片的起始位置
@Override
public BufferedImage getImage() { //每10個毫秒輪換一次
if(isLife()) { //若活著的
return images[0]; //返回第一張圖
} else if(isDead()) { //若死了的
BufferedImage img = images[index++]; //從第2張圖片到最後一張圖片輪換
if (index == images.length) { //如果是最後一張圖片時
state = REMOVE; //狀態改為刪除
}
return img; //返回對應下標的圖片
}
return null; //死了的和刪除的,都返回null
}
}
/** 成員方法:天空移動 */
public void step() {
y +=speed; //y+(向下)
y1+=speed; //y1+(向下)
if(y>=World.HEIGHT){ //若y>=窗口的高
y = -World.HEIGHT; //則修改y的值為負的窗口的高
}
if(y1>=World.HEIGHT){ //若y1>=窗口的高
y1 = -World.HEIGHT; //則修改y1的值為負的窗口的高
}
}
import java.awt.Graphics;
import java.awt.image.BufferedImage;
/**
* 天空
* @author soft01
*/
public class Sky extends FlyingObject{
/** 靜態變量:天空圖片 */
private static BufferedImage image;
static {
image = loadImage("background.png");
}
/** 成員變量:移動速度 */
private int y1; //第二張圖片的y坐標
private int speed; //移動速度
/** 構造方法 */
public Sky(){
super(World.WIDTH,World.HEIGHT,0,0);
y1 = -height;
speed = 1;
}
/** 成員方法:天空移動 */
public void step() {
y +=speed; //y+(向下)
y1+=speed; //y1+(向下)
if(y>=World.HEIGHT){ //若y>=窗口的高
y = -World.HEIGHT; //則修改y的值為負的窗口的高
}
if(y1>=World.HEIGHT){ //若y1>=窗口的高
y1 = -World.HEIGHT; //則修改y1的值為負的窗口的高
}
}
/** 成員方法:獲取圖片 */
public BufferedImage getImage() {
return image;
}
/** 成員方法:畫對象的 g:畫筆 */
public void paintObject(Graphics g) {
g.drawImage(getImage(),x,y,null);
g.drawImage(getImage(),x,y1,null);
}
}
2)飛行物移動為定時發生的,在run()中調用stepAction()實現飛行物移動,
在stepAction()中,天空動,遍歷敵人而後敵人動,遍歷子彈而後子彈動
/** 成員方法:飛行物入場 */
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 action() {
Timer timer = new Timer(); //創建定時器對象
int interval = 10; //定時間隔(以毫秒為單位)
timer.schedule(new TimerTask() {
@Override
public void run() {//定時幹的事(每10個毫秒走一次)
enterAction(); //敵人入場,子彈入場,飛行物移動
shootAction(); //子彈入場,英雄機發射子彈
stepAction(); //飛行物入場
repaint(); //重畫(重新調用paint()方法)
}
},interval,interval); //定時計劃
}
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;
/**
* 整個世界
* @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(); //飛行物入場
repaint(); //重畫(重新調用paint()方法)
}
},interval,interval); //定時計劃
}
/** 成員方法:生成敵人(小敵機、大敵機、小蜜蜂)對象 */
public FlyingObject nextOne() {
Random rand = new Random(); //隨機數對象
int type = rand.nextInt(20); //0~19之間的數
if (type < 8) { //0~7返回小敵機
return new Airplane();
} else if(type < 16){ //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%30 == 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(); //子彈移動
}
}
/** 成員方法: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); //畫子彈
}
}
/** 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學習二(飛機大戰項目)day07