游戏运行图片
源码分两大块:
java类和resources
其中java中又分了constant、tank、util、window、StartGame(主类);constant里只有Constant类;tank有Bomb、Bullet、EnemyTank、HeroTank、Tank类;util中含MyThreadFactroy、MyUtil、PlayAudio、Recorder类;window中只有MainWindow和MyPanel类。
而resources中只有res,res中含audio和data及image,image中为gif类的三张图片(坦克爆炸图片)
一、constant中的Constant类
package constant;
// 系统常量
public class Constant {
// 游戏界面宽度
public static final int WINDOW_WIDTH = 1450;
// 游戏界面高度
public static final int WINDOW_HEIGHT = 950;
// 界面顶部标题栏高度
public static final int WINDOW_TITLE_HEIGHT = 25;
// 信息栏高度
public static final int INFO_BAR_HEIGHT = 100;
// 界面重绘时间
public static final int REPAINT_TIME = 80;
// 游戏状态
public static final int GAME_WIN = 1;
public static final int GAME_RUNNING = 0;
public static final int GAME_FAIL = -1;
public static final int GAME_INIT = -2;
//我方坦克初始数量
public static final int MY_TANK_INIT_NUM = 3;
//敌方坦克初始数量
public static final int ENEMY_TANK_INIT_NUM = 30;
// 坦克轮子宽度
public static final int TANK_WHEEL_WIDTH = 10;
// 坦克轮子高度
public static final int TANK_WHEEL_HEIGHT = 60;
// 坦克主体宽度
public static final int TANK_BODY_WIDTH = 20;
// 坦克主体高度
public static final int TANK_BODY_HEIGHT = 40;
// 坦克速度
public static final int TANK_SPEED = 10;
// 子弹半径
public static final int BULLET_RADIUS = 3;
// 子弹速度
public static final int BULLET_SPEED = 50;
// 子弹每次运行的时间间隔
public static final int BULLET_RUN_INTERVAL_TIME = 200;
// 我方坦克发射子弹最少时间间隔(毫秒),低于这个时间的发射无效
public static final int MY_TANK_SHOT_MIN_INTERVAL_TIME = 10;
// 敌方坦克发射子弹最少时间间隔(毫秒)
public static final int ENEMY_TANK_SHOT_MIN_INTERVAL_TIME = 200;
// 方向
public static final int UP = 0;
public static final int RIGHT = 1;
public static final int DOWN = 2;
public static final int LEFT = 3;
}
二、 tank中的Bomb类
package tank;
// 坦克坐标
public class Bomb {
// 坐标
private int x,y;
// 生命值
private int life;
// 是否存活
private boolean live;
/**
* 初始化
*/
private void init(){
life = 9;
live = true;
}
/**
* 构造器
* @param x
* @param y
*/
public Bomb(int x, int y) {
this.x = x;
this.y = y;
init();
}
/**
* 生命值减1
*/
public void lifeDown(){
if(life > 0){
life --;
return;
}
live = false;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getLife() {
return life;
}
public boolean isLive() {
return live;
}
public void setLive(boolean live) {
this.live = live;
}
}
二、 tank中的Bullet类
package tank;
import constant.Constant;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
// 子弹
public class Bullet{
// 子弹 X 坐标
private int x;
// 子弹 Y 坐标
private int y;
// 子弹方向
private int direction;
// 子弹存活状态
private boolean live = true;
/**
* 构造器
*
* @param x
* @param y
* @param direction
*/
public Bullet(int x, int y, int direction) {
this.x = x;
this.y = y;
this.direction = direction;
}
/**
* 射击
*/
public void shot() {
// 子弹循环移动
while (live) {
// 休眠
try {
TimeUnit.MILLISECONDS.sleep(Constant.BULLET_RUN_INTERVAL_TIME);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 根据方向移动
switch (direction) {
case Constant.UP:
y -= Constant.BULLET_SPEED;
break;
case Constant.RIGHT:
x += Constant.BULLET_SPEED;
break;
case Constant.DOWN:
y += Constant.BULLET_SPEED;
break;
case Constant.LEFT:
x -= Constant.BULLET_SPEED;
break;
default:
}
// 判断子弹是否到边界
if (x <= 0 || x >= Constant.WINDOW_WIDTH || y <= Constant.INFO_BAR_HEIGHT || y >= Constant.WINDOW_HEIGHT) {
live = false;
}
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public boolean isLive() {
return live;
}
public void setLive(boolean live) {
this.live = live;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Bullet bullet = (Bullet) o;
return x == bullet.x && y == bullet.y && direction == bullet.direction && live == bullet.live;
}
@Override
public int hashCode() {
return Objects.hash(x, y, direction, live);
}
}
二、 tank中的EnemyTank类
package tank;
import constant.Constant;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
// 敌方坦克
public class EnemyTank extends Tank {
// 我方坦克集合:可以让敌方坦克自动追击
private List<HeroTank> myTanks = null;
/**
* 构造器
*
* @param x
* @param y
*/
public EnemyTank(int x, int y) {
super(x, y, Constant.DOWN);
}
/**
* 射击
*/
@Override
public void shot() {
// 如果存活就一直发射
while (isLive()) {
try {
TimeUnit.MILLISECONDS.sleep(Constant.ENEMY_TANK_SHOT_MIN_INTERVAL_TIME);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 根据方向移动
switch (getDirection()) {
case Constant.UP:
moveUp();
break;
case Constant.RIGHT:
moveRight();
break;
case Constant.DOWN:
moveDown();
break;
default:
moveLeft();
}
// 可以发射
if (isAllowShot()) {
// 开启线程,发射子弹
getBulletThreadPool().execute(() -> {
// 根据方向创建子弹,并射击
int d = getDirection();
Bullet bullet = null;
switch (d) {
case Constant.UP:
// 创建子弹
bullet = new Bullet(getX() + Constant.TANK_WHEEL_WIDTH + Constant.TANK_BODY_WIDTH / 2 - Constant.BULLET_RADIUS, getY(), d);
break;
case Constant.RIGHT:
// 创建子弹
bullet = new Bullet(getX() + Constant.TANK_WHEEL_HEIGHT, getY() + Constant.TANK_WHEEL_WIDTH + Constant.TANK_BODY_WIDTH / 2 - Constant.BULLET_RADIUS, d);
break;
case Constant.DOWN:
// 创建子弹
bullet = new Bullet(getX() + Constant.TANK_WHEEL_WIDTH + Constant.TANK_BODY_WIDTH / 2 - Constant.BULLET_RADIUS, getY() + Constant.TANK_WHEEL_HEIGHT, d);
break;
case Constant.LEFT:
// 创建子弹
bullet = new Bullet(getX(), getY() + Constant.TANK_WHEEL_WIDTH + Constant.TANK_BODY_WIDTH / 2 - Constant.BULLET_RADIUS, d);
break;
default:
}
if (bullet != null) {
// 加入坦克的子弹集合,并射击
getBullets().add(bullet);
bullet.shot();
}
});
// 发射后把发射状态设为不可发射
setAllowShot(false);
// 开启新线程,设置发射状态。如果在当前线程休眠等待时,会出现阻塞,子弹有停顿现象
getShotIntervalThreadPool().execute(() -> {
try {
// 随机休眠
ThreadLocalRandom random = ThreadLocalRandom.current();
int t = 300 * random.nextInt(10);
TimeUnit.MILLISECONDS.sleep(t);
// 设为可以发射
setAllowShot(true);
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
});
// 改变方向,追击目标坦克
if (myTanks.size() > 0 && myTanks.get(0) != null && myTanks.get(0).isLive()) {
Tank myTank = myTanks.get(0);
// 开启新线程,改变方向
getShotIntervalThreadPool().execute(() -> {
try {
// 随机休眠
ThreadLocalRandom random = ThreadLocalRandom.current();
int t = 1000 + 1000 * random.nextInt(10);
TimeUnit.MILLISECONDS.sleep(t);
// 判断我方坦克位置,从而改变方向
// x 轴距离
int xDistance = myTank.getX() - getX() + Constant.TANK_WHEEL_HEIGHT;
// y 轴距离
int yDistance = myTank.getY() - getY() + Constant.TANK_WHEEL_HEIGHT;
// 改变方向
if (Math.abs(xDistance) < Math.abs(yDistance)) {
// 纵向改变方向
if (yDistance >= 0) {
// 向下
setDirection(Constant.DOWN);
} else {
// 向上
setDirection(Constant.UP);
}
} else {
// 横向改变方向
if (xDistance >= 0) {
// 向右
setDirection(Constant.RIGHT);
} else {
// 向左
setDirection(Constant.LEFT);
}
}
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
});
}
}
}
}
public void setMyTanks(List<HeroTank> myTanks) {
this.myTanks = myTanks;
}
}
二、tank中的HeroTank类
package tank;
import constant.Constant;
import java.util.concurrent.*;
//我放坦克
public class HeroTank extends Tank {
/**
* 构造器
*
* @param x
* @param y
*/
public HeroTank(int x, int y) {
super(x, y, Constant.UP);
}
/**
* 射击
*/
@Override
public void shot() {
// 可以发射
if (isAllowShot()) {
// 开启线程,发射子弹
getBulletThreadPool().execute(() -> {
// 根据方向创建子弹,并射击
int d = getDirection();
Bullet bullet = null;
switch (d) {
case Constant.UP:
// 创建子弹
bullet = new Bullet(getX() + Constant.TANK_WHEEL_WIDTH + Constant.TANK_BODY_WIDTH / 2 - Constant.BULLET_RADIUS, getY(), d);
break;
case Constant.RIGHT:
// 创建子弹
bullet = new Bullet(getX() + Constant.TANK_WHEEL_HEIGHT, getY() + Constant.TANK_WHEEL_WIDTH + Constant.TANK_BODY_WIDTH / 2 - Constant.BULLET_RADIUS, d);
break;
case Constant.DOWN: