Java GUI编程实践2:坦克大战


前言

本项目实现一个简单的坦克游戏程序1。游戏开始时,用户通过键盘操纵坦克移动和射击,与敌人坦克交战,最终记录被击毁次数和击毁敌方坦克数量。

程序功能设计要求

  1. 菜单界面。初始界面显示文字“stage 1”,单击菜单中的“开始”进入游戏界面。
  2. 我方坦克。绘制我方坦克,颜色为红色,我方坦克根据方向键上、下、左、右、移动,当按下空格键时,我方坦克发射红色子弹,当我方坦克子弹击中敌方坦克时,出现爆炸效果,敌方坦克消失,短暂时间后,在初始位置重新生成。
  3. 敌方坦克。绘制10个敌方坦克,颜色为蓝色,敌方坦克随机移动,敌方坦克根据自己的运动方向发射蓝色子弹,当敌方坦克子弹打中我方坦克,出现爆炸效果,我方坦克消失,短暂时间后,在初始位置重新生成。

项目解析

这个小游戏是用IntelliJ IDEA编写的,共有6个java文件:

* TankGameJFrame.java  # 提供进入程序的main()方法,继承JFrame类,实现GUI框架
* Tank.java # 存储我方坦克相关数据的类
* eTank.java # 存储敌方坦克相关数据,实现Runnable接口,用线程实现坦克移动和发射子弹
* Shot.java # 存储子弹相关数据,实现Runnable接口,用线程实现子弹的发射
* Bomb.java # 存储爆炸图片,当坦克被击中时调用
* MyJPanel.java # 游戏场景界面,内有paint()方法,绘制敌我坦克交战的画面

菜单界面开发

程序主界面分为上下两部分,North是菜单,Center是卡片布局,叠放两个JPanel,一个初始面板,显示标签“stage 1”,一个对战面板,为一个MyJPanel的对象。

具体实现代码如下:

		jPanelCenter = new JPanel();
        cardLayout = new CardLayout();
        jPanelCenter.setLayout(cardLayout);
        getContentPane().add(jPanelCenter, BorderLayout.CENTER);

        jPanelFirst = new JPanel();
        jPanelFirst.setLayout(null);
        jPanelFirst.setPreferredSize(new Dimension(800, 600));
        jPanelFirst.setBackground(new Color(120, 100, 156));
        
        label = new Label("Stage: 1");
        label.setBounds(100, 50, 120, 30);
        label.setFont(new Font("stfangsong", 1, 20));
        label.setForeground(new Color(255, 255, 255));
        
        jPanelFirst.add(label);
        jPanelCenter.add("first", jPanelFirst);
        cardLayout.show(jPanelCenter, "first");

        jMenuBar1 = new JMenuBar();
        setJMenuBar(jMenuBar1);
        jMenuGame = new JMenu();
        jMenuBar1.add(jMenuGame);
        jMenuGame.setText("游戏(G)");
        jMenuItemStart = new JMenuItem();
        jMenuGame.add(jMenuItemStart);
        jMenuItemStart.setText("开始");
        jSeparator1 = new JSeparator();
        jMenuGame.add(jSeparator1);
        jMenuItemStart.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                tankPanel = new MyJPanel();
                jPanelCenter.add("game", tankPanel);
                cardLayout.show(jPanelCenter, "game");
                Thread t = new Thread(tankPanel);
                t.start();
                addKeyListener(tankPanel);
            }
        });
        jMenuItemSave = new JMenuItem();
        jMenuGame.add(jMenuItemSave);
        jMenuItemSave.setText("保存");
        jSeparator2 = new JSeparator();
        jMenuGame.add(jSeparator2);
        jMenuItemExit = new JMenuItem();
        jMenuGame.add(jMenuItemExit);
        jMenuItemExit.setText("退出");
        jMenuItemExit.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                System.exit( 0 );
            }
        });
        jMenuSet = new JMenu();
        jMenuBar1.add(jMenuSet);
        jMenuSet.setText("设置(T)");
        jMenuHelp = new JMenu();
        jMenuBar1.add(jMenuHelp);
        jMenuHelp.setText("帮助(P)");

在JMenuItem“开始”事件响应子程序中,建立了MyJPanel类的对象,然后卡片布局切换到该对象面板,开启线程是因为要每隔100毫秒刷新对战面板中的场景,最后为对战面板添加了键盘输入监听器。

坦克的绘制

坦克的外形分为左边矩形框、中间矩形框、右边矩形框、圆形和直线,如图:
Java GUI编程实践三:坦克大战
具体的参数如下:

	g.fill3DRect(t.x, t.y, 5, 30, false); // 左边矩形框
	g.fill3DRect(t.x + 5, t.y + 5, 10, 20, false); // 中间矩形框
	g.fill3DRect(t.x + 15, t.y, 5, 30, false); // 右边矩形框
	g.drawOval(t.x + 8, t.y + 11, 4, 4); // 圆形
	g.drawLine(t.x + 10, t.y + 15, t.x + 10, t.y + 30); // 直线

这样画出来是朝上的坦克,朝右、朝下、朝左的坦克绘制原理是一样的,只需要调整相应参数的值,具体请看完整源代码。

实现我方坦克运动

让MyJPanel实现KeyListener接口,然后添加如下代码:

	@Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_UP) {
            TankGameJFrame.lYTank1.moveUp();
        } else if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
            TankGameJFrame.lYTank1.moveRight();
        } else if(e.getKeyCode() == KeyEvent.VK_DOWN) {
            TankGameJFrame.lYTank1.moveDown();
        } else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
            TankGameJFrame.lYTank1.moveLeft();
        } else if(e.getKeyCode() == KeyEvent.VK_SPACE) {
            TankGameJFrame.lYTank1.showShot();
        }
        this.repaint();
    }

实现子弹飞翔

让Shot.java类实现Runnable接口,添加run()函数:

	@Override
    public void run() {
        while(isLive) {
            try {
                Thread.sleep(20); // 休眠20毫秒
            } catch(InterruptedException e) {}

            if(direction == 0) {  // 0 - 方向向上
                this.setY(y - speed);
                if(this.getY() < 0) {
                    this.isLive = false;
                    break;
                }
            }
            if(direction == 1) { // 1 - 方向向右
                this.setX(x + speed);
                if(this.getX() > 800) {
                    this.isLive = false;
                    break;
                }
            }
            if(direction == 2) { // 2 - 方向向下
                this.setY(y + speed);
                if(this.getY() > 600) {
                    this.isLive = false;
                    break;
                }
            }
            if(direction == 3) { // 3 - 方向向左
                this.setX(x - speed);
                if(this.getX() < 0) {
                    this.isLive = false;
                    break;
                }
            }
        }
    }

源代码

完整的源代码请在GitCode中下载查看:下唐人 / tank_game · GitCode

运行

该项目已经编译好可执行JAR包,可直接运行。方法是打开终端,然后输入:

java -jar tank_game.jar

运行结果展示

Java GUI编程实践三:坦克大战


  1. Java程序设计实战教程——基于成果导向. 北京理工大学出版社. 2022.2 ↩︎

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

下唐人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值