坦克大战
package com.zcw.tank;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/**
* @ClassName : tank
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-07-20 12:03
*/
public class tank {
public static void main(String[] args) {
Frame f = new Frame();
f.setSize(800,600);
f.setResizable(false);
f.setTitle("tank war");
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
package com.zcw.tank.demo;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/**
* @ClassName : TankFrame
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-07-20 12:46
*/
public class TankFrame extends Frame {
int x =200; int y= 200;
public TankFrame(){
setSize(800,600);
setResizable(false);
setTitle("tank war");
setVisible(true);
//添加监听
this.addKeyListener(new MyKeyListener());
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
/**
* 当窗口打开时(重新绘制时),会自动调用这个方法
* 系统自带的画笔:Graphics
* @param g
*/
@Override
public void paint(Graphics g) {
g.fillRect(x,y,50,50);
// x +=10;
// y +=10;
}
class MyKeyListener extends KeyAdapter{
boolean bL = false;
boolean bU = false;
boolean bR =false;
boolean bD = false;
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
switch (key){
case KeyEvent.VK_LEFT:
bL = true;
break;
case KeyEvent.VK_UP:
bU=true;
break;
case KeyEvent.VK_RIGHT:
bR = true;
break;
case KeyEvent.VK_DOWN:
bD=true;
break;
default:
break;
}
// x+=10;
//重新打开窗口
// repaint();
}
@Override
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
switch (key){
case KeyEvent.VK_LEFT:
bL = false;
break;
case KeyEvent.VK_UP:
bU=false;
break;
case KeyEvent.VK_RIGHT:
bR = false;
break;
case KeyEvent.VK_DOWN:
bD=false;
break;
default:
break;
}
}
}
}
package com.zcw.tank;
import com.zcw.tank.demo.TankFrame;
/**
* @ClassName : tank
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-07-20 12:03
*/
public class Tank {
public static void main(String[] args) throws InterruptedException {
TankFrame tf = new TankFrame();
while(true){
Thread.sleep(50);
tf.repaint();
}
}
}
package com.zcw.tank;
public enum Dir {
LEFT,UP,RIGHT,DOWN
}
https://download.csdn.net/download/qq_32370913/12643386
package com.zcw.tank;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
/**
* @ClassName : ResourceMgr
* @Description : 加载图片
* @Author : Zhaocunwei
* @Date: 2020-07-20 22:40
*/
public class ResourceMgr {
public static BufferedImage tankL,tankU,tankR,tankD;
static {
try {
tankL = ImageIO.read(
ResourceMgr.class.getClassLoader()
.getResourceAsStream("images/tankL.gif"));
tankU = ImageIO.read(
ResourceMgr.class.getClassLoader()
.getResourceAsStream("images/tankU.gif"));
tankR = ImageIO.read(
ResourceMgr.class.getClassLoader()
.getResourceAsStream("images/tankR.gif"));
tankD = ImageIO.read(
ResourceMgr.class.getClassLoader()
.getResourceAsStream("images/tankD.gif"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
声音素材
https://download.csdn.net/download/qq_32370913/12643927
package com.zcw.tank;
import javax.sound.sampled.*;
import java.io.IOException;
/**
* @ClassName : Audio
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-07-20 20:41
*/
public class Audio{
byte[] b = new byte[1024 * 1024 * 15];
public void loop() {
try {
while (true) {
int len = 0;
sourceDataLine.open(audioFormat, 1024 * 1024 * 15);
sourceDataLine.start();
//System.out.println(audioInputStream.markSupported());
audioInputStream.mark(12358946);
while ((len = audioInputStream.read(b)) > 0) {
sourceDataLine.write(b, 0, len);
}
audioInputStream.reset();
sourceDataLine.drain();
sourceDataLine.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private AudioFormat audioFormat = null;
private SourceDataLine sourceDataLine = null;
private DataLine.Info dataLine_info = null;
private AudioInputStream audioInputStream = null;
public Audio(String fileName) {
try {
audioInputStream = AudioSystem.getAudioInputStream(Audio.class.getClassLoader().getResource(fileName));
audioFormat = audioInputStream.getFormat();
dataLine_info = new DataLine.Info(SourceDataLine.class, audioFormat);
sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLine_info);
//FloatControl volctrl=(FloatControl)sourceDataLine.getControl(FloatControl.Type.MASTER_GAIN);
//volctrl.setValue(-40);//
} catch (Exception e) {
e.printStackTrace();
}
}
public void play() {
try {
byte[] b = new byte[1024*5];
int len = 0;
sourceDataLine.open(audioFormat, 1024*5);
sourceDataLine.start();
//System.out.println(audioInputStream.markSupported());
audioInputStream.mark(12358946);
while ((len = audioInputStream.read(b)) > 0) {
sourceDataLine.write(b, 0, len);
}
// audioInputStream.reset();
sourceDataLine.drain();
sourceDataLine.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void close() {
try {
audioInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// Audio a = new Audio("audio/explode.wav");
Audio a = new Audio("audio/war1.wav");
a.loop();
}
}
package com.zcw.tank;
import java.awt.*;
/**
* @ClassName : Bullet
* @Description : 炮弹
* @Author : Zhaocunwei
* @Date: 2020-07-20 20:21
*/
public class Bullet {
private static final int SPEED =7;
public static final int WIDTH=ResourceMgr.bulletD.getWidth();
public static final int HEIGHT = ResourceMgr.bulletD.getHeight();
private int x,y;
private Dir dir;
private TankFrame tf =null;
private boolean liveing = true;
private Group group = Group.BAD;
Rectangle rect = new Rectangle();
public Bullet(int x, int y, Dir dir,TankFrame tf,Group group) {
this.x = x;
this.y = y;
this.dir = dir;
this.tf = tf;
this.group = group;
tf.bullets.add(this);
rect.x = this.x;
rect.y = this.y;
rect.width = WIDTH;
rect.height = HEIGHT;
}
public void paint(Graphics g){
if(!liveing){
tf.bullets.remove(this);
}
switch (dir){
case LEFT:
g.drawImage(ResourceMgr.bulletL,x,y,null);
break;
case UP:
g.drawImage(ResourceMgr.bulletU,x,y,null);
break;
case RIGHT:
g.drawImage(ResourceMgr.bulletR,x,y,null);
break;
case DOWN:
g.drawImage(ResourceMgr.bulletD,x,y,null);
break;
}
move();
}
private void move(){
switch (dir){
case LEFT:
x -=SPEED;
break;
case UP:
y -=SPEED;
break;
case RIGHT:
x+=SPEED;
break;
case DOWN:
y+=SPEED;
break;
}
//需要更新 rect 对象
rect.x = this.x;
rect.y = this.y;
if(x<0 || y <0 || x > TankFrame.GAME_WIDTH || y> TankFrame.GAME_HEIGHT){
liveing =false;
}
}
public void collideWith(Tank tank) {
if(this.group == tank.getGroup()){
return;
}
//判断两个方框是否相交
if(rect.intersects(tank.rect)){
tank.die();
this.die();
int eX = tank.getX() + Tank.WIDTH/2 - Explode.WIDTH/2;
int eY = tank.getY() + Tank.HEIGHT/2 -Explode.HEIGHT/2;
tf.explodes.add(new Explode(eX,eY,tf));
}
}
private void die() {
this.liveing=false;
}
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
}
package com.zcw.tank;
/**
* @ClassName : DefaultFireStrategy
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-07-21 14:05
*/
public class DefaultFireStrategy implements FireStrategy{
@Override
public void fire(Tank t) {
int bx = t.x + Tank.WIDTH / 2 - Bullet.WIDTH / 2;
int by = t.y + Tank.HEIGHT / 2 - Bullet.HEIGHT / 2;
new Bullet(bx, by, t.dir, t.tf, t.group);
if(t.group == Group.GOOD){
new Thread(() ->{
new Audio("audio/tank_fire.wav").play();
}).start();
}
}
}
package com.zcw.tank;
public enum Dir {
LEFT,UP,RIGHT,DOWN
}
package com.zcw.tank;
import java.awt.*;
/**
* @ClassName : Bullet
* @Description : 炮弹
* @Author : Zhaocunwei
* @Date: 2020-07-20 20:21
*/
public class Explode {
public static final int WIDTH=ResourceMgr.explodes[0].getWidth();
public static final int HEIGHT = ResourceMgr.explodes[0].getHeight();
private int x,y;
private TankFrame tf =null;
private int step =0;
public Explode(int x, int y, TankFrame tf) {
this.x = x;
this.y = y;
this.tf = tf;
}
public void paint(Graphics g){
g.drawImage(ResourceMgr.explodes[step++],x,y,null);
if(step >=ResourceMgr.explodes.length){
tf.explodes.remove(this);
}
}
}
package com.zcw.tank;
public interface FireStrategy {
void fire(Tank t);
}
package com.zcw.tank;
/**
* @ClassName : FourDirFireStrategy
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-07-21 14:16
*/
public class FourDirFireStrategy implements FireStrategy{
@Override
public void fire(Tank t) {
int bx = t.x + Tank.WIDTH / 2 - Bullet.WIDTH / 2;
int by = t.y + Tank.HEIGHT / 2 - Bullet.HEIGHT / 2;
Dir[] dirs = Dir.values();
for(Dir dir : dirs){
new Bullet(bx, by, dir, t.tf, t.group);
}
if(t.group == Group.GOOD){
new Thread(() ->{
new Audio("audio/tank_fire.wav").play();
}).start();
}
}
}
package com.zcw.tank;
public enum Group {
GOOD,BAD
}
package com.zcw.tank;
import java.awt.*;
import java.awt.image.BufferedImage;
/**
* @ClassName : ImageUtil
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-07-19 19:10
*/
public class ImageUtil {
public static BufferedImage rotateImage(final BufferedImage bufferedimage,
final int degree) {
int w = bufferedimage.getWidth();
int h = bufferedimage.getHeight();
int type = bufferedimage.getColorModel().getTransparency();
BufferedImage img;
Graphics2D graphics2d;
(graphics2d = (img = new BufferedImage(w, h, type))
.createGraphics()).setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2d.rotate(Math.toRadians(degree), w / 2, h / 2);
graphics2d.drawImage(bufferedimage, 0, 0, null);
graphics2d.dispose();
return img;
}
}
package com.zcw.tank;
import java.io.IOException;
import java.util.Properties;
/**
* @ClassName : PropertyMgr
* @Description :获取配置文件信息
* @Author : Zhaocunwei
* @Date: 2020-07-11 20:27
*/
public class PropertyMgr {
static Properties propes = new Properties();
static {
try {
propes.load(PropertyMgr.class.getClassLoader().getResourceAsStream("config"));
} catch (IOException e) {
e.printStackTrace();
}
}
public static Object get(String key){
if(propes == null ){
return null;
}
return propes.get(key);
}
public static void main(String[] args) {
System.out.println(PropertyMgr.get("initTankCount"));
}
}
package com.zcw.tank;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
/**
* @ClassName : ResourceMgr
* @Description : 加载图片
* @Author : Zhaocunwei
* @Date: 2020-07-20 22:40
*/
public class ResourceMgr {
public static BufferedImage goodTankL,goodTankU,goodTankR,goodTankD;
public static BufferedImage badTankL,badTankU,badTankR,badTankD;
public static BufferedImage bulletL,bulletU,bulletR,bulletD;
public static BufferedImage[] explodes = new BufferedImage[16];
static {
try {
goodTankU= ImageIO.read(
ResourceMgr.class
.getClassLoader()
.getResourceAsStream("images/GoodTank1.png"));
goodTankL =ImageUtil.rotateImage(goodTankU,-90);
goodTankR = ImageUtil.rotateImage(goodTankU,90);
goodTankD =ImageUtil.rotateImage(goodTankU,180);
badTankU= ImageIO.read(
ResourceMgr.class
.getClassLoader()
.getResourceAsStream("images/BadTank1.png"));
badTankL =ImageUtil.rotateImage(badTankU,-90);
badTankR = ImageUtil.rotateImage(badTankU,90);
badTankD =ImageUtil.rotateImage(badTankU,180);
bulletU = ImageIO.read(
ResourceMgr.class
.getClassLoader()
.getResourceAsStream("images/bulletU.png")
);
bulletL = ImageUtil.rotateImage(bulletU,-90);
bulletR = ImageUtil.rotateImage(bulletU,90);
bulletD = ImageUtil.rotateImage(bulletU,180);
for(int i=0;i<16;i++){
explodes[i] =ImageIO.read(ResourceMgr.class.getClassLoader()
.getResourceAsStream("images/e"+(i+1)+".gif"));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.zcw.tank;
import java.awt.*;
import java.util.Random;
/**
* @ClassName : tank
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-07-20 12:03
*/
public class Tank {
int x, y;
Dir dir = Dir.DOWN;
private static final int SPEED = 5;
private boolean moving = true;
TankFrame tf = null;
private boolean living = true;
//创建分组,
Group group = Group.BAD;
private Random random = new Random();
Rectangle rect = new Rectangle();
//FourDirFireStrategy 大招
FireStrategy fs = new DefaultFireStrategy();
public static final int WIDTH = ResourceMgr.goodTankU.getWidth();
public static final int HEIGHT = ResourceMgr.goodTankU.getHeight();
public Tank(int x, int y, Dir dir, TankFrame tf, Group group) {
this.x = x;
this.y = y;
this.dir = dir;
this.tf = tf;
this.group = group;
rect.x = this.x;
rect.y = this.y;
rect.width = WIDTH;
rect.height = HEIGHT;
}
public void paint(Graphics g) {
if (!living) {
tf.tanks.remove(this);
}
switch (dir) {
case LEFT:
g.drawImage(
this.group == Group.GOOD ? ResourceMgr.goodTankL
: ResourceMgr.badTankL, x, y, null);
break;
case UP:
g.drawImage(
this.group == Group.GOOD ? ResourceMgr.goodTankU
: ResourceMgr.badTankU, x, y, null);
break;
case RIGHT:
g.drawImage(
this.group == Group.GOOD ? ResourceMgr.goodTankR
: ResourceMgr.badTankR, x, y, null);
break;
case DOWN:
g.drawImage(
this.group == Group.GOOD ? ResourceMgr.goodTankD
: ResourceMgr.badTankD, x, y, null);
break;
}
move();
}
private void move() {
if (!moving) {
return;
}
switch (dir) {
case LEFT:
x -= SPEED;
break;
case UP:
y -= SPEED;
break;
case RIGHT:
x += SPEED;
break;
case DOWN:
y += SPEED;
break;
}
//敌人坦克打出子弹
if (this.group == Group.BAD && random.nextInt(100) > 95) {
this.fire();
//创建随机方向
randmoDir();
}
//边界检测
boundsCheck();
//需要更新 rect 对象
rect.x = this.x;
rect.y = this.y;
}
private void boundsCheck() {
if(this.x < 2){
x=2;
}
if(this.y <28){
y =28;
}
if(this.x > TankFrame.GAME_WIDTH - Tank.WIDTH -2){
x = TankFrame.GAME_WIDTH - Tank.WIDTH -2;
}
if(this.y > TankFrame.GAME_HEIGHT - Tank.HEIGHT -2){
y = TankFrame.GAME_HEIGHT -Tank.HEIGHT - 2;
}
}
public void randmoDir() {
this.dir = Dir.values()[random.nextInt(4)];
}
public void fire() {
fs.fire(this);
}
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 Dir getDir() {
return dir;
}
public void setDir(Dir dir) {
this.dir = dir;
}
public boolean isMoving() {
return moving;
}
public void setMoving(boolean moving) {
this.moving = moving;
}
public static int getWIDTH() {
return WIDTH;
}
public static int getHEIGHT() {
return HEIGHT;
}
public void die() {
this.living = false;
}
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
}
package com.zcw.tank;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName : TankFrame
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-07-20 19:46
*/
public class TankFrame extends Frame {
Tank myTank = new Tank(200,400,Dir.DOWN,this,Group.GOOD);
public static final int GAME_WIDTH=1080,GAME_HEIGHT=960;
List<Bullet> bullets = new ArrayList<>();
List<Tank> tanks = new ArrayList<>();
List<Explode> explodes = new ArrayList<>();
public TankFrame(){
setSize(GAME_WIDTH,GAME_HEIGHT);
setResizable(false);
setTitle("tank war");
setVisible(true);
//添加监听
this.addKeyListener(new MyKeyListener());
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
//解决闪烁问题
Image offScreenImage =null;
@Override
public void update(Graphics g) {
if(offScreenImage ==null){
offScreenImage = this.createImage(GAME_WIDTH,GAME_HEIGHT);
}
Graphics gOffScreen = offScreenImage.getGraphics();
Color c = gOffScreen.getColor();
gOffScreen.setColor(Color.BLACK);
gOffScreen.fillRect(0,0,GAME_WIDTH,GAME_HEIGHT);
gOffScreen.setColor(c);
paint(gOffScreen);
g.drawImage(offScreenImage,0,0,null);
}
/**
* 当窗口打开时(重新绘制时),会自动调用这个方法
* 系统自带的画笔:Graphics
* @param g
*/
@Override
public void paint(Graphics g) {
Color c = g.getColor();
g.setColor(Color.WHITE);
g.drawString("子弹数量:"+bullets.size(),10,60);
g.drawString("敌人的数量"+tanks.size(),10,80);
g.drawString("爆炸的数量"+explodes.size(),10,100);
g.setColor(c);
myTank.paint(g);
for(int i=0;i<bullets.size();i++){
bullets.get(i).paint(g);
}
//画敌方坦克
for(int i=0; i<tanks.size();i++){
tanks.get(i).paint(g);
}
//判断子弹是否与坦克相撞
for(int i =0;i<bullets.size();i++){
for(int j=0;j<tanks.size();j++){
bullets.get(i).collideWith(tanks.get(j));
}
}
//画出爆炸
for(int i=0;i<explodes.size();i++){
explodes.get(i).paint(g);
}
}
class MyKeyListener extends KeyAdapter{
boolean bL = false;
boolean bU = false;
boolean bR =false;
boolean bD = false;
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
switch (key){
case KeyEvent.VK_LEFT:
bL = true;
break;
case KeyEvent.VK_UP:
bU=true;
break;
case KeyEvent.VK_RIGHT:
bR = true;
break;
case KeyEvent.VK_DOWN:
bD=true;
break;
default:
break;
}
setMainTankDir();
}
@Override
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
switch (key){
case KeyEvent.VK_LEFT:
bL = false;
break;
case KeyEvent.VK_UP:
bU=false;
break;
case KeyEvent.VK_RIGHT:
bR = false;
break;
case KeyEvent.VK_DOWN:
bD=false;
break;
case KeyEvent.VK_ENTER :
myTank.fire();
break;
default:
break;
}
setMainTankDir();
}
private void setMainTankDir(){
if(!bL && !bU && !bR && !bD){
myTank.setMoving(false);
}else{
myTank.setMoving(true);
if(bL){
myTank.setDir(Dir.LEFT);
}
if(bU) {
myTank.setDir(Dir.UP);
}
if(bR){
myTank.setDir(Dir.RIGHT);
}
if(bD){
myTank.setDir(Dir.DOWN);
}
}
}
}
}
package com.zcw.tank;
/**
* @ClassName : TankMain
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-07-20 12:53
*/
public class TankMain {
public static void main(String[] args) throws InterruptedException {
TankFrame tf = new TankFrame();
int initTankCount = Integer.parseInt((String)PropertyMgr.get("initTankCount"));
//初始化地方坦克
for(int i =0;i<initTankCount;i++){
tf.tanks.add(new Tank(50 + i*80 ,200,Dir.DOWN,tf,Group.BAD));
}
new Thread(() -> new Audio("audio/war1.wav").loop()).start();
while(true){
Thread.sleep(50);
tf.repaint();
}
}
}