当前位置: 首页 > 知识库问答 >
问题:

如何在我的java游戏中添加流畅的运动?

殷德本
2023-03-14

我的目标是:在像乒乓球这样的东西中,关键控件应该平稳地移动蝙蝠。

期望:希望蝙蝠用钥匙平稳地向上或向下移动。实际结果:蝙蝠像落后或速度变化一样移动。

我试过用速度变量和lerp,但它们滞后。我试过增加和减少y值,但效果更差。我搜索了一下,但找不到解决方案。

我叫矩形蝙蝠和圆形乒乓球。而且,这是我第一天在这里发帖。

游戏截图

以下是panal代码:

import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;

import javax.swing.JPanel;
import javax.swing.Timer;

public class gamePanel extends JPanel implements ActionListener {

    /**
     * 
     */
    private static final long serialVersionUID = 6350159535293799269L;
    static final int SCREEN_WIDTH = 840;
    static final int SCREEN_HEIGHT = 610;
    static final int PONG_SPAWN_FRAME = 50;
    static final int padding = 30;

    
    
    static final int pongSize = 30;
    static final int batHeight = SCREEN_HEIGHT / 4;
    static final int batWidth = SCREEN_WIDTH / 32;
    static final int batSpeed = 4;
    static final int pongSpeed = 3;
    static final int scoreTextSize = 45;
    
    boolean running = false;
    
    int redX = padding;
    int redY = SCREEN_HEIGHT / 2;
    int redVelocity = 0;

    int blueX = SCREEN_WIDTH - padding;
    int blueY = SCREEN_HEIGHT / 2;
    int blueVelocity = 0;

    int redPoints = 0;
    int bluePoints = 0;

    int pongX = SCREEN_WIDTH / 4 - pongSize / 2;
    int pongY = 0;

    int pongVelocityX = pongSpeed;
    int pongVelocityY = pongSpeed;

    final int DELAY = 6;
    Timer timer;

    Random random;

    gamePanel() {
        random = new Random();
        pongY = random.nextInt((int) (SCREEN_HEIGHT - PONG_SPAWN_FRAME) + PONG_SPAWN_FRAME);
        if (pongVelocityY == 0) {
            if (pongY > SCREEN_HEIGHT / 2 + pongSize) {
                pongVelocityY = -pongSpeed;
            } else {
                pongVelocityY = pongSpeed;
            }
        }
        this.setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT));
        this.setBackground(Color.DARK_GRAY);
        this.setFocusable(true);
        this.addKeyListener(new myKeyAdapter());
        startGame();
    }

    void startGame() {
        running = true;
        timer = new Timer(DELAY, this);
        timer.start();

    }

    void restart() {
        redX = padding;
        redY = SCREEN_HEIGHT / 2;
        redVelocity = 0;

        blueX = SCREEN_WIDTH - padding;
        blueY = SCREEN_HEIGHT / 2;
        blueVelocity = 0;

        pongX = SCREEN_WIDTH / 4 - pongSize / 2;
        pongY = 0;

        pongVelocityX = pongSpeed;
        pongVelocityY = pongSpeed;

        spawnPong();

    }

    void spawnPong() {
        pongY = random.nextInt((int) (SCREEN_HEIGHT - PONG_SPAWN_FRAME * 2)) + PONG_SPAWN_FRAME;
        if (pongVelocityY == 0) {
            if (pongY > SCREEN_HEIGHT / 2 + pongSize) {
                pongVelocityY = -pongSpeed;
            } else {
                pongVelocityY = pongSpeed;
            }
        }
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        draw(g);
    }

    void draw(Graphics g) {
        g.setColor(Color.LIGHT_GRAY);
        g.fillOval(pongX, pongY, pongSize, pongSize);
        g.setColor(Color.red);
        g.fillRect(redX - batWidth / 2, redY - batHeight / 2, batWidth, batHeight);
        g.setColor(Color.blue);
        g.fillRect(blueX - batWidth / 2, blueY - batHeight / 2, batWidth, batHeight);
        g.setColor(Color.white);
        g.setFont(new Font("Roman New Times", Font.PLAIN, scoreTextSize));
        g.drawString(String.valueOf(redPoints), SCREEN_WIDTH / 4, scoreTextSize);
        g.drawString(String.valueOf(bluePoints), SCREEN_WIDTH / 4 * 3, scoreTextSize);
    }

    void pongMove() {
        pongX += pongVelocityX;
        pongY += pongVelocityY;
    }

    void batMove() {
        if (redY > batHeight / 2 && redVelocity < 0) {
            redY += redVelocity * batSpeed;
        }
        if (redY < SCREEN_HEIGHT - batHeight / 2 && redVelocity > 0) {
            redY += redVelocity * batSpeed;
        }

        blueY = pongY;
        /*
         * if (blueY>batHeight/2 && blueVelocity < 0) { blueY += blueVelocity *
         * pongSpeed; } if (blueY<SCREEN_HEIGHT-batHeight/2 && blueVelocity > 0) { blueY
         * += blueVelocity * pongSpeed; }
         */
    }

    void batLerp() {
        redVelocity *= 0.5f;
        blueVelocity *= 0.5f; 
    }

    void checkCollision() {
        if ((pongX > blueX - pongSize - batWidth / 2 && pongX < blueX - pongSize + batWidth / 2)
                && (pongY > blueY - batHeight / 2 && pongY < blueY + batHeight / 2)) {
            pongVelocityX *= -1;
        }
        if (pongX < redX + batWidth / 2 && (pongY > redY - batHeight / 2 && pongY < redY + batHeight / 2)) {
            pongVelocityX *= -1;
        }
        if (pongY < 0) {
            pongVelocityY *= -1;
        }
        if (pongY > SCREEN_HEIGHT - pongSize) {
            pongVelocityY *= -1;
        }
        if (pongX < -pongSize) {
            bluePoints += 1;
            restart();
        }
        if (pongX > SCREEN_WIDTH) {
            redPoints += 1;
            restart();
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (running) {
            checkCollision();
            batMove();
            batLerp();
            pongMove();
        }
        repaint();

    }

    public class myKeyAdapter extends KeyAdapter {
        public void keyPressed(KeyEvent e) {
            switch (e.getKeyCode()) {
            case KeyEvent.VK_W:
                redVelocity = -1;
                break;
            case KeyEvent.VK_S:
                redVelocity = 1;
                break;
            case KeyEvent.VK_UP:
                blueVelocity = -1;
                break;
            case KeyEvent.VK_DOWN:
                blueVelocity = 1;
                break;
            }
        }
    }
}

共有1个答案

钦高峯
2023-03-14

我修改了桨的移动,这样桨只有在你按住键的时候才会移动。为了测试,我不得不把游戏慢一点。

我很难理解你的代码。你的J面板类做了太多的工作,而且太难理解。我会从普通的Javagetter/setter类创建一个Ball类和一个Paddle类来保存球和桨的字段。

这是完整的可运行代码。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class ClassicPongGUI implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new ClassicPongGUI());
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Pong");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(new GamePanel());

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public class GamePanel extends JPanel implements ActionListener {

        private static final long serialVersionUID = 6350159535293799269L;

        static final int SCREEN_WIDTH = 840;
        static final int SCREEN_HEIGHT = 610;
        static final int PONG_SPAWN_FRAME = 50;
        static final int padding = 30;

        static final int pongSize = 30;
        static final int batHeight = SCREEN_HEIGHT / 4;
        static final int batWidth = SCREEN_WIDTH / 32;
        static final int batSpeed = 20;
        static final int pongSpeed = 1;
        static final int scoreTextSize = 45;

        boolean running = false;

        int redX = padding;
        int redY = SCREEN_HEIGHT / 2;
        int redVelocity = 0;

        int blueX = SCREEN_WIDTH - padding;
        int blueY = SCREEN_HEIGHT / 2;
        int blueVelocity = 0;

        int redPoints = 0;
        int bluePoints = 0;

        int pongX = SCREEN_WIDTH / 4 - pongSize / 2;
        int pongY = 0;

        int pongVelocityX = pongSpeed;
        int pongVelocityY = pongSpeed;

        final int DELAY = 6;
        Timer timer;

        Random random;

        public GamePanel() {
            random = new Random();
            pongY = random.nextInt((int) (SCREEN_HEIGHT - PONG_SPAWN_FRAME) + PONG_SPAWN_FRAME);
            if (pongVelocityY == 0) {
                if (pongY > SCREEN_HEIGHT / 2 + pongSize) {
                    pongVelocityY = -pongSpeed;
                } else {
                    pongVelocityY = pongSpeed;
                }
            }
            this.setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT));
            this.setBackground(Color.DARK_GRAY);
            this.setFocusable(true);
            this.addKeyListener(new myKeyAdapter());
            startGame();
        }

        void startGame() {
            running = true;
            timer = new Timer(DELAY, this);
            timer.start();

            redX = padding;
            redY = SCREEN_HEIGHT / 2;
            redVelocity = 0;
        }

        void restart() {
            blueX = SCREEN_WIDTH - padding;
            blueY = SCREEN_HEIGHT / 2;
            blueVelocity = 0;

            pongX = SCREEN_WIDTH / 4 - pongSize / 2;
            pongY = 0;

            pongVelocityX = pongSpeed;
            pongVelocityY = pongSpeed;

            spawnPong();

        }

        void spawnPong() {
            pongY = random.nextInt((int) (SCREEN_HEIGHT - PONG_SPAWN_FRAME * 2)) + PONG_SPAWN_FRAME;
            if (pongVelocityY == 0) {
                if (pongY > SCREEN_HEIGHT / 2 + pongSize) {
                    pongVelocityY = -pongSpeed;
                } else {
                    pongVelocityY = pongSpeed;
                }
            }
        }

        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            draw(g);
        }

        void draw(Graphics g) {
            g.setColor(Color.LIGHT_GRAY);
            g.fillOval(pongX, pongY, pongSize, pongSize);
            g.setColor(Color.red);
            g.fillRect(redX - batWidth / 2, redY - batHeight / 2, batWidth, batHeight);
            g.setColor(Color.blue);
            g.fillRect(blueX - batWidth / 2, blueY - batHeight / 2, batWidth, batHeight);
            g.setColor(Color.white);
            g.setFont(new Font("Times New Roman", Font.PLAIN, scoreTextSize));
            g.drawString(String.valueOf(redPoints), SCREEN_WIDTH / 4, scoreTextSize);
            g.drawString(String.valueOf(bluePoints), SCREEN_WIDTH / 4 * 3, scoreTextSize);
        }

        void pongMove() {
            pongX += pongVelocityX;
            pongY += pongVelocityY;
        }

        void batMove() {
            if (redY > batHeight / 2 && redVelocity < 0) {
                redY += redVelocity * batSpeed;
            }
            if (redY < SCREEN_HEIGHT - batHeight / 2 && redVelocity > 0) {
                redY += redVelocity * batSpeed;
            }

            blueY = pongY;
            /*
             * if (blueY>batHeight/2 && blueVelocity < 0) { blueY += blueVelocity *
             * pongSpeed; } if (blueY<SCREEN_HEIGHT-batHeight/2 && blueVelocity > 0) { blueY
             * += blueVelocity * pongSpeed; }
             */
        }

        void batLerp() {
            redVelocity = 0;
            blueVelocity = 0;
        }

        void checkCollision() {
            if ((pongX > blueX - pongSize - batWidth / 2 
                    && pongX < blueX - pongSize + batWidth / 2)
                    && (pongY > blueY - batHeight / 2 
                    && pongY < blueY + batHeight / 2)) {
                pongVelocityX *= -1;
            }
            if (pongX < redX + batWidth / 2 && (pongY > redY - batHeight / 2 
                    && pongY < redY + batHeight / 2)) {
                pongVelocityX *= -1;
            }
            if (pongY < 0) {
                pongVelocityY *= -1;
            }
            if (pongY > SCREEN_HEIGHT - pongSize) {
                pongVelocityY *= -1;
            }
            if (pongX < -pongSize) {
                bluePoints += 1;
                restart();
            }
            if (pongX > SCREEN_WIDTH) {
                redPoints += 1;
                restart();
            }
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (running) {
                checkCollision();
                batMove();
                batLerp();
                pongMove();
            }
            repaint();

        }

        public class myKeyAdapter extends KeyAdapter {
            @Override
            public void keyPressed(KeyEvent e) {
                switch (e.getKeyCode()) {
                case KeyEvent.VK_W:
                    redVelocity = -1;
                    break;
                case KeyEvent.VK_S:
                    redVelocity = 1;
                    break;
                case KeyEvent.VK_UP:
                    redVelocity = -1;
                    break;
                case KeyEvent.VK_DOWN:
                    redVelocity = 1;
                    break;
                }
            }
        }
        
    }

}

我认为这将是一个有趣的项目,所以我修改了代码。GUI的显示方式如下。

W和向上箭头键向上移动蓝色拨片。S和向下箭头键向下移动蓝色拨片。必须按住这些键才能继续运动。松开键停止桨运动,

空格键重新启动游戏。

当我创建Swing GUI时,我使用模型/视图/控制器(MVC)模式。这种模式允许我将关注点分开,一次只关注应用程序的一小部分。

对于Swing GUI,MVC模式定义为:

    < li >视图从模型中读取信息。 < li >视图不会更新模型。 < li >控制器更新模型并重新绘制/验证视图。

一个 Swing GUI 可以有许多控制器类。我为这个Pong游戏创建了三个控制器类。

我创建了8个不同的类。三个类构成应用程序模型,两个类定义视图,三个控制器类管理应用程序。

我创建了一个<code>Ball</code>类来容纳创建球和在屏幕上移动球所需的字段。我使用来保持中心点,使用int来保持球的半径。

球类不是典型的接手/二传手类。moveBall 方法使用极坐标来计算球的新位置。极坐标被转换为笛卡尔坐标,以在绘图JPanel上绘制球。

Paddle 类创建一个 Paddle。我将桨的形状存储在矩形中。这是一个更典型的Java getter / setter类,尽管有代码可以限制桨在Y轴上可以行进的距离。

是应用程序模型。此类包含一个 Ball 实例和两个 Paddle 实例,以及两个分数整数和游戏运行的帧速率。此类的实例通过视图类和控制器类传递。

我创建了一个JFrame和一个绘图J面板。绘图J面板绘制了球的当前位置、两个桨和分数。句号。没有别的了。

控制器类负责移动球和桨以及重绘JPel

我使用KeyBindings将键盘键设置为各种操作。使用KeyBindings,我不必担心绘图JPel是否有焦点。

TimerListener类为Pong游戏制作动画。

MovePaddleAction类根据按下的键向上或向下移动拨片。必须按住键才能继续运动。

RestartAction 类重新启动游戏。

这是完整的可运行代码。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.Point2D;
import java.util.Random;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class ClassicPongGUI implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new ClassicPongGUI());
    }
    
    private final Dimension panelSize;
    
    private GameModel gameModel;
    
    private GamePanel gamePanel;
    
    private Timer timer;
    
    public ClassicPongGUI() {
        this.panelSize = new Dimension(840, 610);
        this.gameModel = new GameModel(panelSize);
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Pong");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        this.gamePanel = new GamePanel(this, gameModel);
        frame.add(gamePanel, BorderLayout.CENTER);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
        
        setKeyBindings();
        startTimer();
    }
    
    private void setKeyBindings() {
        String moveUp = "moveUp";
        String moveDown = "moveDown";
        String restart = "restart";
        
        InputMap inputMap = gamePanel.getInputMap(
                JPanel.WHEN_IN_FOCUSED_WINDOW);
        ActionMap actionMap = gamePanel.getActionMap();
        
        inputMap.put(KeyStroke.getKeyStroke(
                KeyEvent.VK_W, 0), moveUp);
        inputMap.put(KeyStroke.getKeyStroke(
                KeyEvent.VK_UP, 0), moveUp);
        inputMap.put(KeyStroke.getKeyStroke(
                KeyEvent.VK_S, 0), moveDown);
        inputMap.put(KeyStroke.getKeyStroke(
                KeyEvent.VK_DOWN, 0), moveDown);
        inputMap.put(KeyStroke.getKeyStroke(
                KeyEvent.VK_SPACE, 0), restart);
        
        int increment = 15;
        actionMap.put(moveUp, new MovePaddleAction(
                this, gameModel, -increment));
        actionMap.put(moveDown, new MovePaddleAction(
                this, gameModel, increment));
        actionMap.put(restart, new RestartAction(
                this, gameModel));
    }
    
    public void startTimer() {
        int delay = 1000 / gameModel.getFrameRate();
        timer = new Timer(delay, new TimerListener(this, gameModel));
        timer.setInitialDelay(5000);
        timer.start();
    }
    
    public void stopTimer() {
        if (timer != null) {
            timer.stop();
        }
    }
    
    public Dimension getPanelSize() {
        return panelSize;
    }

    public void repaint() {
        gamePanel.repaint();
    }

    public class GamePanel extends JPanel {

        private static final long serialVersionUID = 1L;
        
        private final GameModel model;
        
        public GamePanel(ClassicPongGUI frame, GameModel model) {
            this.model = model;
            
            this.setBackground(Color.DARK_GRAY);
            this.setPreferredSize(frame.getPanelSize());
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            
            drawBall(g);
            drawPaddles(g);
            drawScores(g);
        }

        private void drawBall(Graphics g) {
            Ball ball = model.getBall();
            g.setColor(ball.getColor());
            int radius = ball.getRadius();
            int diameter = radius + radius;
            Point point = ball.getCenterPoint();
            g.fillOval(point.x - radius, point.y - radius, 
                    diameter, diameter);
        }

        private void drawPaddles(Graphics g) {
            Paddle[] paddles = model.getPaddles();
            for (Paddle paddle : paddles) {
                g.setColor(paddle.getColor());
                Rectangle r = paddle.getPaddle();
                g.fillRect(r.x, r.y, r.width, r.height);
            }
        }

        private void drawScores(Graphics g) {
            int[] scores = model.getScore();
            int scoreTextSize = 45;
            g.setColor(Color.WHITE);
            g.setFont(new Font("Times New Roman", 
                    Font.PLAIN, scoreTextSize));
            g.drawString(String.valueOf(scores[0]), 
                    panelSize.width / 4, scoreTextSize);
            g.drawString(String.valueOf(scores[1]), 
                    panelSize.width * 3 / 4, scoreTextSize);
        }
        
    }
    
    public class TimerListener implements ActionListener {
        
        private final ClassicPongGUI frame;
        
        private final GameModel model;

        public TimerListener(ClassicPongGUI frame, GameModel model) {
            this.frame = frame;
            this.model = model;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            int frameRate = model.getFrameRate();
            model.getBall().moveBall(frameRate);
            
            Point point = model.getBall().getCenterPoint();
            Paddle[] paddles = model.getPaddles();
            for (int i = 0; i < paddles.length; i++) {
                Rectangle p = paddles[i].getPaddle();
                int y = point.y - p.height / 2;
                if (i == 0) {
                    paddles[i].setPaddle(y);
                }
                model.contactsPaddle();
            }
            
            if (point.x < 0) {
                model.incrementScore(1, 1);
                model.resetBall();
            }
            
            if (point.x > frame.getPanelSize().width) {
                model.incrementScore(0, 1);
                model.resetBall();
            }
            
            frame.repaint();
        }
        
    }
    
    public class MovePaddleAction extends AbstractAction {

        private static final long serialVersionUID = 1L;
        
        private final int increment;

        private final ClassicPongGUI frame;
        
        private final GameModel model;

        public MovePaddleAction(ClassicPongGUI frame, GameModel model, 
                int increment) {
            this.frame = frame;
            this.model = model;
            this.increment = increment;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            model.getPaddles()[1].movePaddle(increment);
            frame.repaint();
        }
        
    }
    
    public class RestartAction extends AbstractAction {

        private static final long serialVersionUID = 1L;

        private final ClassicPongGUI frame;
        
        private final GameModel model;

        public RestartAction(ClassicPongGUI frame, GameModel model) {
            this.frame = frame;
            this.model = model;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            frame.stopTimer();
            model.restartGame();
            frame.startTimer();
            frame.repaint();
        }
        
    }
        
    public class GameModel {

        private int[] score;
        
        /** frames per second **/
        private final int frameRate;

        private Ball ball;

        private final Dimension panelSize;

        private Paddle[] paddles;

        public GameModel(Dimension panelSize) {
            this.panelSize = panelSize;
            this.score = new int[2];
            this.paddles = new Paddle[2];
            this.frameRate = 50;

            int ballRadius = 15;
            Point centerPoint = new Point(panelSize.width / 2, 
                    panelSize.height / 2);
            this.ball = new Ball(centerPoint, ballRadius, 
                    panelSize, Color.LIGHT_GRAY);

            int batWidth = panelSize.width / 32;
            int batHeight = panelSize.height / 4;
            int padding = 30;
            int x = padding;
            int y = calculateCenterY(batHeight);
            Rectangle r = new Rectangle(x, y, batWidth, batHeight);
            this.paddles[0] = new Paddle(r, panelSize.height, Color.RED);

            x = panelSize.width - padding - batWidth;
            r = new Rectangle(x, y, batWidth, batHeight);
            this.paddles[1] = new Paddle(r, panelSize.height, Color.BLUE);

            resetScore();
        }
        
        public void restartGame() {
            int batHeight = panelSize.height / 4;
            resetBall();
            paddles[0].setPaddle(calculateCenterY(batHeight));
            paddles[1].setPaddle(calculateCenterY(batHeight));
            resetScore();
        }
        
        public void resetBall() {
            ball.setCenterPoint(new Point(panelSize.width / 2, 
                    panelSize.height / 2));
        }

        private int calculateCenterY(int batHeight) {
            return (panelSize.height - batHeight) / 2;
        }
        
        public void contactsPaddle() {
            int radius = ball.getRadius();
            int diameter = radius + radius;
            Point point = ball.getCenterPoint();
            Rectangle b = new Rectangle(point.x - radius, 
                    point.y - radius, diameter, diameter);
            for (Paddle paddle : paddles) {
                if (paddle.getPaddle().intersects(b)) {
                    ball.reverseXDirection(frameRate);
                }
            }
            
        }

        public void resetScore() {
            score[0] = 0;
            score[1] = 0;
        }

        public void incrementScore(int index, int increment) {
            score[index] += increment;
        }

        public int[] getScore() {
            return score;
        }

        public Ball getBall() {
            return ball;
        }

        public Paddle[] getPaddles() {
            return paddles;
        }

        public int getFrameRate() {
            return frameRate;
        }

    }

    public class Paddle {

        private final int upperBound;

        private final Color color;

        private Rectangle paddle;

        public Paddle(Rectangle paddle, int upperBound, Color color) {
            this.paddle = paddle;
            this.upperBound = upperBound;
            this.color = color;
        }

        public void movePaddle(int increment) {
            paddle.y += increment;
            limitMovement();
        }
        
        public void setPaddle(int y) {
            paddle.y = y;
            limitMovement();
        }

        private void limitMovement() {
            paddle.y = Math.max(paddle.y, 0);
            int height = paddle.y + paddle.height;
            height = Math.min(height, upperBound);
            paddle.y = height - paddle.height;
        }

        public Rectangle getPaddle() {
            return paddle;
        }

        public Color getColor() {
            return color;
        }

    }

    public class Ball {
        
        /** Pixels per second **/
        private final double velocity;

        private final int radius;
        private int angle;

        private final Color color;

        private final Dimension panelSize;

        private Point centerPoint;
        
        private Point2D.Double doubleCenterPoint;
        
        private Random random;

        public Ball(Point centerPoint, int radius, Dimension panelSize, 
                Color color) {
            this.centerPoint = centerPoint;
            setDoubleCenterPoint(centerPoint);
            this.radius = radius;
            this.panelSize = panelSize;
            this.color = color;
            this.velocity = 300.0;
            this.random = new Random();
            setRandomAngle();
        }
        
        public void reverseXDirection(int frameRate) {
            angle = bounceXAngle(angle);
            angle += (angle < 0) ? 360 : 0;
            moveBall(frameRate);
        }
        
        public void moveBall(int frameRate) {
            double theta = Math.toRadians(angle);
            double distance = velocity / frameRate;
            doubleCenterPoint.x = Math.cos(theta) * distance + 
                    doubleCenterPoint.x;
            doubleCenterPoint.y = Math.sin(theta) * distance + 
                    doubleCenterPoint.y;
            
            if (doubleCenterPoint.y < radius) {
                double adjustment = radius - doubleCenterPoint.y;
                doubleCenterPoint.y += adjustment;
                angle = bounceYAngle(angle);
            }
            
            if ((doubleCenterPoint.y + radius) > panelSize.height) {
                double adjustment = panelSize.height - 
                        doubleCenterPoint.y - radius;
                doubleCenterPoint.y += adjustment;
                angle = bounceYAngle(angle);
            }
            
            int x = (int) Math.round(doubleCenterPoint.x);
            int y = (int) Math.round(doubleCenterPoint.y);
            this.centerPoint = new Point(x, y);
        }
        
        private int bounceXAngle(int angle) {
            return 180 - angle;
        }

        
        private int bounceYAngle(int angle) {
            return 360 - angle;
        }
        
        public Point getCenterPoint() {
            return centerPoint;
        }

        public void setCenterPoint(Point centerPoint) {
            this.centerPoint = centerPoint;
            setRandomAngle();
            setDoubleCenterPoint(centerPoint);
        }

        private void setDoubleCenterPoint(Point centerPoint) {
            this.doubleCenterPoint = 
                    new Point2D.Double(centerPoint.x, centerPoint.y);
        }
        
        private void setRandomAngle() {
            int[] angles = {30, 150, 210, 330 };
            this.angle = angles[random.nextInt(angles.length)];
        }

        public int getRadius() {
            return radius;
        }

        public Color getColor() {
            return color;
        }

    }

}
 类似资料:
  • 问题内容: 我在想类似的东西: 哪种Java JSON库最适合这种流畅的构建? 更新 :我包GSON,并得到几乎理想的结果...... 问题答案: 我正在使用org.json库,发现它很好并且很友好。 例: 输出:

  • 本文向大家介绍我们如何在Java中的JSONObject中添加JSONArray?,包括了我们如何在Java中的JSONObject中添加JSONArray?的使用技巧和注意事项,需要的朋友参考一下 甲的JSONObject 可以从一个字符串解析文本以产生映射样对象和JSONArray 可以从一个字符串解析文本以产生向量样的对象。我们还可以通过首先创建一个包含很少项目的JSONArray并将这些项

  • 我在用Java做一个2D游戏,我用KeyListener和一些布尔值来检测按键。但问题是,如果我按住一个键,玩家就不会移动半秒钟,然后开始移动。有人知道怎么修吗? public void键按下(...){PlayerX+=3;}如有任何答复,不胜感激,谢谢。

  • 我有以下代码: 在这部分代码中: 如果存在过滤器,则将过滤器应用于流; 想要对此流进行一些偏移和限制,但这不起作用,因为“应该只对一个流进行一次操作(调用中间或终端流操作)”。 映射到dto对象并收集为列表。 如何以其他方式进行流操作skip()和limit()。提前感谢。

  • 3点的面试等到3:30面上,然后十分钟就结束了 我发现秋招后期基本没遇到八股文问题了 1.自我介绍 2.实习内容 3.项目内容 4.是否玩过游戏 5.问工作地能否接受 6.然后面试官介绍工作内容 #校招##秋招#

  • 问题内容: 我添加了AsyncTask来将网络操作卸载到后台线程。我需要确保UI操作位于UI线程上,因此我想在Activity中使用runOnUiThread()。 谢谢你的帮助 WifiApManager connect.java 编辑 我想在TextView中显示已处理的文本 问题答案: 我添加了AsyncTask来将网络操作卸载到后台线程。我需要确保UI操作位于UI线程上,因此我想在Acti