文章目录
坦克大战0.4
增加功能
-
我方坦克在发射的子弹消亡后,才能发射新的子弹。 => 扩展(发多发子弹怎么办)
-
让敌人坦克发射的子弹消亡后,可以再发射子弹
-
当敌人的坦克击中我方坦克时,我放坦克消失,并出现爆炸效果
我方坦克在发射的子弹消亡后,才能发射新的子弹
- 在按下J键时,我们判断当前hero对象的子弹是否已经销毁
- 如果没有销毁,就不去触发 showEnemyTank
- 如果已经销毁,才去触发shotEnemyTank
if (e.getKeyCode() == KeyEvent.VK_J) { //发射子弹
if(hero.shot == null || hero.shot.isLive == false)
hero.shotEnemyTank();
}
- 如果要发射多颗子弹,就是用Vector保存
hero类
Vector<Shot> shots = new Vector<>();
//把新创建的shot放入到shots
shots.add(shot);
- 在绘制我方子弹时,需要遍历该Vector 集合
- 为了优化我们的坦克每次射出多发子弹机制:我们需要把子弹放在一个集合中,我们同样要用Vector集合,我们在hero类创建集合,每次启动一个线程集合时,我们就让子弹集合add(shot),我们在MyPanel类的paint方法中做些修改,将hero的子弹集合shots,遍历取出并绘制,并加入判断语句,如果此子弹为null,并且此子弹isLive属性为true,我们就再画一个子弹,else,此子弹集合元素执行remove()
MyPanel类
//画出敌人的坦克,遍历Vector
for (int i = 0; i < enemyTanks.size(); i++) {
//取出坦克
EnemyTank enemyTank = enemyTanks.get(i);
//判断当前坦克是否存活
if (enemyTank.isLive) { //当敌人坦克是存活的,才画出该坦克
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);
}
}
}
if (e.getKeyCode() == KeyEvent.VK_J) { //发射子弹
if (hero.shot.isLive == false || hero.shot.isLive == true)
hero.shotEnemyTank();
}
让敌人坦克发射的子弹消亡后,可以再发射子弹
- 为了使敌方坦克可以不断射出子弹:我们需要为敌方子弹新建一个vector集合,当敌方坦克子弹集合长度为空时,我们就新建子弹线程集合启动一个线程、并且添加一个敌方坦克集合元素,需要考虑子弹方向,我们依然用switch来控制,因为我们每个敌方坦克都是一个单独的线程与单独的集合,我们得到敌方坦克的坐标位置,通过direct属性,给子弹方向赋值
EnemyTank类
public void run() {
//然后随机的改变坦克方向
while (true) {
//这里我们判断如果shots size() = 0,创建一颗子弹,放入到shots集合中,并启动
if(isLive && shots.size() == 0 ){
Shot s = null;
//判断坦克的方向,创建对应的子弹
switch(getDirect()){
case 0:
s = new Shot(getX() + 20,getY(),0);
break;
case 1:
s = new Shot(getX() + 60,getY(),1);
break;
case 2:
s = new Shot(getX() + 20,getY() + 60,2);
break;
case 3:
s = new Shot(getX() + 20,getY(),3);
break;
}
shots.add(s);
//启动
new Thread(s).start();
}
//根据坦克的方向来继续移动
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() + 60 < 1000){
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) {
// if(getY() + 60 < 750){
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;
}
}
}
}
发射多颗子弹后,保证每颗子弹都能实际命中敌方坦克
因为我们的子弹与敌方坦克都是一个单独的集合与线程,通过我们的子弹线程不断地遍历子弹集合元素,而每颗子弹线程又不断地遍历敌方坦克,用遍历集合的方法,依然调用hitTank()方法,实现多颗子弹命中功能
MyPanel类新建方法
public void hitEnemyTank() {
//遍历我们的子弹
for (int j = 0; j < hero.shots.size(); j++) {
Shot shot = hero.shots.get(j);
//判断是否击中了敌人坦克
if (shot != null && shot.isLive) { //当前我的子弹存活
//遍历所有的坦克
for (int i = 0; i < enemyTanks.size(); i++) {
EnemyTank enemyTank = enemyTanks.get(i);
hitTank(shot, enemyTank);
}
}
}
}
run方法中调用
@Override
public void run() { //每隔10毫秒,重绘区域,刷新绘图区域,子弹就移动
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
hitEnemyTank();
this.repaint();
}
实现敌方坦克子弹命中我方坦克爆炸功能
因为我们之前已经实现过“我方坦克击中敌方坦克爆炸功能”,所以,我们直接利用参数多态,用hitTank方法传入父类参数Tank类,编写一个hitHero方法,遍历敌人的坦克与每个敌人坦克的每个子弹,判断是否击中我放坦克,并调用我们之前写的hitTank方法,实现击中后爆炸
新建hitHero()方法
public void hitHero(){
//遍历所有的敌人坦克
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);
//判断 shot 是否击中我方坦克
if (hero.isLive && shot.isLive){
hitTank(shot,hero);
}
}
}
我们虽然实现了子弹击中坦克后爆炸功能,但是,hero坦克依然存在,我们思路依然很清晰,当我们的坦克被击中时,我们给hero坦克isLive属性为false,并给paint方法一个判断语句,如果isLive == false,则不执行draw.hero
if(hero.isLive)
drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 1); //type坦克类型
未解决bug
1.我们的hero坦克被击中后,依然可以射出子弹
思路:加入isLive判断语句,好像不行
我的的坦克被击中消失后后,可以移动,可以射出子弹,射出的子弹没有颜色,有弹道,并且是“实弹”