Программа не рисует экран правильно

Я создавал короткую программу, которая в основном рисует космический корабль на JPanel и слушает ключи, которые говорят программе стрелять пулями. Проблема в том, что это даже не рисование космического корабля или пуль на экране. Я также подозреваю, что клавиатурные привязки могут не работать, так как это было предыдущей проблемой (которую я мог или не мог исправить), но основной проблемой остается тот факт, что мой экран не окрашивается. Вот мой код:

public enum Direction {
    LEFT, RIGHT, SPACE
}

import javax.swing.JFrame;

public class Main {
    public static void main(String[] args) {
        JFrame frame;

        Ship s1;
        Shoot shoot;

        // Set the frame up
        frame = new JFrame();
        frame.setSize(400, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setVisible(true);

        // Get some more necessary objects
        s1 = new Ship();
        shoot = new Shoot(s1);
        frame.getContentPane().add(shoot);
        s1.setShoot(shoot);

        // Threads
        Thread ship = new Thread(s1);
        ship.start();
    }
}

import java.awt.Graphics;
import java.awt.event.KeyEvent;

import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

public class Shoot extends JPanel {

    Ship s1;

    public Shoot(Ship s1) {
        this.s1 = s1;

        addKeyBinding(KeyEvent.VK_LEFT, "left.pressed", new MoveAction(true, s1, Direction.LEFT), true);
        addKeyBinding(KeyEvent.VK_LEFT, "left.released", new MoveAction(false, s1, Direction.LEFT), false);

        addKeyBinding(KeyEvent.VK_RIGHT, "right.pressed", new MoveAction(true, s1, Direction.RIGHT), true);
        addKeyBinding(KeyEvent.VK_RIGHT, "right.released", new MoveAction(false, s1, Direction.RIGHT), false);

        addKeyBinding(KeyEvent.VK_SPACE, "space.pressed", new MoveAction(true, s1, Direction.SPACE), true);
        addKeyBinding(KeyEvent.VK_SPACE, "space.released", new MoveAction(false, s1, Direction.SPACE), false);

        setDoubleBuffered(true);
    }

    @Override
    public void paintComponent(Graphics g) {
        // Draw the ship
        super.paintComponent(g);
        s1.draw(g);
        g.fill3DRect(40, 50, 10, 10, false);
    }

    protected void addKeyBinding(int keyCode, String name, Action action, boolean keyPressed) {
        if (keyPressed) {
            addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0, false), name, action);
        } else {
            addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0, true), name, action);
        }
    }

    protected void addKeyBinding(KeyStroke keyStroke, String name, Action action) {
        InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
        ActionMap actionMap = getActionMap();
        inputMap.put(keyStroke, name);
        actionMap.put(name, action);
    }

}

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;

public class Ship implements Runnable {
    int x, y, xDirection, bx, by;
    boolean readyToFire, shooting = false;
    Rectangle bullet;
    Shoot shoot;

    public Ship() {
        x = 175;
        y = 275;
        bullet = new Rectangle(0, 0, 3, 5);
    }

    public void draw(Graphics g) {
        // System.out.println("draw() called");
        g.setColor(Color.BLUE);
        g.fillRect(x, y, 40, 10);
        g.fillRect(x + 18, y - 7, 4, 7);
        if (shooting) {
            g.setColor(Color.RED);
            g.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
        }
        shoot.repaint();
    }

    public void move() {
        x += xDirection;
        if (x <= 0)
            x = 0;
        if (x >= 360)
            x = 360;
        shoot.repaint();
    }

    public void shoot() {
        if (shooting) {
            bullet.y--;
            shoot.repaint();
        }
    }

    public void setXDirection(int xdir) {
        xDirection = xdir;
    }

    public void setShoot(Shoot shoot) {
        this.shoot = shoot;
    }

    @Override
    public void run() {
        try {
            while (true) {
                shoot();
                move();
                Thread.sleep(5);
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

    }
}

import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.util.HashSet;

import javax.swing.AbstractAction;

public class MoveAction extends AbstractAction {

    boolean pressed;
    Ship s1;
    Direction dir;
    private Set<Direction> movement;

    public MoveAction(boolean pressed, Ship s1, Direction dir) {
        System.out.println("moveaction class");
        movement = new HashSet<Direction>();
        this.pressed = pressed;
        this.s1 = s1;
        this.dir = dir;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        try {
            if (movement.contains(Direction.LEFT)) {
                if (pressed) {
                    s1.setXDirection(-1);
                } else {
                    s1.setXDirection(0);
                }
            } else if (movement.contains(Direction.RIGHT)) {
                if (pressed) {
                    s1.setXDirection(1);
                } else {
                    s1.setXDirection(0);
                }
            } else if (movement.contains(Direction.SPACE)) {
                if (pressed) {
                    if (s1.bullet == null)
                        s1.readyToFire = true;
                    if (s1.readyToFire) {
                        s1.bullet.x = s1.x + 18;
                        s1.bullet.y = s1.y - 7;
                        s1.shooting = true;
                    }
                } else {
                    s1.readyToFire = false;
                    if (s1.bullet.y <= -7) {
                        s1.bullet = null;
                        s1.shooting = false;
                        s1.bullet = null;
                        s1.bullet = new Rectangle(0, 0, 0, 0);
                        s1.readyToFire = true;
                    }
                }
            }
        } catch (NullPointerException ex) {
            System.out.println("NullPointerException");
        }
    }

Ответы на вопрос(2)

Ваш ответ на вопрос