ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java基础 - 坦克大战(第五章,坦克移动、与被击中效果功能)

2022-01-20 21:03:10  阅读:272  来源: 互联网

标签:Java int 子弹 第五章 isLive shot 坦克 enemyTank


文章目录

坦克大战0.3

陆游曾说:纸上得来终觉浅,绝知此事要躬行。前面已经了解Java线程基础知识,现在我们来实际运用一下。

在坦克大战游戏(0.2版)基础上添加如下功能:当玩家按一下j键,就发射一颗子弹。

  • 为了能射出子弹,需要把每个子弹做成一个线程,并根据KeyListener事件判断用户输入,之后循环判断子弹位置,repaint()子弹,并要根据坦克的每个方向调整x,y轴

新建Shot类

package tankgame3;

/**
 * Create By 刘鸿涛
 * 2022/1/17 5:19
 */
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 (true){
            //子弹休眠
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //根据方向来改变x,y坐标
            switch (direct){
                case 0://上
                    y -= speed;
                    break;
                case 1://右
                    x += speed;
                    break;
                case 2://下
                    y += speed;
                    break;
                case 3://左
                    x -= speed;
                    break;
            }
            //测试,这里我们输出x,y坐标
            System.out.println("子弹 x = " + x + " y= " + y);
            //当子弹移动到面板
            if (!(x >= 0 && x <= 1000 && y >= 0 && y <= 750)){
                isLive = false;
                break;
            }
        }
    }
}

请添加图片描述

坦克大战0.4版

  • 增加功能
  1. 让敌人的坦克也能够发射子弹(可以有多颗子弹)
  2. 当我方坦克击中敌人坦克时,敌人的坦克就消失,如果能做出爆炸效果更好
  3. 让敌人的坦克也可以自由随机的上下左右移动
  4. 控制我方的坦克和敌人的坦克在规定的范围移动
  • 特别说明
  1. 只要能实现就行,方法的好坏我们后面评讲
  2. 完成上面的任务,不会有没有讲过的知识点,这里主要是锻炼大伙灵活运用技术点能力
  3. 一定要自己先动脑筋想想,试着做做。再听老师的评讲才有意义,时间自己掌控(再次提醒,一定要先自己思考,再听老师讲收获会很大)

1.让敌人坦克发射子弹(多颗子弹)

思路

  • 为了使敌方坦克射出子弹,需要把敌方坦克的所有子弹做成一个线程集合里,这里的集合我们用的vector(为了线程安全),敌人坦克是一个独立的集合,敌人子弹也是一个独立的集合,每个子弹线程都被Thread代理,并执行start()。根据判断敌人坦克子弹的状态,判断是否需要移出此线程集合元素,比如是否碰到边缘、是否碰到玩家、是否碰到障碍物

EnemyTank类

Vector<Shot> shots = new Vector<>();

MyPanel类无参构造器

    public MyPanel(){
        hero = new Hero(500,500);   //初始化自己的坦克
        hero.setSpeed(50);               //初始化坦克速度

        //初始化敌人坦克
        for (int i = 0; i < enemyTanksSize; i++) {
            //创建一个敌人的坦克
            EnemyTank enemyTank = new EnemyTank((100 * (i + 1)), 0);
            //设置方向
            enemyTank.setDirect(2);
            //给该enemyTank 加入一颗子弹
            Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirect());
            //加入enemyTank的Vector 成员
            enemyTank.shots.add(shot);
            //启动 shot 对象
            new Thread(shot).start();
            //加入坦克
            enemyTanks.add(enemyTank);
        }
    }

MyPanel类paint()方法

  @Override
    public void paint(Graphics g){
        super.paint(g);
        g.fillRect(0,0,1000,750);    //填充矩形,默认黑色
        //画出坦克 - 封装方法
        //自己的坦克
        drawTank(hero.getX(),hero.getY(),g,hero.getDirect(),1);        //type坦克类型

        //画出hero射击的子弹
        if (hero.shot != null && hero.shot.isLive == true){
            g.draw3DRect(hero.shot.x,hero.shot.y,5 ,5,false);
        }
        //画出敌人的坦克,遍历Vector
        for (int i = 0; i < enemyTanks.size(); i++) {
            //取出坦克
            EnemyTank enemyTank = enemyTanks.get(i);
            drawTank(enemyTank.getX(),enemyTank.getY(),g,enemyTank.getDirect(),0);
            //画出 enemyTank 所有子弹
            for (int j = 0; j < enemyTank.shots.size(); j++){
                //取出子弹
                Shot shot = enemyTank.shots.get(j);
                //绘制
                if (shot.isLive){   //isLive 为 true
                    g.draw3DRect(shot.x,shot.y,2,2,false);
                }else {
                    //从Vector 移除
                    enemyTank.shots.remove(shot);
                }
            }
        }
    }

2.当我方坦克击中敌人坦克时,敌人的坦克就消失

实现子弹击中敌方坦克消失,我们需要写一个方法,判断我方子弹是否碰到敌方坦克,需要考虑敌方坦克面向问题。我们在paint方法中也加入判断语句,如果上面条件为真,则返回敌方坦克isLive属性为false,根据情况paint敌方坦克是否执行。而我们的线程集合每隔100毫秒遍历一次敌方坦克集合,刷新整个游戏区域,实现敌方坦克被击中后消失

hitTank()方法

    public static void hitTank(Shot s, EnemyTank enemyTank){
        //判断 s 击中坦克
        switch (enemyTank.getDirect()){
            case 0: //坦克向上
            case 2: //坦克向下
                if(s.x > enemyTank.getX() && s.x < enemyTank.getX() + 40
                        && s.y > enemyTank.getY() && s.y < enemyTank.getY() + 60){
                    s.isLive = false;
                    enemyTank.isLive = false;
                }
                break;
            case 1: //坦克向右
            case 3: //坦克向左
                if(s.x > enemyTank.getX() && s.x < enemyTank.getX() + 60
                        && s.y > enemyTank.getY() && s.y < enemyTank.getY() + 40){
                    s.isLive = false;
                    enemyTank.isLive = false;
                }
                break;
        }
    }

3.实现敌人坦克爆炸后消失

当敌方坦克被击中后出现爆炸效果,我们新建一个爆炸效果类,这个类需要有x,y大小,需要一个生命周期的方法,来让爆炸效果动态化。当然了,我们的爆炸效果也在一个集合中,也有自己的isLive属性,判断存活时间,我们用Image来初始化三张图片,并路径赋值,在坦克被击中方法里,我们添加执行效果-> 坦克被击中消失后,我们开始执行爆炸类的“生命周期方法”,按条件执行图片放映顺序

新建Bomb类

package tankgame4;

/**
 * Create By 刘鸿涛
 * 2022/1/19 4:56
 */
public class Bomb {
    int x, y;   //炸弹的坐标
    int life = 9;   //炸弹的生命周期
    boolean isLive = true;  //是否还存活

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

    //减少生命值
    public void lifeDown(){
        if(life > 0){
            life--;
        }else {
            isLive = false;
        }
    }
}

注意图片位置

请添加图片描述

当敌方坦克被击中后出现爆炸效果,我们新建一个爆炸效果类,这个类需要有x,y大小,需要一个生命周期的方法,来让爆炸效果动态化。当然了,我们的爆炸效果也在一个集合中,也有自己的isLive属性,判断存活时间,我们用Image来初始化三张图片,并路径赋值,在坦克被击中方法里,我们添加执行效果-> 坦克被击中消失后,我们开始执行爆炸类的“生命周期方法”,按条件执行图片放映顺序

4.实现敌人坦克自由移动

  1. 因为要求敌人的坦克,可以自由移动,因此需要将敌人坦克当做线程使用
  2. 因此,我们需要EnemyTank implements Runnable
  3. 在run方法写上我们相应的业务代码
  4. 在创建敌人坦克对象时,启动线程

为了使敌方坦克自由活动,我们需要为敌方每个坦克做成一个线程,因此,我们的敌人坦克类要实现Runnable接口,我们的run实现逻辑,通过setDirect封装方法,我们用switch循环加上Math.Random随机生成数,随机生成坦克方向,并按for循环来进行移动,每次朝一个方向移动后休眠50毫秒,体现缓冲效果,当然了,如果此线程坦克被击中,那么我们让此线程while循环break,不再执行

5.实现坦克站规定范围内移动

为了能使敌方坦克在游戏范围内移动,我们只需要在敌方坦克随机循环移动时,加入一个if条件即可,当超过范围,则不执行此次循环

package tankgame4;

import java.util.Vector;

/**
 * Create By 刘鸿涛
 * 2022/1/13 2:16
 */
public class EnemyTank extends Tank implements Runnable {
    //在敌人坦克类,使用Vector 保存多个Shot
    Vector<Shot> shots = new Vector<>();
    boolean isLive = true;

    public EnemyTank(int x, int y) {
        super(x, y);
    }

    @Override
    public void run() {
        //然后随机的改变坦克方向
        while (true) {
            //根据坦克的方向来继续移动
            switch (getDirect()) {
                case 0://向上
                    //让坦克保存一个方向,走30步
                    for (int i = 0; i < 30; i++) {
                        if (getY() > 0) {
                            moveUp();
                            //休眠50毫秒
                            try {
                                Thread.sleep(50);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }

                    break;
                case 1://右

                    for (int i = 0; i < 30; i++) {
                        if (getX() < 902) {
                            moveRight();
                            //休眠50毫秒
                            try {
                                Thread.sleep(50);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    break;
                case 2://下

                    for (int i = 0; i < 30; i++) {
                        if (getY() < 620) {
                            moveDown();
                            //休眠50毫秒
                            try {
                                Thread.sleep(50);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    break;
                case 3://左

                    for (int i = 0; i < 30; i++) {
                        if (getX() > 0) {
                            moveLeft();
                            //休眠50毫秒
                            try {
                                Thread.sleep(50);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    break;
            }
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //随机改变坦克方向0 - 3
            setDirect((int) (Math.random() * 4));
            //如果坦克被击中线程终止
            if (!isLive) {
                break;
            }
        }


    }
}

标签:Java,int,子弹,第五章,isLive,shot,坦克,enemyTank
来源: https://blog.csdn.net/qq_39123467/article/details/122609944

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有