使用IDEA製作Java物件導向小遊戲《原諒帽大作戰》

2020-11-13 14:01:04

成果展示

在這裡插入圖片描述

製作思路

第1步:發現類(物件)

人物-小丑: Buffoon
子彈-帽子:Missile
牆體:Wall
爆炸物:Explode

第2步:發現屬性

小丑:寬和高,位置(x,y),移動速度
帽子:寬和高,位置(x,y),移動速度
牆體:寬和高,位置(x,y)
爆炸物:寬和高,位置(x,y)

第3步:發現方法

小丑:移動、攻擊、人物撞邊界
子彈:移動、子彈撞牆、子彈撞邊界
爆炸物:消失

重難點分析

表單如何建立

public class GameClient extends Frame

通過繼承Frame類實現Java表單

public class Frame extends Window implements MenuContainer

Frame類繼承了Window類和MenuContainer介面

如何將圖片載入到表單裡

步驟1:建立常用工具類CommonUtils,新建getImage方法實現將圖片資源轉換為Java物件

public class CommonUtils {
    /**
     * 讀取圖片資源, 轉變為Java物件 Image
     * @param imgPath  圖片路徑
     * @return Image物件
     */
    public static Image getImage(String imgPath) {
        ImageIcon imageIcon = new ImageIcon(imgPath);
        return imageIcon.getImage();
    }
}

步驟2:呼叫getImage方法新增物件圖片

public class GameClient extends Frame {
    Image bg_image = CommonUtils.getImage("images/bg.png");
    Image explode = CommonUtils.getImage("images/explode.png");
    Image missile = CommonUtils.getImage("images/missile.png");
    Image wall_h = CommonUtils.getImage("images/wall-h.png");
    Image wall_v = CommonUtils.getImage("images/wall-v.png");
    Image buffoon = CommonUtils.getImage("images/body/s-left.png");

步驟3:重寫Framed的paint方法,實現表單載入圖片

@Override
    public void paint(Graphics g){
        //畫背景圖
        g.drawImage(bg_image,0,0,1100,700,this);
        //畫小丑
        g.drawImage(buffoon,300,200,80,80,this);
        //畫爆炸物
        g.drawImage(explode,800,400,90,90,this);
        //畫原諒帽
        g.drawImage(missile,300,300,60,60,this);
        //畫橫著的牆體
        g.drawImage(wall_h,400,300,100,20,this);
        //畫豎著的牆體
        g.drawImage(wall_v,400,300,20,100,this);

Graphics類的drawImage方法需要提供Image類引數、表單的x引數、表單的y引數、Image類的寬度width、Image類的長度length以及observer(當轉換了更多影象時要通知的物件)

物件移動的實現

指向標的地圖,通常採用「上北下南,左西右東」的規則確定方向。移動的八個方向通常指的是北、東北、東、東南、南、西南、西、西北。因此在定義移動方向時用上、左、下、右、上右、下右、上左、下左來表示

林家彬設計的

小丑:移動  move<Orientation類傳遞方向引數>
'left向左'   :x = x - this.speed;
'right向右'  :x = x + this.speed;
'down向下'   :y = y + this.speed;
'up向上'     :y = y - this.speed;
'ur東北方向'  : x = x + this.speed;
                y = y - this.speed;
'ul西北方向'  : x = x - this.speed;
                y = y - this.speed;
'dr東南方向'  : x = x + this.speed;
                y = y + this.speed;
'dl西南方向'  : x = x - this.speed;
                y = y + this.speed;

表單關閉的實現

    public void start() {
        //表單新增偵聽方法
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                super.windowClosing(e);
                //退出遊戲
                System.exit(0);
            }
        });

WindowAdapter類
1.接收視窗事件的抽象介面卡類。此類中的方法為空。此類存在的目的是方便建立偵聽器物件。
2.擴充套件此類可建立 WindowEvent 偵聽器併為所需事件重寫該方法。(如果要實現 WindowListener 介面,則必須定義該介面內的所有方法。此抽象類將所有方法都定義為 null,所以只需針對關心的事件定義方法。
3.使用擴充套件的類可以建立偵聽器物件,然後使用視窗的 addWindowListener 方法向該視窗註冊偵聽器。當通過開啟、關閉、啟用或停用、圖示化或取消圖示化而改變了視窗狀態時,將呼叫該偵聽器物件中的相關方法,並將 WindowEvent 傳遞給該方法。
windowAdapter監聽器

按鍵事件觸發的實現

 this.addKeyListener(new KeyAdapter() {
             //鍵盤按下的時候出發
            @Override
            public void keyPressed(KeyEvent e) {
                super.keyPressed(e);
            }
            //鍵盤松開
            @Override
            public void keyReleased(KeyEvent e) {
                //獲取被按下的鍵對應的數值,如,a:67,b:68
                int keyCode = e.getKeyCode();
                switch (keyCode){
                    case KeyEvent.VK_UP:
                        System.out.println("向上走!!!");
                        buffoon.setDir("UP");
                        break;
                    case KeyEvent.VK_DOWN:
                        System.out.println("向下走");
                        buffoon.setDir("DOWN");
                        break;
                    case KeyEvent.VK_RIGHT:
                        System.out.println("向右走");
                        buffoon.setDir("RIGHT");
                        break;
                    case KeyEvent.VK_LEFT:
                        System.out.println("向左走!!");
                        buffoon.setDir("LEFT");
                        break;
                }
                buffoon.move(buffoon.getDir());
            }
        });

按鍵觸發的要點

要點一:‘new KeyAdapter()’ 新建一個按鍵事件的監聽器,並通過addKeyListener()向主表單註冊該監聽器;
要點二:重寫KeyAdapter的方法,分別是KeyTyped(鍵入)、KeyPresdded(按下)、KeyReleased(釋放)。這裡我們只監聽KeyPressed事件並重寫該方法,實現對人物方向狀態的改變;
要點三:KeyEvent e.getKeyCode返回的是按下按鍵對應的鍵值,參考KeyEvent的鍵值屬性。Java 8線上API

建立物件Buffoon.move()方法

    public void move(String dir){
        switch (dir){
            case "UP":
                this.y -= this.speed;
                setDir("STOP");
                break;
            case "DOWN":
                this.y += this.speed;
                setDir("STOP");
                break;
            case "RIGHT":
                this.x += this.speed;
                setDir("STOP");
                break;
            case "LEFT":
                this.x -= this.speed;
                setDir("STOP");
                break;
        }

每次監聽到按鍵事件呼叫move方法實現buffoon物件的移動

每次監聽到按鍵事件呼叫move方法

物件移動的原理

物件移動的畫面也叫動畫,是在螢幕上顯示一系列連續動畫畫面的一幀一幀的圖形,然後在間隔很短的時間顯示下一幀圖形,如此反覆,利用人眼的‘視覺暫留’現象主觀感覺好像畫面的物體在運動。
FPS(Frames Per Second),是每秒鐘的幀數。一幀就是一幅靜態畫像,電影的播放速度是24FPS。幀數越多,所顯示的動作就會越流暢。通常,要避免動作不流暢的最低是30FPS。FPS百度百科

動畫移動的搬運工-執行緒(thread)

什麼是執行緒
執行緒(thread)是作業系統能夠進行運算排程的最小單位。它被包含在程序之中,是程序中的實際運作單位。一條執行緒指的是程序中一個單一順序的控制流,一個程序中可以並行多個執行緒,每條執行緒並行執行不同的任務。

/**
 * 定義一個重新繪製畫面的執行緒,相當於招一個工人專門去從事這項工作
 */
public class RePaintThread implements Runnable{
    @Override
    //執行緒操作的全都在run方法中
    public void run() {
        while (true){
            //每50毫秒 執行一次
            try {
                Thread.sleep(20);
                //重新繪製影象
                gameClient.repaint();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

要點一:Runnable介面
public class RePaintThread implements Runnable
使用實現介面 Runnable 的物件建立一個執行緒時,啟動該執行緒將導致在獨立執行的執行緒中呼叫物件的 run 方法。
要點二:重寫Run方法
方法 run 的常規協定是:它可能執行任何所需的動作。
重新繪製影象
gameClient.repaint();
要點三:Thread.sleep—執行緒反覆執行的時間間隔
1、使用’While(true)'構造死迴圈
2、在死迴圈中執行repaint()重繪圖形方法
3、執行緒中斷異常(InterruptedException)是當前執行緒被中斷的表現之一。遇到這個異常時,如果你不知道如何處理,你應當向上丟擲。
catch從句