Java坦克大战优化
基础思路
举例(敌人坦克与我方坦克):
第一种: 当我方坦克方向向上(宽40,高60),敌人坦克方向向上或向下时。我方坦克左上角或者右上角坐标落在敌人坦克的区域内。
第二种: 当我方坦克方向向上(宽40,高60),敌人坦克方向向左或向右时。我方坦克左上角或者右上角坐标落在敌人坦克的区域内。
第三种:当我方坦克方向向右(宽60,高40),敌人坦克方向向上或向下时。我方坦克右上角或者右下角坐标落在敌人坦克的区域内。
第四种:当我方坦克方向向右(宽60,高40),敌人坦克方向向左或向右时。我方坦克右上角或者右下角坐标落在敌人坦克的区域内。
第五种:当我方坦克方向向下(宽40,高60),敌人坦克方向向上或向下时。我方坦克左下角或者右下角坐标落在敌人坦克的区域内。
第六种:当我方坦克方向向下(宽40,高60),敌人坦克方向向左或向右时。我方坦克左下角或者右下角坐标落在敌人坦克的区域内。
第七种:当我方坦克方向向左(宽60,高40),敌人坦克方向向上或向下时。我方坦克左上角或者右下角坐标落在敌人坦克的区域内。
第八种:当我方坦克方向向左(宽60,高40),敌人坦克方向向左或向右时。我方坦克左下角或者右下角坐标落在敌人坦克的区域内。
刚开始不明白为什么什么要判断两个点的,后来才明白是因为当我方坦克方向向上,敌人坦克方向下,我方坦克在敌方左下角重叠时我方坦克 x 坐标会小很多如图,只判断一个角还是会重叠,所以两个都需要判断。
// 当我坦克是向上方向,敌方坦克是向上或向下方向
if (tank.direction == UP || tank.direction == DOWN) {
// 当前坦克左上角的坐标在重叠的范围内
// 我方坦克左上角坐标 [x, y]
if (x >= tank.x
&& x <= tank.x + WIDTH
&& y >= tank.y
&& y <= tank.y + HEIGHT) {
return true;
}
// 当前坦克右上角的坐标在重叠范围内,当我方坦克在敌方坦克的左方重叠时 我方的 x 坐标会比敌方 x 坐标小,
// 只判断一个左上角还是会重叠,所以要判断两个角的坐标
// 我方坦克右上角坐标 [x + WIDTH, y]
if (x + WIDTH >= tank.x
&& x <= tank.x + WIDTH
&& y >= tank.y
&& y <= tank.y + HEIGHT) {
return true;
}
未优化代码
package com.example.tankgame06;
import java.util.List;
import java.util.Vector;
import static com.example.tankgame04.GameConstant.*;
/**
* @author XiaoAi
* @date 2024/6/22 10:44
*/
public abstract class Tank {
private int x;
private int y;
private int direction; // 0 1 2 3
private int speed = 1;
private List<Bullet> bulletList = new Vector<>(); // 子弹
// 总宽度(x)90 高度(80)
public final static int WIDTH = 90;
public final static int HEIGHT = 80;
private boolean isLive = true;
public static final List<Tank> ALL_TANK = new Vector<>();
public Tank() {
}
public Tank(int x, int y) {
this.x = x;
this.y = y;
}
public void moveUp() {
boolean isTouch = isTouchTank();
if (isTouch) {
return;
}
setY(this.y - speed);
}
public void moveRight() {
boolean isTouch = isTouchTank();
if (isTouch) {
return;
}
setX(this.x + speed);
}
public void moveDown() {
boolean isTouch = isTouchTank();
if (isTouch) {
return;
}
setY(this.y + speed);
}
public void moveLeft() {
boolean isTouch = isTouchTank();
if (isTouch) {
return;
}
setX(this.x - speed);
}
public int getX() {
return x;
}
public void setX(int x) {
if (x >= 0 && x <= TankGame06.WIDTH - Tank.WIDTH) {
this.x = x;
}
}
public int getY() {
return y;
}
public void setY(int y) {
if (y >= 0 && y <= TankGame06.HEIGHT - Tank.HEIGHT) {
this.y = y;
}
}
//....get/set
public void shotTank() {
if (!this.isLive) {
return;
}
List<Bullet> bulletList = getBulletList();
Bullet bullet = null;
switch (getDirection()) {
case UP:
bullet = new Bullet(getX() + WIDTH / 2 - 2, getY() - 10, UP);
break;
case RIGHT:
bullet = new Bullet(getX() + WIDTH + 10, getY() + HEIGHT / 2 + 2, RIGHT);
break;
case DOWN:
bullet = new Bullet(getX() + HEIGHT / 2 + 2, getY() + WIDTH, DOWN);
break;
case LEFT:
bullet = new Bullet(getX() - 10, getY() + HEIGHT / 2 + 2, LEFT);
break;
}
if (bullet != null) {
bulletList.add(bullet);
new Thread(bullet).start();
}
}
/**
* 坦克重叠判断
*
* @return 是否重叠
*/
public boolean isTouchTank() {
int offset = 20;
if (ALL_TANK.size() == 1) {
return false;
}
switch (direction) {
case UP:
for (int i = 0; i < ALL_TANK.size(); i++) {
Tank tank = ALL_TANK.get(i);
if (tank != this) {
// 当我坦克是向上方向,敌方坦克是向上或向下方向
if (tank.direction == UP || tank.direction == DOWN) {
// 当前坦克左上角的坐标在重叠的范围内
// 我方坦克左上角坐标 [x, y]
if (x >= tank.x
&& x <= tank.x + WIDTH
&& y >= tank.y
&& y <= tank.y + HEIGHT) {
return true;
}
// 当前坦克右上角的坐标在重叠范围内,当我方坦克在敌方坦克的左方重叠时 我方的 x 坐标会比敌方 x 坐标小,
// 只判断一个左上角还是会重叠,所以要判断两个角的坐标
// 我方坦克右上角坐标 [x + WIDTH, y]
if (x + WIDTH >= tank.x
&& x <= tank.x + WIDTH
&& y >= tank.y
&& y <= tank.y + HEIGHT) {
return true;
}
}
// 当我坦克是向上方向,敌方坦克是向右或向左方向
// 敌方坦克向右等于旋转九十度高宽互换
if (tank.direction == RIGHT || tank.direction == LEFT) {
// 当前坦克左上角的坐标在重叠的范围内
// 我方坦克左上角坐标 [x, y]
if (x >= tank.x
&& x <= tank.x + HEIGHT
&& y >= tank.y
&& y <= tank.y + WIDTH) {
return true;
}
// 当前坦克右上角的坐标在重叠的范围内
// 我方坦克右上角坐标 [x + WIDTH, y]
if (x + WIDTH >= tank.x
&& x <= tank.x + HEIGHT
&& y >= tank.y
&& y <= tank.y + WIDTH) {
return true;
}
}
}
}
break;
case RIGHT:
// 我方坦克向右,右上角坐标[x + HEIGHT, y ]
// 我方坦克向右,左下角坐标[x + HEIGHT, y + WIDTH]
for (int i = 0; i < ALL_TANK.size(); i++) {
Tank tank = ALL_TANK.get(i);
if (tank != this) {
// 当我坦克是向右方向,敌方坦克是向上或下方向
if (tank.direction == UP || tank.direction == DOWN) {
// 当前坦克右上角的坐标在重叠的范围内
// 当前坦克右上角坐标 [x + HEIGHT, y ]
System.out.println(x + HEIGHT >= tank.x
&& x + HEIGHT <= tank.x + WIDTH);
System.out.println(y >= tank.y
&& y <= tank.y + HEIGHT);
if (x + HEIGHT >= tank.x
&& x + HEIGHT <= tank.x + WIDTH
&& y >= tank.y
&& y <= tank.y + HEIGHT) {
return true;
}
// 当前坦克左下角的坐标在重叠的范围内
// 当前坦克左下角坐标 [x + HEIGHT, y + WIDTH]
if (x + HEIGHT >= tank.x
&& x + HEIGHT <= tank.x + WIDTH
&& y + WIDTH >= tank.y
&& y + WIDTH <= tank.y + HEIGHT) {
return true;
}
}
// 当我坦克是向右方向,敌方坦克是向左或向右方向
if (tank.direction == LEFT || tank.direction == RIGHT) {
// 当前坦克右上角的坐标在重叠的范围内
// 当前坦克右上角坐标 [x + HEIGHT, y]
if (x + HEIGHT >= tank.x
&& x + HEIGHT <= tank.x + HEIGHT
&& y >= tank.y
&& y <= tank.y + WIDTH) {
return true;
}
// 当前坦克左下角的坐标在重叠的范围内
// 当前坦克左下角坐标 [x + HEIGHT, y + WIDTH]
if (x + HEIGHT >= tank.x
&& x + HEIGHT <= tank.x + HEIGHT
&& y + WIDTH >= tank.y
&& y + WIDTH <= tank.y + WIDTH) {
return true;
}
}
}
}
break;
case DOWN:
// 我方坦克向下,左下角坐标 [x, y + HEIGHT]
// 我方坦克向下,右下角坐标 [x + WIDTH, y + HEIGHT]
for (int i = 0; i < ALL_TANK.size(); i++) {
Tank tank = ALL_TANK.get(i);
if (tank != this) {
// 当我坦克是向下方向,敌方坦克是向上或下方向
if (tank.direction == UP || tank.direction == DOWN) {
// 我方左下角在重叠范围内
if (x >= tank.x
&& x <= tank.x + WIDTH
&& y + HEIGHT >= tank.y
&& y + HEIGHT <= tank.y + HEIGHT) {
return true;
}
// 我方右下角在重叠范围内
if (x + WIDTH >= tank.x
&& x + WIDTH <= tank.x + WIDTH
&& y + HEIGHT >= tank.y
&& y + HEIGHT <= tank.y + HEIGHT) {
return true;
}
}
// 当我坦克是向下方向,敌方坦克是向左或右方向
if (tank.direction == LEFT || tank.direction == RIGHT) {
// 我方左下角在重叠范围内
// 左下角坐标 [x, y + HEIGHT]
if (x >= tank.x
&& x <= tank.x + HEIGHT
&& y + HEIGHT >= tank.y
&& y + HEIGHT <= tank.y + WIDTH) {
return true;
}
// 我方右下角在重叠范围内
// 右下角坐标 [x + WIDTH, y + HEIGHT]
if (x + WIDTH >= tank.x
&& x + WIDTH <= tank.x + HEIGHT
&& y + HEIGHT >= tank.y
&& y + HEIGHT <= tank.y + WIDTH) {
return true;
}
}
}
}
break;
case LEFT:
// 我方坦克向左,左上角坐标 [x, y]
// 我方坦克向左,左下角坐标 [x, y + WIDTH]
for (int i = 0; i < ALL_TANK.size(); i++) {
Tank tank = ALL_TANK.get(i);
if (tank != this) {
if (tank.direction == UP || tank.direction == DOWN) {
// 左上角
if (x >= tank.x
&& x <= tank.x + WIDTH
&& y >= tank.y
&& y <= tank.y + HEIGHT) {
return true;
}
// 左下角
if (x >= tank.x
&& x <= tank.x + WIDTH
&& y + WIDTH >= tank.y
&& y + WIDTH <= tank.y + HEIGHT) {
return true;
}
}
if (tank.direction == LEFT || tank.direction == RIGHT) {
// 左上角
if (x >= tank.x
&& x <= tank.x + HEIGHT
&& y >= tank.y
&& y <= tank.y + WIDTH) {
return true;
}
// 左下角
if (x >= tank.x
&& x <= tank.x + HEIGHT
&& y + WIDTH >= tank.y
&& y + WIDTH <= tank.y + WIDTH) {
return true;
}
}
}
}
break;
}
return false;
}
}
优化代码
说是优化其实只是套了一层娃,分离出来一个 calcTouch 方计算是否重叠1对1作比较。
对了一个offset变量偏移量,没有偏移量会重叠一个轮子的宽度如图
加减偏移量主要看你往哪个方向重叠,
如上图就是向右x就要加偏移量,向左重叠就要减偏移量
向下方向重叠y加偏移量,向上方向重叠y减偏移量;
x-- 左移 x++ 右移,y++上移 y–下移;
增加偏移量后
package com.example.tankgame06;
import java.util.List;
import java.util.Vector;
import static com.example.tankgame04.GameConstant.*;
/**
* @author XiaoAi
* @date 2024/6/22 10:44
*/
public abstract class Tank {
private int x;
private int y;
private int direction; // 0 1 2 3
private int speed = 1;
private List<Bullet> bulletList = new Vector<>(); // 子弹
// 总宽度(x)90 高度(80)
public final static int WIDTH = 90;
public final static int HEIGHT = 80;
private boolean isLive = true;
public static final List<Tank> ALL_TANK = new Vector<>();
public Tank() {
}
public Tank(int x, int y) {
this.x = x;
this.y = y;
}
public void moveUp() {
boolean isTouch = isTouchTank();
if (isTouch) {
return;
}
setY(this.y - speed);
}
public void moveRight() {
boolean isTouch = isTouchTank();
if (isTouch) {
return;
}
setX(this.x + speed);
}
public void moveDown() {
boolean isTouch = isTouchTank();
if (isTouch) {
return;
}
setY(this.y + speed);
}
public void moveLeft() {
boolean isTouch = isTouchTank();
if (isTouch) {
return;
}
setX(this.x - speed);
}
public int getX() {
return x;
}
public void setX(int x) {
if (x >= 0 && x <= TankGame06.WIDTH - Tank.WIDTH) {
this.x = x;
}
}
public int getY() {
return y;
}
public void setY(int y) {
if (y >= 0 && y <= TankGame06.HEIGHT - Tank.HEIGHT) {
this.y = y;
}
}
// ... get/set
public void shotTank() {
if (!this.isLive) {
return;
}
List<Bullet> bulletList = getBulletList();
Bullet bullet = null;
switch (getDirection()) {
case UP:
bullet = new Bullet(getX() + WIDTH / 2 - 2, getY() - 10, UP);
break;
case RIGHT:
bullet = new Bullet(getX() + WIDTH + 10, getY() + HEIGHT / 2 + 2, RIGHT);
break;
case DOWN:
bullet = new Bullet(getX() + HEIGHT / 2 + 2, getY() + WIDTH, DOWN);
break;
case LEFT:
bullet = new Bullet(getX() - 10, getY() + HEIGHT / 2 + 2, LEFT);
break;
}
if (bullet != null) {
bulletList.add(bullet);
new Thread(bullet).start();
}
}
/**
* 坦克重叠判断
*
* @return 是否重叠
*/
public boolean isTouchTank() {
int offset = 20;
if (ALL_TANK.size() == 1) {
return false;
}
return isTouch(this, ALL_TANK);
}
public boolean isTouch(Tank myTank, List<Tank> allTank) {
if (allTank == null || allTank.size() == 1) {
return false;
}
for (int i = 0; i < allTank.size(); i++) {
boolean isTouch = calcTouch(myTank, allTank.get(i));
if (isTouch) {
return true;
}
}
return false;
}
/**
* 计算是否重叠
*
* @param tank 我方坦克
* @param enemyTank 敌方坦克
* @return
*/
public boolean calcTouch(Tank tank, Tank enemyTank) {
if (tank == null || enemyTank == null) {
return false;
}
if (tank == enemyTank) {
return false;
}
int x = tank.x;
int y = tank.y;
int offset = 20; // 重叠偏移量 一个轮子的宽度
switch (tank.direction) {
case UP:
// 当我坦克是向上方向,敌方坦克是向上或向下方向
if (enemyTank.direction == UP || enemyTank.direction == DOWN) {
// 当前坦克左上角的坐标在重叠的范围内
// 我方坦克左上角坐标 [x, y]
if (x >= enemyTank.x
&& x <= enemyTank.x + WIDTH
&& y - offset >= enemyTank.y
&& y - offset <= enemyTank.y + HEIGHT) {
return true;
}
// 当前坦克右上角的坐标在重叠范围内,当我方坦克在敌方坦克的左方重叠时 我方的 x 坐标会比敌方 x 坐标小,
// 只判断一个左上角还是会重叠,所以要判断两个角的坐标
// 我方坦克右上角坐标 [x + WIDTH, y]
if (x + WIDTH >= enemyTank.x
&& x <= enemyTank.x + WIDTH
&& y - offset >= enemyTank.y
&& y - offset <= enemyTank.y + HEIGHT) {
return true;
}
}
// 当我坦克是向上方向,敌方坦克是向右或向左方向
// 敌方坦克向右等于旋转九十度高宽互换
if (enemyTank.direction == RIGHT || enemyTank.direction == LEFT) {
// 当前坦克左上角的坐标在重叠的范围内
// 我方坦克左上角坐标 [x, y]
if (x >= enemyTank.x
&& x <= enemyTank.x + HEIGHT
&& y - offset >= enemyTank.y
&& y - offset <= enemyTank.y + WIDTH) {
return true;
}
// 当前坦克右上角的坐标在重叠的范围内
// 我方坦克右上角坐标 [x + WIDTH, y]
if (x + WIDTH >= enemyTank.x
&& x <= enemyTank.x + HEIGHT
&& y - offset >= enemyTank.y
&& y - offset <= enemyTank.y + WIDTH) {
return true;
}
}
break;
case RIGHT:
// 我方坦克向右,右上角坐标[x + HEIGHT, y ]
// 我方坦克向右,左下角坐标[x + HEIGHT, y + WIDTH]
// 当我坦克是向右方向,敌方坦克是向上或下方向
if (enemyTank.direction == UP || enemyTank.direction == DOWN) {
// 当前坦克右上角的坐标在重叠的范围内
// 当前坦克右上角坐标 [x + HEIGHT, y ]
if (x + HEIGHT + offset >= enemyTank.x
&& x + HEIGHT + offset <= enemyTank.x + WIDTH
&& y >= enemyTank.y
&& y <= enemyTank.y + HEIGHT) {
return true;
}
// 当前坦克左下角的坐标在重叠的范围内
// 当前坦克左下角坐标 [x + HEIGHT, y + WIDTH]
if (x + HEIGHT + offset >= enemyTank.x
&& x + HEIGHT + offset <= enemyTank.x + WIDTH
&& y + WIDTH >= enemyTank.y
&& y + WIDTH <= enemyTank.y + HEIGHT) {
return true;
}
}
// 当我坦克是向右方向,敌方坦克是向左或向右方向
if (enemyTank.direction == LEFT || enemyTank.direction == RIGHT) {
// 当前坦克右上角的坐标在重叠的范围内
// 当前坦克右上角坐标 [x + HEIGHT, y]
if (x + HEIGHT + offset >= enemyTank.x
&& x + HEIGHT + offset <= enemyTank.x + HEIGHT
&& y >= enemyTank.y
&& y <= enemyTank.y + WIDTH) {
return true;
}
// 当前坦克左下角的坐标在重叠的范围内
// 当前坦克左下角坐标 [x + HEIGHT, y + WIDTH]
if (x + HEIGHT + offset >= enemyTank.x
&& x + HEIGHT + offset <= enemyTank.x + HEIGHT
&& y + WIDTH >= enemyTank.y
&& y + WIDTH <= enemyTank.y + WIDTH) {
return true;
}
}
break;
case DOWN:
// 我方坦克向下,左下角坐标 [x, y + HEIGHT]
// 我方坦克向下,右下角坐标 [x + WIDTH, y + HEIGHT]
// 当我坦克是向下方向,敌方坦克是向上或下方向
if (enemyTank.direction == UP || enemyTank.direction == DOWN) {
// 我方左下角在重叠范围内
if (x >= enemyTank.x
&& x <= enemyTank.x + WIDTH
&& y + HEIGHT + offset >= enemyTank.y
&& y + HEIGHT + offset <= enemyTank.y + HEIGHT) {
return true;
}
// 我方右下角在重叠范围内
if (x + WIDTH >= enemyTank.x
&& x + WIDTH <= enemyTank.x + WIDTH
&& y + HEIGHT + offset >= enemyTank.y
&& y + HEIGHT + offset <= enemyTank.y + HEIGHT) {
return true;
}
}
// 当我坦克是向下方向,敌方坦克是向左或右方向
if (enemyTank.direction == LEFT || enemyTank.direction == RIGHT) {
// 我方左下角在重叠范围内
// 左下角坐标 [x, y + HEIGHT]
if (x >= enemyTank.x
&& x <= enemyTank.x + HEIGHT
&& y + HEIGHT + offset >= enemyTank.y
&& y + HEIGHT + offset <= enemyTank.y + WIDTH) {
return true;
}
// 我方右下角在重叠范围内
// 右下角坐标 [x + WIDTH, y + HEIGHT]
if (x + WIDTH >= enemyTank.x
&& x + WIDTH <= enemyTank.x + HEIGHT
&& y + HEIGHT + offset >= enemyTank.y
&& y + HEIGHT + offset <= enemyTank.y + WIDTH) {
return true;
}
}
break;
case LEFT:
// 我方坦克向左,左上角坐标 [x, y]
// 我方坦克向左,左下角坐标 [x, y + WIDTH]
if (enemyTank.direction == UP || enemyTank.direction == DOWN) {
// 左上角
if (x - offset>= enemyTank.x
&& x - offset <= enemyTank.x + WIDTH
&& y >= enemyTank.y
&& y <= enemyTank.y + HEIGHT) {
return true;
}
// 左下角
if (x - offset >= enemyTank.x
&& x - offset <= enemyTank.x + WIDTH
&& y + WIDTH >= enemyTank.y
&& y + WIDTH <= enemyTank.y + HEIGHT) {
return true;
}
}
if (enemyTank.direction == LEFT || enemyTank.direction == RIGHT) {
// 左上角
if (x - offset >= enemyTank.x
&& x - offset <= enemyTank.x + HEIGHT
&& y >= enemyTank.y
&& y <= enemyTank.y + WIDTH) {
return true;
}
// 左下角
if (x - offset >= enemyTank.x
&& x - offset <= enemyTank.x + HEIGHT
&& y + WIDTH >= enemyTank.y
&& y + WIDTH <= enemyTank.y + WIDTH) {
return true;
}
}
break;
}
return false;
}
}
源代码网盘链接
游戏记录使用 json字符存储对象,导入fastjson
链接:https://pan.baidu.com/s/1DFc8nw6BGxFTzRV4t48YFA?pwd=gth4
提取码:gth4