坦克大战java程序
目前程序完成的功能:
1.打开游戏选择继续上一局游戏还是重新开始
2.页面打开后有一段背景音乐,增加体验感
3.页面显示击毁的敌方坦克数量
4.玩家坦克由wasd键控制方向,j键控制射击
敌方坦克被击中后,出现爆炸效果
5.敌人坦克随机移动射击
6.坦克移动过程中不会发生重叠现象
目前代码
坦克类(父类)
package ketanglianxi;
public class Tank {
private int x;//̹坦克x坐标
private int y;//̹坦克的y坐标
private int speed =1;
boolean isLive = true;
private int direct;//̹坦克移动方向
public Tank(int x,int y) {
this.x=x;
this.y=y;
}
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 void moveUp() {
y-=speed;
}
public void moveRight() {
x+=speed;
}public void moveDown() {
y+=speed;
}public void moveLeft() {
x-=speed;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
}
玩家坦克类(子类)
import java.util.Vector;
public class Hero extends Tank{
Shot shot = null;//设置子弹类
//将子弹放入Vector集合中
Vector<Shot>shots= new Vector<>();
public Hero(int x,int y) {
super(x,y);
}
//射击敌方坦克
public void shotEnemyTank() {
//玩家坦克设置为五枚子弹
if(shots.size()==5) {
return;
}
//根据坦克前进方向控制子弹方向
switch(getDirect()){
case 0://UP
shot = new Shot(getX()+20,getY(),0);
break;
case 1://RIGHT
shot = new Shot(getX()+60,getY()+20,1);
break;
case 2://DOWN
shot = new Shot(getX()+20,getY()+60,2);
break;
case 3://LEFT
shot = new Shot(getX(),getY()+20,3);
break;
}
shots.add(shot);
//开启进程
new Thread(shot).start();
}
}
敌方坦克(子类)
import java.util.List;
import java.util.Vector;
public class EnemyTank extends Tank implements Runnable{
boolean isLive =true;
Vector <Shot> shots = new Vector<>();
//敌人坦克类,使用Vector保存多个shot
//增加成员,EnemyTank可以得到敌人坦克的Vector
Vector<EnemyTank>enemyTanks = new Vector<>();
//1.enemyTanks在MyPanel类中
public EnemyTank(int x, int y) {
super(x, y);
// TODO Auto-generated constructor stub
}
//这里提供一个方法,可以将MyPanel的成员Vector <Shot> shots = new Vector<>();
//设置到EnemyTank的成员enemyTanks
public void setEnemyTanks(Vector<EnemyTank> enemyTanks) {
this.enemyTanks = enemyTanks;
}
//编写方法,判断当前的这个敌人坦克,是否和enemyTanks中的其他坦克发生重叠
public boolean isTouchEnemyTank() {
//判断当前敌人坦克(this)方向
switch(this.getDirect()) {
case 0://当前坦克向上
//让当前敌人坦克和其他所有的敌人坦克比较
for(int i =0;i<enemyTanks.size();i++) {
//从Vector中取出一个敌人坦克
EnemyTank enemyTank = enemyTanks.get(i);
if(enemyTank!=this) {
//如果敌人坦克是上/下,x的范围[enemyTank.getX(),enemyTank.getX()+40]
//y的范围[enemyTank.getY(),enemyTank.getX()+60]
if(enemyTank.getDirect()==0||enemyTank.getDirect()==2) {
//2.当前坦克左上角坐标[this.getX(),this.getY()]
//3.当前坦克右上角坐标[this.getX()+40,this.getY()]
if(this.getX()>=enemyTank.getX()
&&this.getX()<=enemyTank.getX()+40
&&this.getY()>=enemyTank.getY()
&&this.getY()<=enemyTank.getY()+60)
return true;
if(this.getX()+40>=enemyTank.getX()
&&this.getX()+40<=enemyTank.getX()+40
&&this.getY()>=enemyTank.getY()
&&this.getY()<=enemyTank.getY()+60)
return true;
}
//如果敌人坦克是左或右
//敌人坦克x的范围[enemyTank.getX(),enemyTank.getX()+60]
// y的范围[enemyTank.getY(),enemyTank.getY()+40]
if(enemyTank.getDirect()==1||enemyTank.getDirect()==3) {
if(this.getX()>=enemyTank.getX()
&&this.getX()<=enemyTank.getX()+60
&&this.getY()>=enemyTank.getY()
&&this.getY()<=enemyTank.getY()+40)
return true;
if(this.getX()+40>=enemyTank.getX()
&&this.getX()+40<=enemyTank.getX()+60
&&this.getY()>=enemyTank.getY()
&&this.getY()<=enemyTank.getY()+40)
return true;
}
}
}
break;
case 1://当前坦克向右
for(int i =0;i<enemyTanks.size();i++) {
//从Vector中取出一个敌人坦克
EnemyTank enemyTank = enemyTanks.get(i);
if(enemyTank!=this) {
//如果敌人坦克是左/右,x的范围[enemyTank.getX(),enemyTank.getX()+60]
//y的范围[enemyTank.getY(),enemyTank.getX()+40]
if(enemyTank.getDirect()==0||enemyTank.getDirect()==2) {
//2.当前坦克右上角坐标[this.getX()+60,this.getY()]
//3.当前坦克右下角坐标[this.getX()+60,this.getY()+40]
if(this.getX()+60>=enemyTank.getX()
&&this.getX()+60<=enemyTank.getX()+40
&&this.getY()>=enemyTank.getY()
&&this.getY()<=enemyTank.getY()+60)
return true;
//当前坦克右下角的坐标[this.getX()+60,this.getY()+40]
if(this.getX()+60>=enemyTank.getX()
&&this.getX()+60<=enemyTank.getX()+40
&&this.getY()+40>=enemyTank.getY()
&&this.getY()+40<=enemyTank.getY()+60)
return true;
}
//如果敌人坦克是左或右
//敌人坦克x的范围[enemyTank.getX(),enemyTank.getX()+60]
// y的范围[enemyTank.getY(),enemyTank.getY()+40]
if(enemyTank.getDirect()==1||enemyTank.getDirect()==3) {
//1.当前坦克右上角坐标[this.getX()+60,this.getY()]
if(this.getX()+60>=enemyTank.getX()
&&this.getX()+60<=enemyTank.getX()+60
&&this.getY()>=enemyTank.getY()
&&this.getY()<=enemyTank.getY()+40)
return true;
//2.当前坦克右下角坐标[this.getX()+60,this.getY()+40]
if(this.getX()+60>=enemyTank.getX()
&&this.getX()+60<=enemyTank.getX()+60
&&this.getY()+40>=enemyTank.getY()
&&this.getY()+40<=enemyTank.getY()+40)
return true;
}
}
}
break;
case 2://当前坦克向下
for(int i =0;i<enemyTanks.size();i++) {
//从Vector中取出一个敌人坦克
EnemyTank enemyTank = enemyTanks.get(i);
if(enemyTank!=this) {
//如果敌人坦克是上/下,x的范围[enemyTank.getX(),enemyTank.getX()+60]
//y的范围[enemyTank.getY(),enemyTank.getX()+40]
if(enemyTank.getDirect()==0||enemyTank.getDirect()==2) {
//2.当前坦克左下角坐标[this.getX(),this.getY()+60]
//3.当前坦克右下角坐标[this.getX()+40,this.getY()+60]
if(this.getX()>=enemyTank.getX()
&&this.getX()<=enemyTank.getX()+40
&&this.getY()+60>=enemyTank.getY()
&&this.getY()+60<=enemyTank.getY()+60)
return true;
//当前坦克右下角的坐标[this.getX()+40,this.getY()+60]
if(this.getX()+40>=enemyTank.getX()
&&this.getX()+40<=enemyTank.getX()+40
&&this.getY()+60>=enemyTank.getY()
&&this.getY()+60<=enemyTank.getY()+60)
return true;
}
//如果敌人坦克是左/右
//敌人坦克x的范围[enemyTank.getX(),enemyTank.getX()+60]
// y的范围[enemyTank.getY(),enemyTank.getY()+40]
if(enemyTank.getDirect()==1||enemyTank.getDirect()==3) {
//1.当前坦克左下角坐标[this.getX(),this.getY()+60]
if(this.getX()>=enemyTank.getX()
&&this.getX()<=enemyTank.getX()+60
&&this.getY()+60>=enemyTank.getY()
&&this.getY()+60<=enemyTank.getY()+40)
return true;
//2.当前坦克右下角坐标[this.getX()+40,this.getY()+60]
if(this.getX()+40>=enemyTank.getX()
&&this.getX()+40<=enemyTank.getX()+60
&&this.getY()+60>=enemyTank.getY()
&&this.getY()+60<=enemyTank.getY()+40)
return true;
}
}
}
break;
case 3://当前坦克向左
for(int i =0;i<enemyTanks.size();i++) {
//从Vector中取出一个敌人坦克
EnemyTank enemyTank = enemyTanks.get(i);
if(enemyTank!=this) {
//如果敌人坦克是上/下,x的范围[enemyTank.getX(),enemyTank.getX()+60]
//y的范围[enemyTank.getY(),enemyTank.getX()+40]
if(enemyTank.getDirect()==0||enemyTank.getDirect()==2) {
//2.当前坦克左上角坐标[this.getX(),this.getY()]
//3.当前坦克左下角坐标[this.getX()+60,this.getY()+40]
if(this.getX()>=enemyTank.getX()
&&this.getX()<=enemyTank.getX()+40
&&this.getY()>=enemyTank.getY()
&&this.getY()<=enemyTank.getY()+60)
return true;
//当前坦克左下角的坐标[this.getX(),this.getY()+40]
if(this.getX()>=enemyTank.getX()
&&this.getX()<=enemyTank.getX()+40
&&this.getY()+40>=enemyTank.getY()
&&this.getY()+40<=enemyTank.getY()+60)
return true;
}
//如果敌人坦克是左或右
//敌人坦克x的范围[enemyTank.getX(),enemyTank.getX()+60]
// y的范围[enemyTank.getY(),enemyTank.getY()+40]
if(enemyTank.getDirect()==1||enemyTank.getDirect()==3) {
//1.当前坦克左上角坐标[this.getX(),this.getY()]
if(this.getX()>=enemyTank.getX()
&&this.getX()<=enemyTank.getX()+60
&&this.getY()>=enemyTank.getY()
&&this.getY()<=enemyTank.getY()+40)
return true;
//2.当前坦克左下角坐标[this.getX(),this.getY()+40]
if(this.getX()>=enemyTank.getX()
&&this.getX()<=enemyTank.getX()+60
&&this.getY()+40>=enemyTank.getY()
&&this.getY()+40<=enemyTank.getY()+40)
return true;
}
}
}
break;
}
return false;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true) {
if(isLive&&shots.size()<5) {
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:
for(int i =0;i<30;i++) {
if(getY()>0&&!isTouchEnemyTank()) {
moveUp();
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
break;
case 1:for(int i =0;i<30;i++) {
if(getX()+60<1000&&!isTouchEnemyTank())
{
moveRight();
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
break;
case 2:for(int i =0;i<30;i++) {
if(getY()+60<750&&!isTouchEnemyTank()) {
moveDown();
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
break;
case 3:for(int i =0;i<30;i++) {
if(getX()>0&&!isTouchEnemyTank()) {
moveLeft();
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
break;
}
//由随机数生成函数控制坦克方向
setDirect((int)(Math.random()*4));
if(!isLive) {
break;
}
}
}
}
子弹类
public class Shot implements Runnable{
int x;
int y;
int direct=0;
int speed = 3;
boolean isLive =true;//子弹还存在
Shot(int x,int y,int direct){
this.x=x;
this.y=y;
this.direct=direct;
}
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;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true) {
try {
Thread.sleep(50);//休眠50ms
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
switch(direct) {
case 0:y-=speed;
break;
case 1:x+=speed;
break;
case 2: y+=speed;
break;
case 3:x-=speed;
break;
}
if(!(x>=0&&x<=1000&&y>=0&&y<=750&&isLive)) {
isLive = false;
break;
}
}
}
}
Recorder类
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Vector;
/*该类记录我方击毁敌方坦克数
* 2.当游戏结束,将数据写入到文件(IO)
* 3.当退出游戏时,记录敌人坦克坐标和方向
* 4.将每个敌人信息,恢复成Node对象->Vector
*
*/
//用于记录相关信息,和文件交互
public class Recorder {
//定义变量,记录我方击毁敌人坦克数
private static int allEnemyTankNum = 0;
//定义IO对象,准备写数据到文件中
private static FileWriter fw = null;
private static BufferedReader br = null;
private static BufferedWriter bw =null;
//把记录文件保存到src下
private static String recordFile = "src\\myRecord.txt";
public static String getRecordFile() {
return recordFile;
}
//定义Vector,指向MyPanel对象的敌人坦克Vector
private static Vector<EnemyTank>enemyTanks = null;
//定义一个Node的Vector,用于保存敌人的信息node
private static Vector<Node>nodes= new Vector<>();
public static void setEnemyTanks(Vector<EnemyTank> enemyTanks) {
Recorder.enemyTanks = enemyTanks;
}
//增加一个方法,用于读取recordFile,恢复相关信息
//该方法在继续上局时调用即可
public static Vector<Node> getNodesAndEnemyTankRec(){
try {
br = new BufferedReader(new FileReader(recordFile));
allEnemyTankNum=Integer.parseInt(br.readLine());
//循环读取文件,生成nodes集合
String line="";
while((line=br.readLine())!=null) {
String[] xyd=line.split(" ");
Node node= new Node(Integer.parseInt(xyd[0]),Integer.parseInt(xyd[1]),
Integer.parseInt(xyd[2]));
nodes.add(node);//放入到Vector
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(br!=null) {
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return nodes;
}
//增加一个方法,当游戏退出时,我们将allEnemyTankNum保存到recordFile
//对此方法进行升级,保存敌人坦克的坐标和方向
public static void keepRecord() {
try {
bw = new BufferedWriter((new FileWriter(recordFile)));
bw.write(String.valueOf(allEnemyTankNum)+"\r\n");
//遍历敌人坦克的Vector,然后根据情况保存即可
//定义一个属性,然后通过setXxx得到敌人坦克的Vector
for(int i =0;i<enemyTanks.size();i++) {
//取出敌人坦克
EnemyTank enemyTank = enemyTanks.get(i);
if(enemyTank.isLive) {
//保存该坦克信息
String record = enemyTank.getX()+" "+enemyTank.getY()+" "+enemyTank.getDirect();
//写入到文件
bw.write(record+"\r\n");
}
}
bw.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(bw!=null) {
try {
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static int getAllEnemyTankNum() {
return allEnemyTankNum;
}
public static void setAllEnemyTankNum(int allEnemyTankNum) {
Recorder.allEnemyTankNum = allEnemyTankNum;
}
//当我方坦克击毁一个敌人坦克,就应当allEnemyTankNum++
public static void addAllEnemyTankNum() {
Recorder.allEnemyTankNum++;
}
}
Node类
/*一个Node对象,
* 表示一个坦克信息
*/
public class Node {
private int x;
private int y;
private int direct;
public Node(int x,int y,int direct) {
this.x=x;
this.y=y;
this.direct =direct;
}
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;
}
}
Bomb炸弹类
public class Bomb {
int x,y;//炸弹坐标
int life = 9;//生命值设为9
boolean isLive = true;//生命值设为true
public Bomb(int x, int y) {
this.x = x;
this.y = y;
}
public void lifeDown() {
if(life>0) {
life--;
} else {
isLive = false;
}
}
}
播放声音类
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
//播放声音的类
class AePlayWave extends Thread {
private String filename;
public AePlayWave(String wavfile) {
filename = wavfile;
}
public void run() {
File soundFile = new File(filename);
AudioInputStream audioInputStream = null;
try {
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
} catch (Exception e1) {
e1.printStackTrace();
return;
}
AudioFormat format = audioInputStream.getFormat();
SourceDataLine auline = null;
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
try {
auline = (SourceDataLine) AudioSystem.getLine(info);
auline.open(format);
} catch (Exception e) {
e.printStackTrace();
return;
}
auline.start();
int nBytesRead = 0;
//这是缓冲
byte[] abData = new byte[512];
try {
while (nBytesRead != -1) {
nBytesRead = audioInputStream.read(abData, 0, abData.length);
if (nBytesRead >= 0)
auline.write(abData, 0, nBytesRead);
}
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
auline.drain();
auline.close();
}
}
}
页面类
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.util.Vector;
import javax.swing.JPanel;
public class MyPanel extends JPanel implements KeyListener ,Runnable {
//定义玩家坦克
Hero hero = null;
//定义敌人坦克,放入到Vector
Vector<EnemyTank>enemyTanks = new Vector<>();
//定义一个存放Node对象的Vector,用于恢复敌人坦克的坐标和方法
Vector<Node>nodes = new Vector<>();
//定义一个Vector,用于存放炸弹
Vector<Bomb> bombs = new Vector<>();
int enemyTankSize = 3;
//定义三张炸弹图片,用于存放炸弹
Image image1 =null;
Image image2 =null;
Image image3 =null;
public MyPanel(String key) {//key决定开启新游戏还是继续上次游戏
//先将判断记录文件是否存在
//如果存在,就正常执行,如果文件不存在,提示只能开启新游戏
File file =new File(Recorder.getRecordFile());
if(file.exists()&&"2".equals(key)) {
nodes=Recorder.getNodesAndEnemyTankRec();
}else {
System.out.println("只能开启新游戏");
key="1";
}
//将MyPanel对象的enemyTanks设置给Recorder的enemyTanks
Recorder.setEnemyTanks(enemyTanks);
hero= new Hero(500,100);//
hero.setSpeed(1);
switch(key) {
case "1"://初始化敌人坦克
for(int i =0;i<enemyTankSize;i++) {
EnemyTank enemyTank = new EnemyTank(100*(i+1),0);
//将enemyTanks设置给enemyTank
enemyTank.setEnemyTanks(enemyTanks);
enemyTank.setDirect(2);
new Thread(enemyTank).start();
Shot shot=new Shot(enemyTank.getX()+20,enemyTank.getY()+60,enemyTank.getDirect());
//加入
enemyTank.shots.add(shot);
enemyTanks.add(enemyTank);
//启动shot对象
new Thread(shot).start();
}
break;
case "2"://继续上局游戏
//初始化敌人坦克
for(int i =0;i<nodes.size();i++) {
Node node = nodes.get(i);
EnemyTank enemyTank = new EnemyTank(node.getX(),node.getY());
//将enemyTanks设置给enemyTank
enemyTank.setEnemyTanks(enemyTanks);
enemyTank.setDirect(node.getDirect());
new Thread(enemyTank).start();
Shot shot=new Shot(enemyTank.getX()+20,enemyTank.getY()+60,enemyTank.getDirect());
enemyTank.shots.add(shot);
enemyTanks.add(enemyTank);
new Thread(shot).start();
}
break;
default:
System.out.println("输入错误");
}
//这里,播放指定的音乐
new AePlayWave("src\\bgm.wav").start();
//初始化图片对象
image1=Toolkit.getDefaultToolkit().getImage(MyPanel.class.getResource("/bomb1.jpg"));
image2=Toolkit.getDefaultToolkit().getImage(MyPanel.class.getResource("/bomb1.jpg"));
image3=Toolkit.getDefaultToolkit().getImage(MyPanel.class.getResource("/bomb1.jpg"));
}
//编写方法,显示我方击毁敌方坦克信息
public void showInfo(Graphics g) {
//画出玩家的总成绩
g.setColor(Color.BLACK);
Font font =new Font("宋体",Font.BOLD,25);
g.setFont(font);
g.drawString("您累计击毁敌方坦克",1020,30);
drawTank(1020,60,g,0,1);//画出一个敌方坦克
g.setColor(Color.BLACK);//这里需要重新设置成黑色
g.drawString(Recorder.getAllEnemyTankNum()+"", 1080,100);
}
public void paint(Graphics g) {
super.paint(g);
g.fillRect(0,0,1000,750);//填充矩形,默认黑色
showInfo(g);
if(hero!=null&&hero.isLive) {
//画出坦克
drawTank(hero.getX(),hero.getY(),g,hero.getDirect(),0);
}
for(int i = 0;i<hero.shots.size();i++) {
Shot shot = hero.shots.get(i);
if(shot!=null&&shot.isLive!=false) {
g.setColor(Color.cyan);
g.draw3DRect(shot.x, hero.shot.y, 2, 2,false);
} else {
hero.shots.remove(i);
}
}
for(int i =0;i<bombs.size();i++) {
Bomb bomb = bombs.get(i);
if(bomb.life>6) {
g.drawImage(image1, bomb.x, bomb.y, 60, 60, this);
} else if(bomb.life>3) {
g.drawImage(image2, bomb.x, bomb.y, 60, 60, this);
} else {
g.drawImage(image3, bomb.x, bomb.y, 60, 60, this);
}
bomb.lifeDown();
if(bomb.life==0) {
bombs.remove(bomb);
}
}
for(int i = 0;i<enemyTanks.size();i++) {
EnemyTank enemyTank = enemyTanks.get(i);
if(enemyTank.isLive) { drawTank(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.setColor(Color.yellow);
g.draw3DRect(shot.x, shot.y, 2, 2,false);
}
else {
enemyTank.shots.remove(shot);
}
}
}
}
}
public void drawTank(int x,int y,Graphics g,int direct,int type) {
switch(type) {
case 0://玩家坦克
g.setColor(Color.cyan);
break;
case 1://敌人坦克
g.setColor(Color.yellow);
break;
}
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,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;
case 3:
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;
default:
System.out.println("暂无安排");
}
}
public void hitEnemyTank() {
for(int j =0;j<hero.shots.size();j++) {
Shot shot = hero.shots.get(j);
for(int i =0;i<enemyTanks.size();i++) {
EnemyTank enemyTank=enemyTanks.get(i);
hitTank(shot,enemyTank);
}
}
}
public void hitTank(Shot s,Tank tank) {
switch(tank.getDirect()) {
case 0://̹坦克向上
case 2://̹坦克向下
if(s.x>tank.getX()&&s.x<tank.getX()+40
&&s.y>tank.getY()&&s.y<tank.getY()+60) {
s.isLive=false;
tank.isLive=false;
//坦克被击中后就拿掉
enemyTanks.remove(tank);
//当我方击毁一个敌人坦克时,就对数据allEnemyTankNum++
//因为此处坦克可以是hero坦克,也可以是enemyTank,
if(tank instanceof EnemyTank) {
Recorder.addAllEnemyTankNum();
}
//创建Bomb对象,加入到bombs集合
Bomb bomb = new Bomb(tank.getX(),tank.getY());
bombs.add(bomb);
}
case 1://向右
case 3://向左
if(s.x>tank.getX()&&s.x<tank.getX()+60
&&s.y>tank.getY()&&s.y<tank.getY()+40) {
s.isLive=false;
tank.isLive=false;
enemyTanks.remove(tank);
if(tank instanceof EnemyTank) {
Recorder.addAllEnemyTankNum();
}
Bomb bomb = new Bomb(tank.getX(),tank.getY());
bombs.add(bomb);
}
}
}
//判断是否打到玩家坦克
public void hitHero() {
//遍历敌人家坦克
for(int i = 0;i<enemyTanks.size();i++) {
EnemyTank enemyTank= enemyTanks.get(i);
//遍历敌人坦克的每个子弹
for(int j = 0;j<enemyTank.shots.size();j++) {
Shot shot= enemyTank.shots.get(j);
//
if(hero.isLive&&shot.isLive) {
hitTank(shot,hero);
}
}
}
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if(e.getKeyCode()==KeyEvent.VK_W) {
hero.setDirect(0);
if(hero.getY()>0) {
hero.moveUp();
}
} else if(e.getKeyCode()==KeyEvent.VK_D) {
hero.setDirect(1);
if(hero.getX()+60<1000) {
hero.moveRight();
}
} else if(e.getKeyCode()==KeyEvent.VK_S) {
hero.setDirect(2);
if(hero.getY()+60<750) {
hero.moveDown();
}
} else if(e.getKeyCode()==KeyEvent.VK_A) {
hero.setDirect(3);
if(hero.getX()>0) {
hero.moveLeft();
}
}
hero.shotEnemyTank();
}
repaint();
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void run() {
while(true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(hero.shot!=null&&hero.shot.isLive) {
for(int i = 0;i<enemyTanks.size();i++){//遍历敌人的坦克
EnemyTank enemyTank = enemyTanks.get(i);
hitEnemyTank();
}
}
//判断是否射击到玩家坦克
hitHero();
this.repaint();
}
}
}
主程序
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Scanner;
import javax.swing.JFrame;
public class TankGame01 extends JFrame{
//继承JFrame
MyPanel mp = null;
static Scanner sc=new Scanner(System.in);
public static void main(String[] args) {
TankGame01 tankGame = new TankGame01();
}
public TankGame01() {
System.out.println("请输入选择1:新游戏 2:继续上局");
String key = sc.next();
mp=new MyPanel(key);
//把mp加入thread
Thread thread = new Thread(mp);
thread.start();//开启进程
this.add(mp);//把mp加入
this.setSize(1300,950);
this.addKeyListener(mp);//面板加上监视器
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
//在JFrame中增加相应关闭窗口的处理
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
Recorder.keepRecord();
System.exit(0);
}
});
}
}
我的改进思路:
(一)增加障碍物(铁墙:子弹打不穿;木墙:被子弹打数次后会消失)丰富游戏观感
(二)增加关卡,不同关卡的地图难度、敌方坦克数量及玩家生命值都有改变
(三)增加玩家坦克的生命值,如被击中三次才会失败,退出游戏
(四)丰富页面,选择关卡及选择是否开始新游戏时以弹出对话框的形式,增加用户体验感。