坦克的红点,碰到到别的坦克的范围就不动了
//获取全部的敌人坦克,故此来获得他们的坐标来比较是否碰撞
Vector<Enemy_Tank> enemy_tanks = new Vector<>();
//利用set方法来个坦克集合来赋值
public void setEnemy_tanks(Vector<Enemy_Tank> enemy_tanks) {
this.enemy_tanks = enemy_tanks;
}
//设计判断碰撞的方法
public boolean istouchEnemyTank() {
switch (this.getDirect()) {
case 0://向上
for (int i = 0; i < enemy_tanks.size(); i++) {
Enemy_Tank enemy_tank = enemy_tanks.get(i);
if (enemy_tank != this) {
//敌人坦克向上或向下的坐标[getX(),getY()+60], [getX()+40,getY()+60]
if (enemy_tank.getDirect() == 0 || enemy_tank.getDirect() == 2) {
//this坦克左上角坐标 [getX(),getY()],
if (this.getX() > enemy_tank.getX()
&& this.getX() < enemy_tank.getX() + 40
&& this.getY() > enemy_tank.getY()
&& this.getY() < enemy_tank.getY() + 60) {
return true;
}
//this坦克右上角坐标[getX()+40,getY()]
if (this.getX()+40 > enemy_tank.getX()
&& this.getX()+40 < enemy_tank.getX() + 40
&& this.getY() > enemy_tank.getY()
&& this.getY() < enemy_tank.getY() + 60) {
return true;
}
}
//敌人坦克向左或者向右 左下角坐标[getX(),getY()]
//右下角坐标[getX()+60,getY()+40]
if(enemy_tank.getDirect()==1||enemy_tank.getDirect()==3){
//this坦克左上角坐标 [getX(),getY()],
if (this.getX() > enemy_tank.getX()
&& this.getX() < enemy_tank.getX() + 60
&& this.getY() > enemy_tank.getY()
&& this.getY() < enemy_tank.getY() + 40) {
return true;
}
//this坦克右上角坐标[getX()+40,getY()]
if (this.getX()+40 > enemy_tank.getX()
&& this.getX()+40 < enemy_tank.getX() + 60
&& this.getY() > enemy_tank.getY()
&& this.getY() < enemy_tank.getY() + 40) {
return true;
}
}
}
}
break;
case 1://向右
//敌人坦克的范围是不用改变的知识自己的坦克坐标改变了
for (int i = 0; i < enemy_tanks.size(); i++) {
Enemy_Tank enemy_tank = enemy_tanks.get(i);
if (enemy_tank != this) {
//敌人坦克向上或向下的坐标[getX(),getY()+60], [getX()+40,getY()+60]
if (enemy_tank.getDirect() == 0 || enemy_tank.getDirect() == 2) {
//this坦克右上角坐标 [getX()+60,getY()],
if (this.getX()+60 > enemy_tank.getX()
&& this.getX()+60 < enemy_tank.getX() + 40
&& this.getY() > enemy_tank.getY()
&& this.getY() < enemy_tank.getY() + 60) {
return true;
}
//this坦克右下角坐标[getX()+60,getY()+40]
if (this.getX()+60 > enemy_tank.getX()
&& this.getX()+60 < enemy_tank.getX() + 40
&& this.getY()+40 > enemy_tank.getY()
&& this.getY()+40 < enemy_tank.getY() + 60) {
return true;
}
}
//敌人坦克向左或者向右 左下角坐标[getX(),getY()]
//右下角坐标[getX()+60,getY()+40]
if(enemy_tank.getDirect()==1||enemy_tank.getDirect()==3){
//this坦克右上角坐标 [getX()+60,getY()],
if (this.getX()+60 > enemy_tank.getX()
&& this.getX()+60 < enemy_tank.getX() + 60
&& this.getY() > enemy_tank.getY()
&& this.getY() < enemy_tank.getY() + 40) {
return true;
}
//this坦克右下角坐标[getX()+60,getY()+40]
if (this.getX()+60 > enemy_tank.getX()
&& this.getX()+60 < enemy_tank.getX() + 60
&& this.getY()+40 > enemy_tank.getY()
&& this.getY()+40 < enemy_tank.getY() + 40) {
return true;
}
}
}
}
break;
case 2://向下
//敌人坦克的范围是不用改变的只是自己的坦克坐标改变了
for (int i = 0; i < enemy_tanks.size(); i++) {
Enemy_Tank enemy_tank = enemy_tanks.get(i);
if (enemy_tank != this) {
//敌人坦克向上或向下的坐标[getX(),getY()+60],
// [getX()+40,getY()+60]
if (enemy_tank.getDirect() == 0 || enemy_tank.getDirect() == 2) {
//this坦克左下角坐标 [getX(),getY()+60],
if (this.getX() > enemy_tank.getX()
&& this.getX() < enemy_tank.getX() + 40
&& this.getY()+60 > enemy_tank.getY()
&& this.getY()+60 < enemy_tank.getY() + 60) {
return true;
}
//this坦克右下角坐标[getX()+40,getY()+60]
if (this.getX()+40 > enemy_tank.getX()
&& this.getX()+40 < enemy_tank.getX() + 40
&& this.getY()+60 > enemy_tank.getY()
&& this.getY()+60 < enemy_tank.getY() + 60) {
return true;
}
}
//敌人坦克向左或者向右 左下角坐标[getX(),getY()]
//右下角坐标[getX()+60,getY()+40]
if(enemy_tank.getDirect()==1||enemy_tank.getDirect()==3){
//this坦克左下角坐标 [getX(),getY()+60],
if (this.getX()> enemy_tank.getX()
&& this.getX() < enemy_tank.getX() + 60
&& this.getY()+60 > enemy_tank.getY()
&& this.getY()+60 < enemy_tank.getY() + 40) {
return true;
}
//this坦克右下角坐标[getX()+40,getY()+60]
if (this.getX()+40 > enemy_tank.getX()
&& this.getX()+40 < enemy_tank.getX() + 60
&& this.getY()+60 > enemy_tank.getY()
&& this.getY()+60 < enemy_tank.getY() + 40) {
return true;
}
}
}
}
break;
case 3://向左
//敌人坦克的范围是不用改变的只是自己的坦克坐标改变了
for (int i = 0; i < enemy_tanks.size(); i++) {
Enemy_Tank enemy_tank = enemy_tanks.get(i);
if (enemy_tank != this) {
//敌人坦克向上或向下的坐标[getX(),getY()+60],
// [getX()+40,getY()+60]
if (enemy_tank.getDirect() == 0 || enemy_tank.getDirect() == 2) {
//this坦克左上角坐标 [getX(),getY()],
if (this.getX() > enemy_tank.getX()
&& this.getX() < enemy_tank.getX() + 40
&& this.getY()> enemy_tank.getY()
&& this.getY() < enemy_tank.getY() + 60) {
return true;
}
//this坦克左下角坐标[getX(),getY()+40]
if (this.getX() > enemy_tank.getX()
&& this.getX() < enemy_tank.getX() + 40
&& this.getY()+40 > enemy_tank.getY()
&& this.getY()+40 < enemy_tank.getY() + 60) {
return true;
}
}
//敌人坦克向左或者向右 左下角坐标[getX(),getY()]
//右下角坐标[getX()+60,getY()+40]
if(enemy_tank.getDirect()==1||enemy_tank.getDirect()==3){
//this坦克左上角坐标 [getX(),getY()],
if (this.getX()> enemy_tank.getX()
&& this.getX() < enemy_tank.getX() + 60
&& this.getY() > enemy_tank.getY()
&& this.getY() < enemy_tank.getY() + 40) {
return true;
}
//this坦克左下角坐标[getX(),getY()+40]
if (this.getX() > enemy_tank.getX()
&& this.getX()< enemy_tank.getX() + 60
&& this.getY()+40 > enemy_tank.getY()
&& this.getY()+40 < enemy_tank.getY() + 40) {
return true;
}
}
}
}
break;
}
//没有进入switch返回false
return false;
}
//根据方向来移动坦克
switch (getDirect()) {
case 0://一次就移动XX步
for (int i = 0; i < StepNum; i++) {
try {
Thread.sleep(SleepNum);
} catch (InterruptedException e) {
e.printStackTrace();
}
//坦克的坐标向上不能小于0,小于0就出界了&&坦克还不能重叠
if (getY() > 0&&!istouchEnemyTank()) {
moveUp();
}
}
break;
case 1:
for (int i = 0; i < StepNum; i++) {
try {
Thread.sleep(SleepNum);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (getX() + 70 < 1180&&!istouchEnemyTank()) {//坦克的X坐标向上不能大于1200,小于1200就出界了
moveRight();
}
}
break;
case 2:
for (int i = 0; i < StepNum; i++) {
try {
Thread.sleep(SleepNum);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (getY() + 70 < 800&&!istouchEnemyTank()) {//坦克的X坐标向上不能大于850,小于850就出界了
moveDown();
}
}
break;
case 3://一次就移动100步
for (int i = 0; i < StepNum; i++) {
try {
Thread.sleep(SleepNum);//延时50毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
if (getX() > 0&&!istouchEnemyTank()) {
moveLeft();
}
}
break;
}
Tank_Frame
package com.Tank.TankGame06;
import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.util.Scanner;
/**
* @author 你是大**吗?
* version 1.0
*/
@SuppressWarnings({"all"})
public class Tank_Frame extends JFrame {
//定义一个面板放到框架上
MyPanel mp=null;
static Scanner scanner=new Scanner(System.in);
public static void main(String[] args) {
Tank_Frame tank_frame = new Tank_Frame();
}
public Tank_Frame() {
System.out.println("请输入1:开始下一局,2:继续上一局");
String key = scanner.next();
mp=new MyPanel(key);
// mp=new MyPanel();
//创建MyPane线程并调用
Thread mp_thread = new Thread(mp);
mp_thread.start();//启动线程
this.add(mp);//添加到画框上
//设置大小
this.setSize(1600,850);
//添加监视器到画框上 //窗口 JFrame 对象可以监听键盘事件, 即可以监听到面板发生的键盘事件
this.addKeyListener(mp);
//按x关闭程序
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);//显示
//监听程序何时关闭
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
try {
Recorder.WriteRecord();
} catch (IOException ioException) {
ioException.printStackTrace();
}
System.exit(0);
}
});
}
}
Shot
package com.Tank.TankGame06;
/**
* @author 你是大**吗?
* version 1.0
* 制作炮弹的移动
*/
@SuppressWarnings({"all"})
public class Shot implements Runnable {//实现Runnable 子弹单独起一个线程
private int x;
private int y;
private int direct;//需要和坦克的方向相对应
private int speed=2;//速度设为3
boolean shotlive=true;//记录坦克是否还在生存
//构造器
public Shot(int x, int y, int direct) {
this.x = x;
this.y = y;
this.direct = direct;
}
@Override
public void run() {
//对子弹的x,y坐标的变化来控制子弹的移动,
while(true){
//移动之前需要sleep否在一瞬即逝
try {
Thread.sleep(50);//50毫秒动一次
} catch (InterruptedException e) {
e.printStackTrace();
}
//设置子弹的移动
switch (direct){//根据炮弹筒的位置来改变
case 0://向上
y-=speed;
break;
case 1://向右
x+=speed;
break;
case 2://向下
y+=speed;
break;
case 3://向左
x-=speed;
break;
}
// System.out.println("x = "+x+" y = "+y);
//循环结束条件是子弹碰到边界就退出或者是子弹碰到坦克销毁了,线程退出
if(!(x>=0&&x<=1200&&y>=0&&y<=850&&shotlive)){
//遇到边界或子弹销毁退出
System.out.println("子弹线程结束...");
shotlive=false;
break;
}
}
}
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 int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
}
Recorder
package com.Tank.TankGame06;
import java.io.*;
import java.util.Vector;
/**
* @author 你是大**吗?
* version 1.0
* 存盘记录到文件
*/
@SuppressWarnings({"all"})
public class Recorder {
private static int enemyTankNum = 0;
//字节读处理流
private static BufferedReader br=null;
private static BufferedWriter bw = null;//处理流
//数据存储的文件名
private static String recordFile = "e:\\recordFile.txt";
//Node集合用于保存再文件中读出来的坦克坐标
public static Vector<Node> nodes =new Vector<>();
//保存敌人坦克的集合
private static Vector<Enemy_Tank> enemy_tanks=null;
//获取文件中坦克信息的方法,用于恢复坦克
public static Vector GetTankDetial() {
//先读击毁的坦克数量
try {
br = new BufferedReader(new FileReader(recordFile));
enemyTankNum=Integer.parseInt(br.readLine());//转为int
String line=null;
while((line=br.readLine())!=null){//连续读一行数据 40 31 0
String[] split = line.split(" ");
Node node = new Node(Integer.parseInt(split[0]),
Integer.parseInt(split[1]), Integer.parseInt(split[2]));
//添加到Nodes集合
nodes.add(node);
}
if(br!=null)
br.close();
} catch (IOException e) {
e.printStackTrace();
}
return nodes;
}
//利用set方法获取敌人坦克集合
public static void setEnemy_tanks(Vector<Enemy_Tank> enemy_tanks) {
Recorder.enemy_tanks = enemy_tanks;
}
//当按X号的时候关闭--完善功能记录存活的坦克的坐标
public static void WriteRecord() throws IOException {
bw = new BufferedWriter(new FileWriter(recordFile));
//写入数据击毁坦克数量
// write底层代码cb[nextChar++] = (char) c;
//强转会出错,定位不到预期效果,所以变为字符串的
bw.write(enemyTankNum+"\r\n");
//写入存活的敌人坦克坐标
for (int i = 0; i < enemy_tanks.size(); i++) {
Enemy_Tank enemy_tank = enemy_tanks.get(i);
if(enemy_tank.isLive){//若是存活的就放入
String content=enemy_tank.getX()+" "+enemy_tank.getY()+" "+enemy_tank.getDirect();
bw.write(content+"\r\n");
// bw.newLine();~"\r\n"
}
}
//关闭流
if (bw != null)
bw.close();
}
//返回文件名
public static String getRecordFile() {
return recordFile;
}
public static int getAllenemyTankNum() {
return enemyTankNum;
}
public static void setAllenemyTankNum(int enemyTankNum) {
Recorder.enemyTankNum = enemyTankNum;
}
//击毁坦克数量+1
public static void addEnemyTankNum() {
enemyTankNum++;
}
}
Node
package com.Tank.TankGame06;
/**
* @author 你是大**吗?
* version 1.0
*/
@SuppressWarnings({"all"})
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;
}
}
MyTank
package com.Tank.TankGame06;
import java.util.Vector;
/**
* @author 你是大**吗?
* version 1.0
*/
@SuppressWarnings({"all"})
public class MyTank extends Father_Tank {
Shot shot = null;
boolean isLive=true;
//创建一个shot集合可以存放多个子弹实现发射多次
Vector<Shot> shots=new Vector<>();
public MyTank(int x, int y) {
super(x, y);
}
//在坦克里面创建子弹
public void shotEnemyTank(){
switch (getDirect()){//根据坦克方向来绘制子弹
case 0:
shot = new Shot(getX() + 20, getY() - 10, 0);
break;
case 1://右
shot = new Shot(getX() + 70, getY() + 20, 1);
break;
case 2:
shot = new Shot(getX() + 20, getY() +70, 2);
break;
case 3:
shot = new Shot(getX() -10, getY() + 20, 3);
break;
}
//把创建的子弹放到shots集合
shots.add(shot);
//启动刚放进集合的shot子弹的线程
System.out.println("启动子弹线程...");
new Thread(shot).start();
}
}
MyPanel
package com.Tank.TankGame06;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.util.Vector;
/**
* @author 你是大**吗?
* version 1.0
* 坦克大战绘图区域
*/
@SuppressWarnings({"all"})
public class MyPanel extends JPanel implements KeyListener, Runnable {
MyTank myTank = null;//在画板上创建一个MyTank对象
//创建一个敌人坦克集合Vector是线程安全的
Vector<Enemy_Tank> enemytanks = new Vector<Enemy_Tank>();
//创建一个Node集合取出文件中的坦克
Vector<Node> nodes=new Vector<>();
//创建一个炸弹集合用于存放炸弹
//当坦克被击中是给bombs集合添加一个炸弹
Vector<Bomb> bombs = new Vector<>();
//定义三张爆炸图片,用于爆炸效果
Image image1 = null;
Image image2 = null;
Image image3 = null;
int EnemytankNum = 10;
public MyPanel(String key) {
//先判断文件是否存在第一次文件不存在,故此没有上一局游戏
File file = new File(Recorder.getRecordFile());
if(file.exists()){//存在就获取上一局的信息
nodes= Recorder.GetTankDetial();
}else{
System.out.println("文件不存在,开启新游戏");
key="1";//否则开始新游戏
}
//设置存活的坦克到文件
Recorder.setEnemy_tanks(enemytanks);
//创建我方坦克
myTank = new MyTank(500, 600);
myTank.setSpeed(10);//设置速度为2
switch (key){
case "1":
//摁了1就是重开,击毁坦克数量为0
Recorder.setAllenemyTankNum(0);
//把敌人的坦克放到EnemytankVectors集合
for (int i = 0; i < EnemytankNum; i++) {
//放的位置
Enemy_Tank enemy_tank = new Enemy_Tank(100 * (i + 1), 0);
//把集合enemytanks放入每个坦克,可以用集合里面的所有坦克进行比较
enemy_tank.setEnemy_tanks(enemytanks);
enemy_tank.setDirect(2);//初始敌人的坦克炮弹筒向下
//启动敌人坦克的线程
new Thread(enemy_tank).start();//启动线程了在run里面又添加了一个子弹所以一开始就又俩元素了
//创建一个子弹
Shot shot = new Shot(enemy_tank.getX() + 20, enemy_tank.getY() + 70, enemy_tank.getDirect());
//把子弹放到enemy_tank 的shots集合
enemy_tank.shots.add(shot);
//启动该子弹的线程--这样子弹才会动
new Thread(shot).start();
//把坦克放到坦克集合
enemytanks.add(enemy_tank);
}
break;
case "2":
//把敌人的坦克放到EnemytankVectors集合
for (int i = 0; i < nodes.size(); i++) {
//取出存的对象
Node node = nodes.get(i);
//放的位置
//恢复上一局的位置
Enemy_Tank enemy_tank = new Enemy_Tank(node.getX(),node.getY());
//把集合enemytanks放入每个坦克,可以用集合里面的所有坦克进行比较
enemy_tank.setEnemy_tanks(enemytanks);
enemy_tank.setDirect(node.getDirect());
//启动敌人坦克的线程
new Thread(enemy_tank).start();//启动线程了在run里面又添加了一个子弹所以一开始就又俩元素了
//创建一个子弹
Shot shot = new Shot(enemy_tank.getX() + 20, enemy_tank.getY() + 70, enemy_tank.getDirect());
//把子弹放到enemy_tank 的shots集合
enemy_tank.shots.add(shot);
//启动该子弹的线程--这样子弹才会动
new Thread(shot).start();
//把坦克放到坦克集合
enemytanks.add(enemy_tank);
}
break;
default:
System.out.println("输入有误");
break;
}
//初始化图片对象
//把照片放到了当前包没直接放在out
//MyPanel.class.getResource("bomb_1.gif"):在MyPanel类的包开始搜索照片 "bomb_1.gif"前面没有加/是代表相对路径
image1 = Toolkit.getDefaultToolkit().getImage(MyPanel.class.getResource("bomb_1.gif"));
image2 = Toolkit.getDefaultToolkit().getImage(MyPanel.class.getResource("bomb_2.gif"));
image3 = Toolkit.getDefaultToolkit().getImage(MyPanel.class.getResource("bomb_3.gif"));
//播放音乐
new AePlayWave("src\\DJ.wav").start();
}
//画出提示信息
public void ShowInfo(Graphics g) {
g.setColor(Color.blue);
//设置字体
Font font = new Font("楷书", Font.BOLD, 25);
g.setFont(font);
//画出
g.drawString("爷您累计击毁敌方坦克数量",1250,50);
//画出坦克标识
DrawTank(1250,100,g,0,1);
//画出击毁数量
g.setColor(Color.blue);
g.drawString(Recorder.getAllenemyTankNum()+"",1320,138);
}
@Override
public void paint(Graphics g) {
super.paint(g);
//调用击毁坦克信息方法
ShowInfo(g);
//填充面板为黑色
g.setColor(Color.BLACK);
g.fillRect(0, 0, 1200, 850);//直接填充一个黑色矩形
//画出我们坦克封装方法
if (myTank != null && myTank.isLive) {
DrawTank(myTank.getX(), myTank.getY(), g, myTank.getDirect(), 0);
}
//画出敌人坦克
for (int i = 0; i < enemytanks.size(); i++) {//画出现有的坦克,所以要用enemytanks.size()
//画出敌人坦克
Enemy_Tank enemy_tank = enemytanks.get(i);
if (enemy_tank.isLive) {//所示敌人坦克还活着就画
DrawTank(enemy_tank.getX(), enemy_tank.getY(), g, enemy_tank.getDirect(), 1);
//画出当前坦克的所有子弹
for (int j = 0; j < enemy_tank.shots.size(); j++) {
//获取该坦克里的一个子弹
Shot shot = enemy_tank.shots.get(j);
//画子弹
if (shot.shotlive) {//若是该子弹存活这就开画
g.drawOval(shot.getX(), shot.getY(), 5, 5);
} else {
//不存活就该销毁了,在集合中删除
enemy_tank.shots.remove(shot);
}
}
}
}
// //画出我方子弹封装方法
//循环对集合里面的子弹进行重绘
for (int i = 0; i < myTank.shots.size(); i++) {
Shot shot = myTank.shots.get(i);
if (shot != null && shot.shotlive) {//这样的画只会调用这一次,所以要用MyPanel来实现
// //Runnable起一个线程实时重绘画面
// //这里的x,y坐标是动态变化的 ,paint方法被调用一次,子弹就变化一次
g.drawOval(shot.getX(), shot.getY(), 5, 5);
} else {//否则是个报废的子弹要移出
myTank.shots.remove(shot);
}
}
//画出炸弹--若是集合里面有炸弹我们就画
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);
//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();//生命值--
//如果生命值为0,该炸弹也该在集合里面删除了
if (bomb.life == 0) {
bombs.remove(bomb);
}
}
}
/**
* @param x 坦克左上角横坐标
* @param y 坦克左上角纵坐标
* @param g 画笔
* @param direct 坦克的方向 (0:上 1:右 2,下 3:左)
* @param type 坦克的类型 0:我们的坦克 1:敌方的坦克
*/
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.red);
break;
default:
System.out.println("暂时不提供别的颜色...");
break;
}
// 根据坦克方向, 来绘制坦克
switch (direct) {//坦克的方向 (0:上 1:右 2,下 3:左)
case 0:
g.fill3DRect(x, y, 10, 60, false);//画左边的板子
g.fill3DRect(x + 30, y, 10, 60, false);//画出右边的板子
g.fill3DRect(x + 10, y + 12, 20, 36, false);//画出中间的方块
g.fillOval(x + 10, y + 20, 20, 20);//画出圆盖
g.drawLine(x + 20, y + 30, x + 20, y - 10);//画炮筒子
break;
case 1:
g.fill3DRect(x, y, 60, 10, false);//画上边的板子
g.fill3DRect(x, y + 30, 60, 10, false);//画出下边的板子
g.fill3DRect(x + 12, y + 10, 36, 20, false);//画出中间的方块
g.fillOval(x + 20, y + 10, 20, 20);//画出圆盖
g.drawLine(x + 20, y + 20, x + 70, 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 + 12, 20, 36, false);//画出中间的方块
g.fillOval(x + 10, y + 20, 20, 20);//画出圆盖
g.drawLine(x + 20, y + 30, x + 20, y + 70);//画炮筒子
break;
case 3:
g.fill3DRect(x, y, 60, 10, false);//画上边的板子
g.fill3DRect(x, y + 30, 60, 10, false);//画出下边的板子
g.fill3DRect(x + 12, y + 10, 36, 20, false);//画出中间的方块
g.fillOval(x + 20, y + 10, 20, 20);//画出圆盖
g.drawLine(x + 20, y + 20, x - 10, y + 20);//画炮筒子
break;
default:
System.out.println("暂无。。。。。");
break;
}
}
//创建方法--判断子弹是否击中敌方坦克
//什么时候来判断坦克被击中了没有呢,在run里面因为在run里面坦克隔一段时间就重绘一次
//借助这个循环来判断
public void hitTank(Shot s, Enemy_Tank Tank) {
//根据坦克的方向分为两种情况,
switch (Tank.getDirect()) {
case 0://上下的情况
case 2://子弹在这个区间,子弹和坦克就可以销毁了
if (s.getX() > Tank.getX() && s.getX() < Tank.getX() + 50
&& s.getY() > Tank.getY() && s.getY() < Tank.getY() + 60) {
s.shotlive = false;
Tank.isLive = false;
enemytanks.remove(Tank);//删除被击中的坦克,就不会出现在打击还爆炸的情况了
//记录被击毁的坦克数量
Recorder.addEnemyTankNum();
//击中一个坦克就把一个炸弹对象放到bombs集合
Bomb bomb = new Bomb(Tank.getX(), Tank.getY());
bombs.add(bomb);
}
break;
case 1://左右的情况
case 3:
if (s.getX() > Tank.getX() && s.getX() < Tank.getX() + 60
&& s.getY() > Tank.getY() && s.getY() < Tank.getY() + 50) {
s.shotlive = false;
Tank.isLive = false;
enemytanks.remove(Tank);//删除被击中的坦克,就不会出现在打击还爆炸的情况了
//记录被击毁的坦克数量
Recorder.addEnemyTankNum();
//击中一个坦克就把一个炸弹对象放到bombs集合
Bomb bomb = new Bomb(Tank.getX(), Tank.getY());
bombs.add(bomb);
}
break;
}
}
//重载了
public void hitTank(Shot s, MyTank myTank) {
//根据坦克的方向分为两种情况,
switch (myTank.getDirect()) {
case 0://上下的情况
case 2://子弹在这个区间,子弹和坦克就可以销毁了
if (s.getX() > myTank.getX() && s.getX() < myTank.getX() + 40
&& s.getY() > myTank.getY() && s.getY() < myTank.getY() + 60) {
s.shotlive = false;
myTank.isLive = false;
//击中我方坦克就把一个炸弹对象放到bombs集合
Bomb bomb = new Bomb(myTank.getX(), myTank.getY());
bombs.add(bomb);
myTank = null;//删除被击中的坦克,就不会出现在打击还爆炸的情况了
}
break;
case 1://左右的情况
case 3:
if (s.getX() > myTank.getX() && s.getX() < myTank.getX() + 60
&& s.getY() > myTank.getY() && s.getY() < myTank.getY() + 40) {
s.shotlive = false;
myTank.isLive = false;
//击中一个坦克就把一个炸弹对象放到bombs集合
Bomb bomb = new Bomb(myTank.getX(), myTank.getY());
bombs.add(bomb);
//myTank=null;//删除被击中的坦克,就不会出现在打击还爆炸的情况了
}
break;
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override//按键来控制方向
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_W) {
//改为向上-W键
myTank.setDirect(0);
//坦克移动
if (myTank.getY() > 0) {//限制y值要大于0不要上边越界
myTank.moveUp();
}
} else if (e.getKeyCode() == KeyEvent.VK_D) {
//改为向右-D键
myTank.setDirect(1);
if (myTank.getX() + 70 < 1180) {
myTank.moveRight();
}
} else if (e.getKeyCode() == KeyEvent.VK_S) {
//改为向下-S键
myTank.setDirect(2);
if (myTank.getY() + 70 < 800) {
myTank.moveDown();
}
} else if (e.getKeyCode() == KeyEvent.VK_A) {
//改为向左-A键
myTank.setDirect(3);
if (myTank.getX() > 0) {
myTank.moveLeft();
}
}
//监听到J键表示开始射击了
if (e.getKeyCode() == KeyEvent.VK_J) {
//调用MyTank的shotEnemyTank方法创建子弹调用线程
//shot子弹为null或者生命记号为假就在创建子弹---发射一颗子弹
// if(myTank.shot==null||!myTank.shot.shotlive) {
// myTank.shotEnemyTank();
// }
//发射多颗子弹,摁一下就发射一颗
if (myTank.shots.size() < 100) {//限制发射的子弹数量
myTank.shotEnemyTank();
}
}
this.repaint();//重绘,重新调用一下paint方法重新画一下
}
//判断我方子弹有没有射击到坦克
public void hitMyTank() {
//遍历敌人每个坦克的子弹集合里面的子弹和我方坦克有没有碰撞
for (int i = 0; i < enemytanks.size(); i++) {
Enemy_Tank enemy_tank = enemytanks.get(i);
for (int j = 0; j < enemy_tank.shots.size(); j++) {
//敌人坦克集合取出一个子弹
Shot shot = enemy_tank.shots.get(j);
//先判断我方坦克还存活嘛//判断是不是存活的子弹是存活的子弹才有资格来击中坦克
if (myTank.isLive && shot != null && shot.shotlive) {
//判断该子弹有没有射击到我方坦克
hitTank(shot, myTank);
}
}
}
}
//判断我方子弹有没有射击到坦克
public void hitEnemyTank() {
//循环遍历敌人子弹集合里面的子弹和坦克有没有碰撞
for (int i = 0; i < myTank.shots.size(); i++) {
//取出一个子弹就和敌人坦克集合里面的对象一一比较
Shot shot = myTank.shots.get(i);
//要先判断shot是不是null,要是没有摁Q键shot就是空 并且子弹还要是活着的,要不都子弹都不存在了,在绘制就错了
if (shot != null && shot.shotlive) {//先判断我的子弹存活嘛
for (int j = 0; j < enemytanks.size(); j++) {
//遍历集合里的所有坦克是否被击中
Enemy_Tank enemy_tank = enemytanks.get(j);
//调用判断方法
if (enemy_tank.isLive && enemy_tank != null) {
hitTank(shot, enemy_tank);
}
}
}
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void run() {//要在Tank_Frame里面调用
while (true) {
try {
Thread.sleep(80);//每80毫秒重绘一次整个页面才能完成子弹的移动,因为画子弹的方法在paint了
} catch (InterruptedException e) {
e.printStackTrace();
}
//判断敌人坦克有没有被击中
hitEnemyTank();
//判断我方坦克有没有被击中
hitMyTank();
this.repaint();//this代表Mypanel
}
}
}
Father_Tank
package com.Tank.TankGame06;
/**
* @author 你是大**吗?
* version 1.0
*/
@SuppressWarnings({"all"})
public class Father_Tank {
private int x;
private int y;
private int direct;
private int speed=1;//这样就体现了面向对象速度可以调节
public boolean isLive=true;
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;
}
public int getDirect() {
return direct;
}
public void setDirect(int direct) {
this.direct = direct;
}
public Father_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;
}
}
Enemy_Tank
package com.Tank.TankGame06;
import java.util.Vector;
/**
* @author 你是大**吗?
* version 1.0
*/
@SuppressWarnings({"all"})
public class Enemy_Tank extends Father_Tank implements Runnable {
public final int StepNum = 30;
public final int BulletNum = 3;
public final int SleepNum = 50;
//在敌人坦克里面创建Vector集合保存shot对象
Vector<Shot> shots = new Vector<>();
//在添加敌人坦克的时候再去添加shot对象
// boolean isLive = true;//存活记号
//获取全部的敌人坦克,故此来获得他们的坐标来比较是否碰撞
Vector<Enemy_Tank> enemy_tanks = new Vector<>();
//利用set方法来个坦克集合来赋值
public void setEnemy_tanks(Vector<Enemy_Tank> enemy_tanks) {
this.enemy_tanks = enemy_tanks;
}
//设计判断碰撞的方法
public boolean istouchEnemyTank() {
switch (this.getDirect()) {
case 0://向上
for (int i = 0; i < enemy_tanks.size(); i++) {
Enemy_Tank enemy_tank = enemy_tanks.get(i);
if (enemy_tank != this) {
//敌人坦克向上或向下的坐标[getX(),getY()+60], [getX()+40,getY()+60]
if (enemy_tank.getDirect() == 0 || enemy_tank.getDirect() == 2) {
//this坦克左上角坐标 [getX(),getY()],
if (this.getX() > enemy_tank.getX()
&& this.getX() < enemy_tank.getX() + 40
&& this.getY() > enemy_tank.getY()
&& this.getY() < enemy_tank.getY() + 60) {
return true;
}
//this坦克右上角坐标[getX()+40,getY()]
if (this.getX()+40 > enemy_tank.getX()
&& this.getX()+40 < enemy_tank.getX() + 40
&& this.getY() > enemy_tank.getY()
&& this.getY() < enemy_tank.getY() + 60) {
return true;
}
}
//敌人坦克向左或者向右 左下角坐标[getX(),getY()]
//右下角坐标[getX()+60,getY()+40]
if(enemy_tank.getDirect()==1||enemy_tank.getDirect()==3){
//this坦克左上角坐标 [getX(),getY()],
if (this.getX() > enemy_tank.getX()
&& this.getX() < enemy_tank.getX() + 60
&& this.getY() > enemy_tank.getY()
&& this.getY() < enemy_tank.getY() + 40) {
return true;
}
//this坦克右上角坐标[getX()+40,getY()]
if (this.getX()+40 > enemy_tank.getX()
&& this.getX()+40 < enemy_tank.getX() + 60
&& this.getY() > enemy_tank.getY()
&& this.getY() < enemy_tank.getY() + 40) {
return true;
}
}
}
}
break;
case 1://向右
//敌人坦克的范围是不用改变的知识自己的坦克坐标改变了
for (int i = 0; i < enemy_tanks.size(); i++) {
Enemy_Tank enemy_tank = enemy_tanks.get(i);
if (enemy_tank != this) {
//敌人坦克向上或向下的坐标[getX(),getY()+60], [getX()+40,getY()+60]
if (enemy_tank.getDirect() == 0 || enemy_tank.getDirect() == 2) {
//this坦克右上角坐标 [getX()+60,getY()],
if (this.getX()+60 > enemy_tank.getX()
&& this.getX()+60 < enemy_tank.getX() + 40
&& this.getY() > enemy_tank.getY()
&& this.getY() < enemy_tank.getY() + 60) {
return true;
}
//this坦克右下角坐标[getX()+60,getY()+40]
if (this.getX()+60 > enemy_tank.getX()
&& this.getX()+60 < enemy_tank.getX() + 40
&& this.getY()+40 > enemy_tank.getY()
&& this.getY()+40 < enemy_tank.getY() + 60) {
return true;
}
}
//敌人坦克向左或者向右 左下角坐标[getX(),getY()]
//右下角坐标[getX()+60,getY()+40]
if(enemy_tank.getDirect()==1||enemy_tank.getDirect()==3){
//this坦克右上角坐标 [getX()+60,getY()],
if (this.getX()+60 > enemy_tank.getX()
&& this.getX()+60 < enemy_tank.getX() + 60
&& this.getY() > enemy_tank.getY()
&& this.getY() < enemy_tank.getY() + 40) {
return true;
}
//this坦克右下角坐标[getX()+60,getY()+40]
if (this.getX()+60 > enemy_tank.getX()
&& this.getX()+60 < enemy_tank.getX() + 60
&& this.getY()+40 > enemy_tank.getY()
&& this.getY()+40 < enemy_tank.getY() + 40) {
return true;
}
}
}
}
break;
case 2://向下
//敌人坦克的范围是不用改变的只是自己的坦克坐标改变了
for (int i = 0; i < enemy_tanks.size(); i++) {
Enemy_Tank enemy_tank = enemy_tanks.get(i);
if (enemy_tank != this) {
//敌人坦克向上或向下的坐标[getX(),getY()+60],
// [getX()+40,getY()+60]
if (enemy_tank.getDirect() == 0 || enemy_tank.getDirect() == 2) {
//this坦克左下角坐标 [getX(),getY()+60],
if (this.getX() > enemy_tank.getX()
&& this.getX() < enemy_tank.getX() + 40
&& this.getY()+60 > enemy_tank.getY()
&& this.getY()+60 < enemy_tank.getY() + 60) {
return true;
}
//this坦克右下角坐标[getX()+40,getY()+60]
if (this.getX()+40 > enemy_tank.getX()
&& this.getX()+40 < enemy_tank.getX() + 40
&& this.getY()+60 > enemy_tank.getY()
&& this.getY()+60 < enemy_tank.getY() + 60) {
return true;
}
}
//敌人坦克向左或者向右 左下角坐标[getX(),getY()]
//右下角坐标[getX()+60,getY()+40]
if(enemy_tank.getDirect()==1||enemy_tank.getDirect()==3){
//this坦克左下角坐标 [getX(),getY()+60],
if (this.getX()> enemy_tank.getX()
&& this.getX() < enemy_tank.getX() + 60
&& this.getY()+60 > enemy_tank.getY()
&& this.getY()+60 < enemy_tank.getY() + 40) {
return true;
}
//this坦克右下角坐标[getX()+40,getY()+60]
if (this.getX()+40 > enemy_tank.getX()
&& this.getX()+40 < enemy_tank.getX() + 60
&& this.getY()+60 > enemy_tank.getY()
&& this.getY()+60 < enemy_tank.getY() + 40) {
return true;
}
}
}
}
break;
case 3://向左
//敌人坦克的范围是不用改变的只是自己的坦克坐标改变了
for (int i = 0; i < enemy_tanks.size(); i++) {
Enemy_Tank enemy_tank = enemy_tanks.get(i);
if (enemy_tank != this) {
//敌人坦克向上或向下的坐标[getX(),getY()+60],
// [getX()+40,getY()+60]
if (enemy_tank.getDirect() == 0 || enemy_tank.getDirect() == 2) {
//this坦克左上角坐标 [getX(),getY()],
if (this.getX() > enemy_tank.getX()
&& this.getX() < enemy_tank.getX() + 40
&& this.getY()> enemy_tank.getY()
&& this.getY() < enemy_tank.getY() + 60) {
return true;
}
//this坦克左下角坐标[getX(),getY()+40]
if (this.getX() > enemy_tank.getX()
&& this.getX() < enemy_tank.getX() + 40
&& this.getY()+40 > enemy_tank.getY()
&& this.getY()+40 < enemy_tank.getY() + 60) {
return true;
}
}
//敌人坦克向左或者向右 左下角坐标[getX(),getY()]
//右下角坐标[getX()+60,getY()+40]
if(enemy_tank.getDirect()==1||enemy_tank.getDirect()==3){
//this坦克左上角坐标 [getX(),getY()],
if (this.getX()> enemy_tank.getX()
&& this.getX() < enemy_tank.getX() + 60
&& this.getY() > enemy_tank.getY()
&& this.getY() < enemy_tank.getY() + 40) {
return true;
}
//this坦克左下角坐标[getX(),getY()+40]
if (this.getX() > enemy_tank.getX()
&& this.getX()< enemy_tank.getX() + 60
&& this.getY()+40 > enemy_tank.getY()
&& this.getY()+40 < enemy_tank.getY() + 40) {
return true;
}
}
}
}
break;
}
//没有进入switch返回false
return false;
}
public Enemy_Tank(int x, int y) {
super(x, y);
}
@Override
public void run() {
while (true) {
//先判断敌人坦克的子弹情况小于x个并且坦克存活就加入新的子弹
if (isLive && shots.size() <= BulletNum) {
Shot shot = null;
switch (getDirect()) {
case 0:
shot = new Shot(getX() + 20, getY() - 10, 0);
break;
case 1://右
shot = new Shot(getX() + 70, getY() + 20, 1);
break;
case 2:
shot = new Shot(getX() + 20, getY() + 70, 2);
break;
case 3:
shot = new Shot(getX() - 10, getY() + 20, 3);
break;
}
//添加到shot集合
shots.add(shot);
//启动新子弹对象的线程
new Thread(shot).start();
}
//根据方向来移动坦克
switch (getDirect()) {
case 0://一次就移动XX步
for (int i = 0; i < StepNum; i++) {
try {
Thread.sleep(SleepNum);
} catch (InterruptedException e) {
e.printStackTrace();
}
//坦克的坐标向上不能小于0,小于0就出界了&&坦克还不能重叠
if (getY() > 0&&!istouchEnemyTank()) {
moveUp();
}
}
break;
case 1:
for (int i = 0; i < StepNum; i++) {
try {
Thread.sleep(SleepNum);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (getX() + 70 < 1180&&!istouchEnemyTank()) {//坦克的X坐标向上不能大于1200,小于1200就出界了
moveRight();
}
}
break;
case 2:
for (int i = 0; i < StepNum; i++) {
try {
Thread.sleep(SleepNum);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (getY() + 70 < 800&&!istouchEnemyTank()) {//坦克的X坐标向上不能大于850,小于850就出界了
moveDown();
}
}
break;
case 3://一次就移动100步
for (int i = 0; i < StepNum; i++) {
try {
Thread.sleep(SleepNum);//延时50毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
if (getX() > 0&&!istouchEnemyTank()) {
moveLeft();
}
}
break;
}
//随机的改变坦克方向
setDirect((int) (Math.random() * 4));//[0,4)直接
//啥时候线程结束呢,生命记号没了就结束该线程
if (isLive == false) {
System.out.println("该坦克线程结束了");
break;
}
}
}
}
Bomb
package com.Tank.TankGame06;
/**
* @author 你是大**吗?
* version 1.0
* 炸弹类
*/
@SuppressWarnings({"all"})
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=0了图片也不显示了炸弹该销毁了
life--;
}else {
islive=false;
}
}
}
AePlayWave
package com.Tank.TankGame06;
import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;
/**
* @author 韩顺平
* @version 1.0
*/
public 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();
}
}
}