I recently created pong game using Java. This is my first time not copying any code from the internet or using any help. While it does work, my code feels well written but no streamlined or smooth (other than the fact that I made additional classes that would help create further code in this project). When playing it, it also does go through the paddle sometimes. Here's the code:Mainimport javax.swing.JFrame;public class Main {    public static void main(String[] args) {        JFrame frame = new JFrame();        View view = new View();        Model model = new Model(view);        frame.setSize(750, 750);        frame.getContentPane().add(view);        frame.setVisible(true);        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    }}Viewimport java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.Rectangle;import javax.swing.AbstractAction;import javax.swing.ActionMap;import javax.swing.InputMap;import javax.swing.JPanel;import javax.swing.KeyStroke;public class View extends JPanel {    Model model;    Rectangle bounds;    public View() {        setBackground(Color.BLACK);        bounds = new Rectangle(0, 0, 705, 670);    }    public void setModel(Model model) {        this.model = model;    }    public void addKeyBinding(String name, int keyEvent, boolean pressed, AbstractAction action) {        InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);        ActionMap actionMap = getActionMap();        inputMap.put(KeyStroke.getKeyStroke(keyEvent, 0, !pressed), name);        actionMap.put(name, action);    }    @Override    public void paintComponent(Graphics g) {        super.paintComponent(g);        if (model.getEntities() != null) {            for (Entity entity : model.getEntities()) {                entity.paint(g);            }            g.setColor(Color.BLUE);            g.setFont(new Font(Arial, 1, 20));            g.drawString(model.getPaddleScore(1) +  :  + model.getPaddleScore(2), 350, 20);        } else {            System.out.println(Something is wrong with the entities...);        }    }    @Override    public Rectangle getBounds() {        return bounds;    }}Entityimport java.awt.Dimension;import java.awt.Graphics;import java.awt.Point;public interface Entity {    public Dimension getSize();    public Point getLocation();    public void setLocation(Point p);    public void paint(Graphics g);}Paddleimport java.awt.Color;import java.awt.Dimension;import java.awt.Graphics;import java.awt.Point;import java.awt.event.KeyEvent;public class Paddle implements Entity {    int score = 0;    int paddleNum;    int paddleX = 0, paddleY = 0;    View view;    Point location = new Point(0, 0);    public Paddle(int paddleNum) {        this.paddleNum = paddleNum;    }    public void createBindings() {        if (paddleNum == 1) {            view.addKeyBinding(leftup.pressed, KeyEvent.VK_W, true, new LeftAction(Direction.LEFT_UP, true));            view.addKeyBinding(leftup.released, KeyEvent.VK_W, false, new LeftAction(Direction.LEFT_UP, false));            view.addKeyBinding(leftdown.pressed, KeyEvent.VK_S, true, new LeftAction(Direction.LEFT_DOWN, true));            view.addKeyBinding(leftdown.released, KeyEvent.VK_S, false, new LeftAction(Direction.LEFT_DOWN, false));        } else {            view.addKeyBinding(rightup.pressed, KeyEvent.VK_UP, true, new RightAction(Direction.RIGHT_UP, true));            view.addKeyBinding(rightup.released, KeyEvent.VK_UP, false, new RightAction(Direction.RIGHT_UP, false));            view.addKeyBinding(rightdown.pressed, KeyEvent.VK_DOWN, true,                    new RightAction(Direction.RIGHT_DOWN, true));            view.addKeyBinding(rightdown.released, KeyEvent.VK_DOWN, false,                    new RightAction(Direction.RIGHT_DOWN, false));        }    }    @Override    public Dimension getSize() {        return new Dimension(25, 100);    }    @Override    public Point getLocation() {        return new Point(location);    }    @Override    public void setLocation(Point p) {        location = p;    }    public void setView(View view) {        this.view = view;    }    public void resetScore() {        score = 0;    }    public void increaseScore() {        score++;    }    public int getScore() {        return score;    }    @Override    public void paint(Graphics g) {        g.setColor(Color.WHITE);        g.fillRect(getLocation().x, getLocation().y, getSize().width, getSize().height);    }}Ballimport java.awt.Color;import java.awt.Dimension;import java.awt.Graphics;import java.awt.Point;public class Ball implements Entity {    Point location = new Point(0, 0);    int x = 0, y = 0;    public Ball() {    }    @Override    public Dimension getSize() {        return new Dimension(20, 20);    }    @Override    public Point getLocation() {        return new Point(location);    }    @Override    public void setLocation(Point p) {        location = p;    }    public void setX(int x) {        this.x = x;    }    public int getX() {        return x;    }    public void setY(int y) {        this.y = y;    }    public int getY() {        return y;    }    @Override    public void paint(Graphics g) {        g.setColor(Color.RED);        g.fillOval(getLocation().x, getLocation().y, getSize().width, getSize().height);    }}Modelimport java.awt.Point;import java.awt.Rectangle;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.util.ArrayList;import java.util.HashSet;import java.util.List;import java.util.Set;import javax.swing.JOptionPane;import javax.swing.Timer;public class Model {    Paddle paddle1;    Paddle paddle2;    Ball ball;    static Set<Direction> keys = new HashSet<Direction>(25);    Timer timer;    boolean first = false;    boolean direction = false, axis = false;    double ballX = 0, ballY = 0;    double p1X = 0, p1Y = 0;    double p2X = 0, p2Y = 0;    double incline = -0.5;    List<Entity> entities = new ArrayList<Entity>(20);    View view;    public Model(View view) {        this.view = view;        startTimer();        view.setModel(this);    }    public void startTimer() {        timer = new Timer(2, new ActionListener() {            @Override            public void actionPerformed(ActionEvent arg0) {                update(view.getBounds());                view.repaint();            }        });        timer.start();    }    public void update(Rectangle bounds) {        if (paddle1 == null || paddle2 == null || ball == null) {            paddle1 = new Paddle(1);            paddle2 = new Paddle(2);            ball = new Ball();            ballX = 300;            ballY = 300;            p1X = 30;            p2X = 650;            p1Y = 350;            p2Y = 350;            paddle1.setView(view);            paddle2.setView(view);            paddle1.createBindings();            paddle2.createBindings();            entities.add(paddle1);            entities.add(paddle2);            entities.add(ball);        }        if (paddle1.getScore() > 7) {            JOptionPane.showMessageDialog(view, Player 1 has won!);            paddle1.resetScore();            paddle2.resetScore();        } else if (paddle2.getScore() > 7) {            JOptionPane.showMessageDialog(view, Player 2 has won!);            paddle1.resetScore();            paddle2.resetScore();        }        setDirection(direction, incline);        bounce();        // TODO Add functionality for changing ball location...        // TODO Don't forget to use collision detection!!!        if (keys.contains(Direction.LEFT_UP)) {            p1Y -= 2;        } else if (keys.contains(Direction.LEFT_DOWN)) {            p1Y += 2;        }        if (keys.contains(Direction.RIGHT_UP)) {            p2Y -= 2;        } else if (keys.contains(Direction.RIGHT_DOWN)) {            p2Y += 2;        }        paddle1.setLocation(new Point((int) p1X, (int) p1Y));        paddle2.setLocation(new Point((int) p2X, (int) p2Y));        ball.setLocation(new Point((int) ballX, (int) ballY));    }    public Entity[] getEntities() {        return entities.toArray(new Entity[0]);    }    public void bounce() {        // TODO Paddle collision detection        if (ballX < p1X + paddle1.getSize().width && ballY > p1Y && ballY < p1Y + paddle2.getSize().height) {            direction = true;        }        if (ballX + ball.getSize().width > p2X && ballY > p2Y && ballY < p2Y + paddle1.getSize().height) {            direction = false;        }        if (ballX < view.getBounds().x) {            paddle2.increaseScore();            direction = !direction;            ballX = 300;            ballY = 300;            // direction = true;        }        if (ball.getLocation().x > view.getBounds().x + view.getBounds().width) {            paddle1.increaseScore();            direction = !direction;            ballX = 300;            ballY = 300;            // direction = false;        }        if (ball.getLocation().y < view.getBounds().y) {            ballY++;            incline *= -1;        }        if (ball.getLocation().y > view.getBounds().height) {            ballY--;            incline *= -1;        }        /////////////        if (paddle1.getLocation().y < view.getBounds().y) {            p1Y = view.getBounds().x - 1;        }        if (paddle1.getLocation().y + paddle1.getSize().height > view.getBounds().height + 22) {            p1Y = view.getBounds().height - paddle1.getSize().height + 22;        }        if (paddle2.getLocation().y < view.getBounds().y) {            p2Y = view.getBounds().x - 1;        }        if (paddle2.getLocation().y + paddle2.getSize().height > view.getBounds().height + 22) {            p2Y = view.getBounds().height - paddle2.getSize().height + 22;        }    }    public void setDirection(boolean Xdir, double inc) {        ballY += inc;        if (Xdir) {            ballX++;        } else if (!Xdir) {            ballX--;        }    }    public int getPaddleScore(int paddleNum) {        if (paddleNum == 1)            return paddle1.getScore();        else {            return paddle2.getScore();        }    }}LeftAction & RightActionimport java.awt.event.ActionEvent;import javax.swing.AbstractAction;public class LeftAction extends AbstractAction {    Direction dir;    boolean pressed;    public LeftAction(Direction dir, boolean pressed) {        this.dir = dir;        this.pressed = pressed;    }    @Override    public void actionPerformed(ActionEvent arg0) {        if (pressed) {            Model.keys.add(dir);        } else {            Model.keys.remove(dir);        }    }}import java.awt.event.ActionEvent;import javax.swing.AbstractAction;public class RightAction extends AbstractAction {    Direction dir;    boolean pressed;    public RightAction(Direction dir, boolean pressed) {        this.dir = dir;        this.pressed = pressed;    }    @Override    public void actionPerformed(ActionEvent e) {        if (pressed) {            Model.keys.add(dir);        } else {            Model.keys.remove(dir);        }    }}Directionpublic enum Direction {    LEFT_UP, LEFT_DOWN, RIGHT_UP, RIGHT_DOWN}Let me know what you think!
Java Swing Pong game
java;game;swing