Java 坦克大战项目学习阶段记录及总结

/*首先要声明的是,这个并不是坦克大战项目编写细节的过程分享,只是个人的阶段学习记录及总结,坦克大战的项目可以参考B站上韩顺平老师的视频教学*/

阶段一:

小总结:今天刚开始,跟着视频一起学习编写坦克大战的项目,首先,我觉得对于编写一个项目,最重要的就是要构思好一个框架,比如,你写一个项目,要设几个类,每个类分别有什么作用。但是也不要太过于想提前想好要写什么方法(函数),我们只需要先构思好大的类,具体的,等到我们自己去写的时候,是可以慢慢再实现的。最重要的,一定是首先要有一个明确的思路。比如这个坦克大战的编写,目前写了五个类:主程序类,游戏界面绘制类,坦克基类,我的坦克类,敌方坦克类。思路是:先进行游戏界面的绘制,再画出坦克的图形,此时是静态的。然后再到动态的坦克编写,今天最后完成的,就是敌方坦克的绘制,因为敌方坦克会有许多特有的方法,所以要单独成一个类。因此,我对面向对象设计,或者说是对程序设计的感受是,最重要的就是有一个明确的思路,有一个框架,里面的内容是可以慢慢去填充的。  

今天“手痒”测试了一下,给敌方一个坦克添加了键盘监听事件,让我觉得写成之后,甚至可以写一个双人1V1的坦克大战,但是我在移动的时候,我发现,一次只能移动一辆坦克,要想同时移动两辆坦克,目前肯定是不行的。下一个阶段是学习多线程,因此我想到了实现多线程,应该就是为了多个坦克可以同时移动。

以下是今天的代码记录截图:

五个类(根据英文应该能猜到各自对应什么) 

1.主程序类(TankGame01)

package com.wak.TankGame01Version;

import javax.swing.*;

/*坦克大战游戏主程序*/
public class TankGame01 extends JFrame {
    public static void main(String[] args) {
        //启动!
        new TankGame01();
    }

    //定义GamePanel,创建游戏环境
    GamePanel gamePanel = null;

    //加载游戏环境
    public TankGame01(){
        //1.0版本
        this.setTitle("坦克大战1.0");
        //加载游戏环境
        gamePanel = new GamePanel();
        //将游戏区域加载到界面里
        this.add(gamePanel);
        //将键盘监听器加载到界面里
        this.addKeyListener(gamePanel);
        //设置界面可视化
        this.setVisible(true);
        //设置界面的大小
        this.setSize(1000,800);
        //设置界面可关闭
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

}

2.游戏界面绘制类(GamePanel)

package com.wak.TankGame01Version;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

/*坦克大战的绘图区域*/
public class GamePanel extends JPanel implements KeyListener {
    //定义一个自己的坦克
    MyTank myTank = null;

    //创建敌方坦克
    Vector<OpTank> opTanks = new Vector<>();
    //设置敌方坦克数量
    int opTanksSize = 3;

    public GamePanel(){
        myTank = new MyTank(200,600);   //初始化坦克的位置
        myTank.setSpeed(3); //设置坦克的速度

        for(int i=0;i<opTanksSize;i++){
            OpTank opTank = new OpTank((100 * i + 100),0);
            opTank.setDirect(2);
            opTanks.add(opTank);
        }
    }


    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillRect(0,0,1000,800);    //默认背景是黑色

        //画出坦克-封装方法
        DrawTank(myTank.getX(),myTank.getY(),g,myTank.getDirect(),0);
        DrawTank(myTank.getX(),myTank.getY(),g,myTank.getDirect(),0);
        for(int i=0;i<opTanks.size();i++){
            //取出敌方坦克
            OpTank opTank = opTanks.get(i);
            DrawTank(opTank.getX(),opTank.getY(),g,opTank.getDirect(),1);
        }
    }

    //编写方法,画出坦克

    /**
     *
     * @param x 坦克的x坐标
     * @param y 坦克的y坐标
     * @param g 画笔
     * @param direct    坦克方向(上下左右)
     * @param type  坦克类型
     */
    public void DrawTank(int x,int y,Graphics g,int direct,int type){
        //坦克的类型
        switch (type){
            case 0: //自己的坦克
                g.setColor(Color.CYAN);
                break;
            case 1: //敌人的坦克
                g.setColor(Color.RED);
                break;
        }

        switch (direct){
            case 0: //表示向上
                g.fill3DRect(x,y,10,60,false);  //坦克的左边轮子
                g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
                g.drawLine(x,y + 20,x + 10,y + 20);
                g.drawLine(x,y + 30,x + 10,y + 30);
                g.drawLine(x,y + 40,x + 10,y + 40);
                g.drawLine(x,y + 50,x + 10,y + 50);

                g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
                g.drawLine(x + 40,y + 10,x + 50,y + 10);     //坦克右轮的履带
                g.drawLine(x + 40,y + 20,x + 50,y + 20);
                g.drawLine(x + 40,y + 30,x + 50,y + 30);
                g.drawLine(x + 40,y + 40,x + 50,y + 40);
                g.drawLine(x + 40,y + 50,x + 50,y + 50);

                g.fill3DRect(x + 10,y + 10,30,40,false);    //坦克的身体
                g.fillOval(x + 10,y + 15,30,30);    //坦克的炮盖
                g.drawLine(x + 25,y + 30,x + 25,y); //坦克的炮筒
                break;

            case 1: //表示向右
                g.fill3DRect(x,y,60,10,false);  //坦克左边的轮子
                g.drawLine(x + 10,y,x + 10 ,y + 10);    //坦克左轮的履带
                g.drawLine(x + 20,y,x + 20 ,y + 10);
                g.drawLine(x + 30,y,x + 30 ,y + 10);
                g.drawLine(x + 40,y,x + 40 ,y + 10);
                g.drawLine(x + 50,y,x + 50 ,y + 10);


                g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
                g.drawLine(x + 10,y + 40,x + 10,y + 50);
                g.drawLine(x + 20,y + 40,x + 20,y + 50);
                g.drawLine(x + 30,y + 40,x + 30,y + 50);
                g.drawLine(x + 40,y + 40,x + 40,y + 50);
                g.drawLine(x + 50,y + 40,x + 50,y + 50);


                g.fill3DRect( x + 10,y + 10,40,30,false);   //坦克的身体
                g.fillOval(x + 15,y + 10,30,30);    //坦克的炮盖
                g.drawLine(x + 30,y + 25,x +60,y + 25); //坦克的炮筒
                break;

            case 2: //表示向下
                g.fill3DRect(x,y,10,60,false);  //坦克的左边轮子
                g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
                g.drawLine(x,y + 20,x + 10,y + 20);
                g.drawLine(x,y + 30,x + 10,y + 30);
                g.drawLine(x,y + 40,x + 10,y + 40);
                g.drawLine(x,y + 50,x + 10,y + 50);

                g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
                g.drawLine(x + 40,y + 10,x + 50,y + 10);    //坦克右轮的履带
                g.drawLine(x + 40,y + 20,x + 50,y + 20);
                g.drawLine(x + 40,y + 30,x + 50,y + 30);
                g.drawLine(x + 40,y + 40,x + 50,y + 40);
                g.drawLine(x + 40,y + 50,x + 50,y + 50);

                g.fill3DRect(x + 10,y + 10,30,40,false);    //坦克的身体
                g.fillOval(x + 10,y + 15,30,30);    //坦克的炮盖
                g.drawLine(x + 25,y + 30,x + 25,y + 60); //坦克的炮筒
                break;

            case 3: //表示向左
                g.fill3DRect(x,y,60,10,false);  //坦克左边的轮子
                g.drawLine(x + 10,y,x + 10 ,y + 10);    //坦克左轮的履带
                g.drawLine(x + 20,y,x + 20 ,y + 10);
                g.drawLine(x + 30,y,x + 30 ,y + 10);
                g.drawLine(x + 40,y,x + 40 ,y + 10);
                g.drawLine(x + 50,y,x + 50 ,y + 10);


                g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
                g.drawLine(x + 10,y + 40,x + 10,y + 50);
                g.drawLine(x + 20,y + 40,x + 20,y + 50);
                g.drawLine(x + 30,y + 40,x + 30,y + 50);
                g.drawLine(x + 40,y + 40,x + 40,y + 50);
                g.drawLine(x + 50,y + 40,x + 50,y + 50);


                g.fill3DRect( x + 10,y + 10,40,30,false);   //坦克的身体
                g.fillOval(x + 15,y + 10,30,30);    //坦克的炮盖
                g.drawLine(x + 30,y + 25,x,y + 25); //坦克的炮筒
                break;

            default:
                System.out.println("暂时没有处理");
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_W){
            myTank.setDirect(0);
            myTank.MoveUp();
        }else if(e.getKeyCode() == KeyEvent.VK_D){
            myTank.setDirect(1);
            myTank.MoveRight();
        }else if(e.getKeyCode() == KeyEvent.VK_S){
            myTank.setDirect(2);
            myTank.MoveDown();
        }else if(e.getKeyCode() == KeyEvent.VK_A){
            myTank.setDirect(3);
            myTank.MoveLeft();
        }
//        else if(e.getKeyCode() == KeyEvent.VK_UP){
//            opTanks.get(0).setDirect(0);
//            opTanks.get(0).MoveUp();
//        }else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
//            opTanks.get(0).setDirect(1);
//            opTanks.get(0).MoveRight();
//        }else if(e.getKeyCode() == KeyEvent.VK_DOWN){
//            opTanks.get(0).setDirect(2);
//            opTanks.get(0).MoveDown();
//        }else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
//            opTanks.get(0).setDirect(3);
//            opTanks.get(0).MoveLeft();
//        }
        this.repaint();

    }

    @Override
    public void keyReleased(KeyEvent e) {

    }
}

3.坦克基类(Tank)

package com.wak.TankGame01Version;

/*坦克的基类*/
public class Tank {
    private int x;  //坦克的横坐标
    private int y;  //坦克的纵坐标
    private int direct = 0; //坦克的方向
    private int speed = 1;  //坦克的速度

    public Tank(){
        this.x = 100;   //默认坦克的初始x坐标为100
        this.y = 100;   //默认坦克的初始y坐标为100
    }

    public Tank(int x,int y){   //自己设置坦克的初始x,y坐标
        this.x = x;
        this.y = y;
    }


    //设置坦克的x坐标
    public void setX(int x){
        this.x = x;
    }

    //设置坦克的y坐标
    public void setY(int y){
        this.y = y;
    }

    //获得坦克的x坐标
    public int getX(){
        return x;
    }

    //获得坦克的y坐标
    public int getY(){
        return y;
    }

    //设置坦克的方向
    public void setDirect(int direct){
        this.direct = direct;
    }

    //获得坦克的方向
    public int getDirect(){
        return direct;
    }

    //设置坦克的速度
    public void setSpeed(int speed){
        this.speed = speed;
    }

    //获得坦克的速度
    public int getSpeed(){
        return speed;
    }

    //坦克的上右下左移动
    public void MoveUp(){
        y -= speed;
    }
    public void MoveRight(){
        x += speed;
    }
    public void MoveDown(){
        y += speed;
    }
    public void MoveLeft(){
        x -= speed;
    }
}


4.我的坦克类(MyTank)

package com.wak.TankGame01Version;

/*自己的坦克*/
public class MyTank extends Tank{
    //创建一个坦克
    private MyTank myTank = null;
    //设置坦克的初始化坐标
    public MyTank(int x,int y){
        this.setX(x);
        this.setY(y);
    }


}

5.敌方坦克类(OpTank)

package com.wak.TankGame01Version;

public class OpTank extends Tank{
    private OpTank opTank = null;

    public OpTank(int x,int y){
        this.setX(x);
        this.setY(y);
    }


}

运行效果:(蓝色是我的坦克,红色是敌方坦克,蓝色坦克可以上下左右移动)

阶段二:

小总结:今天接续昨天的内容,完成了我的坦克的发射炮弹,敌方坦克发射子弹,敌方坦克消失,敌方坦克自由移动,以及控制坦克移动的范围。我发现到这里,才真正写到了坦克大战的比较核心的、难的部分,那就是多线程。先简要的说一下今天学习的编写思路吧:因为炮弹是我的和敌方坦克都有的,所以需要单独写一个类,所以今天加了一个Shot类,但是因为你要射击的时候,它也要在界面上移动,所以这时候就需要用到多线程,像敌方坦克发射炮弹,敌方坦克移动,都是要用到多线程,而其中的另一个关键就是,在哪里启动,而这其中有很多思路是很巧妙的,比如,对于控制坦克的移动范围,我以为要另外写一个方法去进行判断的时候,韩老师的思路就是直接在控制坦克上下左右移动的代码上进行一个if判断,这样直接且非常巧妙的解决了问题,再比如,绘制敌方坦克的时候,先判断一下敌方坦克是否存活,再进行绘制,这样又提高了代码的运行效率,等等等。我发现,对于写一个程序,甚至是一段代码,一定要先想一想,构思一下,确立好思路再动手,尽量发散一下思维。

以下是今天的代码记录截图:

六个类(根据英文应该能猜到各自对应什么) 

 1.主程序类(TankGame01)

package com.wak.TankGame01Version;

import javax.swing.*;

/*坦克大战游戏主程序*/
public class TankGame01 extends JFrame {
    public static void main(String[] args) {
        //启动!
        new TankGame01();
    }

    //定义GamePanel,创建游戏环境
    GamePanel gamePanel = null;

    //加载游戏环境
    public TankGame01(){
        //1.0版本
        this.setTitle("坦克大战1.0");
        //加载游戏环境
        gamePanel = new GamePanel();
        //将游戏区域加载到界面里
        this.add(gamePanel);
        //将游戏界面的炮弹线程加入到界面里
        Thread thread = new Thread(gamePanel);
        //启动子线程
        thread.start();
        //将键盘监听器加载到界面里
        this.addKeyListener(gamePanel);
        //设置界面可视化
        this.setVisible(true);
        //设置界面的大小
        this.setSize(1000,800);
        //设置界面可关闭
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

}

2.游戏界面绘制类(GamePanel)

package com.wak.TankGame01Version;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

/*坦克大战的绘图区域*/

//为了监听键盘事件,实现KeyListener
//
public class GamePanel extends JPanel implements KeyListener,Runnable{
    //定义一个自己的坦克
    MyTank myTank = null;

    //创建敌方坦克
    Vector<OpTank> opTanks = new Vector<>();
    //设置敌方坦克数量
    int opTanksSize = 3;

    public GamePanel(){
        myTank = new MyTank(200,600);   //初始化坦克的位置
        myTank.setSpeed(3); //设置坦克的速度

        for(int i=0;i<opTanksSize;i++){
            OpTank opTank = new OpTank((100 * i + 100),0);
            //设置方向
            opTank.setDirect(2);
            //启动敌人坦克线程
            new Thread(opTank).start();
            //给该opTank加入一颗炮弹
            Shot shot = new Shot(opTank.getX() + 25,opTank.getY() + 60,2);
            //存放到Vector中
            opTank.shots.add(shot);
            //启动线程对象
            new Thread(shot).start();
            //加入
            opTanks.add(opTank);
        }
    }


    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillRect(0,0,1000,800);    //默认背景是黑色

        //画出坦克-封装方法
        //画出我的坦克
        DrawTank(myTank.getX(),myTank.getY(),g,myTank.getDirect(),0);
        //画出敌人的坦克
        for(int i=0;i<opTanks.size();i++){
            //取出敌方坦克
            OpTank opTank = opTanks.get(i);
            //判断敌方坦克是否存活
            if(opTank.isLive) { //当敌人坦克是存活的时候,才去画
                DrawTank(opTank.getX(), opTank.getY(), g, opTank.getDirect(), 1);
                //画出敌人的坦克发出的炮弹
                for (int j = 0; j < opTank.shots.size(); j++) {
                    //取出子弹
                    Shot shot = opTank.shots.get(j);
                    //绘制
                    if (shot.isLive) {
                        g.setColor(Color.WHITE);
                        g.fill3DRect(shot.x, shot.y, 4, 4, false);
                    } else {
                        opTank.shots.remove(shot);
                    }
                }
            }

        }

        //画出我的坦克发出的炮弹
        if(myTank.shot != null && myTank.shot.isLive == true){
            g.setColor(Color.CYAN);
            g.fill3DRect(myTank.shot.x,myTank.shot.y,4,4,false);
        }



    }

    //编写方法,画出坦克

    /**
     *
     * @param x 坦克的x坐标
     * @param y 坦克的y坐标
     * @param g 画笔
     * @param direct    坦克方向(上下左右)
     * @param type  坦克类型
     */
    public void DrawTank(int x,int y,Graphics g,int direct,int type){
        //坦克的类型
        switch (type){
            case 0: //自己的坦克
                g.setColor(Color.CYAN);
                break;
            case 1: //敌人的坦克
                g.setColor(Color.RED);
                break;
        }

        switch (direct){
            case 0: //表示向上
                g.fill3DRect(x,y,10,60,false);  //坦克的左边轮子
                g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
                g.drawLine(x,y + 20,x + 10,y + 20);
                g.drawLine(x,y + 30,x + 10,y + 30);
                g.drawLine(x,y + 40,x + 10,y + 40);
                g.drawLine(x,y + 50,x + 10,y + 50);

                g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
                g.drawLine(x + 40,y + 10,x + 50,y + 10);     //坦克右轮的履带
                g.drawLine(x + 40,y + 20,x + 50,y + 20);
                g.drawLine(x + 40,y + 30,x + 50,y + 30);
                g.drawLine(x + 40,y + 40,x + 50,y + 40);
                g.drawLine(x + 40,y + 50,x + 50,y + 50);

                g.fill3DRect(x + 10,y + 10,30,40,false);    //坦克的身体
                g.fillOval(x + 10,y + 15,30,30);    //坦克的炮盖
                g.drawLine(x + 25,y + 30,x + 25,y); //坦克的炮筒
                break;

            case 1: //表示向右
                g.fill3DRect(x,y,60,10,false);  //坦克左边的轮子
                g.drawLine(x + 10,y,x + 10 ,y + 10);    //坦克左轮的履带
                g.drawLine(x + 20,y,x + 20 ,y + 10);
                g.drawLine(x + 30,y,x + 30 ,y + 10);
                g.drawLine(x + 40,y,x + 40 ,y + 10);
                g.drawLine(x + 50,y,x + 50 ,y + 10);


                g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
                g.drawLine(x + 10,y + 40,x + 10,y + 50);
                g.drawLine(x + 20,y + 40,x + 20,y + 50);
                g.drawLine(x + 30,y + 40,x + 30,y + 50);
                g.drawLine(x + 40,y + 40,x + 40,y + 50);
                g.drawLine(x + 50,y + 40,x + 50,y + 50);


                g.fill3DRect( x + 10,y + 10,40,30,false);   //坦克的身体
                g.fillOval(x + 15,y + 10,30,30);    //坦克的炮盖
                g.drawLine(x + 30,y + 25,x +60,y + 25); //坦克的炮筒
                break;

            case 2: //表示向下
                g.fill3DRect(x,y,10,60,false);  //坦克的左边轮子
                g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
                g.drawLine(x,y + 20,x + 10,y + 20);
                g.drawLine(x,y + 30,x + 10,y + 30);
                g.drawLine(x,y + 40,x + 10,y + 40);
                g.drawLine(x,y + 50,x + 10,y + 50);

                g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
                g.drawLine(x + 40,y + 10,x + 50,y + 10);    //坦克右轮的履带
                g.drawLine(x + 40,y + 20,x + 50,y + 20);
                g.drawLine(x + 40,y + 30,x + 50,y + 30);
                g.drawLine(x + 40,y + 40,x + 50,y + 40);
                g.drawLine(x + 40,y + 50,x + 50,y + 50);

                g.fill3DRect(x + 10,y + 10,30,40,false);    //坦克的身体
                g.fillOval(x + 10,y + 15,30,30);    //坦克的炮盖
                g.drawLine(x + 25,y + 30,x + 25,y + 60); //坦克的炮筒
                break;

            case 3: //表示向左
                g.fill3DRect(x,y,60,10,false);  //坦克左边的轮子
                g.drawLine(x + 10,y,x + 10 ,y + 10);    //坦克左轮的履带
                g.drawLine(x + 20,y,x + 20 ,y + 10);
                g.drawLine(x + 30,y,x + 30 ,y + 10);
                g.drawLine(x + 40,y,x + 40 ,y + 10);
                g.drawLine(x + 50,y,x + 50 ,y + 10);


                g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
                g.drawLine(x + 10,y + 40,x + 10,y + 50);
                g.drawLine(x + 20,y + 40,x + 20,y + 50);
                g.drawLine(x + 30,y + 40,x + 30,y + 50);
                g.drawLine(x + 40,y + 40,x + 40,y + 50);
                g.drawLine(x + 50,y + 40,x + 50,y + 50);


                g.fill3DRect( x + 10,y + 10,40,30,false);   //坦克的身体
                g.fillOval(x + 15,y + 10,30,30);    //坦克的炮盖
                g.drawLine(x + 30,y + 25,x,y + 25); //坦克的炮筒
                break;

            default:
                System.out.println("暂时没有处理");
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_W){
            myTank.setDirect(0);
            if(myTank.getY() > 0) {
                myTank.MoveUp();
            }
        }else if(e.getKeyCode() == KeyEvent.VK_D){
            myTank.setDirect(1);
            if(myTank.getX() + 60 < 1000) {
                myTank.MoveRight();
            }
        }else if(e.getKeyCode() == KeyEvent.VK_S){
            myTank.setDirect(2);
            if(myTank.getY() + 60 < 800) {
                myTank.MoveDown();
            }
        }else if(e.getKeyCode() == KeyEvent.VK_A){
            myTank.setDirect(3);
            if(myTank.getX() + 60 > 0) {
                myTank.MoveLeft();
            }
        }
//        else if(e.getKeyCode() == KeyEvent.VK_UP){
//            opTanks.get(0).setDirect(0);
//            opTanks.get(0).MoveUp();
//        }else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
//            opTanks.get(0).setDirect(1);
//            opTanks.get(0).MoveRight();
//        }else if(e.getKeyCode() == KeyEvent.VK_DOWN){
//            opTanks.get(0).setDirect(2);
//            opTanks.get(0).MoveDown();
//        }else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
//            opTanks.get(0).setDirect(3);
//            opTanks.get(0).MoveLeft();
//        }


        //如果玩家按下J键,我的坦克就会发出一个炮弹
        if(e.getKeyCode() == KeyEvent.VK_J){
            System.out.println("玩家按下了J键,开始射击!");

            myTank.shotOpTank();
        }

        this.repaint();

    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void run() {
        while(true) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //判断是否击中了敌人的坦克
            if(myTank.shot != null && myTank.shot.isLive){
                for(int i=0;i<opTanks.size();i++){  //遍历敌人的所有坦克
                    HitTank(myTank.shot,opTanks.get(i));
                }
            }


            this.repaint();
        }
    }

    //编写方法判断炮弹是否打中坦克
    public void HitTank(Shot s,OpTank opTank){
        //判断是否击中坦克
        switch (opTank.getDirect()){
            case 0: //敌人坦克向上的方向
            case 2: //敌人坦克向下的方向
                if(s.x > opTank.getX() && s.x < opTank.getX() + 50 && s.y > opTank.getY() && s.y < opTank.getY() + 60){
                    s.isLive = false;
                    opTank.isLive = false;
                }
                break;
            case 1: //敌人坦克向右的方向
            case 3: //敌人坦克向左的方向
                if(s.x > opTank.getX() && s.x < opTank.getX() + 60 && s.y > opTank.getY() && s.y < opTank.getY() + 50){
                    s.isLive = false;
                    opTank.isLive = false;
                    //当坦克被击中后将坦克从集合中移除
                    opTanks.remove(opTank);
                }
                break;
        }
    }

}

3.坦克基类(Tank)

package com.wak.TankGame01Version;

/*坦克的基类*/
public class Tank {
    private int x;  //坦克的横坐标
    private int y;  //坦克的纵坐标
    private int direct = 0; //坦克的方向
    private int speed = 1;  //坦克的速度

    public Tank(){
        this.x = 100;   //默认坦克的初始x坐标为100
        this.y = 100;   //默认坦克的初始y坐标为100
    }

    public Tank(int x,int y){   //自己设置坦克的初始x,y坐标
        this.x = x;
        this.y = y;
    }


    //设置坦克的x坐标
    public void setX(int x){
        this.x = x;
    }

    //设置坦克的y坐标
    public void setY(int y){
        this.y = y;
    }

    //获得坦克的x坐标
    public int getX(){
        return x;
    }

    //获得坦克的y坐标
    public int getY(){
        return y;
    }

    //设置坦克的方向
    public void setDirect(int direct){
        this.direct = direct;
    }

    //获得坦克的方向
    public int getDirect(){
        return direct;
    }

    //设置坦克的速度
    public void setSpeed(int speed){
        this.speed = speed;
    }

    //获得坦克的速度
    public int getSpeed(){
        return speed;
    }

    //坦克的上右下左移动
    public void MoveUp(){
        y -= speed;
    }
    public void MoveRight(){
        x += speed;
    }
    public void MoveDown(){
        y += speed;
    }
    public void MoveLeft(){
        x -= speed;
    }
}


4.我的坦克类(MyTank)

package com.wak.TankGame01Version;

/*自己的坦克*/
public class MyTank extends Tank{
    //创建一个坦克
    private MyTank myTank = null;

    Shot shot = null;
    //设置坦克的初始化坐标
    public MyTank(int x,int y){
        this.setX(x);
        this.setY(y);
    }

    //射击
    public void shotOpTank(){
        //设置炮弹的初始化坐标及方向
        switch (this.getDirect()){
            case 0:
                shot = new Shot(this.getX() + 25,this.getY(),0);
                break;
            case 1:
                shot = new Shot(this.getX() + 60,this.getY() + 25,1);
                break;
            case 2:
                shot = new Shot(this.getX() + 25,this.getY() + 60,2);
                break;
            case 3:
                shot = new Shot(this.getX(),this.getY() + 25,3);
        }


        //启动我们的Shot线程
        new Thread(shot).start();
    }
}

5.敌方坦克类(OpTank)

package com.wak.TankGame01Version;

import java.util.Vector;

public class OpTank extends Tank implements Runnable{
    private OpTank opTank = null;   //创建一个敌方坦克
    boolean isLive = true;   //敌方坦克的存活状态
    Vector<Shot> shots = new Vector<>();    //存储多个炮弹

    public OpTank(int x,int y){
        this.setX(x);
        this.setY(y);
    }

    @Override
    public void run() {
        while(true){
            switch (this.getDirect()){
                case 0:
                    for(int i=0;i<80;i++) {
                        if (getY() > 0){
                            MoveUp();
                        }
                        //休眠
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 1:
                    for (int i=0;i<80;i++){
                        if(getX() + 60< 1000) {
                            MoveRight();
                        }
                        //休眠
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 2:
                    for (int i=0;i<80;i++){
                        if(getY() + 60 < 1000) {
                            MoveDown();
                        }
                        //休眠
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 3:
                    for (int i=0;i<80;i++){
                        if(getY() + 60 < 800) {
                            MoveLeft();
                        }
                        //休眠
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
            }
            setDirect((int)(Math.random() * 4));
            if(!isLive){
               break;
            }
        }
    }
}

6.炮弹类(Shot)

package com.wak.TankGame01Version;

public class Shot implements Runnable{
    int x;  //子弹的x坐标
    int y;  //子弹的y坐标
    int direct = 0; //子弹的方向
    int speed = 2;  //子弹的速度
    boolean isLive = true;  //子弹的存活状态

    public Shot(int x,int y,int direct){
        this.x = x;
        this.y = y;
        this.direct = direct;
    }

    @Override
    public void run() { //射击
        while(isLive){
            //休眠
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            switch (direct){
                case 0: //向上
                    y -= speed;
                    break;
                case 1: //向右
                    x += speed;
                    break;
                case 2: //向下
                    y += speed;
                    break;
                case 3: //向左
                    x -= speed;
                    break;
            }

            System.out.println("炮弹的x坐标:" + x + ",炮弹的y坐标:" + y);
            //如果炮弹弹撞到墙壁,则销毁
            //当炮弹碰到敌人坦克时,也应当结束
            if(!(x >= 0 && x <= 1000 && y >=0 && y <= 800 && isLive)){
                isLive = false;
                System.out.println("炮弹已销毁");
            }
        }
    }
}

运行效果截图:

阶段三:

小总结:今天完成了,坦克发射多颗炮弹,敌方坦克移动发射,我方坦克被炮弹击中,防止敌方坦克重叠,记录玩家成绩,记录敌人坦克信息。今天觉得比较有创新的点就是防止坦克重叠,还是以坦克的一个点出发,从坐标出发,这样思路就很明确。今天的一个小插曲是,最后韩老师还教了一个继续上局游戏的操作,但是,这个视频中,我发现,有很多内容之前都没学过,但是我先跟着敲了(这就为后面埋下了一个伏笔),结果当我正式运行的时候,开始新的游戏,是正常的,除了对记录击毁多少个敌人的次数,是上一局继承下来的(我觉得这个问题后面可以用一个if语句进行,清零操作),但是,当我继续上局游戏时,运行出来,敌方的坦克全部消失,然后我就又重新看视频,找问题,改了几个地方,发现越改越错,当时脑子直接懵了,然后我就一直Ctrl-Z,还好,最后改回来了,我本来想把这个内容加上去的,但是我发现以我现在的能力,我可以把这个时间去用来写一些跟游戏更贴切的内容,比如现在运行出来只有我的坦克和对面坦克,还没有掩体等,坦克的速度,初始位置,以及炮弹的速度,都还没有进行调试,相比于那个,这才是重点,这也是明天的内容。今天新增了一个Recorder类和一个Node类(记录坦克的位置信息等,但是由于后面的内容我没有继续再写了,这个类也就相当于白建的)。

以下是今天的代码记录截图:

七个类 (根据英文应该能猜到各自对应什么)

1.主程序类(TankGame01)

package com.wak.TankGame01Version;

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

/*坦克大战游戏主程序*/
public class TankGame01 extends JFrame {
    public static void main(String[] args) {
        //启动!
        new TankGame01();
    }

    //定义GamePanel,创建游戏环境
    GamePanel gamePanel = null;

    //加载游戏环境
    public TankGame01(){
        //1.0版本
        this.setTitle("坦克大战1.0");
        //加载游戏环境
        gamePanel = new GamePanel();
        //将游戏区域加载到界面里
        this.add(gamePanel);
        //将游戏界面的炮弹线程加入到界面里
        Thread thread = new Thread(gamePanel);
        //启动子线程
        thread.start();
        //将键盘监听器加载到界面里
        this.addKeyListener(gamePanel);
        //设置界面可视化
        this.setVisible(true);
        //设置界面的大小
        this.setSize(1400,950);
        //设置界面可关闭
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //在JFrame中增加相应关闭窗口的处理
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                Recorder.KeepRecord();
                System.exit(0);
            }
        });
    }

}

2.游戏界面绘制类(GamePanel)

package com.wak.TankGame01Version;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

/*坦克大战的绘图区域*/

//为了监听键盘事件,实现KeyListener
//
public class GamePanel extends JPanel implements KeyListener,Runnable{
    //定义一个自己的坦克
    MyTank myTank = null;
    //创建敌方坦克
    Vector<OpTank> opTanks = new Vector<>();
    //定义一个存放Node对象的Vector,用于恢复敌方坦克的坐标和方向
    Vector<Node> nodes = new Vector<>();
    //设置敌方坦克数量
    int opTanksSize = 6;

    public GamePanel(/*String key*/){
//        Recorder.getNodesAndEnemyTankRec();
        myTank = new MyTank(200,600);   //初始化坦克的位置
        myTank.setSpeed(3); //设置坦克的速度

        //将GamePanel对象的 opTanks 设置给 Recorder 的 opTanks
        Recorder.setOpTanks(opTanks);



        for(int i=0;i<opTanksSize;i++){
            OpTank opTank = new OpTank((100 * i + 100),0);
            opTank.setOpTanks(opTanks);
            //设置方向
            opTank.setDirect(2);
            //启动敌人坦克线程
            new Thread(opTank).start();
            //给该opTank加入一颗炮弹
            Shot shot = new Shot(opTank.getX() + 25,opTank.getY() + 60,2);
            //存放到Vector中
            opTank.shots.add(shot);
            //启动线程对象
            new Thread(shot).start();
            //加入
            opTanks.add(opTank);
        }

    }

    //编写方法,显示我方击毁敌方坦克的信息
    public void showInfo(Graphics g){
        //画出玩家的总成绩
        g.setColor(Color.BLACK);
        Font font = new Font("宋体",Font.BOLD,25);
        g.setFont(font);

        g.drawString("您累计击毁敌方坦克的数量",1020,30);
        DrawTank(1020,60,g,0,1);
        g.setColor(Color.BLACK);
        g.drawString(Recorder.getAllOpTanksNum() + "",1080,100);
    }



    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillRect(0,0,1000,800);    //默认背景是黑色

        showInfo(g);
        //画出坦克-封装方法
        //画出我的坦克
        if(myTank.isLive) {
            DrawTank(myTank.getX(), myTank.getY(), g, myTank.getDirect(), 0);
        }
        //画出敌人的坦克
        for(int i=0;i<opTanks.size();i++){
            //取出敌方坦克
            OpTank opTank = opTanks.get(i);
            //判断敌方坦克是否存活
            if(opTank.isLive) { //当敌人坦克是存活的时候,才去画
                DrawTank(opTank.getX(), opTank.getY(), g, opTank.getDirect(), 1);
                //画出敌人的坦克发出的炮弹
                for (int j = 0; j < opTank.shots.size(); j++) {
                    //取出子弹
                    Shot shot = opTank.shots.get(j);
                    //绘制
                    if (shot.isLive) {
                        g.setColor(Color.WHITE);
                        g.fill3DRect(shot.x, shot.y, 4, 4, false);
                    } else {
                        opTank.shots.remove(shot);
                    }
                }
            }

        }

        //画出我的坦克发出的炮弹
        if(myTank.isLive) {
            for (int i = 0; i < myTank.shots.size(); i++) {
                if (myTank.shots.get(i) != null && myTank.shots.get(i).isLive == true) {
                    g.setColor(Color.CYAN);
                    g.fill3DRect(myTank.shots.get(i).x, myTank.shots.get(i).y, 4, 4, false);
                } else {
                    myTank.shots.remove(i);
                }
            }
        }

    }

    //编写方法,画出坦克

    /**
     *
     * @param x 坦克的x坐标
     * @param y 坦克的y坐标
     * @param g 画笔
     * @param direct    坦克方向(上下左右)
     * @param type  坦克类型
     */
    public void DrawTank(int x,int y,Graphics g,int direct,int type){
        //坦克的类型
        switch (type){
            case 0: //自己的坦克
                g.setColor(Color.CYAN);
                break;
            case 1: //敌人的坦克
                g.setColor(Color.RED);
                break;
        }

        switch (direct){
            case 0: //表示向上
                g.fill3DRect(x,y,10,60,false);  //坦克的左边轮子
                g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
                g.drawLine(x,y + 20,x + 10,y + 20);
                g.drawLine(x,y + 30,x + 10,y + 30);
                g.drawLine(x,y + 40,x + 10,y + 40);
                g.drawLine(x,y + 50,x + 10,y + 50);

                g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
                g.drawLine(x + 40,y + 10,x + 50,y + 10);     //坦克右轮的履带
                g.drawLine(x + 40,y + 20,x + 50,y + 20);
                g.drawLine(x + 40,y + 30,x + 50,y + 30);
                g.drawLine(x + 40,y + 40,x + 50,y + 40);
                g.drawLine(x + 40,y + 50,x + 50,y + 50);

                g.fill3DRect(x + 10,y + 10,30,40,false);    //坦克的身体
                g.fillOval(x + 10,y + 15,30,30);    //坦克的炮盖
                g.drawLine(x + 25,y + 30,x + 25,y); //坦克的炮筒
                break;

            case 1: //表示向右
                g.fill3DRect(x,y,60,10,false);  //坦克左边的轮子
                g.drawLine(x + 10,y,x + 10 ,y + 10);    //坦克左轮的履带
                g.drawLine(x + 20,y,x + 20 ,y + 10);
                g.drawLine(x + 30,y,x + 30 ,y + 10);
                g.drawLine(x + 40,y,x + 40 ,y + 10);
                g.drawLine(x + 50,y,x + 50 ,y + 10);


                g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
                g.drawLine(x + 10,y + 40,x + 10,y + 50);
                g.drawLine(x + 20,y + 40,x + 20,y + 50);
                g.drawLine(x + 30,y + 40,x + 30,y + 50);
                g.drawLine(x + 40,y + 40,x + 40,y + 50);
                g.drawLine(x + 50,y + 40,x + 50,y + 50);


                g.fill3DRect( x + 10,y + 10,40,30,false);   //坦克的身体
                g.fillOval(x + 15,y + 10,30,30);    //坦克的炮盖
                g.drawLine(x + 30,y + 25,x +60,y + 25); //坦克的炮筒
                break;

            case 2: //表示向下
                g.fill3DRect(x,y,10,60,false);  //坦克的左边轮子
                g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
                g.drawLine(x,y + 20,x + 10,y + 20);
                g.drawLine(x,y + 30,x + 10,y + 30);
                g.drawLine(x,y + 40,x + 10,y + 40);
                g.drawLine(x,y + 50,x + 10,y + 50);

                g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
                g.drawLine(x + 40,y + 10,x + 50,y + 10);    //坦克右轮的履带
                g.drawLine(x + 40,y + 20,x + 50,y + 20);
                g.drawLine(x + 40,y + 30,x + 50,y + 30);
                g.drawLine(x + 40,y + 40,x + 50,y + 40);
                g.drawLine(x + 40,y + 50,x + 50,y + 50);

                g.fill3DRect(x + 10,y + 10,30,40,false);    //坦克的身体
                g.fillOval(x + 10,y + 15,30,30);    //坦克的炮盖
                g.drawLine(x + 25,y + 30,x + 25,y + 60); //坦克的炮筒
                break;

            case 3: //表示向左
                g.fill3DRect(x,y,60,10,false);  //坦克左边的轮子
                g.drawLine(x + 10,y,x + 10 ,y + 10);    //坦克左轮的履带
                g.drawLine(x + 20,y,x + 20 ,y + 10);
                g.drawLine(x + 30,y,x + 30 ,y + 10);
                g.drawLine(x + 40,y,x + 40 ,y + 10);
                g.drawLine(x + 50,y,x + 50 ,y + 10);


                g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
                g.drawLine(x + 10,y + 40,x + 10,y + 50);
                g.drawLine(x + 20,y + 40,x + 20,y + 50);
                g.drawLine(x + 30,y + 40,x + 30,y + 50);
                g.drawLine(x + 40,y + 40,x + 40,y + 50);
                g.drawLine(x + 50,y + 40,x + 50,y + 50);


                g.fill3DRect( x + 10,y + 10,40,30,false);   //坦克的身体
                g.fillOval(x + 15,y + 10,30,30);    //坦克的炮盖
                g.drawLine(x + 30,y + 25,x,y + 25); //坦克的炮筒
                break;

            default:
                System.out.println("暂时没有处理");
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {    //控制键盘WDSA键,操控我的坦克上右下左移动
        if(e.getKeyCode() == KeyEvent.VK_W){
            myTank.setDirect(0);
            if(myTank.getY() > 0) {
                myTank.MoveUp();
            }
        }else if(e.getKeyCode() == KeyEvent.VK_D){
            myTank.setDirect(1);
            if(myTank.getX() + 60 < 1000) {
                myTank.MoveRight();
            }
        }else if(e.getKeyCode() == KeyEvent.VK_S){
            myTank.setDirect(2);
            if(myTank.getY() + 60 < 800) {
                myTank.MoveDown();
            }
        }else if(e.getKeyCode() == KeyEvent.VK_A){
            myTank.setDirect(3);
            if(myTank.getX() + 60 > 0) {
                myTank.MoveLeft();
            }
        }
//        else if(e.getKeyCode() == KeyEvent.VK_UP){
//            opTanks.get(0).setDirect(0);
//            opTanks.get(0).MoveUp();
//        }else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
//            opTanks.get(0).setDirect(1);
//            opTanks.get(0).MoveRight();
//        }else if(e.getKeyCode() == KeyEvent.VK_DOWN){
//            opTanks.get(0).setDirect(2);
//            opTanks.get(0).MoveDown();
//        }else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
//            opTanks.get(0).setDirect(3);
//            opTanks.get(0).MoveLeft();
//        }


        //如果玩家按下J键,我的坦克就会发出一个炮弹
        if(e.getKeyCode() == KeyEvent.VK_J){
//            System.out.println("玩家按下了J键,开始射击!");
//            if(myTank.shot == null || myTank.shot.isLive == false) {    //当坦克只能发射一颗炮弹时,先判断
//                myTank.shotOpTank();
//            }
            myTank.shotOpTank();
        }

        this.repaint();

    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void run() {
        while(true) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //判断是否击中了敌人的坦克
            for(int j=0;j<myTank.shots.size();j++) {
                if (myTank.shots.get(j) != null && myTank.shots.get(j).isLive) {
                    for (int i = 0; i < opTanks.size(); i++) {  //遍历敌人的所有坦克
                        HitTank(myTank.shots.get(j), opTanks.get(i));
                    }
                }
            }
            HitMyTank();
            this.repaint();
        }
    }

    //编写方法判断敌方坦克的炮弹是否打中我的坦克
    public void HitMyTank(){
        for(int i=0;i<opTanks.size();i++){
            for(int j=0;j<opTanks.get(i).shots.size();j++){
                if(myTank.isLive && opTanks.get(i).shots.get(j).isLive){
                    HitTank(opTanks.get(i).shots.get(j),myTank);
                }
            }
        }
    }


    //编写方法判断炮弹是否打中坦克
    public void HitTank(Shot s,Tank opTank){
        //判断是否击中坦克
        switch (opTank.getDirect()){
            case 0: //敌人坦克向上的方向
            case 2: //敌人坦克向下的方向
                if(s.x > opTank.getX() && s.x < opTank.getX() + 50 && s.y > opTank.getY() && s.y < opTank.getY() + 60){
                    s.isLive = false;
                    opTank.isLive = false;
                    //当坦克被击中后将坦克从集合中移除
                    opTanks.remove(opTank);
                    //解读,因为opTank可以是没有Tank,也可以是opTank
                    if(opTank instanceof OpTank){
                        Recorder.addAllOpTanksNum();
                    }
                }
                break;
            case 1: //敌人坦克向右的方向
            case 3: //敌人坦克向左的方向
                if(s.x > opTank.getX() && s.x < opTank.getX() + 60 && s.y > opTank.getY() && s.y < opTank.getY() + 50){
                    s.isLive = false;
                    opTank.isLive = false;
                    //当坦克被击中后将坦克从集合中移除
                    opTanks.remove(opTank);
                    //解读,因为opTank可以是没有Tank,也可以是opTank
                    if(opTank instanceof OpTank){
                        Recorder.addAllOpTanksNum();
                    }
                }
                break;
        }
    }

}

3.坦克基类(Tank)

package com.wak.TankGame01Version;

/*坦克的基类*/
public class Tank {
    private int x;  //坦克的横坐标
    private int y;  //坦克的纵坐标
    private int direct = 0; //坦克的方向
    private int speed = 1;  //坦克的速度
    boolean isLive = true;      //坦克的存活状态

    public Tank(){
        this.x = 100;   //默认坦克的初始x坐标为100
        this.y = 100;   //默认坦克的初始y坐标为100
    }

    public Tank(int x,int y){   //自己设置坦克的初始x,y坐标
        this.x = x;
        this.y = y;
    }


    //设置坦克的x坐标
    public void setX(int x){
        this.x = x;
    }

    //设置坦克的y坐标
    public void setY(int y){
        this.y = y;
    }

    //获得坦克的x坐标
    public int getX(){
        return x;
    }

    //获得坦克的y坐标
    public int getY(){
        return y;
    }

    //设置坦克的方向
    public void setDirect(int direct){
        this.direct = direct;
    }

    //获得坦克的方向
    public int getDirect(){
        return direct;
    }

    //设置坦克的速度
    public void setSpeed(int speed){
        this.speed = speed;
    }

    //获得坦克的速度
    public int getSpeed(){
        return speed;
    }

    //坦克的上右下左移动
    public void MoveUp(){
        y -= speed;
    }
    public void MoveRight(){
        x += speed;
    }
    public void MoveDown(){
        y += speed;
    }
    public void MoveLeft(){
        x -= speed;
    }
}


4.我的坦克类(MyTank)

package com.wak.TankGame01Version;

import java.util.Vector;

/*自己的坦克*/
public class MyTank extends Tank{

    //创建一个坦克
    private MyTank myTank = null;

    //定义一个shot对象,表示一个射击(线程)
    Shot shot = null;
    //创建一个存储炮弹的集合
    Vector<Shot> shots = new Vector<>();
    //设置坦克的初始化坐标
    public MyTank(int x,int y){
        this.setX(x);
        this.setY(y);
    }

    //射击
    public void shotOpTank(){
        //设置炮弹的初始化坐标及方向
        if(shots.size() < 5) {
            switch (this.getDirect()) {
                case 0:
                    shot = new Shot(this.getX() + 25, this.getY(), 0);
                    break;
                case 1:
                    shot = new Shot(this.getX() + 60, this.getY() + 25, 1);
                    break;
                case 2:
                    shot = new Shot(this.getX() + 25, this.getY() + 60, 2);
                    break;
                case 3:
                    shot = new Shot(this.getX(), this.getY() + 25, 3);
            }
        //将发射的炮弹弹存入集合中

            shots.add(shot);
        }
        //启动我们的Shot线程
        new Thread(shot).start();

    }
}

5.敌方坦克类(OpTank)

package com.wak.TankGame01Version;

import java.util.Vector;

public class OpTank extends Tank implements Runnable{
    private OpTank opTank = null;   //创建一个敌方坦克
    Vector<Shot> shots = new Vector<>();    //存储多个炮弹
    Vector<OpTank> opTanks = new Vector<>();    //增加成员,可以得到敌人坦克的Vector集合
    public OpTank(int x,int y){
        this.setX(x);
        this.setY(y);
    }

    public void setOpTanks(Vector<OpTank> opTanks){
        this.opTanks = opTanks;
    }

    public boolean isTouchOpTank(){
        //判断当前敌人坦克的方向
        switch (this.getDirect()){
            case 0: //上
                for(int j=0;j<opTanks.size();j++){
                    //取出一个敌方坦克
                    OpTank o = opTanks.get(j);
                    if(o != this){  //不能跟自己比
                        //如果敌人是向上或者向下
                        if(o.getDirect() == 0 || o.getDirect() == 2){
                            //当前坦克左上角的坐标
                            if(this.getX() >= o.getX()
                                    && this.getX() <= o.getX() + 50
                                    && this.getY() <= o.getY() + 60
                                    && this.getY() >= o.getY()){
                                return true;
                            }
                            //当前坦克右上角的坐标
                            if(this.getX() + 50 >= o.getX()
                                    && this.getX() + 50<= o.getX() + 50
                                    && this.getY() <= o.getY() + 60
                                    && this.getY() >= o.getY()){
                             return true;
                            }
                        }
                        //如果敌人是向右或者向左
                        if(o.getDirect() == 1 || o.getDirect() == 3){
                            //当前坦克左上角的坐标
                            if(this.getX() >= o.getX()
                                    && this.getX() <= o.getX() + 60
                                    && this.getY() >= o.getY()
                                    && this.getY() <= o.getY() + 50){
                                return true;
                            }
                            //当前坦克右上角的坐标
                            if(this.getX() + 50>= o.getX()
                                    && this.getX() + 50<= o.getX() + 60
                                    && this.getY() >= o.getY()
                                    && this.getY() <= o.getY() + 50){
                                return true;
                            }
                        }
                    }
                }
                break;
            case 1: //右
                for(int j=0;j<opTanks.size();j++){
                    //取出一辆坦克
                    OpTank o = opTanks.get(j);
                    if(o != this){  //不能跟自己比
                        //如果敌方坦克是向上或向下
                        if(o.getDirect() == 0 || o.getDirect() == 2){
                            //当前坦克右上角的坐标
                            if(this.getX() + 60 >= o.getX()
                                    && this.getX() + 60 <= o.getX() + 50
                                    && this.getY() >= o.getY()
                                    && this.getY() <= o.getY() + 60){
                                return true;
                            }
                            //当前坦克右下角的坐标
                            if(this.getX() + 60 >= o.getX()
                                    && this.getX() + 60 <= o.getX() + 50
                                    && this.getY() + 50 >= o.getY()
                                    && this.getY() + 50 <= o.getY() + 60){
                                return true;
                            }
                        }
                        //如果敌方坦克是向右或向左
                        if(o.getDirect() == 1 || o.getDirect() == 3){
                            //当前坦克右上角的坐标
                            if(this.getX() + 60 >= o.getX()
                                    && this.getX() + 60 <= o.getX() + 60
                                    && this.getY() >= o.getY()
                                    && this.getY() <= o.getY() + 50){
                                return true;
                            }
                            //当前坦克右下角的坐标
                            if(this.getX() + 60 >= o.getX()
                                    && this.getX() + 60 <= o.getX() + 60
                                    && this.getY() + 50 >= o.getY()
                                    && this.getY() + 50 <= o.getY() + 50){
                                return true;
                            }
                        }
                    }
                }
                break;
            case 2: //下
                for(int j=0;j<opTanks.size();j++){
                    //取出一辆坦克
                    OpTank o = opTanks.get(j);
                    if(o != this){  //不能跟自己比
                        //如果敌方坦克是向上或向下
                        if(o.getDirect() == 0 || o.getDirect() == 2){
                            //当前坦克左下角的坐标
                            if(this.getX() >= o.getX()
                                    && this.getX() <= o.getX() + 60
                                    && this.getY() + 60 >= o.getY()
                                    && this.getY() + 60 <= o.getY()){
                                return true;
                            }
                            //当前坦克右下角的坐标
                            if(this.getX() + 50>= o.getX()
                                    && this.getX() + 50 <= o.getX() + 60
                                    && this.getY() + 60 >= o.getY()
                                    && this.getY() + 60 <= o.getY()){
                                return true;
                            }
                        }
                        //如果敌方坦克是向右或向左
                        if(o.getDirect() == 1 || o.getDirect() == 3){
                            //当前坦克左下角的坐标
                            if(this.getX() >= o.getX()
                                    && this.getX() + 60 <= o.getX() + 60
                                    && this.getY() >= o.getY()
                                    && this.getY() + 50 <= o.getY() + 50){
                                return true;
                            }
                            //当前坦克右下角的坐标
                            if(this.getX() + 50 >= o.getX()
                                    && this.getX() + 50 <= o.getX() + 60
                                    && this.getY() + 60 >= o.getY()
                                    && this.getY() + 60 <= o.getY() + 50){
                                return true;
                            }
                        }
                    }
                }
                break;
            case 3: //左
                for(int j=0;j<opTanks.size();j++){
                    //取出一辆坦克
                    OpTank o = opTanks.get(j);
                    if(o != this){  //不能跟自己比
                        //如果敌方坦克是向上或向下
                        if(o.getDirect() == 0 || o.getDirect() == 2){
                            //当前坦克左上角的坐标
                            if(this.getX() >= o.getX()
                                    && this.getX() <= o.getX() + 60
                                    && this.getY() >= o.getY()
                                    && this.getY() <= o.getY()){
                                return true;
                            }
                            //当前坦克左下角的坐标
                            if(this.getX() >= o.getX()
                                    && this.getX() <= o.getX() + 60
                                    && this.getY() + 50 >= o.getY()
                                    && this.getY() + 50 <= o.getY()){
                                return true;
                            }
                        }
                        //如果敌方坦克是向右或向左
                        if(o.getDirect() == 1 || o.getDirect() == 3){
                            //当前坦克左上角的坐标
                            if(this.getX() >= o.getX()
                                    && this.getX() <= o.getX() + 60
                                    && this.getY() >= o.getY()
                                    && this.getY() <= o.getY() + 50){
                                return true;
                            }
                            //当前坦克左下角的坐标
                            if(this.getX() >= o.getX()
                                    && this.getX() <= o.getX() + 60
                                    && this.getY() + 50 >= o.getY()
                                    && this.getY() + 50 <= o.getY() + 50){
                                return true;
                            }
                        }
                    }
                }
                break;
        }
        return false;
    }

    @Override
    public void run() {
        while(true){

            //这里判断坦克的方向,创建对应的炮弹
            if(isLive && shots.size() < 6){
                Shot s = null;
                switch (getDirect()){
                    case 0:
                        s = new Shot(getX() + 25,getY(),0);
                        break;
                    case 1:
                        s = new Shot(getX() + 60,getY() + 25,1);
                        break;
                    case 2:
                        s = new Shot(getX() + 25,getY() + 60,2);
                        break;
                    case 3:
                        s = new Shot(getX(),getY() + 25,3);
                        break;
                }

                //每隔1秒发射一个炮弹
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                shots.add(s);

                new Thread(s).start();
            }
            //坦克移动的方向
            switch (this.getDirect()){
                case 0:
                    for(int i=0;i<80;i++) {
                        if (getY() > 0 && !isTouchOpTank()){
                            MoveUp();
                        }
                        //休眠
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 1:
                    for (int i=0;i<80;i++){
                        if(getX() + 60< 1000 && !isTouchOpTank()) {
                            MoveRight();
                        }
                        //休眠
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 2:
                    for (int i=0;i<80;i++){
                        if(getY() + 60 < 800 && !isTouchOpTank()) {
                            MoveDown();
                        }
                        //休眠
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 3:
                    for (int i=0;i<80;i++){
                        if(getX() > 0 && !isTouchOpTank()) {
                            MoveLeft();
                        }
                        //休眠
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
            }
            setDirect((int)(Math.random() * 4));
            if(!isLive){
               break;
            }
        }
    }
}

6.炮弹类(Shot)

package com.wak.TankGame01Version;

public class Shot implements Runnable{
    int x;  //子弹的x坐标
    int y;  //子弹的y坐标
    int direct = 0; //子弹的方向
    int speed = 2;  //子弹的速度
    boolean isLive = true;  //子弹的存活状态

    public Shot(int x,int y,int direct){
        this.x = x;
        this.y = y;
        this.direct = direct;
    }

    @Override
    public void run() { //射击
        while(isLive){
            //休眠
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            switch (direct){
                case 0: //向上
                    y -= speed;
                    break;
                case 1: //向右
                    x += speed;
                    break;
                case 2: //向下
                    y += speed;
                    break;
                case 3: //向左
                    x -= speed;
                    break;
            }

            System.out.println("炮弹的x坐标:" + x + ",炮弹的y坐标:" + y);
            //如果炮弹弹撞到墙壁,则销毁
            //当炮弹碰到敌人坦克时,也应当结束
            if(!(x >= 0 && x <= 1000 && y >=0 && y <= 800 && isLive)){
                isLive = false;
                System.out.println("炮弹已销毁");
            }
        }
    }
}

7.记录信息类(Recorder)

package com.wak.TankGame01Version;

import java.awt.*;
import java.io.*;
import java.util.Vector;

public class Recorder {
    private static int allOpTanksNum = 0;
    //定义IO对象,准备写数据到文件中
    private static FileWriter fw = null;
    private static BufferedWriter bw = null;
    private static BufferedReader br = null;
    private static String recordFile = "D:\\myTankGameRecord.txt";
    //定义Vec,指向GamePanel对象的 敌人坦克Vector
    private static Vector<OpTank> opTanks = null;
    //定义一个Node 的Vector,用于保存敌人的信息node
    private static Vector<Node> nodes = new Vector<>();

    public static void setOpTanks(Vector<OpTank> opTanks){
        Recorder.opTanks = opTanks;
    }

    public static int getAllOpTanksNum(){
        return allOpTanksNum;
    }

    public static void setAllOpTanksNum(int allOpTanksNum){
        Recorder.allOpTanksNum = allOpTanksNum;
    }


    //当我方坦克击毁一个敌人坦克,就应当allOpTanksNum++
    public static void addAllOpTanksNum(){
        Recorder.allOpTanksNum++;
    }

    //增加一个方法,当游戏退出时,我们将allOpTanksNum保存到recordFile
    //对KeepRecord方法进行升级,保存敌人坦克的坐标和方向
    public static void KeepRecord(){
        try {
            bw = new BufferedWriter((new FileWriter((recordFile))));
            bw.write(allOpTanksNum + "\r\n");
            //遍历敌人坦克的Vector,然后根据情况保存即可
            for(int i=0;i<opTanks.size();i++){
                //取出敌人坦克
                OpTank o = opTanks.get(i);
                if(o.isLive){
                    //保存该opTank的信息
                    String record = o.getX() + " " + o.getY() + " " + o.getDirect();
                    //写入到文件
                    bw.write(record + "\r\n");
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (bw != null) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

//    //增加一个方法,用于读取recordFile,恢复相关信息
//    public static Vector<Node> getNodesAndEnemyTankRec(){
//        try {
//            br = new BufferedReader(new FileReader(recordFile));
//
//        } catch (FileNotFoundException e) {
//            e.printStackTrace();
//        }finally {
//
//        }
//        return null;
//    }
}

运行效果截图:

阶段四:

小总结:今天完成了界面画面的布置,包括画了一条小河,草地,和障碍物(墙体),以及坦克碰到障碍物会停止前进,炮弹打到墙壁会销毁。今天真的是写这个项目这么久来,让我最印象深刻的一次今天,我在写完障碍物,遇到一个问题(当时没有截图或者录视频保存下来,可惜的是),就是我在离界面顶部Y坐标为100的位置时,坦克只会在这个Y坐标为0到100的范围内移动,于是我就觉得很奇怪,然后我就强制让他们只能朝下移动,结果发现,到了Y坐标等于100这个线的时候,所有的坦克全都不动了,只是发射炮弹,不会再继续往下移动。我又重新看了一遍我的方法,没有问题,于是我只好找学长求助,因为当我让他们自由可以改变方向移动时,他们能突破Y坐标为100的这条我暂且称之为“诡异线”,因为学长们对我的代码也不是特别熟悉,所以他们也没有给出一个正确答案,然后我就去找我之前的大四室友(已经在苏宁易购工作了),在通过测试时,我们发现一个问题,因为我是设置的六个坦克,从左到右依次排开,初始化他们是先向下移动的,当移动完之后,有一个坦克正好碰到了障碍物,而其他的没有,于是我们就猜测是不是这个影响了其他坦克,于是我们就把这个前面是障碍物的坦克删除掉,但是还是不行,我们最后只测试一个,发现这个坦克就可以突破这个“诡异线”,于是我想到了,就算把那个正好碰到坦克的障碍物删除,但是有一个坦克的右下角,与障碍物的一个角挨着了,因为我的判断是够与墙壁碰撞的判断条件,是写的大于等于,或者小于等于,就是这个等号,让代码运行过程有问题,后来总结出,尤其是在写这种游戏时,有的边界条件不能卡的太死,要不然就会出问题,因为这个毕竟是像素块,说不定就有个时候,越过了这个边界,然后就卡住了。但是由于是第一次写,还有很多知识点没有完全掌握好,所以当解决完这个问题后,整个人真的是,或许这就是代码的魅力吧!

以下是今天的代码记录截图:

七个类(根据英文应该能猜到各自对应什么)

 

1.主程序类(TankGame01)

package com.wak.TankGame01Version;

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

/*坦克大战游戏主程序*/
public class TankGame01 extends JFrame {
    public static void main(String[] args) {
        //启动!
        new TankGame01();
    }

    //定义GamePanel,创建游戏环境
    GamePanel gamePanel = null;

    //加载游戏环境
    public TankGame01(){
        //1.0版本
        this.setTitle("坦克大战1.0");
        //加载游戏环境
        gamePanel = new GamePanel();
        //将游戏区域加载到界面里
        this.add(gamePanel);
        //将游戏界面的炮弹线程加入到界面里
        Thread thread = new Thread(gamePanel);
        //启动子线程
        thread.start();
        //将键盘监听器加载到界面里
        this.addKeyListener(gamePanel);
        //设置界面可视化
        this.setVisible(true);
        //设置界面的大小
        this.setSize(1600,950);
        //设置界面可关闭
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //在JFrame中增加相应关闭窗口的处理
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                Recorder.KeepRecord();
                System.exit(0);
            }
        });
    }

}

 

2.游戏界面绘制类(GamePanel)

package com.wak.TankGame01Version;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

/*坦克大战的绘图区域*/

//为了监听键盘事件,实现KeyListener
//
public class GamePanel extends JPanel implements KeyListener,Runnable{
    //定义一个自己的坦克
    MyTank myTank = null;
    //创建敌方坦克
    Vector<OpTank> opTanks = new Vector<>();
    //定义一个存放Node对象的Vector,用于恢复敌方坦克的坐标和方向
    Vector<Node> nodes = new Vector<>();
    //设置敌方坦克数量
    int opTanksSize = 6;

    public GamePanel(/*String key*/){
//        Recorder.getNodesAndEnemyTankRec();
        myTank = new MyTank(580,810);   //初始化我的坦克的位置
        myTank.setSpeed(3); //设置我的坦克的速度
//        myTank.shot.setShotSpeed(5);    //设置我的坦克的炮弹的速度

        //将GamePanel对象的 opTanks 设置给 Recorder 的 opTanks
        Recorder.setOpTanks(opTanks);


        //初始化敌方坦克
        for(int i=0;i<opTanksSize;i++){
            OpTank opTank = new OpTank((200 * i + 90),0);
            opTank.setOpTanks(opTanks);
            //设置方向
            opTank.setDirect(2);
            //设置敌人坦克的速度
            opTank.setSpeed(1);
            //启动敌人坦克线程
            new Thread(opTank).start();
            //给该opTank加入一颗炮弹
            Shot shot = new Shot(opTank.getX() + 25,opTank.getY() + 60,2);
            //存放到Vector中
            opTank.shots.add(shot);
            //启动线程对象
            new Thread(shot).start();
            //加入
            opTanks.add(opTank);
        }

    }

    //编写方法,显示我方击毁敌方坦克的信息
    public void showInfo(Graphics g){
        //画出玩家的总成绩
        g.setColor(Color.BLACK);
        Font font = new Font("宋体",Font.BOLD,25);
        g.setFont(font);

        g.drawString("您累计击毁敌方坦克的数量",1220,30);
        DrawTank(1220,60,g,0,1);
        g.setColor(Color.BLACK);
        g.drawString(Recorder.getAllOpTanksNum() + "",1280,100);
    }



    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillRect(0,0,1200,900);    //默认背景是黑色

        //设置背景为蓝色,代表河流
        g.setColor(Color.cyan);
        g.fill3DRect(100,400,1000,200,false);

        //设置背景为绿色,代表草地
        g.setColor(Color.GREEN);
        for(int i=0;i<7;i++) {
            g.fill3DRect(15 * i,100,5,600,false);
            g.fill3DRect(1100 + 15 * i,100,5,600,false);
        }
        for(int i=0;i<41;i++) {
            g.fill3DRect(0,100 + 15 * i,95,5,false);
            g.fill3DRect(1100,100 + 15 * i,95,5,false);
        }

        //设置背景为亮灰色,代表墙体
        g.setColor(Color.LIGHT_GRAY);

        g.fill3DRect(500,660,200,50,false);
        for(int i=1;i<5;i++) {
            g.drawLine(500, 660 + i*10, 700, 660 + i*10);
        }
        for(int i=1;i<20;i++){
            g.drawLine(500 + i*10,660,500 + i*10,710);
        }

        g.fill3DRect(260,660,60,130,false);
        for(int i=1;i<6;i++){
            g.drawLine(260 + i*10,660,260 + i*10,790);
        }
        for(int i=1;i<13;i++){
            g.drawLine(260,660 + i*10,320,660 + i*10);
        }

        g.fill3DRect(880,660,60,130,false);
        for(int i=1;i<6;i++){
            g.drawLine(880 + i*10,660,880 + i*10,790);
        }
        for(int i=1;i<13;i++){
            g.drawLine(880,660 + i*10,940,660 + i*10);
        }

        g.fill3DRect(350,100,60,240,false);
        for(int i=1;i<6;i++){
            g.drawLine(350 + i*10,100,350 + i*10,340);
        }
        for(int i=1;i<24;i++){
            g.drawLine(350,100 + i*10,410,100 + i*10);
        }

        g.fill3DRect(790,100,60,240,false);
        for(int i=1;i<6;i++){
            g.drawLine(790 + i*10,100,790 + i*10,340);
        }
        for(int i=1;i<24;i++){
            g.drawLine(790,100 + i*10,850,100 + i*10);
        }

        g.fill3DRect(550,160,100,100,false);
        for(int i=1;i<10;i++){
            g.drawLine(550 + i*10,160 ,550 + i*10,260);
        }
        for(int i=1;i<10;i++){
            g.drawLine(550,160 + i*10,650,160 + i*10);
        }

//        g.fill3DRect(160,100,130,60,false);
//        for(int i=1;i<13;i++){
//            g.drawLine(160 + i*10,100,160 + i*10,160);
//        }
//        for(int i=1;i<6;i++){
//            g.drawLine(160,100 + i*10,290,100 + i*10);
//        }

//        g.fill3DRect(910,100,130,60,false);
//        for(int i=1;i<13;i++){
//            g.drawLine(910 + i*10,100,910 + i*10,160);
//        }
//        for(int i=1;i<6;i++){
//            g.drawLine(910,100 + i*10,1040,100 + i*10);
//        }


        showInfo(g);
        //画出坦克-封装方法
        //画出我的坦克
        if(myTank.isLive) {
            DrawTank(myTank.getX(), myTank.getY(), g, myTank.getDirect(), 0);
        }
        //画出敌人的坦克
        for(int i=0;i<opTanks.size();i++){
            //取出敌方坦克
            OpTank opTank = opTanks.get(i);
            //判断敌方坦克是否存活
            if(opTank.isLive) { //当敌人坦克是存活的时候,才去画
                DrawTank(opTank.getX(), opTank.getY(), g, opTank.getDirect(), 1);
                //画出敌人的坦克发出的炮弹
                for (int j = 0; j < opTank.shots.size(); j++) {
                    //取出子弹
                    Shot shot = opTank.shots.get(j);
                    //绘制
                    if (shot.isLive) {
                        g.setColor(Color.RED);
                        g.fill3DRect(shot.x, shot.y, 4, 4, true);
                    } else {
                        opTank.shots.remove(shot);
                    }
                }
            }

        }

        //画出我的坦克发出的炮弹
        if(myTank.isLive) {
            for (int i = 0; i < myTank.shots.size(); i++) {
                if (myTank.shots.get(i) != null && myTank.shots.get(i).isLive == true) {
                    g.setColor(Color.YELLOW);
                    g.fill3DRect(myTank.shots.get(i).x, myTank.shots.get(i).y, 4, 4, false);
                } else {
                    myTank.shots.remove(i);
                }
            }
        }

    }

    //编写方法,画出坦克

    /**
     *
     * @param x 坦克的x坐标
     * @param y 坦克的y坐标
     * @param g 画笔
     * @param direct    坦克方向(上下左右)
     * @param type  坦克类型
     */
    public void DrawTank(int x,int y,Graphics g,int direct,int type){
        //坦克的类型
        switch (type){
            case 0: //自己的坦克
                g.setColor(Color.PINK);
                break;
            case 1: //敌人的坦克
                g.setColor(Color.RED);
                break;
        }

        switch (direct){
            case 0: //表示向上
                g.fill3DRect(x,y,10,60,false);  //坦克的左边轮子
                g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
                g.drawLine(x,y + 20,x + 10,y + 20);
                g.drawLine(x,y + 30,x + 10,y + 30);
                g.drawLine(x,y + 40,x + 10,y + 40);
                g.drawLine(x,y + 50,x + 10,y + 50);

                g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
                g.drawLine(x + 40,y + 10,x + 50,y + 10);     //坦克右轮的履带
                g.drawLine(x + 40,y + 20,x + 50,y + 20);
                g.drawLine(x + 40,y + 30,x + 50,y + 30);
                g.drawLine(x + 40,y + 40,x + 50,y + 40);
                g.drawLine(x + 40,y + 50,x + 50,y + 50);

                g.fill3DRect(x + 10,y + 10,30,40,false);    //坦克的身体
                g.fillOval(x + 10,y + 15,30,30);    //坦克的炮盖
                g.drawLine(x + 25,y + 30,x + 25,y); //坦克的炮筒
                break;

            case 1: //表示向右
                g.fill3DRect(x,y,60,10,false);  //坦克左边的轮子
                g.drawLine(x + 10,y,x + 10 ,y + 10);    //坦克左轮的履带
                g.drawLine(x + 20,y,x + 20 ,y + 10);
                g.drawLine(x + 30,y,x + 30 ,y + 10);
                g.drawLine(x + 40,y,x + 40 ,y + 10);
                g.drawLine(x + 50,y,x + 50 ,y + 10);


                g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
                g.drawLine(x + 10,y + 40,x + 10,y + 50);
                g.drawLine(x + 20,y + 40,x + 20,y + 50);
                g.drawLine(x + 30,y + 40,x + 30,y + 50);
                g.drawLine(x + 40,y + 40,x + 40,y + 50);
                g.drawLine(x + 50,y + 40,x + 50,y + 50);


                g.fill3DRect( x + 10,y + 10,40,30,false);   //坦克的身体
                g.fillOval(x + 15,y + 10,30,30);    //坦克的炮盖
                g.drawLine(x + 30,y + 25,x +60,y + 25); //坦克的炮筒
                break;

            case 2: //表示向下
                g.fill3DRect(x,y,10,60,false);  //坦克的左边轮子
                g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
                g.drawLine(x,y + 20,x + 10,y + 20);
                g.drawLine(x,y + 30,x + 10,y + 30);
                g.drawLine(x,y + 40,x + 10,y + 40);
                g.drawLine(x,y + 50,x + 10,y + 50);

                g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
                g.drawLine(x + 40,y + 10,x + 50,y + 10);    //坦克右轮的履带
                g.drawLine(x + 40,y + 20,x + 50,y + 20);
                g.drawLine(x + 40,y + 30,x + 50,y + 30);
                g.drawLine(x + 40,y + 40,x + 50,y + 40);
                g.drawLine(x + 40,y + 50,x + 50,y + 50);

                g.fill3DRect(x + 10,y + 10,30,40,false);    //坦克的身体
                g.fillOval(x + 10,y + 15,30,30);    //坦克的炮盖
                g.drawLine(x + 25,y + 30,x + 25,y + 60); //坦克的炮筒
                break;

            case 3: //表示向左
                g.fill3DRect(x,y,60,10,false);  //坦克左边的轮子
                g.drawLine(x + 10,y,x + 10 ,y + 10);    //坦克左轮的履带
                g.drawLine(x + 20,y,x + 20 ,y + 10);
                g.drawLine(x + 30,y,x + 30 ,y + 10);
                g.drawLine(x + 40,y,x + 40 ,y + 10);
                g.drawLine(x + 50,y,x + 50 ,y + 10);


                g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
                g.drawLine(x + 10,y + 40,x + 10,y + 50);
                g.drawLine(x + 20,y + 40,x + 20,y + 50);
                g.drawLine(x + 30,y + 40,x + 30,y + 50);
                g.drawLine(x + 40,y + 40,x + 40,y + 50);
                g.drawLine(x + 50,y + 40,x + 50,y + 50);


                g.fill3DRect( x + 10,y + 10,40,30,false);   //坦克的身体
                g.fillOval(x + 15,y + 10,30,30);    //坦克的炮盖
                g.drawLine(x + 30,y + 25,x,y + 25); //坦克的炮筒
                break;

            default:
                System.out.println("暂时没有处理");
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {    //控制键盘WDSA键,操控我的坦克上右下左移动
        if(e.getKeyCode() == KeyEvent.VK_W){
            myTank.setDirect(0);
            if(myTank.getY() > 0 && !isMyTankTouchWall()) {
                myTank.MoveUp();
            }
        }else if(e.getKeyCode() == KeyEvent.VK_D){
            myTank.setDirect(1);
            if(myTank.getX() + 60 < 1200 && !isMyTankTouchWall()) {
                myTank.MoveRight();
            }
        }else if(e.getKeyCode() == KeyEvent.VK_S){
            myTank.setDirect(2);
            if(myTank.getY() + 60 < 900 && !isMyTankTouchWall()) {
                myTank.MoveDown();
            }
        }else if(e.getKeyCode() == KeyEvent.VK_A){
            myTank.setDirect(3);
            if(myTank.getX() + 60 > 0 && !isMyTankTouchWall()) {
                myTank.MoveLeft();
            }
        }
//        else if(e.getKeyCode() == KeyEvent.VK_UP){
//            opTanks.get(0).setDirect(0);
//            opTanks.get(0).MoveUp();
//        }else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
//            opTanks.get(0).setDirect(1);
//            opTanks.get(0).MoveRight();
//        }else if(e.getKeyCode() == KeyEvent.VK_DOWN){
//            opTanks.get(0).setDirect(2);
//            opTanks.get(0).MoveDown();
//        }else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
//            opTanks.get(0).setDirect(3);
//            opTanks.get(0).MoveLeft();
//        }




        //如果玩家按下J键,我的坦克就会发出一个炮弹
        if(e.getKeyCode() == KeyEvent.VK_J){
//            System.out.println("玩家按下了J键,开始射击!");
//            if(myTank.shot == null || myTank.shot.isLive == false) {    //当坦克只能发射一颗炮弹时,先判断
//                myTank.shotOpTank();
//            }
            myTank.shotOpTank();
        }

        this.repaint();

    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void run() {
        while(true) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //判断是否击中了敌人的坦克
            for(int j=0;j<myTank.shots.size();j++) {
                if (myTank.shots.get(j) != null && myTank.shots.get(j).isLive) {
                    for (int i = 0; i < opTanks.size(); i++) {  //遍历敌人的所有坦克
                        HitTank(myTank.shots.get(j), opTanks.get(i));
                    }
                }
            }
            HitMyTank();
            this.repaint();
        }
    }

    //编写方法判断敌方坦克的炮弹是否打中我的坦克
    public void HitMyTank(){
        for(int i=0;i<opTanks.size();i++){
            for(int j=0;j<opTanks.get(i).shots.size();j++){
                if(myTank.isLive && opTanks.get(i).shots.get(j).isLive){
                    HitTank(opTanks.get(i).shots.get(j),myTank);
                }
            }
        }
    }


    //编写方法判断炮弹是否打中坦克
    public void HitTank(Shot s,Tank opTank){
        //判断是否击中坦克
        switch (opTank.getDirect()){
            case 0: //敌人坦克向上的方向
            case 2: //敌人坦克向下的方向
                if(s.x > opTank.getX() && s.x < opTank.getX() + 50 && s.y > opTank.getY() && s.y < opTank.getY() + 60){
                    s.isLive = false;
                    opTank.isLive = false;
                    //当坦克被击中后将坦克从集合中移除
                    opTanks.remove(opTank);
                    //解读,因为opTank可以是没有Tank,也可以是opTank
                    if(opTank instanceof OpTank){
                        Recorder.addAllOpTanksNum();
                    }
                }
                break;
            case 1: //敌人坦克向右的方向
            case 3: //敌人坦克向左的方向
                if(s.x > opTank.getX() && s.x < opTank.getX() + 60 && s.y > opTank.getY() && s.y < opTank.getY() + 50){
                    s.isLive = false;
                    opTank.isLive = false;
                    //当坦克被击中后将坦克从集合中移除
                    opTanks.remove(opTank);
                    //解读,因为opTank可以是没有Tank,也可以是opTank
                    if(opTank instanceof OpTank){
                        Recorder.addAllOpTanksNum();
                    }
                }
                break;
        }
    }

    //判断我方坦克是否触碰到了墙壁
    public boolean isMyTankTouchWall(){
        //判断敌人当前的方向
        switch (myTank.getDirect()){
            case 0: //向上
                if(myTank.getX() > 500 && myTank.getX() < 700 && myTank.getY() > 660 && myTank.getY() < 710
//                            || o.getX() > 160 && o.getX() <= 290 && o.getY() > 100 && o.getY() <= 160
//                            || o.getX() > 910 && o.getX() <= 1040 && o.getY() > 100 && o.getY() <= 160
                        || myTank.getX() > 550 && myTank.getX() < 650 && myTank.getY() > 160 && myTank.getY() < 260
                        || myTank.getX() > 790 && myTank.getX() < 850 && myTank.getY() > 100 && myTank.getY() < 160
                        || myTank.getX() > 350 && myTank.getX() < 410 && myTank.getY() > 100 && myTank.getY() < 340
                        || myTank.getX() > 880 && myTank.getX() < 940 && myTank.getY() > 660 && myTank.getY() < 790
                        || myTank.getX() > 260 && myTank.getX() < 320 && myTank.getY() > 660 && myTank.getY() < 790){
                    return true;
                }
                //当前坦克的右上角坐标
                if(myTank.getX() + 50 > 500 && myTank.getX() + 50 < 700 && myTank.getY() > 660 && myTank.getY() < 710
//                            || o.getX() + 50 >= 160 && o.getX() + 50 <= 290 && o.getY() >= 100 && o.getY() <= 160
//                            || o.getX() + 50 >= 910 && o.getX() + 50 <= 1040 && o.getY() >= 100 && o.getY() <= 160
                        || myTank.getX() + 50 > 550 && myTank.getX() + 50 < 650 && myTank.getY() > 160 && myTank.getY() < 260
                        || myTank.getX() + 50 > 790 && myTank.getX() + 50 < 850 && myTank.getY() > 100 && myTank.getY() < 160
                        || myTank.getX() + 50 > 350 && myTank.getX() + 50 < 410 && myTank.getY() > 100 && myTank.getY() < 340
                        || myTank.getX() + 50 > 880 && myTank.getX() + 50 < 940 && myTank.getY() > 660 && myTank.getY() < 790
                        || myTank.getX() + 50 > 260 && myTank.getX() + 50 < 320 && myTank.getY() > 660 && myTank.getY() < 790) {
                    return true;
                }
                break;
            case 1: //向右
                //当前坦克的右上角坐标
                if (myTank.getX() + 60 > 500 && myTank.getX() + 60 < 700 && myTank.getY() > 660 && myTank.getY() < 710
//                            || o.getX() + 60 >= 160 && o.getX() + 60 <= 290 && o.getY() >= 100 && o.getY() <= 160
//                            || o.getX() + 60 >= 910 && o.getX() + 60 <= 1040 && o.getY() >= 100 && o.getY() <= 160
                        || myTank.getX() + 60 > 550 && myTank.getX() + 60 < 650 && myTank.getY() > 160 && myTank.getY() < 260
                        || myTank.getX() + 60 > 790 && myTank.getX() + 60 < 850 && myTank.getY() > 100 && myTank.getY() < 160
                        || myTank.getX() + 60 > 350 && myTank.getX() + 60 < 410 && myTank.getY() > 100 && myTank.getY() < 340
                        || myTank.getX() + 60 > 880 && myTank.getX() + 60 < 940 && myTank.getY() > 660 && myTank.getY() < 790
                        || myTank.getX() + 60 > 260 && myTank.getX() + 60 < 320 && myTank.getY() > 660 && myTank.getY() < 790){
                    return true;
                }
                //当前坦克的右下角坐标
                if(myTank.getX() + 60 > 500 && myTank.getX() + 60 < 700 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 710
//                            || o.getX() + 60 >= 160 && o.getX() + 60 <= 290 && o.getY() + 50 >= 100 && o.getY() + 50 <= 160
//                            || o.getX() + 60 >= 910 && o.getX() + 60 <= 1040 && o.getY() + 50 >= 100 && o.getY() + 50 <= 160
                        || myTank.getX() + 60 > 550 && myTank.getX() + 60 < 650 && myTank.getY() + 50 > 160 && myTank.getY() + 50 < 260
                        || myTank.getX() + 60 > 790 && myTank.getX() + 60 < 850 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 160
                        || myTank.getX() + 60 > 350 && myTank.getX() + 60 < 410 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 340
                        || myTank.getX() + 60 > 880 && myTank.getX() + 60 < 940 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 790
                        || myTank.getX() + 60 > 260 && myTank.getX() + 60 < 320 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 790){
                    return true;
                }
                break;
            case 2: //向下
                //当前坦克的左下角坐标
                if(myTank.getX() > 500 && myTank.getX() < 700 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 710
//                            || o.getX() >= 160 && o.getX() <= 290 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
//                            || o.getX() >= 910 && o.getX() <= 1040 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
                        || myTank.getX() > 550 && myTank.getX() < 650 && myTank.getY() + 60 > 160 && myTank.getY() + 60 < 260
                        || myTank.getX() > 790 && myTank.getX() < 850 && myTank.getY() + 60 > 100 && myTank.getY() + 60 < 160
                        || myTank.getX() > 350 && myTank.getX() < 410 && myTank.getY() + 60 > 100 && myTank.getY() + 60 < 340
                        || myTank.getX() > 880 && myTank.getX() < 940 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 790
                        || myTank.getX() > 260 && myTank.getX() < 320 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 790){
                    return true;
                }
                //当前坦克的右下角坐标
                if(myTank.getX() + 50 > 500 && myTank.getX() + 50 < 700 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 710
//                            || o.getX() + 50 >= 160 && o.getX() + 50 <= 290 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
//                            || o.getX() + 50 >= 910 && o.getX() + 50 <= 1040 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
                        || myTank.getX() + 50 > 550 && myTank.getX() + 50 < 650 && myTank.getY() + 60 > 160 && myTank.getY() + 60 < 260
                        || myTank.getX() + 50 > 790 && myTank.getX() + 50 < 850 && myTank.getY() + 60 > 100 && myTank.getY() + 60 < 160
                        || myTank.getX() + 50 > 350 && myTank.getX() + 50 < 410 && myTank.getY() + 60 > 100 && myTank.getY() + 60 < 340
                        || myTank.getX() + 50 > 880 && myTank.getX() + 50 < 940 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 790
                        || myTank.getX() + 50 > 260 && myTank.getX() + 50 < 320 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 790){
                    return true;
                }
                break;
            case 3: //向左
                //当前坦克的左上角坐标
                if(myTank.getX() > 500 && myTank.getX() < 700 && myTank.getY() > 660 && myTank.getY() < 710
//                            || o.getX() >= 160 && o.getX() <= 290 && o.getY() >= 100 && o.getY() <= 160
//                            || o.getX() >= 910 && o.getX() <= 1040 && o.getY() >= 100 && o.getY() <= 160
                        || myTank.getX() > 550 && myTank.getX() < 650 && myTank.getY() > 160 && myTank.getY() < 260
                        || myTank.getX() > 790 && myTank.getX() < 850 && myTank.getY() > 100 && myTank.getY() < 160
                        || myTank.getX() > 350 && myTank.getX() < 410 && myTank.getY() > 100 && myTank.getY() < 340
                        || myTank.getX() > 880 && myTank.getX() < 940 && myTank.getY() > 660 && myTank.getY() < 790
                        || myTank.getX() > 260 && myTank.getX() < 320 && myTank.getY() > 660 && myTank.getY() < 790){
                    return true;
                }
                //当前坦克的左下角坐标
                if(myTank.getX() > 500 && myTank.getX() < 700 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 710
                        || myTank.getX() > 160 && myTank.getX() < 290 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 160
                        || myTank.getX() > 910 && myTank.getX() < 1040 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 160
                        || myTank.getX() > 550 && myTank.getX() < 650 && myTank.getY() + 50 > 160 && myTank.getY() + 50 < 260
                        || myTank.getX() > 790 && myTank.getX() < 850 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 160
                        || myTank.getX() > 350 && myTank.getX() < 410 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 340
                        || myTank.getX() > 880 && myTank.getX() < 940 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 790
                        || myTank.getX() > 260 && myTank.getX() < 320 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 790){
                    return true;
                }
                break;
        }
        return false;
    }

}

3.坦克基类(Tank)

package com.wak.TankGame01Version;

/*坦克的基类*/
public class Tank {
    private int x;  //坦克的横坐标
    private int y;  //坦克的纵坐标
    private int direct = 0; //坦克的方向
    private int speed = 1;  //坦克的速度
    boolean isLive = true;      //坦克的存活状态

    public Tank(){
        this.x = 100;   //默认坦克的初始x坐标为100
        this.y = 100;   //默认坦克的初始y坐标为100
    }

    public Tank(int x,int y){   //自己设置坦克的初始x,y坐标
        this.x = x;
        this.y = y;
    }


    //设置坦克的x坐标
    public void setX(int x){
        this.x = x;
    }

    //设置坦克的y坐标
    public void setY(int y){
        this.y = y;
    }

    //获得坦克的x坐标
    public int getX(){
        return x;
    }

    //获得坦克的y坐标
    public int getY(){
        return y;
    }

    //设置坦克的方向
    public void setDirect(int direct){
        this.direct = direct;
    }

    //获得坦克的方向
    public int getDirect(){
        return direct;
    }

    //设置坦克的速度
    public void setSpeed(int speed){
        this.speed = speed;
    }

    //获得坦克的速度
    public int getSpeed(){
        return speed;
    }

    //坦克的上右下左移动
    public void MoveUp(){
        y -= speed;
    }
    public void MoveRight(){
        x += speed;
    }
    public void MoveDown(){
        y += speed;
    }
    public void MoveLeft(){
        x -= speed;
    }
}


4.我的坦克类(MyTank)

package com.wak.TankGame01Version;

import java.util.Vector;

/*自己的坦克*/
public class MyTank extends Tank{

    //创建一个坦克
    private MyTank myTank = null;

    //定义一个shot对象,表示一个射击(线程)
    Shot shot = null;
    //创建一个存储炮弹的集合
    Vector<Shot> shots = new Vector<>();
    //设置坦克的初始化坐标
    public MyTank(int x,int y){
        this.setX(x);
        this.setY(y);
    }

    //射击
    public void shotOpTank(){
        //设置炮弹的初始化坐标及方向
        if(shots.size() < 5) {
            switch (this.getDirect()) {
                case 0:
                    shot = new Shot(this.getX() + 25, this.getY(), 0);
                    shot.speed = 4;
                    break;
                case 1:
                    shot = new Shot(this.getX() + 60, this.getY() + 25, 1);
                    shot.speed = 4;
                    break;
                case 2:
                    shot = new Shot(this.getX() + 25, this.getY() + 60, 2);
                    shot.speed = 4;
                    break;
                case 3:
                    shot = new Shot(this.getX(), this.getY() + 25, 3);
                    shot.speed = 4;
                    break;
            }
        //将发射的炮弹弹存入集合中

            shots.add(shot);
        }
        //启动我们的Shot线程
        new Thread(shot).start();

    }
}

5.敌方坦克类(OpTank)

package com.wak.TankGame01Version;

import java.util.Vector;

public class OpTank extends Tank implements Runnable{
    private OpTank opTank = null;   //创建一个敌方坦克
    Vector<Shot> shots = new Vector<>();    //存储多个炮弹
    Vector<OpTank> opTanks = new Vector<>();    //增加成员,可以得到敌人坦克的Vector集合
    public OpTank(int x,int y){
        this.setX(x);
        this.setY(y);
    }

    public void setOpTanks(Vector<OpTank> opTanks){
        this.opTanks = opTanks;
    }

    public boolean isTouchOpTank(){ //防止坦克间重叠
        //判断当前敌人坦克的方向
        switch (this.getDirect()){
            case 0: //上
                for(int j=0;j<opTanks.size();j++){
                    //取出一个敌方坦克
                    OpTank o = opTanks.get(j);
                    if(o != this){  //不能跟自己比
                        //如果敌人是向上或者向下
                        if(o.getDirect() == 0 || o.getDirect() == 2){
                            //当前坦克左上角的坐标
                            if(this.getX() >= o.getX()
                                    && this.getX() <= o.getX() + 50
                                    && this.getY() <= o.getY() + 60
                                    && this.getY() >= o.getY()){
                                return true;
                            }
                            //当前坦克右上角的坐标
                            if(this.getX() + 50 >= o.getX()
                                    && this.getX() + 50<= o.getX() + 50
                                    && this.getY() <= o.getY() + 60
                                    && this.getY() >= o.getY()){
                             return true;
                            }
                        }
                        //如果敌人是向右或者向左
                        if(o.getDirect() == 1 || o.getDirect() == 3){
                            //当前坦克左上角的坐标
                            if(this.getX() >= o.getX()
                                    && this.getX() <= o.getX() + 60
                                    && this.getY() >= o.getY()
                                    && this.getY() <= o.getY() + 50){
                                return true;
                            }
                            //当前坦克右上角的坐标
                            if(this.getX() + 50>= o.getX()
                                    && this.getX() + 50<= o.getX() + 60
                                    && this.getY() >= o.getY()
                                    && this.getY() <= o.getY() + 50){
                                return true;
                            }
                        }
                    }
                }
                break;
            case 1: //右
                for(int j=0;j<opTanks.size();j++){
                    //取出一辆坦克
                    OpTank o = opTanks.get(j);
                    if(o != this){  //不能跟自己比
                        //如果敌方坦克是向上或向下
                        if(o.getDirect() == 0 || o.getDirect() == 2){
                            //当前坦克右上角的坐标
                            if(this.getX() + 60 >= o.getX()
                                    && this.getX() + 60 <= o.getX() + 50
                                    && this.getY() >= o.getY()
                                    && this.getY() <= o.getY() + 60){
                                return true;
                            }
                            //当前坦克右下角的坐标
                            if(this.getX() + 60 >= o.getX()
                                    && this.getX() + 60 <= o.getX() + 50
                                    && this.getY() + 50 >= o.getY()
                                    && this.getY() + 50 <= o.getY() + 60){
                                return true;
                            }
                        }
                        //如果敌方坦克是向右或向左
                        if(o.getDirect() == 1 || o.getDirect() == 3){
                            //当前坦克右上角的坐标
                            if(this.getX() + 60 >= o.getX()
                                    && this.getX() + 60 <= o.getX() + 60
                                    && this.getY() >= o.getY()
                                    && this.getY() <= o.getY() + 50){
                                return true;
                            }
                            //当前坦克右下角的坐标
                            if(this.getX() + 60 >= o.getX()
                                    && this.getX() + 60 <= o.getX() + 60
                                    && this.getY() + 50 >= o.getY()
                                    && this.getY() + 50 <= o.getY() + 50){
                                return true;
                            }
                        }
                    }
                }
                break;
            case 2: //下
                for(int j=0;j<opTanks.size();j++){
                    //取出一辆坦克
                    OpTank o = opTanks.get(j);
                    if(o != this){  //不能跟自己比
                        //如果敌方坦克是向上或向下
                        if(o.getDirect() == 0 || o.getDirect() == 2){
                            //当前坦克左下角的坐标
                            if(this.getX() >= o.getX()
                                    && this.getX() <= o.getX() + 60
                                    && this.getY() + 60 >= o.getY()
                                    && this.getY() + 60 <= o.getY()){
                                return true;
                            }
                            //当前坦克右下角的坐标
                            if(this.getX() + 50>= o.getX()
                                    && this.getX() + 50 <= o.getX() + 60
                                    && this.getY() + 60 >= o.getY()
                                    && this.getY() + 60 <= o.getY()){
                                return true;
                            }
                        }
                        //如果敌方坦克是向右或向左
                        if(o.getDirect() == 1 || o.getDirect() == 3){
                            //当前坦克左下角的坐标
                            if(this.getX() >= o.getX()
                                    && this.getX() + 60 <= o.getX() + 60
                                    && this.getY() >= o.getY()
                                    && this.getY() + 50 <= o.getY() + 50){
                                return true;
                            }
                            //当前坦克右下角的坐标
                            if(this.getX() + 50 >= o.getX()
                                    && this.getX() + 50 <= o.getX() + 60
                                    && this.getY() + 60 >= o.getY()
                                    && this.getY() + 60 <= o.getY() + 50){
                                return true;
                            }
                        }
                    }
                }
                break;
            case 3: //左
                for(int j=0;j<opTanks.size();j++){
                    //取出一辆坦克
                    OpTank o = opTanks.get(j);
                    if(o != this){  //不能跟自己比
                        //如果敌方坦克是向上或向下
                        if(o.getDirect() == 0 || o.getDirect() == 2){
                            //当前坦克左上角的坐标
                            if(this.getX() >= o.getX()
                                    && this.getX() <= o.getX() + 60
                                    && this.getY() >= o.getY()
                                    && this.getY() <= o.getY()){
                                return true;
                            }
                            //当前坦克左下角的坐标
                            if(this.getX() >= o.getX()
                                    && this.getX() <= o.getX() + 60
                                    && this.getY() + 50 >= o.getY()
                                    && this.getY() + 50 <= o.getY()){
                                return true;
                            }
                        }
                        //如果敌方坦克是向右或向左
                        if(o.getDirect() == 1 || o.getDirect() == 3){
                            //当前坦克左上角的坐标
                            if(this.getX() >= o.getX()
                                    && this.getX() <= o.getX() + 60
                                    && this.getY() >= o.getY()
                                    && this.getY() <= o.getY() + 50){
                                return true;
                            }
                            //当前坦克左下角的坐标
                            if(this.getX() >= o.getX()
                                    && this.getX() <= o.getX() + 60
                                    && this.getY() + 50 >= o.getY()
                                    && this.getY() + 50 <= o.getY() + 50){
                                return true;
                            }
                        }
                    }
                }
                break;
        }
        return false;
    }


    //判断敌方坦克是否触碰到了墙壁
    public boolean isTouchWall(){
        //判断敌人当前的方向
        switch (getDirect()){
            case 0: //向上
                for(int i=0;i<opTanks.size();i++){  //取出一个坦克
                    OpTank o = opTanks.get(i);
                    //当前坦克的左上角坐标
                    if(o.getX() > 500 && o.getX() < 700 && o.getY() > 660 && o.getY() < 710
//                            || o.getX() > 160 && o.getX() <= 290 && o.getY() > 100 && o.getY() <= 160
//                            || o.getX() > 910 && o.getX() <= 1040 && o.getY() > 100 && o.getY() <= 160
                            || o.getX() > 550 && o.getX() < 650 && o.getY() > 160 && o.getY() < 260
                            || o.getX() > 790 && o.getX() < 850 && o.getY() > 100 && o.getY() < 160
                            || o.getX() > 350 && o.getX() < 410 && o.getY() > 100 && o.getY() < 340
                            || o.getX() > 880 && o.getX() < 940 && o.getY() > 660 && o.getY() < 790
                            || o.getX() > 260 && o.getX() < 320 && o.getY() > 660 && o.getY() < 790){
                        return true;
                    }
                    //当前坦克的右上角坐标
                    if(o.getX() + 50 > 500 && o.getX() + 50 < 700 && o.getY() > 660 && o.getY() < 710
//                            || o.getX() + 50 >= 160 && o.getX() + 50 <= 290 && o.getY() >= 100 && o.getY() <= 160
//                            || o.getX() + 50 >= 910 && o.getX() + 50 <= 1040 && o.getY() >= 100 && o.getY() <= 160
                            || o.getX() + 50 > 550 && o.getX() + 50 < 650 && o.getY() > 160 && o.getY() < 260
                            || o.getX() + 50 > 790 && o.getX() + 50 < 850 && o.getY() > 100 && o.getY() < 160
                            || o.getX() + 50 > 350 && o.getX() + 50 < 410 && o.getY() > 100 && o.getY() < 340
                            || o.getX() + 50 > 880 && o.getX() + 50 < 940 && o.getY() > 660 && o.getY() < 790
                            || o.getX() + 50 > 260 && o.getX() + 50 < 320 && o.getY() > 660 && o.getY() < 790){
                        return true;
                    }
                }
                break;
            case 1: //向右
                for(int i=0;i<opTanks.size();i++) {  //取出一个坦克
                    OpTank o = opTanks.get(i);
                    //当前坦克的右上角坐标
                    if (o.getX() + 60 > 500 && o.getX() + 60 < 700 && o.getY() > 660 && o.getY() < 710
//                            || o.getX() + 60 >= 160 && o.getX() + 60 <= 290 && o.getY() >= 100 && o.getY() <= 160
//                            || o.getX() + 60 >= 910 && o.getX() + 60 <= 1040 && o.getY() >= 100 && o.getY() <= 160
                            || o.getX() + 60 > 550 && o.getX() + 60 < 650 && o.getY() > 160 && o.getY() < 260
                            || o.getX() + 60 > 790 && o.getX() + 60 < 850 && o.getY() > 100 && o.getY() < 160
                            || o.getX() + 60 > 350 && o.getX() + 60 < 410 && o.getY() > 100 && o.getY() < 340
                            || o.getX() + 60 > 880 && o.getX() + 60 < 940 && o.getY() > 660 && o.getY() < 790
                            || o.getX() + 60 > 260 && o.getX() + 60 < 320 && o.getY() > 660 && o.getY() < 790){
                        return true;
                    }
                    //当前坦克的右下角坐标
                    if(o.getX() + 60 > 500 && o.getX() + 60 < 700 && o.getY() + 50 > 660 && o.getY() + 50 < 710
//                            || o.getX() + 60 >= 160 && o.getX() + 60 <= 290 && o.getY() + 50 >= 100 && o.getY() + 50 <= 160
//                            || o.getX() + 60 >= 910 && o.getX() + 60 <= 1040 && o.getY() + 50 >= 100 && o.getY() + 50 <= 160
                            || o.getX() + 60 > 550 && o.getX() + 60 < 650 && o.getY() + 50 > 160 && o.getY() + 50 < 260
                            || o.getX() + 60 > 790 && o.getX() + 60 < 850 && o.getY() + 50 > 100 && o.getY() + 50 < 160
                            || o.getX() + 60 > 350 && o.getX() + 60 < 410 && o.getY() + 50 > 100 && o.getY() + 50 < 340
                            || o.getX() + 60 > 880 && o.getX() + 60 < 940 && o.getY() + 50 > 660 && o.getY() + 50 < 790
                            || o.getX() + 60 > 260 && o.getX() + 60 < 320 && o.getY() + 50 > 660 && o.getY() + 50 < 790){
                        return true;
                    }
                }
                break;
            case 2: //向下
                for(int i=0;i<opTanks.size();i++) {  //取出一个坦克
                    OpTank o = opTanks.get(i);
                    //当前坦克的左下角坐标
                    if(o.getX() > 500 && o.getX() < 700 && o.getY() + 60 > 660 && o.getY() + 60 < 710
//                            || o.getX() >= 160 && o.getX() <= 290 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
//                            || o.getX() >= 910 && o.getX() <= 1040 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
                            || o.getX() > 550 && o.getX() < 650 && o.getY() + 60 > 160 && o.getY() + 60 < 260
                            || o.getX() > 790 && o.getX() < 850 && o.getY() + 60 > 100 && o.getY() + 60 < 160
                            || o.getX() > 350 && o.getX() < 410 && o.getY() + 60 > 100 && o.getY() + 60 < 340
                            || o.getX() > 880 && o.getX() < 940 && o.getY() + 60 > 660 && o.getY() + 60 < 790
                            || o.getX() > 260 && o.getX() < 320 && o.getY() + 60 > 660 && o.getY() + 60 < 790){
                        return true;
                    }
                    //当前坦克的右下角坐标
                    if(o.getX() + 50 > 500 && o.getX() + 50 < 700 && o.getY() + 60 > 660 && o.getY() + 60 < 710
//                            || o.getX() + 50 >= 160 && o.getX() + 50 <= 290 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
//                            || o.getX() + 50 >= 910 && o.getX() + 50 <= 1040 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
                            || o.getX() + 50 > 550 && o.getX() + 50 < 650 && o.getY() + 60 > 160 && o.getY() + 60 < 260
                            || o.getX() + 50 > 790 && o.getX() + 50 < 850 && o.getY() + 60 > 100 && o.getY() + 60 < 160
                            || o.getX() + 50 > 350 && o.getX() + 50 < 410 && o.getY() + 60 > 100 && o.getY() + 60 < 340
                            || o.getX() + 50 > 880 && o.getX() + 50 < 940 && o.getY() + 60 > 660 && o.getY() + 60 < 790
                            || o.getX() + 50 > 260 && o.getX() + 50 < 320 && o.getY() + 60 > 660 && o.getY() + 60 < 790){
                        return true;
                    }
                }
                break;
            case 3: //向左
                for(int i=0;i<opTanks.size();i++) {  //取出一个坦克
                    OpTank o = opTanks.get(i);
                    //当前坦克的左上角坐标
                    if(o.getX() > 500 && o.getX() < 700 && o.getY() > 660 && o.getY() < 710
//                            || o.getX() >= 160 && o.getX() <= 290 && o.getY() >= 100 && o.getY() <= 160
//                            || o.getX() >= 910 && o.getX() <= 1040 && o.getY() >= 100 && o.getY() <= 160
                            || o.getX() > 550 && o.getX() < 650 && o.getY() > 160 && o.getY() < 260
                            || o.getX() > 790 && o.getX() < 850 && o.getY() > 100 && o.getY() < 160
                            || o.getX() > 350 && o.getX() < 410 && o.getY() > 100 && o.getY() < 340
                            || o.getX() > 880 && o.getX() < 940 && o.getY() > 660 && o.getY() < 790
                            || o.getX() > 260 && o.getX() < 320 && o.getY() > 660 && o.getY() < 790){
                        return true;
                    }
                    //当前坦克的左下角坐标
                    if(o.getX() > 500 && o.getX() < 700 && o.getY() + 50 > 660 && o.getY() + 50 < 710
                            || o.getX() > 160 && o.getX() < 290 && o.getY() + 50 > 100 && o.getY() + 50 < 160
                            || o.getX() > 910 && o.getX() < 1040 && o.getY() + 50 > 100 && o.getY() + 50 < 160
                            || o.getX() > 550 && o.getX() < 650 && o.getY() + 50 > 160 && o.getY() + 50 < 260
                            || o.getX() > 790 && o.getX() < 850 && o.getY() + 50 > 100 && o.getY() + 50 < 160
                            || o.getX() > 350 && o.getX() < 410 && o.getY() + 50 > 100 && o.getY() + 50 < 340
                            || o.getX() > 880 && o.getX() < 940 && o.getY() + 50 > 660 && o.getY() + 50 < 790
                            || o.getX() > 260 && o.getX() < 320 && o.getY() + 50 > 660 && o.getY() + 50 < 790){
                        return true;
                    }
                }
                break;
        }
        return false;
    }


    @Override
    public void run() {
        while(true){

            //这里判断坦克的方向,创建对应的炮弹
            if(isLive && shots.size() < 6){
                Shot s = null;
                switch (getDirect()){
                    case 0:
                        s = new Shot(getX() + 25,getY(),0);
                        break;
                    case 1:
                        s = new Shot(getX() + 60,getY() + 25,1);
                        break;
                    case 2:
                        s = new Shot(getX() + 25,getY() + 60,2);
                        break;
                    case 3:
                        s = new Shot(getX(),getY() + 25,3);
                        break;
                }

                //每隔2秒发射一个炮弹
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                shots.add(s);

                new Thread(s).start();
            }

            //坦克移动的方向
            switch (this.getDirect()){
                case 0:
                    for(int i=0;i<60;i++) {
                        if (getY() > 0 && !isTouchOpTank() && !isTouchWall()){
                            MoveUp();
                        }
                        //休眠
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 1:
                    for (int i=0;i<60;i++){
                        if(getX() + 60< 1200 && !isTouchOpTank() && !isTouchWall()) {
                            MoveRight();
                        }
                        //休眠
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 2:
                    for (int i=0;i<60;i++){
                        if(getY() + 60 < 900 && !isTouchOpTank() && !isTouchWall()) {
                            MoveDown();
                        }
                        //休眠
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 3:
                    for (int i=0;i<60;i++){
                        if(getX() > 0 && !isTouchOpTank() && !isTouchWall()) {
                            MoveLeft();
                        }
                        //休眠
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
            }
            setDirect((int)(Math.random() * 4));
//            System.out.println("坦克的x坐标" + getX() + " y坐标 "+ getY() );
            if(!isLive){
               break;
            }
        }
    }
}

6.炮弹类(Shot)

package com.wak.TankGame01Version;

public class Shot implements Runnable{
    int x;  //子弹的x坐标
    int y;  //子弹的y坐标
    int direct = 0; //子弹的方向
    int speed = 4;  //子弹的速度
    boolean isLive = true;  //子弹的存活状态

    public Shot(int x,int y,int direct){
        this.x = x;
        this.y = y;
        this.direct = direct;
    }

    public void setShotSpeed(int speed){
        this.speed = speed;
    }

    @Override
    public void run() { //射击
        while(isLive){
            //休眠
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            switch (direct){
                case 0: //向上
                    y -= speed;
                    break;
                case 1: //向右
                    x += speed;
                    break;
                case 2: //向下
                    y += speed;
                    break;
                case 3: //向左
                    x -= speed;
                    break;
            }

//            System.out.println("炮弹的x坐标:" + x + ",炮弹的y坐标:" + y);
            //如果炮弹弹撞到墙壁,则销毁
            //当炮弹碰到敌人坦克时,也应当结束
            if(!(x > 0 && x < 1200 && y > 0 && y <= 900 && isLive)
//                    || x >= 160 && x <= 290 && y >= 100 && y <= 160
//                    || x >= 910 && x<= 1040 && y >= 100 && y <= 160
                    || x > 550 && x < 650 && y > 160 && y < 260
                    || x > 790 && x < 850 && y > 100 && y < 340
                    || x > 350 && x < 410 && y > 100 && y < 340
                    || x > 880 && x < 940 && y > 660 && y < 790
                    || x > 260 && x < 320 && y > 660 && y < 790
                    || x > 500 && x < 700 && y > 660 && y < 710){
                isLive = false;
//                System.out.println("炮弹已销毁");
            }
        }
    }
}

7.记录信息类(Recorder)

package com.wak.TankGame01Version;

import java.awt.*;
import java.io.*;
import java.util.Vector;

public class Recorder {
    private static int allOpTanksNum = 0;
    //定义IO对象,准备写数据到文件中
    private static FileWriter fw = null;
    private static BufferedWriter bw = null;
    private static BufferedReader br = null;
    private static String recordFile = "D:\\myTankGameRecord.txt";
    //定义Vec,指向GamePanel对象的 敌人坦克Vector
    private static Vector<OpTank> opTanks = null;
    //定义一个Node 的Vector,用于保存敌人的信息node
    private static Vector<Node> nodes = new Vector<>();

    public static void setOpTanks(Vector<OpTank> opTanks){
        Recorder.opTanks = opTanks;
    }

    public static int getAllOpTanksNum(){
        return allOpTanksNum;
    }

    public static void setAllOpTanksNum(int allOpTanksNum){
        Recorder.allOpTanksNum = allOpTanksNum;
    }


    //当我方坦克击毁一个敌人坦克,就应当allOpTanksNum++
    public static void addAllOpTanksNum(){
        Recorder.allOpTanksNum++;
    }

    //增加一个方法,当游戏退出时,我们将allOpTanksNum保存到recordFile
    //对KeepRecord方法进行升级,保存敌人坦克的坐标和方向
    public static void KeepRecord(){
        try {
            bw = new BufferedWriter((new FileWriter((recordFile))));
            bw.write(allOpTanksNum + "\r\n");
            //遍历敌人坦克的Vector,然后根据情况保存即可
            for(int i=0;i<opTanks.size();i++){
                //取出敌人坦克
                OpTank o = opTanks.get(i);
                if(o.isLive){
                    //保存该opTank的信息
                    String record = o.getX() + " " + o.getY() + " " + o.getDirect();
                    //写入到文件
                    bw.write(record + "\r\n");
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (bw != null) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

//    //增加一个方法,用于读取recordFile,恢复相关信息
//    public static Vector<Node> getNodesAndEnemyTankRec(){
//        try {
//            br = new BufferedReader(new FileReader(recordFile));
//
//        } catch (FileNotFoundException e) {
//            e.printStackTrace();
//        }finally {
//
//        }
//        return null;
//    }
}

运行效果截图:

 

 

总结:

这次短学期实践,给我带来了很大收获,让我的时间变得充实,让我收获了写电子笔记,写总结的好习惯,让我能像被封印在椅子上一样,就这么写代码写一整个下午,也深刻的意识到写一个项目或者是一段代码,一定要先有自己的思路,思路是最重要的,是基础,才能去实现,也很感谢老师们,和学长学姐们,以及各位与我一起参加短学期实践的小伙伴们,是他们让我认识到了自己的不足,是他们让我学会了很多对于学习中很有用的方法,见证到了代码的魅力,让我们一起继续加油,尽最大的努力,做最好的自己,为了我爱的和爱我的!

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值