java坦克大战1.0——敌人坦克发射子弹+敌人消失+爆炸

目录

1.敌人坦克发射子弹

1.功能分析

 2.代码:

1.EnemyTank类:

2.MyPanel类 

2.敌人消失

1.功能分析:

2.代码 

1.EnemyTank类:

2.MyPanel类

3.Shot类

3.爆炸效果

1.功能分析

2.代码

1.Bomb类

2.MyPanel类

最终代码:

1.MyPanel类

2.Bomb类

3.Shot类

4.EnemyTank类


1.敌人坦克发射子弹

1.功能分析

让敌人的坦克也能够发射多颗子弹

  1. 在敌人坦克类,使用Vector保存多个Shot
  2. 当每创建一个敌人坦克对象,给该敌人对象初始化一个Shot对象,同时启动Shot
  3. 在绘制敌人坦克时,需要变量敌人坦克对象Vertor,绘制所有的子弹,当子弹isLive==false时就从Vertor移除

 2.代码:

1.EnemyTank类:
public class EnemyTank extends Tank {Vector<Shot> shots=new Vector<>();boolean isLive=true;public EnemyTank(int x, int y) {super(x, y);}
}

我们在敌人tank类里面增加了一组Vector集合用于存shot类,以及设置一个标记为了识别子弹是否被销毁。

2.MyPanel类 
 for (int e = 0; e < enemyTankSize; e++) {EnemyTank enemyTank=new EnemyTank(100*(e+1),0);enemyTank.setDirect(3);Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirect());enemyTank.shots.add(shot);new Thread(shot).start();enemyTanks.add(enemyTank);}

我们在初始化敌人坦克的时候,我们加入一颗子弹。并开启子弹的线程。 

for (int i=0;i<enemyTanks.size();i++) {EnemyTank enemyTank = enemyTanks.get(i);draw_tank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 1);//画出子弹for (int j = 0; j < enemyTank.shots.size(); j++) {//取出子弹Shot shot = enemyTank.shots.get(j);//绘制if(shot.isLive()){g.fill3DRect(shot.getX(),shot.getY(),2,2,false);}else {enemyTank.shots.remove(shot);}}}}

我们在MyPanel类里面的 paint方法里面加了判断子弹,以及绘制子弹动画并移除的语句。

2.敌人消失

1.功能分析:

  1. 敌人消失,就是让子弹在遇到坦克的时候让enemytank和子弹的标记为false
  2. 然后在绘制坦克的时候判断标记。

2.代码 

1.EnemyTank类:
public class EnemyTank extends Tank {Vector<Shot> shots=new Vector<>();boolean isLive=true;public EnemyTank(int x, int y) {super(x, y);}
}

 在类里面加一行:

boolen isLive=true;

这里变量类型你可以自己设置,对于这种我们一般建议用default。

2.MyPanel类
public void hitTank(Shot s, EnemyTank enemyTank){switch (enemyTank.getDirect()){case 0:case 2:if(s.getX()>enemyTank.getX()&&s.getX()<enemyTank.getX()+40&&s.getY()>enemyTank.getY()&&s.getY()<enemyTank.getY()+60){s.setLive(false);enemyTank.isLive=false;enemyTanks.remove(enemyTank);}break;case 1:case 3:if (s.getX()>enemyTank.getX()&&s.getX()<enemyTank.getX()+60&&s.getY()>enemyTank.getY()&&s.getY()<enemyTank.getY()+40) {s.setLive(false);enemyTank.isLive=false;enemyTanks.remove(enemyTank);}break;}}

因为我们设置的坦克是矩形的也就说他是一个规则的形状,那么在判断子弹和坦克的接触时,我们可以判断坦克的方向获得坦克的坐标然后和子弹的坐标相匹配。从而得到子弹是否进入了我们坦克的区域然后标记我们的坦克和子弹,并将坦克移除集合。

for (int i=0;i<enemyTanks.size();i++) {EnemyTank enemyTank = enemyTanks.get(i);if(enemyTank.isLive){//确定坦克被击中draw_tank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 1);//画出子弹for (int j = 0; j < enemyTank.shots.size(); j++) {//取出子弹Shot shot = enemyTank.shots.get(j);//绘制if(shot.isLive()){g.fill3DRect(shot.getX(),shot.getY(),2,2,false);}else {enemyTank.shots.remove(shot);}}}}

 在绘制敌人的坦克的时候我我们加上一层if判断,判断是否还为true,不为true将子弹移除集合。这里我们为了不让子弹线程在移除后继续运行,我们对shot类run方法条件进行修改

3.Shot类
 if (!(x>=0&&x<=1000&&y>=0&&y<=750)&&isLive) {isLive=false;break;}

在判段条件里加了一个isLive,在确定子弹销毁的时候,就结束子弹线程。

3.爆炸效果

1.功能分析

  1. 实现爆炸的动态图,我们可以用一张,或多张图,去绘制同一个爆炸的生命周期。、
  2. 爆炸是紧跟在子弹之后的,所以我们去写hitTank方法。

2.代码

1.Bomb类
public class Bomb {int x,y;int life=16;//炸弹生命周期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;}}
}

我们在这里设置生命周期,以及坐标,和标准位

2.MyPanel类
Vector<Bomb> bombs=new Vector<>();Image image1=null;int enemyTankSize=3;public MyPanel(){hero=new Hero(100,100);hero.setSpeed(1);//初始化敌人的tankfor (int e = 0; e < enemyTankSize; e++) {EnemyTank enemyTank=new EnemyTank(100*(e+1),0);enemyTank.setDirect(3);Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirect());enemyTank.shots.add(shot);new Thread(shot).start();enemyTanks.add(enemyTank);}//初始化image1=Toolkit.getDefaultToolkit().getImage("./bomb1.gif");}

在初始化的时候,增加了一个bombs集合来存储爆炸的效果,以及设置一次爆炸所需要的gif图片,当然也可以是两个,三个去做这个爆炸效果。

 public void hitTank(Shot s, EnemyTank enemyTank){switch (enemyTank.getDirect()){case 0:case 2:if(s.getX()>enemyTank.getX()&&s.getX()<enemyTank.getX()+40&&s.getY()>enemyTank.getY()&&s.getY()<enemyTank.getY()+60){s.setLive(false);enemyTank.isLive=false;Bomb bomb=new Bomb(enemyTank.getX(), enemyTank.getY());bombs.add(bomb);enemyTanks.remove(enemyTank);}break;case 1:case 3:if (s.getX()>enemyTank.getX()&&s.getX()<enemyTank.getX()+60&&s.getY()>enemyTank.getY()&&s.getY()<enemyTank.getY()+40) {s.setLive(false);enemyTank.isLive=false;Bomb bomb=new Bomb(enemyTank.getX(), enemyTank.getY());bombs.add(bomb);enemyTanks.remove(enemyTank);}break;}}

在hitTank方法里面增加一次bomb效果

 for (int i = 0; i <bombs.size() ; i++) {Bomb bomb = bombs.get(i);//根据bomb对象的life值去画出炸弹if(bomb.life>0){g.drawImage(image1,bomb.x,bomb.y,60,60,this);}bomb.lifeDown();//life为0if(bomb.life==0){bombs.remove(bomb);}}

并在paint去绘制图像,完成一个生命周期的图画绘制。然后移除

最终代码:

1.MyPanel类

package game;import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;//绘图区
//为了监听键盘事件,实现接口KeyListener
//将子弹变成线程使用
public class MyPanel extends JPanel implements KeyListener,Runnable {//定义我的坦克Hero hero=null;//定义敌人的坦克,放入到vector里面Vector<EnemyTank> enemyTanks=new Vector<>();Vector<Bomb> bombs=new Vector<>();Image image1=null;int enemyTankSize=3;public MyPanel(){hero=new Hero(100,100);hero.setSpeed(1);//初始化敌人的tankfor (int e = 0; e < enemyTankSize; e++) {EnemyTank enemyTank=new EnemyTank(100*(e+1),0);enemyTank.setDirect(3);Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirect());enemyTank.shots.add(shot);new Thread(shot).start();enemyTanks.add(enemyTank);}//初始化image1=Toolkit.getDefaultToolkit().getImage("./bomb1.gif");}@Overridepublic 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()){g.fill3DRect(hero.shot.getX(),hero.shot.getY(),2,2,false);}//画炸弹for (int i = 0; i <bombs.size() ; i++) {Bomb bomb = bombs.get(i);//根据bomb对象的life值去画出炸弹if(bomb.life>0){g.drawImage(image1,bomb.x,bomb.y,60,60,this);}bomb.lifeDown();//life为0if(bomb.life==0){bombs.remove(bomb);}}//画出敌人的坦克for (int i=0;i<enemyTanks.size();i++) {EnemyTank enemyTank = enemyTanks.get(i);if(enemyTank.isLive){//确定坦克被击中draw_tank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 1);//画出子弹for (int j = 0; j < enemyTank.shots.size(); j++) {//取出子弹Shot shot = enemyTank.shots.get(j);//绘制if(shot.isLive()){g.fill3DRect(shot.getX(),shot.getY(),2,2,false);}else {enemyTank.shots.remove(shot);}}}}}//编写方法,画出坦克/**** @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("暂时没有处理");}}//编写方法,判断子弹是否击中public void hitTank(Shot s, EnemyTank enemyTank){switch (enemyTank.getDirect()){case 0:case 2:if(s.getX()>enemyTank.getX()&&s.getX()<enemyTank.getX()+40&&s.getY()>enemyTank.getY()&&s.getY()<enemyTank.getY()+60){s.setLive(false);enemyTank.isLive=false;Bomb bomb=new Bomb(enemyTank.getX(), enemyTank.getY());bombs.add(bomb);enemyTanks.remove(enemyTank);}break;case 1:case 3:if (s.getX()>enemyTank.getX()&&s.getX()<enemyTank.getX()+60&&s.getY()>enemyTank.getY()&&s.getY()<enemyTank.getY()+40) {s.setLive(false);enemyTank.isLive=false;Bomb bomb=new Bomb(enemyTank.getX(), enemyTank.getY());bombs.add(bomb);enemyTanks.remove(enemyTank);}break;}}@Overridepublic void keyTyped(KeyEvent e) {}//处理wsad按下的键@Overridepublic 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();}@Overridepublic void keyReleased(KeyEvent e) {}@Overridepublic void run() {while (true) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}//判断是否击中敌人坦克if(hero.shot!=null&&hero.shot.isLive()){//遍历敌人所有的坦克for (int i = 0; i < enemyTanks.size(); i++) {EnemyTank enemyTank = enemyTanks.get(i);hitTank(hero.shot,enemyTank);}}this.repaint();}}
}

2.Bomb类

package game;public class Bomb {int x,y;int life=16;//炸弹生命周期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;}}
}

3.Shot类

package game;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;@Overridepublic 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:x-=speed;break;case 3:y+=speed;break;}System.out.println("x="+x+"y="+y);//当子弹碰到敌人坦克时结束线程if (!(x>=0&&x<=1000&&y>=0&&y<=750)&&isLive) {isLive=false;break;}}}
}

4.EnemyTank类

package game;import java.util.Vector;public class EnemyTank extends Tank {Vector<Shot> shots=new Vector<>();boolean isLive=true;public EnemyTank(int x, int y) {super(x, y);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2998885.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

pgvector扩展在IvorySQL Oracle兼容模式下的应用实践

向量数据库是生成式人工智能(GenAI)的关键组成部分。作为PostgreSQL的重要扩展&#xff0c;pgvector支持高达16000维的向量计算能力&#xff0c;使得PostgreSQL能够直接转化为高效的向量数据库。 IvorySQL基于PostgreSQL开发&#xff0c;因此它同样支持添加pgvector扩展。在Ora…

springboot图书个性化推荐系统的设计与实现+1w字文档

项目演示视频: 【源码免费送】基于springboot图书个性化推荐系统的设计与实现录像 摘 要 本论文主要论述了如何使用JAVA语言开发一个图书个性化推荐系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项…

大米生产线投资全解析:成本、影响因素及市场潜力

在粮食加工行业中&#xff0c;大米生产线的投资一直是备受关注的热点。那么&#xff0c;大米生产线究竟需要多少钱?其成本受哪些因素影响?与星派来深入解析这一问题&#xff0c;并探讨大米生产线的市场潜力。 一、大米生产线的投资成本 大米生产线的投资成本因多种因素而异&a…

【HTTP协议】了解http需要学习哪些内容

HTTP&#xff08;Hypertext Transfer Protocol&#xff09;是超文本传输协议&#xff0c;互联网上应用最广泛的一种协议&#xff0c;它负责在客户端和服务器之间传输数据。本文将从HTTP协议的基本原理、请求-响应模型、常见特性以及应用场景等方面进行总结。 1. HTTP基本原理 …

InternVL——GPT-4V 的开源替代方案

您的浏览器不支持 video 标签。 在人工智能领域&#xff0c;InternVL 无疑是一颗耀眼的新星。它被认为是最接近 GPT-4V 表现的可商用开源模型&#xff0c;为我们带来了许多惊喜。 InternVL 具备强大的功能&#xff0c;不仅能够处理图像和文本数据&#xff0c;还能精妙地理解…

Gone框架介绍8 - gone支持的注入方式总结

文章目录 Gone支持哪些方式注入&#xff1f;共有属性注入 vs 私有属性注入匿名注入 vs 具名注入匿名埋葬 和 具名埋葬匿名注入具名注入 支持注入的属性类型1.指针类型2.值类型3.接口类型4.Slice 类型5.Map 类型指针注入 vs 接口注入Slice注入 vs Map注入 我从头到尾实现了一个G…

天天看源码就是“智商税”?

点击下方“JavaEdge”&#xff0c;选择“设为星标” 第一时间关注技术干货&#xff01; 免责声明~ 任何文章不要过度深思&#xff01; 万事万物都经不起审视&#xff0c;因为世上没有同样的成长环境&#xff0c;也没有同样的认知水平&#xff0c;更「没有适用于所有人的解决方案…

四种网络IO模型

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;面经 ⛺️稳中求进&#xff0c;晒太阳 IO的定义 IO是计算机内存与外部设备之间拷贝数据的过程。CPU访问内存的速度远高于外部设备。因此CPU是先把外部设备的数据读取到内存&#xff0c;在…

网络编程中有关字节序、地址的转换

大家好&#xff0c;这里是小缺&#xff0c;一名对嵌入式软件开发充满热情的探索者。这一篇文章主要内容是带大家了解网络编程中的字节序和地址转换。 1.1 字节序概述 字节序概念 字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。 分类 小端格式:将…

详细介绍如何使用YOLOv9 在医疗数据集上进行实例分割-含源码+数据集下载

深度学习彻底改变了医学图像分析。通过识别医学图像中的复杂模式,它可以帮助我们解释有关生物系统的重要见解。因此,如果您希望利用深度学习进行医疗诊断,本文可以成为在医疗数据集上微调YOLOv9 实例分割的良好起点。 实例分割模型不是简单地将区域分类为属于特定细胞类型,…

标贝语音识别技术在金融领域中的应用实例

随着语音识别技术与文本挖掘、自然语言处理等技术的不断融合&#xff0c;智能语音交互技术在金融领域中爆发了出巨大的应用潜力。标贝科技根据自身与金融领域合作的经验为大家梳理出以下几点智能语音识别技术在金融领域中的应用实例。 一、智能柜台服务 语音识别的主要功能就…

ctfshow web78 获取flag(用老版的火狐浏览器)

题&#xff1a; 第一种&#xff1a;利用input伪协议 ,获取到flag ?filephp://input POST data <?php system(tac ls) ?> 第二种&#xff1a;利用flter协议,获取到flag https://21d9e58a-c0fd-47ea-a9c4-d875100f2fdb.challenge.ctf.show/?filephp://filter/readcon…

大语言模型在人类层面预测未来的研究与应用

概述 这项研究将探讨语言模型&#xff08;LM&#xff09;能否预测未来事件。在这项研究中&#xff0c;将开发一个系统来自动收集信息、生成和汇总预测结果。将从一个竞争性预测平台收集有关问题的数据&#xff0c;以评估 LM 的预测能力。结果表明&#xff0c;LM 可以与具有竞争…

# 使用 spring boot 时,@Autowired 注解 自动装配注入时,变量报红解决方法:

使用 spring boot 时&#xff0c;Autowired 注解 自动装配注入时&#xff0c;变量报红解决方法&#xff1a; 1、使用 Resource 代替 Autowired 注解&#xff0c;根据类型注入改为根据名称注入&#xff08;建议&#xff09;。 2、在 XXXMapper 上添加 Repository 注解&#xff0…

【MATLAB】解决不同版本MATLAB出现中文乱码的问题

解决不同版本MATLAB出现中文乱码的问题 方法1&#xff1a;更改保存类型为GBK方法2&#xff1a;记事本打开方法3&#xff1a;Notepad参考 低版本matlab打开高版本Matlab的.m文件时&#xff0c;出现中文乱码问题。比如下图&#xff1a; 出现原因为&#xff1a; 编码格式不统一问…

使用Redis Topic广播模式,实现类似mq消息的发布和订阅

一、背景 不同的mq中间件&#xff0c;不仅支持发送队列消息&#xff0c;也都可以发送广播消息。 有时候&#xff0c;我们的业务逻辑需要发送广播消息&#xff0c;却不想引入mq中间件时&#xff0c;推荐你使用redis的topic机制来实现。 原因是&#xff1a;它比较轻量级&#x…

为了不让共享单车进城,出租车司机剑走偏锋杀红了眼……

最近&#xff0c;小柴上网冲浪的时候&#xff0c;刷到一些看上去非常离谱的画面&#xff0c;不知道柴油们有没有刷到&#xff0c;大概是下面这样的&#xff0c;一道道出租车堆起来的钢铁长城…… 大量的出租车司机不出车&#xff0c;竟然联起手来&#xff0c;将车停在路边&…

Vue生命周期都有哪些?

定义 Vue的生命周期就是实例从创建到销毁的一个过程&#xff0c;即从创建、初始化数据、编译模板、挂载Dom($el)->渲染、更新->渲染&#xff0c;卸载等一系列的过程。el是挂载点如<div id"app"></div>。 Vue的生命周期分为八个阶段 1.beforeCreate…

在线教程|零门槛部署 Llama 3,70B 版本只占 1.07G 存储空间,新用户免费体验 8B 版本

4 月 18 日&#xff0c;Meta 宣布开源 Llama 3&#xff0c;这个号称「迄今为止最好的开源大模型」一经发布&#xff0c;立刻引爆科技圈&#xff01; 发布当天恰逢斯坦福大学教授、AI 顶尖专家吴恩达的生日&#xff0c;作为 AI 开源倡导者&#xff0c;他激动地发文表示&#xff…

Adobe推出AI视频超分辨率工具VideoGigaGAN

&#x1f989; AI新闻 &#x1f680; Adobe推出AI视频超分辨率工具VideoGigaGAN 摘要&#xff1a;Adobe公司最新推出的AI工具VideoGigaGAN&#xff0c;利用上采样技术将视频分辨率从128128提升至10241024。这一工具基于GigaGAN模型开发&#xff0c;专注于生成视频超分辨率&am…