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

基于Java Swing制作一個(gè)Pong小游戲

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

之前呢我們用Python的Pygame做過(guò)這個(gè)Pong游戲

這一次,我們用Java的Swing來(lái)實(shí)現(xiàn)類(lèi)似的效果

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

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

接下來(lái)是項(xiàng)目目錄

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

好啦,現(xiàn)在先來(lái)寫(xiě)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)然后實(shí)例化GamePanel面板(待會(huì)寫(xiě)),然后綁定事件并添加到container容器中,設(shè)置窗口可見(jiàn)

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

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

接下來(lái)我們來(lái)看看一個(gè)同樣非常重要的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();
            }
        }
    }
}

這個(gè)就while循環(huán)實(shí)現(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);
    }
}

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

最后是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ù)和類(lèi)成員和方法

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

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制作一個(gè)Pong小游戲的文章就介紹到這了,更多相關(guān)Java Swing制作Pong游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論