java坦克大战1.0——发射子弹

目录

1.逻辑分析:

2. 代码

1.Shot类

2.Hero类

3.MyPanel类

4.HspTankGame03类


1.逻辑分析:

  1. 当发射一颗子弹后就相当于启动一个线程
  2. Hero有子弹的对象,当按下j,我们就启动一个线程,让子弹不停的移动,形成射击的效果。
  3. 我们MyPanel需要不停的重绘,才能出现该效果。
  4. 当子弹移动到面板的边界时就销毁。

2. 代码

1.Shot类

包含子弹的多种属性和方法

public class Shot implements Runnable{
    //子弹的坐标
    private int x;
    private int y;
    private int direct=0;

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getDirect() {
        return direct;
    }

    public void setDirect(int direct) {
        this.direct = direct;
    }

    public boolean isLive() {
        return isLive;
    }

    public void setLive(boolean live) {
        isLive = live;
    }

    public int getSpeed() {
        return speed;
    }

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

    private boolean isLive=true;

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

    private int speed=2;
    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            //根据方向改变
            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<=750)) {
                isLive=false;
                break;
            }

        }
    }
}

因为这个子弹相对于坦克其实是相对独立的,所以我们把他单独一个类,并且做个线程处理。在run方法里面我们根据坦克的方向绘制出子弹的运动方向和轨迹。

2.Hero类

public class Hero extends Tank {
    public Hero(int x, int y) {
        super(x, y);
    }
    //定义一个shot对象
    Shot shot=null;
    public void shotEnemyTank(){
        //根据当前hero对象的位置和方向来创建Shot
        switch (getDirect()){
            case 0://向上
                shot=new Shot(getX()+20,getY(),0);
                break;
            case 1://向右
                shot=new Shot(getX()+60,getY()+20,1);
                break;
            case 2://向下
                shot=new Shot(getX()+20,getY()+60,2);
                break;
            case 3://向下
                shot=new Shot(getX(),getY()+20,3);
                break;
        }
        new Thread(shot).start();
    }
    //启动shot线程


}

我们对于hero增加了一个方法,把坦克的参数传到子弹类里面去。并开启了shot的线程。

3.MyPanel类

public class MyPanel extends JPanel implements KeyListener,Runnable {
    //定义我的坦克
    Hero hero=null;
    //定义敌人的坦克,放入到vector里面
    Vector<EnemyTank> enemyTanks=new Vector<>();

    int enemyTankSize=3;
    public MyPanel(){
        hero=new Hero(100,100);
        hero.setSpeed(1);
        //初始化敌人的tank
        for (int e = 0; e < enemyTankSize; e++) {
            EnemyTank enemyTank=new EnemyTank(100*(e+1),0);
            enemyTank.setDirect(3);
            enemyTanks.add(enemyTank);

        }
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillRect(0,0,1000,750);//

        //画出坦克-封装方法
        draw_tank(hero.getX(),hero.getY(),g,hero.getDirect(),0);
        //画出hero射击的子弹
        if(hero.shot!=null&&hero.shot.isLive()==true)
        {
            g.fill3DRect(hero.shot.getX(),hero.shot.getY(),2,2,false);
        }
        //画出敌人的坦克
        for (EnemyTank enemyTank : enemyTanks) {
            draw_tank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 1);
        }
    }
    //编写方法,画出坦克

    /**
     *
     * @param x 坦克左上角x的坐标
     * @param y 坦克的左上角y的坐标
     * @param g 画笔
     * @param direct 坦克方向
     * @param type 坦克类型
     */
    public void draw_tank(int x,int y,Graphics g,int direct,int type){
        switch (type){
            case 0:
                g.setColor(Color.CYAN);
                break;
            case 1:
                g.setColor(Color.orange);
                break;

        }
        //根据tank的方向绘制
        //根据坦克的方向绘制对应形象的坦克
        switch (direct){
            case 0://表示向上
                g.fill3DRect( x, y,10,60,false);
                g.fill3DRect( x+30, y,10,60,false);
                g.fill3DRect( x+10, y+10,20,40,false);
                g.fillOval(x+10,y+20,20,20);
                g.drawLine(x+20,y+30,x+20,y);
                break;
            case 1://表示向右
                g.fill3DRect( x, y,60,10,false);
                g.fill3DRect( x, y+30,60,10,false);
                g.fill3DRect( x+10, y+10,40,20,false);
                g.fillOval(x+20,y+10,20,20);
                g.drawLine(x+30,y+20,x+60,y+20);
                break;
            case 2://表示向左
                g.fill3DRect( x, y,60,10,false);
                g.fill3DRect( x, y+30,60,10,false);
                g.fill3DRect( x+10, y+10,40,20,false);
                g.fillOval(x+20,y+10,20,20);
                g.drawLine(x+30,y+20,x,y+20);
                break;
            case 3://表示向上
                g.fill3DRect( x, y,10,60,false);
                g.fill3DRect( x+30, y,10,60,false);
                g.fill3DRect( x+10, y+10,20,40,false);
                g.fillOval(x+10,y+20,20,20);
                g.drawLine(x+20,y+30,x+20,y+60);
                break;
            default:
                System.out.println("暂时没有处理");
        }

    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    //处理wsad按下的键
    @Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode()==KeyEvent.VK_W)
        {
            //改变坦克的方向
            hero.setDirect(0);
            hero.move_up();

        } else if (e.getKeyCode()==KeyEvent.VK_D) {
            hero.setDirect(1);
            hero.move_right();

        } else if (e.getKeyCode()==KeyEvent.VK_A) {
            hero.setDirect(2);
            hero.move_left();
        } else if (e.getKeyCode()==KeyEvent.VK_S) {
            hero.setDirect(3);
            hero.move_down();
        }
        if(e.getKeyCode()==KeyEvent.VK_J) {

            System.out.println("用户按下j");
            hero.shotEnemyTank();
        }
        this.repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            this.repaint();
        }
    }
}

在画板类里面我们增加了一个监听按键,以及监听j的按键为了启动子弹的线程。并在画板上面建立一个线程为了绘制子弹。这里我们会说为什么又要用一个线程。这个线程是为了让画板在执行。因为如果不去为了画板开一个线程,那么子弹就会画了一次就结束了,后面线程虽然还在运行。但是在画板上不能体现。

4.HspTankGame03类


public class HspTankGame03 extends JFrame {
    //定义MyPanel
    MyPanel mp=null;
    public static void main(String[] args) {
        HspTankGame03 hspTankGame01=new HspTankGame03();
    }
    public HspTankGame03(){
        mp=new MyPanel();
        Thread thread = new Thread(mp);
        thread.start();HspTankGame03
        this.add(mp);
        this.addKeyListener(mp);//增加监听事件
        this.setSize(1000,750);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }
}

在主进程里面加一个画板的进程开启就行了。结果如下:

子弹就显现出来了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值