项目演示视频
项目下载地址:Java坦克大战项目源码。-Java文档类资源-优快云文库
也可以关注我之后私信我留个邮箱留言要哪个源码,我会把源码
免费发送到你的邮箱。
用到的java技术
1.多线程
2.文件i/o操作
3.数据库
4.java面向对象编程
多线程技术应用到了坦克的子弹,移动,绘制,敌人坦克等等;
文件i/o操作作用到了保存坦克的数量以及坐标来实现继续上一局;
数据库当时是用Vector代替;
坦克及子弹的显示:显示是用的JPanel绘制实现的。
switch (direction) {
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;
部分实现代码
单独写的绘制坦克类,根据传进的方向参数而绘制出相应方向的坦克;
子弹碰撞检测:根据传进的子弹对象参数和坦克参数来进行相应的判定。
// 子弹碰撞检测方法
public void BulletCollision(ShotBullet bulletBody, Tank TankBody) {
switch (TankBody.getDirectionNum()) {
case 0:
case 2:
if (bulletBody.x > TankBody.getX() &&
bulletBody.x < TankBody.getX() + 40 &&
bulletBody.y > TankBody.getY() &&
bulletBody.y < TankBody.getY() + 60) {
// 将子弹和敌人状态设为false,等同于杀死
bulletBody.bulletState = false;
TankBody.TankState = false;
// 子弹击中就把敌方坦克从vector里删除掉
enemyTankVector.remove(TankBody);
// 判断击中的坦克是不是enemytank类型如果是就把击毁坦克数加一
if (TankBody instanceof EnemyTank) {
Recorder.addWreckTankNum();
}
// 如果子弹碰到敌人则新建一个爆炸动画
Bomb bomb = new Bomb(TankBody.getX(), TankBody.getY());
bombVector.add(bomb);
}
break;
部分实现代码
// 判断己方子弹是否击中敌方坦克,依次遍历每个子弹依次判断
public void hitEnemyTank() {
for (int i = 0; i < ownHero.shotBulletVector.size(); i++) {
ShotBullet shotBullet = ownHero.shotBulletVector.get(i);
// shotBullet不能为空,同时shotBullet是活着的状态
if (shotBullet != null && shotBullet.bulletState) {
for (int j = 0; j < enemyTankVector.size(); j++) {
EnemyTank enemyTank = enemyTankVector.get(j);
BulletCollision(shotBullet, enemyTank);
}
}
}
}
这里是己方坦克是否击中敌方坦克
// 判断敌方子弹是否击中己方坦克,依次遍历每个子弹依次判断
public void hitHeroTank() {
// 先遍历敌方坦克数量
for (int i = 0; i < enemyTankVector.size(); i++) {
EnemyTank enemyTank = enemyTankVector.get(i);// 遍历取得敌方坦克
// 遍历敌方坦克的子弹数量
for (int j = 0; j < enemyTank.bulletsVector.size(); j++) {
ShotBullet shotBullet = enemyTank.bulletsVector.get(j);// 取得敌方坦克子弹
// 己方英雄和子弹必须是活的才会继续判断是否击中
if (ownHero.TankState && shotBullet.bulletState) {
BulletCollision(shotBullet, ownHero);
}
}
}
}
判断敌方坦克是否击中自己
实现继续上一局:主要是把坦克的坐标写入到文件,需要的时候在读取。
//写入txt文件的方法
public static void infoWrite() {
try {
// 要存入的文件路径
bw = new BufferedWriter(new FileWriter(filePath));
bw.write(wreckTankNum + "\r\n");
// 遍历坦克个数,把坐标写入到文件
for (int i = 0; i < Recorder.enemyTankVector.size(); i++) {
EnemyTank enemyTank = enemyTankVector.get(i);
String tankInfo = enemyTank.getX() +
" " + enemyTank.getY() +
" " + enemyTank.getDirectionNum();
bw.write(tankInfo + "\r\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
写入文件的方法
//用于读取filePath里的信息
public static Vector<Nodes> getNodeAndEnemyTankInfo() {
try {
br = new BufferedReader(new FileReader(filePath));
wreckTankNum = Integer.parseInt(br.readLine());
String line = "";
while ((line = br.readLine()) != null) {
// 分割字符串,取得想要的部分
String[] fileSplit = line.split(" ");
Nodes nodes = new Nodes(Integer.parseInt(fileSplit[0]), Integer.parseInt(fileSplit[1])
, Integer.parseInt(fileSplit[2]));
// 把nodes放到nodesVector里面
nodesVector.add(nodes);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return nodesVector;
}
读取文件方法
把读取的信息赋给一个集合里,到时候使用
如果用户选择的是继续上一局,用被赋值的集合初始化游戏坦克坐标
switch (userChoose) {
case "1":// 表示开始新游戏
// 把击毁坦克数量重置为零
Recorder.setWreckTankNum(0);
// 把敌方坦克遍历到enemyTanks里面
for (int i = 0; i < enemyTankNumber; i++) {
EnemyTank enemyTank = new EnemyTank((100 * (i + 1)), 0);//创建敌人坦克
// 把enemyTankVector传到setEnemyTankVector方法中
enemyTank.setEnemyTankVector(enemyTankVector);
enemyTank.setDirectionNum(2);// 2表示下面方向
enemyTank.setSpeed(3);// 设置敌方坦克移动速度
new Thread(enemyTank).start();//启动敌方坦克移动线程
enemyTankVector.add(enemyTank);// 往vector里添加敌方坦克
ShotBullet enemyShotBullet = new ShotBullet(enemyTank.getX() + 20,
enemyTank.getY() + 60, enemyTank.getDirectionNum());
enemyTank.bulletsVector.add(enemyShotBullet);
new Thread(enemyShotBullet).start();// 启动敌方坦克子弹线程
}
// 表示用户输入正确
judgeUserChoose = true;
break;
case "2":// 表示继续上次游戏
// 把敌方坦克遍历到enemyTanks里面
for (int i = 0; i < nodesVector.size(); i++) {
Nodes nodes = nodesVector.get(i);
EnemyTank enemyTank = new EnemyTank(nodes.getX(), nodes.getY());//创建敌人坦克
// 把enemyTankVector传到setEnemyTankVector方法中
enemyTank.setEnemyTankVector(enemyTankVector);
enemyTank.setDirectionNum(nodes.getDirection());// 表示方向
enemyTank.setSpeed(3);// 设置敌方坦克移动速度
new Thread(enemyTank).start();//启动敌方坦克移动线程
enemyTankVector.add(enemyTank);// 往vector里添加敌方坦克
ShotBullet enemyShotBullet = new ShotBullet(enemyTank.getX() + 20,
enemyTank.getY() + 60, enemyTank.getDirectionNum());
enemyTank.bulletsVector.add(enemyShotBullet);
new Thread(enemyShotBullet).start();// 启动敌方坦克子弹线程
}
// 表示用户输入正确
judgeUserChoose = true;
break;
}
判断用户是否继续上一局
项目难点
这个项目的难点主要是设置敌方坦克不重叠的地方,其实用到的东西没那么难,主要是需要想到的地方很多。
//编写方法,判断当前的这个敌人坦克,是否和 enemyTanks 中的其他坦克发生的重叠或者碰撞
public boolean judgeTankCollice() {
// 判断当前敌人坦克(this)方向
switch (this.getDirectionNum()) {
case 0://上
//让当前敌人坦克和其它所有的敌人坦克比较
for (int i = 0; i < enemyTankVector.size(); i++) {
//从vector中取出一个敌人坦克
EnemyTank enemyTankGat = enemyTankVector.get(i);
//不和自己比较
if (enemyTankGat != this) {
//如果敌人坦克是上/下
//1. 如果敌人坦克是上/下 x的范围 [enemyTank.getX(), enemyTank.getX() + 40]
// y的范围 [enemyTank.getY(), enemyTank.getY() + 60]
if (enemyTankGat.getDirectionNum() == 0 || enemyTankGat.getDirectionNum() == 2) {
//2. 当前坦克 左上角的坐标 [this.getX(), this.getY()]
if (this.getX() >= enemyTankGat.getX()
&& this.getX() <= enemyTankGat.getX() + 40
&& this.getY() >= enemyTankGat.getY()
&& this.getY() <= enemyTankGat.getY() + 60) {
return true;
}
//3. 当前坦克 右上角的坐标 [this.getX() + 40, this.getY()]
if (this.getX() + 40 >= enemyTankGat.getX()
&& this.getX() + 40 <= enemyTankGat.getX() + 40
&& this.getY() >= enemyTankGat.getY()
&& this.getY() <= enemyTankGat.getY() + 60) {
return true;
}
}
//如果敌人坦克是 右/左
//1. 如果敌人坦克是右/左 x的范围 [enemyTank.getX(), enemyTank.getX() + 60]
// y的范围 [enemyTank.getY(), enemyTank.getY() + 40]
if (enemyTankGat.getDirectionNum() == 1 || enemyTankGat.getDirectionNum() == 3) {
//2. 当前坦克 左上角的坐标 [this.getX(), this.getY()]
if (this.getX() >= enemyTankGat.getX()
&& this.getX() <= enemyTankGat.getX() + 60
&& this.getY() >= enemyTankGat.getY()
&& this.getY() <= enemyTankGat.getY() + 40) {
return true;
}
//3. 当前坦克 右上角的坐标 [this.getX() + 40, this.getY()]
if (this.getX() + 40 >= enemyTankGat.getX()
&& this.getX() + 40 <= enemyTankGat.getX() + 60
&& this.getY() >= enemyTankGat.getY()
&& this.getY() <= enemyTankGat.getY() + 40) {
return true;
}
}
}
}
break;
case 1://右
//让当前敌人坦克和其它所有的敌人坦克比较
for (int i = 0; i < enemyTankVector.size(); i++) {
//从vector 中取出一个敌人坦克
EnemyTank enemyTank = enemyTankVector.get(i);
//不和自己比较
if (enemyTank != this) {
//如果敌人坦克是上/下
//老韩分析
//1. 如果敌人坦克是上/下 x的范围 [enemyTank.getX(), enemyTank.getX() + 40]
// y的范围 [enemyTank.getY(), enemyTank.getY() + 60]
if (enemyTank.getDirectionNum() == 0 || enemyTank.getDirectionNum() == 2) {
//2. 当前坦克 右上角的坐标 [this.getX() + 60, this.getY()]
if (this.getX() + 60 >= enemyTank.getX()
&& this.getX() + 60 <= enemyTank.getX() + 40
&& this.getY() >= enemyTank.getY()
&& this.getY() <= enemyTank.getY() + 60) {
return true;
}
//3. 当前坦克 右下角的坐标 [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;
}
}
//如果敌人坦克是 右/左
//老韩分析
//1. 如果敌人坦克是右/左 x的范围 [enemyTank.getX(), enemyTank.getX() + 60]
// y的范围 [enemyTank.getY(), enemyTank.getY() + 40]
if (enemyTank.getDirectionNum() == 1 || enemyTank.getDirectionNum() == 3) {
//2. 当前坦克 右上角的坐标 [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;
}
//3. 当前坦克 右下角的坐标 [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 < enemyTankVector.size(); i++) {
//从vector 中取出一个敌人坦克
EnemyTank enemyTank = enemyTankVector.get(i);
//不和自己比较
if (enemyTank != this) {
//如果敌人坦克是上/下
//老韩分析
//1. 如果敌人坦克是上/下 x的范围 [enemyTank.getX(), enemyTank.getX() + 40]
// y的范围 [enemyTank.getY(), enemyTank.getY() + 60]
if (enemyTank.getDirectionNum() == 0 || enemyTank.getDirectionNum() == 2) {
//2. 当前坦克 左下角的坐标 [this.getX(), 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;
}
//3. 当前坦克 右下角的坐标 [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;
}
}
//如果敌人坦克是 右/左
//老韩分析
//1. 如果敌人坦克是右/左 x的范围 [enemyTank.getX(), enemyTank.getX() + 60]
// y的范围 [enemyTank.getY(), enemyTank.getY() + 40]
if (enemyTank.getDirectionNum() == 1 || enemyTank.getDirectionNum() == 3) {
//2. 当前坦克 左下角的坐标 [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;
}
//3. 当前坦克 右下角的坐标 [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 < enemyTankVector.size(); i++) {
//从vector 中取出一个敌人坦克
EnemyTank enemyTank = enemyTankVector.get(i);
//不和自己比较
if (enemyTank != this) {
//如果敌人坦克是上/下
//老韩分析
//1. 如果敌人坦克是上/下 x的范围 [enemyTank.getX(), enemyTank.getX() + 40]
// y的范围 [enemyTank.getY(), enemyTank.getY() + 60]
if (enemyTank.getDirectionNum() == 0 || enemyTank.getDirectionNum() == 2) {
//2. 当前坦克 左上角的坐标 [this.getX(), this.getY() ]
if (this.getX() >= enemyTank.getX()
&& this.getX() <= enemyTank.getX() + 40
&& this.getY() >= enemyTank.getY()
&& this.getY() <= enemyTank.getY() + 60) {
return true;
}
//3. 当前坦克 左下角的坐标 [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;
}
}
//如果敌人坦克是 右/左
//老韩分析
//1. 如果敌人坦克是右/左 x的范围 [enemyTank.getX(), enemyTank.getX() + 60]
// y的范围 [enemyTank.getY(), enemyTank.getY() + 40]
if (enemyTank.getDirectionNum() == 1 || enemyTank.getDirectionNum() == 3) {
//2. 当前坦克 左上角的坐标 [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;
}
//3. 当前坦克 左下角的坐标 [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;
}
判断重叠代码
结尾
通过这些项目让我学到了很多很多。让我巩固了java基础部分。
该项目是一个Java实现的坦克大战游戏,涉及多线程技术用于坦克的移动、子弹发射等,文件I/O用于保存游戏进度,数据库操作用Vector替代。游戏包含坦克及子弹的绘制,碰撞检测算法,以及继续上一局功能。难点在于防止敌方坦克重叠的逻辑判断。项目帮助巩固了Java基础并提升了问题解决能力。
799

被折叠的 条评论
为什么被折叠?



