欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Java Swing制作一個Pong小游戲

 更新時間:2023年01月05日 14:46:03   作者:Leleprogrammer  
《Pong》是美國雅達利公司(ATARI)開發(fā)的視頻游戲,該作模擬了兩個打乒乓球的人,就是在兩條線中間有一個點在動,操縱器就是一個搖桿上有一個按鈕的那種。本文就來用Java Swing制作一個Pong小游戲吧

之前呢我們用Python的Pygame做過這個Pong游戲

這一次,我們用Java的Swing來實現(xiàn)類似的效果

首先我們列出本次的項目結(jié)構(gòu)

這個程序分為四個部分,一個程序入口,一個模型,一個刷新幀,一個視圖,模型里面放入球和擋板的類,視圖里面放入主窗口Frame和主面板Panel

接下來是項目目錄

src資源下面,我們把東西全部寫到com.mr包下,main里的Start是主入口,model里面分別是Ball和Board,service下是刷新幀的服務(wù),view視圖下分別為主窗體和主面板 

好啦,現(xiàn)在先來寫GameFrame的代碼

package com.mr.view;
 
import javax.swing.*;
import java.awt.*;
 
public class GameFrame extends JFrame {
    private Container container;
    private GamePanel panel;
    public GameFrame() {
        setTitle("Pong");
        setBounds(300,300,850,1000);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        container=getContentPane();
        panel=new GamePanel();
        addKeyListener(panel);
        container.add(panel);
        setVisible(true);
    }
}

首先啊,還是和平常一樣聲明package,導(dǎo)入一些東西,然后主窗體繼承自JFrame,設(shè)置以下標(biāo)題和窗口大小,還有關(guān)閉后退出程序的設(shè)置(setDefaultCloseOperation)然后實例化GamePanel面板(待會寫),然后綁定事件并添加到container容器中,設(shè)置窗口可見

然后是GamePanel的代碼,也是整個程序的核心,在這里我們要做出對賽點、得分、球體碰撞等檢測,并繪制圖形

package com.mr.view;
 
import com.mr.model.Ball;
import com.mr.model.Board;
import com.mr.service.Fresh;
 
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
 
public class GamePanel extends JPanel implements KeyListener {
    private BufferedImage img;
    private Graphics2D g2;
    public ArrayList<Object> select;
    private Fresh fresh;
    private Board b1;
    private Board b2;
    private Ball ball;
    private int score1;
    private int score2;
    private int winPoint;
    private int matchPoint; // 0表示沒有賽點,1表示玩家1的賽點,2表示玩家2的賽點
    private int winner;
    public GamePanel() {
        img=new BufferedImage(850,1000,BufferedImage.TYPE_INT_BGR);
        g2=img.createGraphics();
        select=new ArrayList<>();
        b1=new Board(0);
        b2=new Board(1);
        ball=new Ball();
        score1=0;
        score2=0;
        matchPoint=0;
        winPoint=11;
        winner=0;
        fresh=new Fresh(this);
        fresh.start();
    }
    private void paintImage() {
        g2.setColor(Color.WHITE);
        if (winner==0) {
            int width=10;
            g2.fillRect(425-width/2,0,width,1000);
            g2.fillRect(b1.x,b1.y,b1.width,b1.height);
            g2.fillRect(b2.x,b2.y,b2.width,b2.height);
            g2.fillOval(ball.x-ball.r,ball.y-ball.r,ball.r*2,ball.r*2);
        }
        g2.setFont(new Font("黑體",Font.BOLD,56));
        g2.drawString(String.valueOf(score1),295,150);
        g2.drawString(String.valueOf(score2),525,150);
        g2.setFont(new Font("黑體",Font.PLAIN,22));
        if (winner==0) {
            switch (matchPoint) {
                case 1:
                    g2.drawString("賽點",295,200);
                    break;
                case 2:
                    g2.drawString("賽點",525,200);
                    break;
                default:
                    break;
            }
        } else {
            g2.drawString("玩家"+String.valueOf(winner)+"獲勝",winner==1?295:525,200);
        }
    }
    public void paint(Graphics g) {
        if (winner==0) {
            move();
            ball.move(b1.getBound(),b2.getBound());
            checkPoint();
            checkMatchPoint();
            b1.checkBound();
            b2.checkBound();
        }
        g2.setColor(Color.BLACK);
        g2.fillRect(0,0,850,1000);
        paintImage();
        g.drawImage(img,0,0,this);
    }
    private void checkPoint() {
        if (ball.x<=0) {
            score2+=1;
        } else if (ball.x+ball.r*2>=850) {
            score1+=1;
        } else {
            return;
        }
        ball=new Ball();
    }
    private void checkMatchPoint() {
        if (score1==winPoint) {
            winner=1;
            return;
        } else if (score2==winPoint) {
            winner=2;
            return;
        }
        if (score1+1==winPoint&&score2+1!=winPoint) {
            matchPoint=1;
        } else if (score1+1!=winPoint&&score2+1==winPoint) {
            matchPoint=2;
        } else if (score1+1==winPoint&&score2+1==winPoint) {
            matchPoint=0;
            winPoint++;
        } else if (score1+1!=winPoint&&score2+1!=winPoint) {
            matchPoint=0;
        }
    }
    private void move() {
        for (Object code:select) {
            if (code==(Object)KeyEvent.VK_W) {
                b1.y-=b1.speed;
            } else if (code==(Object)KeyEvent.VK_S) {
                b1.y+=b1.speed;
            } else if (code==(Object)KeyEvent.VK_UP) {
                b2.y-=b2.speed;
            } else if (code==(Object)KeyEvent.VK_DOWN) {
                b2.y+=b2.speed;
            }
        }
    }
    @Override
    public void keyPressed(KeyEvent event) {
        if (select.indexOf(event.getKeyCode())==-1) {
            select.add(event.getKeyCode());
        }
    }
    @Override
    public void keyReleased(KeyEvent event) {
        select.remove((Object)event.getKeyCode());
    }
    @Override
    public void keyTyped(KeyEvent event) {
        ;
    }
}

聲明com.mr.view包下,導(dǎo)入一些東西,然后創(chuàng)建主類GamePanel,繼承自JPanel并實現(xiàn)KeyListener事件,接下來就是聲明變量,一個主圖片img以及對應(yīng)的g2,select用于儲存按下的按鍵,這個待會講,接下來是fresh刷新幀線程,兩塊板,一個球,兩個玩家的分?jǐn)?shù),勝利所需要的分?jǐn)?shù),賽點歸屬于誰,是否出現(xiàn)了贏家等。接下來來到構(gòu)造函數(shù),先創(chuàng)建img主圖片850x1000還有g(shù)2,初始化一些東西,這里Board的0和1表示歸屬于哪個玩家,0則為左手邊的,1則為右手邊的。接下來創(chuàng)建球(ps.這些類待會就來寫),然后分?jǐn)?shù)初始化,賽點為0,表示沒有人獲得賽點,獲勝分?jǐn)?shù)為11分,和乒乓球一樣,然后winner為0表示沒有贏家,創(chuàng)建線程,這里傳入了自己,是為了待會可以通過repaint方式不斷重繪,然后啟動線程。paint中,沒有獲勝,則移動板(move),移動球,檢查得分,檢查賽點,保持兩塊板處于場內(nèi)(窗口內(nèi)),然后設(shè)置顏色為黑色,填充背景為黑色,繪制,并把主圖片畫在g中。paintImage中對板、球、得分、中線進行繪制,不難理解。好,GamePanel的最后,我們來講講剛剛的那個select,因為我們要同時檢測做個鍵盤按鈕,但是這個KeyListener只支持一次性按下一個,按下多個也只會獲取到一個,所以我們用一種方法來解決,我們創(chuàng)建一個select數(shù)組,按下按鍵且按鍵不在select中則添加到select中,松開則刪除,這樣同時按下多個按鈕,這些按鈕(就像排著隊伍一樣)相繼添加到select中,這樣也便于了我們移動板的if判斷。

接下來我們來看看一個同樣非常重要的Fresh刷新幀線程

package com.mr.service;
 
import com.mr.view.GamePanel;
 
public class Fresh extends Thread {
    public final int INTERVAL=20;
    private GamePanel panel;
    public Fresh(GamePanel panel) {
        this.panel=panel;
    }
    public void run() {
        while (true) {
            panel.repaint();
            try {
                Thread.sleep(INTERVAL);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

這個就while循環(huán)實現(xiàn)啦~~~

然后是Ball

package com.mr.model;
 
import java.awt.*;
import java.util.Random;
 
public class Ball {
    public int x;
    public int y;
    public int r;
    private int xspeed;
    private int yspeed;
    private int max_speed;
    private int min_speed;
    private int max_speed2;
    private int min_speed2;
    public Ball() {
        x=425;
        y=500;
        r=15;
        Random rd=new Random();
        xspeed=rd.nextInt(1,3)==1?rd.nextInt(4,7):rd.nextInt(-6,-3);
        yspeed=rd.nextInt(1,3)==1?rd.nextInt(4,7):rd.nextInt(-6,-3);
        max_speed=12;
        min_speed=3;
        max_speed2=-3;
        min_speed2=-12;
    }
    public void move(Rectangle b1,Rectangle b2) {
        x+=xspeed;
        y+=yspeed;
        Random rd=new Random();
        if (getBound().intersects(b1)||getBound().intersects(b2)) {
            xspeed=-xspeed;
            yspeed+=rd.nextInt(-2,3);
        }
        else if (y-r<=0||y+r>=965) {
            yspeed=-yspeed;
            xspeed+=rd.nextInt(-2,3);
        }
        if (xspeed>max_speed&&xspeed>0) {
            xspeed=max_speed;
        }
        if (yspeed>max_speed&&yspeed>0) {
            yspeed=max_speed;
        }
        if (xspeed<min_speed&&xspeed>0) {
            xspeed=min_speed;
        }
        if (yspeed<min_speed&&yspeed>0) {
            yspeed=min_speed;
        }
        if (xspeed>max_speed2&&xspeed<0) {
            xspeed=max_speed2;
        }
        if (yspeed>max_speed&&yspeed<0) {
            yspeed=max_speed2;
        }
        if (xspeed<min_speed&&xspeed<0) {
            xspeed=min_speed2;
        }
        if (yspeed<min_speed&&yspeed<0) {
            yspeed=min_speed2;
        }
    }
    private Rectangle getBound() {
        return new Rectangle(x-r,y-r,r*2,r*2);
    }
}

這個模型嘛,一般情況下都有x和y還有大小,因為這個是個圓,所以我們用半徑r,然后xspeed和yspeed表示各個方向的速度從而實現(xiàn)斜著移動,還有max_speed和min_speed用于把動態(tài)變換的速度限制于這個范圍內(nèi),待會每碰到一次墻壁或板,就會適當(dāng)增加或減少速度,所以要把速度限制在特定范圍內(nèi),max_speed2和min_speed2也一樣,前2者是用于正數(shù)速度的,后2者是用于負(fù)數(shù)速度的,然后移動的時候就對一些碰撞等情況進行檢測就好了,getBound用于返回對象的Rect長方形對象,用于檢測碰撞。

最后是Board

package com.mr.model;
 
import java.awt.*;
 
public class Board {
    public int x;
    public int y;
    public int width;
    public int height;
    public int speed;
    public Board(int type) {
        width=8;
        height=120;
        speed=15;
        y=500-height/2;
        if (type==0) {
            x=0;
        } else {
            x=850-15-width;
        }
    }
    public void checkBound() {
        if (y+height>=985) {
            y=985-height;
        }
        if (y<=0) {
            y=0;
        }
    }
    public Rectangle getBound() {
        return new Rectangle(x,y,width,height);
    }
}

Board和Ball也有著差不多的一些參數(shù)和類成員和方法

現(xiàn)在全部就都寫完了,最后畫上點睛之筆,寫上最后的程序入口就大功告成啦!??!

Start.java:

package com.mr.main;
 
import com.mr.view.GameFrame;
 
public class Start {
    public static void main(String[] args) {
        GameFrame gameFrame=new GameFrame();
    }
}

到此這篇關(guān)于基于Java Swing制作一個Pong小游戲的文章就介紹到這了,更多相關(guān)Java Swing制作Pong游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot+RabbitMQ方式收發(fā)消息的實現(xiàn)示例

    SpringBoot+RabbitMQ方式收發(fā)消息的實現(xiàn)示例

    這篇文章主要介紹了SpringBoot+RabbitMQ方式收發(fā)消息的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 使用Mybatis接收Integer參數(shù)的問題

    使用Mybatis接收Integer參數(shù)的問題

    這篇文章主要介紹了使用Mybatis接收Integer參數(shù)的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • spring cloud升級到spring boot 2.x/Finchley.RELEASE遇到的坑

    spring cloud升級到spring boot 2.x/Finchley.RELEASE遇到的坑

    這篇文章主要介紹了spring cloud升級到spring boot 2.x/Finchley.RELEASE遇到的坑,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • java數(shù)學(xué)歸納法非遞歸求斐波那契數(shù)列的方法

    java數(shù)學(xué)歸納法非遞歸求斐波那契數(shù)列的方法

    這篇文章主要介紹了java數(shù)學(xué)歸納法非遞歸求斐波那契數(shù)列的方法,涉及java非遞歸算法的使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • java編程調(diào)用存儲過程中得到新增記錄id號的實現(xiàn)方法

    java編程調(diào)用存儲過程中得到新增記錄id號的實現(xiàn)方法

    這篇文章主要介紹了java編程調(diào)用存儲過程中得到新增記錄id號的實現(xiàn)方法,涉及Java數(shù)據(jù)庫操作中存儲過程的相關(guān)使用技巧,需要的朋友可以參考下
    2015-10-10
  • Java創(chuàng)建、識別條形碼和二維碼方法示例

    Java創(chuàng)建、識別條形碼和二維碼方法示例

    這篇文章主要給大家介紹了關(guān)于Java創(chuàng)建、識別條形碼和二維碼的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Java?Spring的使用注解開發(fā)詳解

    Java?Spring的使用注解開發(fā)詳解

    這篇文章主要為大家介紹了Java?Spring注解開發(fā),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • java poi設(shè)置生成的word的圖片為上下型環(huán)繞以及其位置的實現(xiàn)

    java poi設(shè)置生成的word的圖片為上下型環(huán)繞以及其位置的實現(xiàn)

    這篇文章主要介紹了java poi設(shè)置生成的word的圖片為上下型環(huán)繞以及其位置的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 深入理解LinkedHashSet集合的底層機制

    深入理解LinkedHashSet集合的底層機制

    這篇文章主要介紹了LinkedHashSet的底層機制詳解,LinkedHashSet根據(jù)元素的hashCode值來決定元素的存儲位置,同時使用鏈表維護元素的次序,?這使得元素看起來是以插入順序保存的,需要的朋友可以參考下
    2023-10-10
  • Java線程池FutureTask實現(xiàn)原理詳解

    Java線程池FutureTask實現(xiàn)原理詳解

    這篇文章主要介紹了Java線程池FutureTask實現(xiàn)原理詳解,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02

最新評論