7.线程的应用03

7.4坦克大战5.0版

增加功能:

  1. 我方坦克在发射的子弹消亡之后,才能发射新的子弹==>拓展:发射多颗子弹怎么办,控制一次最多只能发射5颗子弹
  2. 让敌人坦克发射的子弹消亡之后,可以再发射子弹
  3. 当地人的坦克击中我方坦克之后,我方坦克小时,并出现爆炸效果

7.4.1功能1plus:我方坦克连发子弹

思路:

  1. 要发射多颗子弹,就使用Vector保存子弹对象

  2. 在绘制我方子弹的时候需要遍历Vector集合

  3. 同时要修改击中判定方法hitTank

修改处1:Hero类:

package li.TankGame.version05;

import java.util.Vector;

/**
* @author 李
* @version 5.0
*/
public class Hero extends Tank {
//定义一个shot对象,表示一个射击(线程)
Shot shot = null;
//定义一个集合用来装hero发射的子弹对象,使其可以发射多颗子弹
Vector<Shot> shots = new Vector<>(); public Hero(int x, int y) {
super(x, y);
} //射击
public void shotEnemyTank() {
if (shots.size() == 5) {//如果当前的子弹已经有 5颗,就不继续创建新的shot对象,直到当前子弹集合中的子弹对象被移除
return ;
}
//创建Shot对象,根据当前Hero对象的坐标位置和方向来设置子弹的位置和方向
switch (getDirect()) {//获取Hero对象的方向
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; }
//把新创建的shot放入到shots集合中
shots.add(shot);
//启动Shot线程
new Thread(shot).start();
}
}

2:MyPanel的paint方法(部分):

//画出hero发射的子弹
for (int i = 0; i < hero.shots.size(); i++) {
Shot shot = hero.shots.get(i);
if (shot != null && shot.isLive) { //如果子弹对象不为空,并且处于存活状态(isLive=true)
System.out.println("hero的子弹被绘制");
g.draw3DRect(hero.shots.get(i).x, hero.shots.get(i).y, 2, 2, false);
} else {//如果该shot对象已经无效,就从shot集合中删除
hero.shots.remove(shot);
}
}

3:在MyPanel的hitTank方法之前再封装一个hitEnemyTank方法:

public void hitEnemyTank(){
//判断是否击中敌人坦克
for (int i = 0; i <hero.shots.size() ; i++) {
Shot shot=hero.shots.get(i);//shot为当前的子弹对象
if (shot != null && shot.isLive) {//如果当前我的子弹不为空并且子弹还存活
//就遍历敌人所有的坦克
for (int j = 0; j < enemyTanks.size(); j++) {
EnemyTank enemyTank = enemyTanks.get(j);
hitTank(shot, enemyTank);
}
}
}
}
  1. 在MyPanel的run方法里,删除调用的hitTank方法,转为调用hitEnemyTank方法

7.4.2功能2:敌人的子弹消亡之后可以再发射子弹

修改位置:Enemy类:

package li.TankGame.version05;

import java.util.Vector;

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) { //这我们先判断当前的坦克是否存活
// 在判断shots.size<3是否真,为真,说明当前的3颗子弹已经消亡了,
// 就创建一颗子弹,放到shots集合中,并启动线程
if (isLive && (shots.size() < 3)) {//可以通过控制数字来修改敌人坦克一次发射几颗子弹
Shot s = null;
//判断坦克的方创建对应的子弹
switch (getDirect()) {
case 0://向上
s = new Shot(getX() + 20, getY(), 0);
break;
case 1://向右
s = new Shot(getX() + 60, getY() + 20, 1);
break;
case 2://向下
s = new Shot(getX() + 20, getY() + 60, 2);
break;
case 3://向左
s = new Shot(getX(), getY() + 20, 3);
break;
}
shots.add(s);
new Thread(s).start();
}
//根据坦克的方法来继续移动
switch (getDirect()) {
case 0://上
//让坦克保持一个方向走50步
for (int i = 0; i < 50; i++) {
if (getY() > 0) {
moveUp();
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 1://右
//让坦克保持一个方向走50步
for (int i = 0; i < 50; i++) {
if (getX() + 60 < 700) {//700为面板宽度
moveRight();//走一步
}
try {
Thread.sleep(50);//每走一步就休眠50毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 2://下
for (int i = 0; i < 50; i++) {
if (getY() + 60 < 550) {//550为面板宽度
moveDown();
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 3://左
for (int i = 0; i < 50; i++) {
if (getX() > 0) {
moveLeft();
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
}
//随机地改变坦克的方向 0-3
setDirect((int) (Math.random() * 4));//[0,4)的取整
//如果被击中了,就退出线程
if (!isLive) {
break;//退出线程
}
}
}
}

7.4.3功能3:我方坦克被击中时销毁并出现爆炸效果

思路:编写方法,判断敌人的坦克是否击中我们的坦克

修改1:在Tank类中增加isLive属性

boolean isLive = true ;

2:修改MyPanel类的hitTank方法的参数改为(Shot s, Tank enemyTank):即将获得的坦克类型改为父类Tank

3 :在hitTank方法前面增加hitHero方法:

public void hitHeroTank() {
//遍历敌人所有的坦克
for (int i = 0; i < enemyTanks.size(); i++) {
//取出当前的敌人坦克
EnemyTank enemyTank = enemyTanks.get(i);
//取出当enemyTank所有子弹
for (int j = 0; j < enemyTank.shots.size(); j++) {
//取出一颗子弹
Shot shot = enemyTank.shots.get(j);
//判断该子弹是否击中我们的坦克
if (hero.isLive && shot.isLive) {
hitTank(shot, hero);
}
}
}
}

4:在MyPanel类的paint方法里面增加绘出hero坦克的条件:

原来:

现在:

//画出自己的坦克-封装方法
if (hero != null && hero.isLive) {
drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 1);
}

ps:关于我方坦克被打爆后还是可以再继续移动操作的问题,是因为并没有处理hero对象,可以在Hero类中先判断hero对象的isLive为true,之后再进行移动发射等操作。该问题之后再解决。

day05-线程的应用04的更多相关文章

  1. java多线程系类:JUC线程池:04之线程池原理(三)(转)

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--"基础篇& ...

  2. java 多线程 day05 线程范围内的数据共享

    import java.util.HashMap;import java.util.Map;import java.util.Random;/** * Created by chengtao on 1 ...

  3. iOS中多线程知识总结(一)

    这一段开发中一直在处理iOS多线程的问题,但是感觉知识太散了,所以就把iOS中多线程的知识点总结了一下. 1.基本概念 1)什么是进程?进程的特性是什么? 进程是指在系统中正在运行的一个应用程序.   ...

  4. ffmpeg 和 SDL 的结合使用

    FFmpeg是一套可以用来记录.转换数字音频.视频,并能将其转化为流的开源计算机程序.采用LGPL或GPL许可证.它提供了录制.转换以及流化音视 频的完整解决方案.它包含了非常先进的音频/视频编解码库 ...

  5. java:多线程基础之Runnable、Callable与Thread

    java.lang包下有二个非常有用的东西:Runnable接口与Thread类,Thread实现了Runnable接口(可以认为Thread是Runnable的子类),利用它们可以实现最基本的多线程 ...

  6. 分布式数据库中间件–(2) Cobar与client握手身份验证

    Cobar启动完毕,监听特定端口.整个认证的流程图: NIOAcceptor类继承自Thread类,该类的对象会以线程的方式执行,进行连接的监听. NIOAcceptor启动的初始化步骤例如以下: 1 ...

  7. 20160227.CCPP体系详解(0037天)

    程序片段(01):01.一对一模式.c+02.中介者模式.c+03.广播模式.c 内容概要:事件 ///01.一对一模式.c #include <stdio.h> #include < ...

  8. [Python 网络编程] TCP编程/群聊服务端 (二)

    群聊服务端 需求分析: 1. 群聊服务端需支持启动和停止(清理资源); 2. 可以接收客户端的连接; 接收客户端发来的数据 3. 可以将每条信息分发到所有客户端 1) 先搭架子: #TCP Serve ...

  9. python 并发编程之多线程

    一.线程理论 1.什么是线程 ​ 多线程(即多个控制线程)的概念是,在一个进程中存在多个线程,多个线程共享该进程的地址空间,相当于一个车间内有多条流水线,都共用一个车间的资源. 所以,进程只是用来把资 ...

  10. 20160227.CCPP体系具体解释(0037天)

    程序片段(01):01.一对一模式.c+02.中介者模式.c+03.广播模式.c 内容概要:事件 ///01.一对一模式.c #include <stdio.h> #include < ...

随机推荐

  1. jenkins配置自动执行sql脚本

    shell脚本: bigsql="select big_version,small_version from d0mstore.db_current_version order by big ...

  2. 正在运行中的docker容器设置自动重启

    # demo : 你的容器名称 docker update –-restart=always demo

  3. SLSA 框架与软件供应链安全防护

    随着软件供应链攻击浪潮愈演愈烈,Google 发布了一系列指南来确保软件包的完整性,旨在防止影响软件供应链的未经授权的代码修改.新的 Google SLSA 框架(Supply-chain Level ...

  4. Python图像处理丨图像腐蚀与图像膨胀

    摘要:本篇文章主要讲解Python调用OpenCV实现图像腐蚀和图像膨胀的算法. 本文分享自华为云社区<[Python图像处理] 八.图像腐蚀与图像膨胀>,作者: eastmount . ...

  5. Mac Sierra开启读写NTFS

    查看卷标diskutil list sudo vim /etc/fstab,开启WinD盘符读写,添加如下: LABEL=WinD none ntfs rw,auto,nobrowse 磁盘工具重新挂 ...

  6. S32K148-CAN收发

    最近在搞一个转换板开发,大概意思把CAN信号转换成SPI信号,方案有两种:1)通过硬件电路直接把信号的bit位一位一位移给两个集成芯片:2)通过MCU接收CAN信号,再把信号变量转换成SPI信号发送给 ...

  7. ajax03_跨域访问问题

    ajax跨域访问问题 什么是跨域访问 从一个域名去访问另一个域名的资源 或者从一个站点去访问另一个站点的资源 哪些请求方式可以发送跨域请求 超链接 form表单 传统js代码 javascript标签 ...

  8. 如何用WebGPU流畅渲染百万级2D物体?

    大家好~本文使用WebGPU和光线追踪算法,从0开始实现和逐步优化Demo,展示了从渲染500个2D物体都吃力到流畅渲染4百万个2D物体的优化过程和思路 目录 需求 成果 1.选择渲染的算法 2.实现 ...

  9. 如何创建一个带诊断工具的.NET镜像

    现阶段的问题 现在是云原生和容器化时代,.NET Core对于云原生来说有非常好的兼容和亲和性,dotnet社区以及微软为.NET Core提供了非常方便的镜像容器化方案.所以现在大多数的dotnet ...

  10. python开发环境配置(Windows)

    简介 由于在搭建pyhon开发环境时会出现各种各样的问题,因此将这些问题记录下来 1.下载python 从官网下载对应系统的python版本(最新稳定版即可):官网地址为:python下载地址, 建议 ...