1. 程式人生 > >雷霆戰機小遊戲java

雷霆戰機小遊戲java

Shootgame類

package com.hyxy.shoot;

import java.awt.Color;

import java.awt.Font;

import java.awt.Graphics;

import java.awt.event.MouseAdapter;

import java.awt.event.MouseEvent;

import java.awt.image.BufferedImage;

import java.util.Arrays;

import java.util.Timer;

import java.util.TimerTask;

import javax.imageio.ImageIO;

import javax.swing.JFrame;

import javax.swing.JPanel;

/**

 * 遊戲面板型別,需要繼承Jpanel

 * @author Administrator

 *

 */

public class ShootGame extends JPanel{

    //定義兩個屬性,分別是遊戲面板的寬高

    public static final int WIDTH=400;

    public static final int HEIGHT=654;

    //面板上需要有一個英雄機屬性

    protected Hero hero=new Hero();

    protected FlyingObject[] objects={};//所有飛行物

    protected Bullet[] bullets={};//所有子彈

    protected int score;//面板上的總分

    protected int life;//面板上的命數

    protected int state;

    protected static final int startgame=0;//開始狀態

    protected static final int running=1;//執行狀態

    protected static final int pausegame=2;//暫停狀態

    protected static final int over=3;//結束狀態

    //定義所有的圖片屬性

    public static BufferedImage hero0;

    public static BufferedImage hero1;

    public static BufferedImage airplane;

    public static BufferedImage bee;

    public static BufferedImage bullet;

    public static BufferedImage background;

    public static BufferedImage start;

    public static BufferedImage pause;

    public static BufferedImage gameover;

    //使用靜態塊給圖片賦值

    static{

       try {

           hero0=ImageIO.read(ShootGame.class.getResource("hero0.png"));

           hero1=ImageIO.read(ShootGame.class.getResource("hero1.png"));

           airplane=ImageIO.read(ShootGame.class.getResource("airplane.png"));

           bee=ImageIO.read(ShootGame.class.getResource("bee.png"));

           bullet=ImageIO.read(ShootGame.class.getResource("bullet.png"));

           background=ImageIO.read(ShootGame.class.getResource("background.png"));

           start=ImageIO.read(ShootGame.class.getResource("start.png"));

           pause=ImageIO.read(ShootGame.class.getResource("pause.png"));

           gameover=ImageIO.read(ShootGame.class.getResource("gameover.png"));

       } catch (Exception e) {

           e.printStackTrace();

       }

    }

    /**

     * 重寫面板繪製功能

     */

    public void paint(Graphics g){

       //繪製背景圖片

       g.drawImage(background, 0, 0, null);

       paintHero(g);//繪製英雄機物件

       paintBullets(g);//繪製所有的子彈

       paintFlyingObject(g);//繪製敵機或蜜蜂

       paintScore(g);//繪製分數和生命

       paintState(g);//繪製遊戲狀態

    }

    private void paintState(Graphics g) {

       switch(state){

       case startgame:

           g.drawImage(start, 0, 0, null);

           break;

       case pausegame:

           g.drawImage(pause, 0, 0, null);

           break;

       case over:

           g.drawImage(gameover, 0, 0, null);

           break;

       }

    }

    private void paintScore(Graphics g) {

       int x=10;

       int y=20;

       g.setFont(new Font(Font.SANS_SERIF,Font.BOLD,20));

       g.setColor(new Color(0xFF0000));

       g.drawString("分數:"+score, x, y);

       g.drawString("生命:"+hero.getLife(), x, y+20);

    }

    private void paintFlyingObject(Graphics g) {

       for(int i=0;i<objects.length;i++){

           FlyingObject obj=objects[i];

           g.drawImage(obj.image, obj.x, obj.y, null);

       }

    }

    private void paintBullets(Graphics g) {

       for(int i=0;i<bullets.length;i++){

           Bullet b=bullets[i];

           g.drawImage(b.image, b.x, b.y, null);

       }

    }

    /**繪製英雄機*/

    private void paintHero(Graphics g) {

       //獲取英雄機圖片

       BufferedImage image=hero.image;

       g.drawImage(image, hero.x, hero.y, null);

    }

    Timer timer;//新增定時器屬性

    /**

     * 程式的所有執行邏輯功能

     */

    public void action(){

       //新增滑鼠監聽事件

       MouseAdapter l=new MouseAdapter(){

           //滑鼠的移動事件

           public void mouseMoved(MouseEvent e){

              if(state==running){

                  //獲取滑鼠的座標

                  int x=e.getX();

                  int y=e.getY();

                  //英雄機與滑鼠位置關聯

                  hero.moveTo(x, y);

              }

           }

           /**滑鼠點選即進入runnning狀態*/

           @Override

           public void mouseClicked(MouseEvent e) {

              switch (state) {

              case startgame:

                  state=running;

                  break;

              case over:

                  state=startgame;

                  //所有的資料都要重置

                  hero=new Hero();

                  score=0;

                  bullets=new Bullet[0];

                  objects=new FlyingObject[0];

                  break;

              }

           }

           /**滑鼠離開即進入pausegame狀態*/

           @Override

           public void mouseExited(MouseEvent e) {

              if(state==running){

                  state=pausegame;

              }

           }

           /**滑鼠進入即進入running狀態*/

           @Override

           public void mouseEntered(MouseEvent e) {

              if(state==pausegame){

                  state=running;

              }

           }

       };

       //將監聽事件繫結到面板上

       this.addMouseListener(l);

       //新增監聽事件的滑鼠滑動效果

       this.addMouseMotionListener(l);

        timer=new Timer();

        /**

         * 設定定時器任務,

         * 第一個為任務內容

         * 第二個引數為多少毫秒後開始執行任務,

         * 第三個是每隔多少毫秒執行任務

         * */

        timer.schedule(new TimerTask(){

            public void run(){

               if(state==running){

                   enterAction();//飛行物進場

                   stepAction();//所有飛行物開始走步

                   shootAction();//射擊行為

                   boomAction();//碰撞行為

                   outOfBoundsAction();//處理飛行物越界情況

                   checkGameOver();//檢查遊戲是否結束

               }

               //重寫繪製效果

               repaint();

            }

        }, 10, 10);

    }

    /**處理越界行為,將沒有越界的裝入新的陣列*/

    protected void outOfBoundsAction() {

       FlyingObject[] objLives={};

        for(int i=0;i<objects.length;i++){

           FlyingObject obj=objects[i];

           if(!obj.outOfBounds()){

              objLives=Arrays.copyOf(objLives, objLives.length+1);

              objLives[objLives.length-1]=obj;

           }

       }

       objects=objLives;

       Bullet[] bsLives={};

       for(int i=0;i<bullets.length;i++){

           Bullet b=bullets[i];

           if(!b.outOfBounds()){

              bsLives=Arrays.copyOf(bsLives, bsLives.length+1);

              bsLives[bsLives.length-1]=b;

           }

       }

       bullets=bsLives;

    }

    /**檢查遊戲是否結束*/

    protected void checkGameOver() {

       if(isGameover()){

           state=over;//遊戲結束後,更改狀態

       }

    }

    /**判斷遊戲是否結束

     * 條件是,生命值為0

     * */

    private boolean isGameover() {

       int index=-1;

       for(int i=0;i<objects.length;i++){

           FlyingObject obj=objects[i];

           if(hero.hit(obj)){

              hero.substractLife();//減一條命

              hero.setDoubleFire(0);//重置火力值

              //讓飛行物消失

              index=i;//記錄敵機下標

              if(index!=-1){

                  objects[index]=objects[objects.length-1];

                  objects=Arrays.copyOf(objects, objects.length-1);

              }

              break;

           }

       }

       return hero.getLife()<=0;

    }

    /**子彈與敵機或蜜蜂進行碰撞*/

    protected void boomAction() {

       for(int i=0;i<bullets.length;i++){

           Bullet b=bullets[i];

           //判斷b是否與飛行物相撞

           boom(b);

       }

    }

    /**檢視子彈與飛行物相撞的情況*/

    private void boom(Bullet b) {

       int index=-1;//用於記錄被擊中的飛行的下標

       for(int i=0;i<objects.length;i++){

           FlyingObject obj=objects[i];

           //檢視飛行物是否被飛行物擊中

           boolean f=obj.shootBy(b);

           if(f){

              index=i;

              break;

           }

       }

       //需要將被擊中的飛行物刪除

       if(index!=-1){

           //儲存被擊中的飛行物

           FlyingObject obj=objects[index];

           //將之從陣列中刪除

           objects[index]=objects[objects.length-1];

           //縮容一位

           objects=Arrays.copyOf(objects, objects.length-1);

           //檢視被擊中的是敵機還是蜜蜂

           if(obj instanceof Bee){

              //是蜜蜂

              Bee bee=(Bee)obj;

              int awardType=bee.getType();//獲取獎勵型別

              switch(awardType){

              case Award.DOUBLE_FIRE: //變成雙倍火力

                  hero.addDoubleFire();

                  break;

              case Award.LIFT: //英雄機生命+1

                  hero.addLife();

                  break;

              }

           }else{

              //是敵機

              Airplane air=(Airplane)obj;

              score+=air.getScore();

           }

       }

    }

    /**英雄機發射子彈的功能*/

    int shootIndex;//定義變數,計運算元彈發射頻率

    protected void shootAction() {

       shootIndex++;

       /*400毫秒一發射,自定義*/

       if(shootIndex%30==0){

           Bullet[] bs=hero.shoot();//產生子彈

           //將產生的子彈存入遊戲面板的子彈陣列

           bullets=Arrays.copyOf(bullets, bullets.length+bs.length);

           System.arraycopy(bs, 0, bullets,bullets.length-bs.length, bs.length);

       }

    }

    /**所有飛行物開始走步*/

    protected void stepAction() {

       //敵機和蜜蜂開始走步

       for(int i=0;i<objects.length;i++){

           FlyingObject obj=objects[i];

           obj.step();

       }

       for(int i=0;i<bullets.length;i++){

           Bullet b=bullets[i];

           b.step();

       }

       hero.step();

    }

    /**讓所有的飛行物即敵機和蜜蜂進場*/

    int objectIndex;//用來控制飛行物入場的頻率

    protected void enterAction() {

       objectIndex++;

       /**飛行物入場:每300毫秒就進入一個*/

       if(objectIndex%90==0){

           /**

            * 隨機產生一個飛行物

            */

           FlyingObject obj=randomOne();

           objects=Arrays.copyOf(objects, objects.length+1);

           objects[objects.length-1]=obj;

       }

    }

    /**隨機一個敵機或者是蜜蜂*/

    private FlyingObject randomOne() {

       int num=(int)(Math.random()*20);

       if(num==19){

           Bee b=new Bee();

           return b;

       }else{

           Airplane air=new Airplane();

           return air;

       }

    }

    public static void main(String[] args) {

       //建立一個視窗

       JFrame frame=new JFrame("雷霆戰機");

       //設定視窗大小

       frame.setSize(WIDTH, HEIGHT);

       //建立遊戲面板物件

       ShootGame panel=new ShootGame();

       //將面板嵌入視窗

       frame.add(panel);

       //設定關閉即結束

       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

       //設定視窗居中

       frame.setLocationRelativeTo(null);

       //設定視窗在螢幕最前端

       frame.setAlwaysOnTop(true);

       //設定視窗可見

       frame.setVisible(true);

       //執行程式邏輯

       panel.action();

    }

}

FlyingObject:

package com.hyxy.shoot;

import java.awt.image.BufferedImage;

/**

 * 定義抽象型別:飛行物

 * 將面板上的所有飛行物的共有特徵及其

 * 功能封裝到這個抽象類

 * @author Administrator

 *

 */

public abstract class FlyingObject {

    protected BufferedImage image//圖片

    protected int x;//繪製起始橫座標

    protected int y;//繪製起始縱座標

    protected int width;//圖片的寬

    protected int height;//圖片的高

    //共同功能

    public abstract void step();//走步行為

    public abstract boolean outOfBounds();//越界行為

    /**

     * 檢視飛行物是否被子彈擊中

     * @param b 子彈物件

     * @return  true:表示被擊中

     *          false:表示沒被擊中

     */

    public boolean shootBy(Bullet b) {

       /**計算飛行物中心到子彈中心的距*/

       //x軸的中心距離

       int x1=this.x+width/2; //飛行物的中心x座標

       int y1=this.y+height/2; //飛行物的中心y座標

       int x2=b.x+b.width /2;

       int y2=b.y+b.height/2;

       /**滿足碰撞的條件:

        * 1.兩個中心的x軸小於子彈與飛行物一半寬度之和的一半

        * 2.兩個中心的y軸小於子彈與飛行物一半高度的之和一半

        * */

       //x軸兩個中心的距離

       double xdis=Math.abs((x1-x2));

       double ydis=Math.abs((y1-y2));

       //y軸兩個中心的距離

       return xdis<(width+b.width)/2&&ydis<(height+b.height)/2;

    }

}

Award類

package com.hyxy.shoot;

/**

 * 定義獎勵介面

 * @author Administrator

 *如果從蜜蜂身上獲取0,就表示雙倍火力

 *如果從蜜蜂身上獲取0,就表示生命值

 */

public interface Award {

    int DOUBLE_FIRE=0;//雙倍火力

    int LIFT=1;//生命

    /**

     *獲取獎勵型別的方法

     * @return

     */

    public int getType();

}

Enemy類

package com.hyxy.shoot;

/**

 * 定義敵人介面:

 * 敵人被擊中後,只需要提供分數

 * @author Administrator

 *

 */

public interface Enemy {

    /**提供獲取分數的方法*/

    public int getScore();

}

Hero類:

package com.hyxy.shoot;

import java.awt.image.BufferedImage;

/**

 * 定義定義英雄機型別繼承FlyingObject

 * 英雄機需要新增自己的獨有屬性

 * @author Administrator

 *

 */

public class Hero extends FlyingObject{

    protected BufferedImage[] images;//圖片陣列

    protected int double_fire;//火力值

    protected int life;//生命值

    /**

     * 新增構造器,給屬性初始化

     */

    public Hero(){

       image=ShootGame.hero0;//設定英雄機的初始圖片

       x=140;//在面板x軸上的初始位置

       y=440;//在面板y軸上的初始位置

       width=image.getWidth();

       height=image.getHeight();

       images=new BufferedImage[]{

              ShootGame.hero0,ShootGame.hero1//兩張圖片

       };

       double_fire=0;//預設單倍火力

       life=3;//預設3條命

    }

    /**

     * 英雄機的走步行為即兩張圖片的交換

     *設計 每四百毫秒交換一次

     *    每十毫秒呼叫一次step()方法

     *   

     * */

    protected int index;//用來統計圖片的交換頻率

    @Override

    public void step() {

       index++;

       /**

        * 每10毫秒 index都會自動加一

        * */

       image=images[index/10%images.length];

    }

    /**英雄機設定成永不越界,即返回flase*/

    @Override

    public boolean outOfBounds() {

       // TODO Auto-generated method stub

       return false;

    }

    /**

     * 隨著滑鼠移動而移動

     * @param滑鼠的橫座標

     * @param滑鼠的縱座標

     */

    public void moveTo(int x,int y){

       /**通過滑鼠的位置計算英雄機的位置

            * 滑鼠位於英雄機的中心位置

            * */

         this.x=x-width/2;

         this.y=y-height/2;

    }

    /**

     * 英雄機的射擊功能

     * @return

     */

    public Bullet[] shoot(){

       if(double_fire==0){

           Bullet[] bs=new Bullet[1];

           //子彈的橫座標

           int x=this.x+width/2;

           //子彈的縱座標

           int y=this.y-ShootGame.bullet.getHeight();

           bs[0]=new Bullet(x,y);

           return bs;

       }else{

           //雙倍火力

           Bullet[] bs=new Bullet[2];

           int x1=width/4;

           int y1=ShootGame.bullet.getHeight();

           bs[0]=new Bullet(this.x+x1,this.y-y1);

           bs[1]=new Bullet(this.x+x1*3,this.y-y1);

           return bs;

       }

    }

    /**設定雙倍火力,讓屬性double_fire大於0就行*/

    public void addDoubleFire() {

       double_fire+=40;

    }

    /**設定加命*/

    public void addLife() {

       life++;

    } 

    /**設定減命*/

    public void substractLife() {

       life--;

    }

    /**設定獲取英雄機的總命數*/

    public int getLife(){

       return life;

    }

    /**用來設定火力值:英雄機被撞,重置火力值*/

    public void setDoubleFire(int fire){

       this.double_fire=fire;

    }

    /**判斷英雄機是否與飛行物碰撞*/

    public boolean hit(FlyingObject obj) {

       //飛行物的中心座標

       int x1=obj.x +obj.width/2;

       int y1=obj.y+obj.height/2;

       //英雄機的座標

       int x2=this.x+this.width/2;

       int y2=this.y+this.height/2;

       int xdis=Math.abs(x1-x2);

       int ydis=Math.abs(y1-y2);

       return xdis<(this.width+obj.width)/2

              &&

              ydis<(this.height+obj.height)/2;

    }

}

Bullet類

package com.hyxy.shoot;

/**

 * 定義子彈型別:Bullet

 *