关于gui界面跳转的问题

问题遇到的现象和发生背景

分别写了两快代码一个飞机大战一个gui连数据库登录,想把他们两连起来,登录然后开始游戏
然后出现了错误

问题相关代码,请勿粘贴截图

~~~
代码如下(重点部加粗)

package cn.zzy.game;
//主窗口
import cn.zzy.game.utils.GameUtils;
import cn.zzy.obj.*;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/*
 飞机游戏的主窗口
 */
//继承JFrame
public class MyGameFrame extends JFrame {

   // 游戏状态0未开始1游戏中2暂停3.通关失败4.通关成功
   public static int state = 0;
    //游戏得分
    public static int score = 0;

    //双缓存技术:重新创建一个空的图片,把所有组件先绘制在空的图片上面,把绘制好的图片一次性绘制到主窗口中
    //双缓存的图片
    Image offScreenImage = null;
    //窗口宽度
    int width =600;
    //窗口高度
    int height = 600;
    //游戏的重绘次数
    int count = 1;
    //敌机出现的次数
    int enemyCount = 0;

   //在窗口类中获取背景类的对象
   BgObj bgObj = new BgObj(GameUtils.bgImg,0,-2000,2);//y值于背景图高度有关
   // 创建我方飞机的对象  参数依次为飞机的图片,横坐标,纵坐标,宽高,移动速度,窗口引用当前对象
   public PlaneObj planeObj = new PlaneObj(GameUtils.planeImg,290,550,20,30,0,this);
   //敌方boss对象
   public BossObj bossObj = null;
   //我方子弹 ShellObj shellObj = new ShellObj(GameUtils.shellImg,planeObj.getX()+3,planeObj.getY()-16,14,29,5,this);

    //初始化窗口
    public void launchFrame(){
        //窗口标题
        this.setTitle("FIY");
        //设置窗口大小
        this.setSize(width,height);
        //设置窗口初始位置
        //this.setLocation(0,0);
        //窗口初始位置为中间
        this.setLocationRelativeTo(null);
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }//关闭窗口结束程序
        });
        this.setVisible(true); //使窗口可见

        GameUtils.gameObjList.add(bgObj);
        GameUtils.gameObjList.add(planeObj);
        //GameUtils.gameObjList.add(bossObj);

        //游戏的点击启动事件
        this.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getButton() == 1 && state == 0){ //按下鼠标左键&&游戏未开始
                    state = 1;
                    repaint();
                }
            }
        });
        //在launch方法中添加键盘的监听事件
        //暂停
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == 32){
                    switch (state){
                        case 1:
                            state = 2;
                            break;
                        case 2:
                            state = 1;
                            break;
                        default:
                    }
                }
                //keyPressed表示键盘的键按一下
                //空格键的代号为32
            }
        });

        //背景图不断移动,需要重复调用paint方法
        while (true){
            if (state == 1){
                createObj();
                repaint();
            }
            try {
                Thread.sleep(25);//线程休眠
                //每间隔25毫秒调用一次repaint方法
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public void paint(Graphics g) { //自动被调用,g相当于一支画笔
        if (offScreenImage == null){
            offScreenImage = createImage(width,height);
        }
       // 接着获取offScreenImage的画笔对象
        Graphics gImage = offScreenImage.getGraphics();
        //填充一个宽600高600的区域
        gImage.fillRect(0,0,width,height);

        if (state == 0){
            gImage.drawImage(GameUtils.bgImg, 0, 0, null);
            gImage.drawImage(GameUtils.bossImg, 220, 120, null);
            gImage.drawImage(GameUtils.explodeImg, 270, 350, null);
            GameUtils.drawWord(gImage,"点击开始游戏",Color.YELLOW,40,180,300);
//            gImage.setColor(Color.YELLOW);
//            gImage.setFont(new Font("仿宋",Font.BOLD,40));//仿宋,加粗,字体大小40
//            gImage.drawString("点击开始游戏",180,300);
        }
        if (state == 1){//运行中
            GameUtils.gameObjList.addAll(GameUtils.explodeObjList);
//            //将BgObj的paintSelf方法,绘制到state 1的代码块中
//            bgObj.paintSelf(gImage);
//            //在paint方法中,让飞机的对象调用自身的paintSelf方法
//            planeObj.paintSelf(gImage);
            for (int i = 0; i < GameUtils.gameObjList.size(); i++) {
                GameUtils.gameObjList.get(i).paintSelf(gImage);
            }
            GameUtils.gameObjList.removeAll(GameUtils.removeList);
        }
        if (state == 3){//游戏失败
            gImage.drawImage(GameUtils.explodeImg, planeObj.getX()-35, planeObj.getY()-50, null);
            GameUtils.drawWord(gImage,"GAME OVER",Color.RED,50,180,300);
        }
        if (state == 4){//游戏通关
            gImage.drawImage(GameUtils.explodeImg, bossObj.getX()+30, bossObj.getY(), null);
            GameUtils.drawWord(gImage,"游戏通关",Color.green,50,180,300);
        }
        //计分面板
        GameUtils.drawWord(gImage,score+"分",Color.green,40,30,100);
        //最后把新图片一次性绘制到主窗口中
        g.drawImage(offScreenImage,0,0,null);
        count++;
        System.out.println(GameUtils.gameObjList.size());
    }
    //子弹和敌机的越界消失
    //记住我方子弹,敌方子弹,敌方飞机他们移动后的坐标不能重复,否则会产生碰撞检测的错误

     //批量创建子弹和敌机
    void createObj(){
        //通过匿名类的方式创建子弹对象,并添加到shellObjList中
        //我方子弹
        if (count%15 == 0) {//每调用15次paint方法,才生产一颗子弹
            GameUtils.shellObjList.add(new ShellObj(GameUtils.shellImg, planeObj.getX() + 3, planeObj.getY() - 16, 14, 29, 5, this));
            //再通过索引获取 shellObjList的最后一个元素,将这个元素添加到gameObjList中
            GameUtils.gameObjList.add(GameUtils.shellObjList.get(GameUtils.shellObjList.size() - 1));
            //接着将之前绘制背景和飞机的图片和方法代码全部删掉
            //然后在launch 方法中,将所有要绘制的游戏物体,全部添加到gameObjList中
            //然后在paint方法中,state ==1的代码块下遍历gameObjList

        }
        //敌方飞机
        if (count%15 == 0) {//敌方飞机刷新次数
            GameUtils.enemyObjList.add(new EnemyObj(GameUtils.enemyImg,(int) (Math.random()*12)*50/*随机生成0-550之间是50倍数的随机数*/,0,49,36,5,this));//
            GameUtils.gameObjList.add(GameUtils.enemyObjList.get(GameUtils.enemyObjList.size()-1));
            //将enemyObjList中的最后一个元素添加到gameObjList中
            enemyCount++;
        }
        //敌方飞机子弹
        if (count%15 == 0 && bossObj != null) {
            GameUtils.bulletObjList.add(new BulletObj(GameUtils.bulletImg,bossObj.getX()+76,bossObj.getY()+85,15,25,5,this));
            GameUtils.gameObjList.add(GameUtils.bulletObjList.get(GameUtils.bulletObjList.size()-1));
        }
        if (enemyCount > 30 && bossObj == null){
            bossObj = bossObj = new BossObj(GameUtils.bossImg,250,20,155,100,5,this);
            GameUtils.gameObjList.add(bossObj);
        }
    }
   ** public static void main(String[] args) {
     Login login = new Login();
        login.launchFrame2();
    }
}**

—————————————————————————————————————————————————————————————

package cn.zzy.game;

import cn.zzy.game.utils.MysqlUtil;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;


public class Login extends JFrame{
    public static void launchFrame2(){
        JFrame jFrame = new JFrame("登录");
        jFrame.setLayout(new FlowLayout(FlowLayout.LEFT));
        jFrame.setBounds(460,300,300,200);

        JLabel label1 = new JLabel("账号");
        JTextField usernameText = new JTextField("",22);
        JLabel label2 = new JLabel("密码");
        JPasswordField passwordText = new JPasswordField("",22);
        JTextField out = new JTextField("登录状态",26);
        JButton button = new JButton("登录");

        jFrame.add(label1);
        jFrame.add(usernameText);
        jFrame.add(label2);
        jFrame.add(passwordText);
        jFrame.add(out);
        jFrame.add(button);

        jFrame.setResizable(false);//禁止调大小
        button.setSize(40,20);
        jFrame.setVisible(true);
        button.addActionListener(new AbstractAction() {
            //boolean flag = false;
            @Override
            public void actionPerformed(ActionEvent e) {
                String username= usernameText.getText();
                String pwd = passwordText.getText();
                try { //ctrl+alt+t:快速包裹
                    Connection connection = MysqlUtil.getConnection();
                    Statement statement = connection.createStatement();
                    ResultSet rs = statement.executeQuery("select  * from user");
                   **int flag =0;
                    while (rs.next()){
                        if (rs.getString(2).equals(username) && rs.getString(3).equals(pwd)){
                            flag = 1;
                            out.setText("成功");
                            MyGameFrame f = new MyGameFrame();
                            f.launchFrame();//调用
                        }**
                    }
                    if (flag == 0){
                        out.setText("失败");
                    }

                } catch (Exception exception) {
                    exception.printStackTrace();
                }finally {
                    try {
                        MysqlUtil.close();
                    } catch (SQLException throwables) {
                        throwables.printStackTrace();
                    }
                }

            }

        });
        jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//默认关闭
    }

}

运行结果及报错内容

img

我的解答思路和尝试过的方法
我想要达到的结果


启动顺序搞反了吧,应该是把main方法放在Login类里面,先启动Login类,登录成功再显示游戏窗口。