java实现坦克大战

源码: java实现坦克大战-课程设计期末作业-Java文档类资源-CSDN文库

代码总体上来说借鉴了尚学堂“手把手教你一小时写出坦克大战”(感谢),也从中加入了一些自己的想法(相对来说较少),子弹碰撞后消失,添加音效,随机生成地形等;话不多说,直接上思维导图(比较粗略)

目录

​编辑

窗口初始化

准备工作

窗口初始化

游戏父类的编写

方向类

 游戏父类

添加坦克类

Tank

四个方向的移动——玩家(键盘监听)、人机(随机移动)

射击——玩家(键盘监听)、人机(随机移动)

总 

 Player

 键盘监听器

 总

 人机

初始化子弹类

玩家子弹

 子弹射击 

碰撞检测

 总

 人机子弹

 击中玩家

 总

添加围墙、基地

Base

Wall

Grass

Fe

优化

爆炸

音乐

重写GamePanel

 游戏最终成品


窗口初始化

准备工作

首先创建一个TankWar项目,在scr相同路径下创建images、music文件夹,将需要使用的图片、音乐分别放在images、music中。创建一个com.tankwar(包),注意命名规范

窗口初始化

在com.tankwar中创建GamePanel类

import javax.swing.JFrame;
public class GamePanel extends JFrame{
	//窗口大小
	private int width=1260;
	private int height=800;
	//窗口初始化
	public void launch() {
		//标题
		setTitle("坦克大战");
		//初始化窗口大小
		setSize(width,height);
		//使屏幕居中
		setLocationRelativeTo(null);
		//添加关闭事件
		setDefaultCloseOperation(3);
		//用户不能调整
		setResizable(false);
		//使窗口可见
		setVisible(true);
		
	}
	
	public static void main(String[]args) {
		GamePanel gamePanel=new GamePanel();
		gamePanel.launch();
	}
}

 运行结果java实现坦克大战_第1张图片

 导入窗口图片与屏幕刷新

程序在运行时屏幕的每,对象的位置以及图像的每一次改变都需要屏幕的一次刷新,而屏幕的每一次刷新都需要重新绘制屏幕,所以会出现闪屏现象。如果想要解决这种问题,需要运用双缓存技术

java 双缓冲技术解决屏幕闪烁问题_穆梓先生的博客-CSDN博客


import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;

import javax.swing.JFrame;
public class GamePanel extends JFrame{
	//窗口大小
	private int width=1260;
	private int height=800;
	
	
	//定义双缓存图片
	Image offScreenImage=null;
	//临时变量
	private int a=1;
	//游戏状态 0 未开始,1 开始,2 暂停,3 失败,4 胜利
	private int state=0;
	//游戏是否开始
	private boolean start=false;
	
	//窗口初始化
	public void launch() {
		//标题
		setTitle("坦克大战");
		//初始化窗口大小
		setSize(width,height);
		//使屏幕居中
		setLocationRelativeTo(null);
		//添加关闭事件
		setDefaultCloseOperation(3);
		//用户不能调整
		setResizable(false);
		//使窗口可见
		setVisible(true);
		
		/*
		 * 控制屏幕刷新时间
		 */
		while(true) {
			repaint();
			try {
				Thread.sleep(25);//刷新休眠时间
			} catch (Exception e) {
				e.printStackTrace();
				// TODO: handle exception
			}
		}
		
	}
	
	public void paint(Graphics g) {
		//创建和容器一样大小的image
		if(offScreenImage==null) {
			offScreenImage=this.createImage(width,height);
		}
		//获得该图片的画布
		Graphics gImage=offScreenImage.getGraphics();
		//填充整个画布
		gImage.fillRect(0,0,width,height);
		if(state==0) {//游戏未开始
			gImage.drawImage(Toolkit.getDefaultToolkit().getImage("images/interface.png"),0,0,this);
		}else if(state==1) {//游戏开始
			
		}else if(state==2) {//游戏暂停
			
		}else if(state==3) {//游戏失败
			
		}else if(state==4) {//游戏胜利
			
		}
		g.drawImage(offScreenImage,0,0,null);
	}
	
	public static void main(String[]args) {
		GamePanel gamePanel=new GamePanel();
		gamePanel.launch();
	}
}

 程序运行结果

java实现坦克大战_第2张图片

 添加鼠标监听器

在游戏中点击“PLAYER”方可进入游戏,需要加入鼠标监听器

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
public class GamePanel extends JFrame{
	//窗口大小
	private int width=1260;
	private int height=800;
	
	
	//定义双缓存图片
	Image offScreenImage=null;
	//临时变量
	private int a=1;
	//游戏状态 0 未开始,1 开始,2 暂停,3 失败,4 胜利
	private int state=0;
	//游戏是否开始
	private boolean start=false;
	
	//窗口初始化
	public void launch() {
		//标题
		setTitle("坦克大战");
		//初始化窗口大小
		setSize(width,height);
		//使屏幕居中
		setLocationRelativeTo(null);
		//添加关闭事件
		setDefaultCloseOperation(3);
		//用户不能调整
		setResizable(false);
		//使窗口可见
		setVisible(true);
		
		/*
		 * 控制屏幕刷新时间
		 */
		while(true) {
			repaint();
			try {
				Thread.sleep(25);
			} catch (Exception e) {
				e.printStackTrace();
				// TODO: handle exception
			}
		}
		
	}
	
	public void paint(Graphics g) {
		//创建和容器一样大小的image
		if(offScreenImage==null) {
			offScreenImage=this.createImage(width,height);
		}
		//获得该图片的画布
		Graphics gImage=offScreenImage.getGraphics();
		//填充整个画布
		gImage.fillRect(0,0,width,height);
		if(state==0) {//游戏未开始
			gImage.drawImage(Toolkit.getDefaultToolkit().getImage("images/interface.png"),0,0,this);
			//添加鼠标事件
			this.addMouseListener(new GamePanel.MouseMonitor());
		}else if(state==1) {//游戏开始
			
		}else if(state==2) {//游戏暂停
			
		}else if(state==3) {//游戏失败
			
		}else if(state==4) {//游戏胜利
			
		}
		g.drawImage(offScreenImage,0,0,null);
	}
	
	/*
	 * 添加鼠标监听
	 */
	private class MouseMonitor extends MouseAdapter{
		@Override
		public void mouseClicked(MouseEvent e) {
			Point p=new Point(e.getX(),e.getY());
			if(!start&&state==0) {
				if(p.x>450&&p.x<750&&p.y>400&&p.y<480) {//“PLAYER  X,Y坐标范围”
					state=1;
					start=true;
				}
			}else if(state==3||state==4) {
				
			}
		}
	}
	
	public static void main(String[]args) {
		GamePanel gamePanel=new GamePanel();
		gamePanel.launch();
	}
}

游戏父类的编写

方向类

游戏中坦克需要运用到“方向”,可以单独创建一个枚举类,或者在坦克类中定义“方向”成员变量。

/*
 * 首先枚举是一个特殊的class
 * 这个class相当于final static 修饰,不能被继承
 * 他的构造方法强制被私有化
 * 所有的枚举都继承自java.lang.Enum类。由于java不支持多继承,所以枚举对象不能再继承其他类
 */
public enum Direction {
	//每个成员变量都是final static 修饰
	UP,LEFT,RIGHT,DOWN
}

 游戏父类

游戏中的坦克、子弹、基地、墙体、爆炸图片等元素,在绘画到面板上的过程中,需要运用到坐标,大小、移动速度、主界面画板。将其抽取出来,创建游戏父类

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;

public abstract class GameObject {
	//游戏元素图片
	Image img;
	//游戏元素的横纵坐标
	int x;
	int y;
	//游戏元素的宽,高
	int width;
	int height;
	//游戏元素的移动速度
	int speed;
	//游戏元素的移动方向
	Direction direction;
	//引入主界面
	GamePanel gamePanel;
	
	public GameObject() {
		
	}
	public GameObject(String img,int x,int y,GamePanel gamePanel) {
		this.img=Toolkit.getDefaultToolkit().getImage(img);
		this.x=x;
		this.y=y;
		this.gamePanel=gamePanel;
	}
	
	public Image getImag() {
		return img;
	}
	public void setImg(String img) {
		this.img=Toolkit.getDefaultToolkit().getImage(img);
	}
	
	
	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 getWidth() {
        return width;
    }
    public void setWidth(int width) {
        this.width = width;
    }

    
    public int getHeight() {
        return height;
    }
    public void setHeight(int height) {
        this.height = height;
    }

    
    public double getSpeed() {
        return speed;
    }
    public void setSpeed(int speed) {
        this.speed = speed;
    }
    
    
    public Direction getDirection() {
        return direction;
    }
    public void setDirection(Direction direction) {
        this.direction = direction;
    }

    
    public GamePanel getGamePanel() {
        return gamePanel;
    }
    public void setGamePanel(GamePanel gamepanel) {
        this.gamePanel = gamePanel;
    }

    //继承元素绘制自己的方法
    public abstract void paintSelf(Graphics g);

    //获取当前游戏元素的矩形,是为碰撞检测而写
    public abstract Rectangle getRec();
}

添加坦克类

Tank

注:蓝色字体的写在子类中

坦克具有哪些特有属性?

四个方向移动的图片

    //向上移动时的图片
	private String upImage;
	//向下移动时的图片
	private String downImage;
	//向右移动时的图片
	private String rightImage;
	//向左移动时的图片
	private String leftImage;

四个方向的移动——玩家(键盘监听)、人机(随机移动

1、墙体碰撞检测

2、边界碰撞检测

3、人机碰撞检测

4、移动


1、墙体碰撞检测

/*
	 * 坦克与墙碰撞检测
	 */
	public boolean hitWall(int x,int y) {
		//假设玩家坦克前进,下一个位置形成的矩形
		Rectangle next=new Rectangle(x,y,width,height);
		//地图里所有的墙体
		Listwalls=this.gamePanel.wallList;
		Listfes=this.gamePanel.feList;
		//判断两个矩形是否相交
		for(Wall w:walls) {
			if(w.getRec().intersects(next)) {
				return true;
			}
		}
		for(Fe f:fes) {
			if(f.getRec().intersects(next)) {
				return true;
			}
		}
		return false;
	}

2、边界碰撞检测

/*
	 * 边界与坦克碰撞检测
	 */
	public boolean moveToBorder(int x,int y) {
		if(x<10) {
			return true;
		}else if(x>this.gamePanel.getWidth()-width) {
			return true;
		}
		if(y<30) {
			return true;
		}else if(y>this.gamePanel.getHeight()-height) {
			return true;
		}
		return false;
	}

 3、人机碰撞检测

/*
	 * 人机碰撞检测
	 */
	public boolean hitTank(int x,int y) {
		int a=0;
		//假设人机坦克前进,下一个位置形成的矩形
		Rectangle next=new Rectangle(x,y,width,height);
		//地图里所有的人机
		Listbots=this.gamePanel.botList;
		//判断两个矩形是否相交
		for(Bot b:bots) {
			if(b.getRec().intersects(next)) {
				a++;
				if(a==2) {
					return true;
				}
			}
		}
		return false;
	}

 4、移动

     /*
	 * 坦克移动
	 */
	public void leftWard() {
		direction=Direction.LEFT;
		setImg(leftImage);
		if(!hitWall(x-speed,y)&&!moveToBorder(x-speed,y)&&alive&&!hitTank(x-speed,y)) {
			this.x-=speed;
		}
	}
	
	public void rightWard() {
		direction=Direction.RIGHT;
		setImg(rightImage);
		if(!hitWall(x+speed,y)&&!moveToBorder(x+speed,y)&&alive&&!hitTank(x+speed,y)) {
			this.x+=speed;
		}
	}
	public void upWard() {
		direction=Direction.UP;
		setImg(upImage);
		if(!hitWall(x,y-speed)&&!moveToBorder(x,y-speed)&&alive&&!hitTank(x,y-speed)) {
			this.y-=speed;
		}
	}
	public void downWard() {
		direction=Direction.DOWN;
		setImg(downImage);
		if(!hitWall(x,y+speed)&&!moveToBorder(x,y+speed)&&alive&&!hitTank(x-speed,y+speed)) {
			this.y+=speed;
		}
	}

射击——玩家(键盘监听)、人机(随机移动)

1、子弹射击方向应与坦克移动方向一致

2、射击子弹CD

3、射击


 1、子弹射击方向应与坦克移动方向一致

坦克坐标点为坦克图片左上角,所以子弹初始坐标应该为坦克的坐标加上坦克高度或宽度的一半。

/*
	 * 根据方向确定头部位置,x和y是左上角的点
	 */
	public Point getHeadPoint() {
		switch(direction) {
		case UP:
			return new Point(x+width/2,y);
		case LEFT:
			return new Point(x,y+height/2);
		case DOWN:
			return new Point(x+width/2,y+height);
		case RIGHT:
			return new Point(x+width,y+height/2);
			default:
				return null;
		}
	}

 2、射击子弹CD

/*
	 * 坦克射击cd
	 */
	public class AttackCD extends Thread{
		public void run() {
			attackCoolDown=false;
			try {
				//休眠1秒
				Thread.sleep(attackCoolDownTime);//attackCoolDownTime为定义的成员变量单位为ms
			}catch (InterruptedException e) {
				e.printStackTrace();
			}
			//将攻击功能解除冷却状态
			attackCoolDown=true;
			this.stop();//不是很理解
		}
	}

 3、射击

/*
	 * 射击
	 */
	public void attack() {
		Point p=getHeadPoint();
		if(attackCoolDown&&alive) {
			Bullet bullet=new Bullet("images/bullet/bulletGreen.gif",p.x-10,p.y-10, direction, this.gamePanel);
			this.gamePanel.bulletList.add(bullet);//将子弹添加至子弹集合
			attackCoolDown=false;
			new AttackCD().start();
		}
	}

总 

这里由于还未创建其他类所以会报错,在后续会添加上的(博主偷个懒直接把源码粘贴过来了)

import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.List;

public class Tank extends GameObject{
	
	//向上移动时的图片
	private String upImage;
	//向下移动时的图片
	private String downImage;
	//向右移动时的图片
	private String rightImage;
	//向左移动时的图片
	private String leftImage;
	
	//坦克size
	int width=54;
	int height=54;
	
	//坦克初始方向
	Direction direction=Direction.UP;
	//坦克速度
	private int speed=3;
	//攻击冷却
	private boolean attackCoolDown=true;
	//攻击冷却事件毫秒间隔1000ms发射子弹
	private int attackCoolDownTime=100;
	//坦克是否活着
	public boolean alive=true;
	/*
	 * 坦克坐标,方向,图片,方向,面板
	 */
	public Tank(String img,int x,int y,String upImage,String downImage,String leftImage,String rightImage,GamePanel gamePanel) {
		super(img,x,y,gamePanel);
		this.upImage=upImage;
		this.leftImage=leftImage;
		this.downImage=downImage;
		this.rightImage=rightImage;	
	}
	
	/*
	 * 坦克移动
	 */
	public void leftWard() {
		direction=Direction.LEFT;
		setImg(leftImage);
		if(!hitWall(x-speed,y)&&!moveToBorder(x-speed,y)&&alive&&!hitTank(x-speed,y)) {
			this.x-=speed;
		}
	}
	
	public void rightWard() {
		direction=Direction.RIGHT;
		setImg(rightImage);
		if(!hitWall(x+speed,y)&&!moveToBorder(x+speed,y)&&alive&&!hitTank(x+speed,y)) {
			this.x+=speed;
		}
	}
	public void upWard() {
		direction=Direction.UP;
		setImg(upImage);
		if(!hitWall(x,y-speed)&&!moveToBorder(x,y-speed)&&alive&&!hitTank(x,y-speed)) {
			this.y-=speed;
		}
	}
	public void downWard() {
		direction=Direction.DOWN;
		setImg(downImage);
		if(!hitWall(x,y+speed)&&!moveToBorder(x,y+speed)&&alive&&!hitTank(x-speed,y+speed)) {
			this.y+=speed;
		}
	}
	
	/*
	 * 射击
	 */
	public void attack() {
		Point p=getHeadPoint();
		if(attackCoolDown&&alive) {
			Bullet bullet=new Bullet("images/bullet/bulletGreen.gif",p.x-10,p.y-10, direction, this.gamePanel);
			this.gamePanel.bulletList.add(bullet);//将子弹添加至子弹集合
			attackCoolDown=false;
			new AttackCD().start();
		}
	}
	
	/*
	 * 坦克射击cd
	 */
	public class AttackCD extends Thread{
		public void run() {
			attackCoolDown=false;
			try {
				//休眠1秒
				Thread.sleep(attackCoolDownTime);
			}catch (InterruptedException e) {
				e.printStackTrace();
			}
			//将攻击功能解除冷却状态
			attackCoolDown=true;
			this.stop();//不是很理解
		}
	}
	/*
	 * 根据方向确定头部位置,x和y是左上角的点
	 */
	public Point getHeadPoint() {
		switch(direction) {
		case UP:
			return new Point(x+width/2,y);
		case LEFT:
			return new Point(x,y+height/2);
		case DOWN:
			return new Point(x+width/2,y+height);
		case RIGHT:
			return new Point(x+width,y+height/2);
			default:
				return null;
		}
	}
	/*
	 * 坦克与墙碰撞检测
	 */
	public boolean hitWall(int x,int y) {
		//假设玩家坦克前进,下一个位置形成的矩形
		Rectangle next=new Rectangle(x,y,width,height);
		//地图里所有的墙体
		Listwalls=this.gamePanel.wallList;
		Listfes=this.gamePanel.feList;
		//判断两个矩形是否相交
		for(Wall w:walls) {
			if(w.getRec().intersects(next)) {
				return true;
			}
		}
		for(Fe f:fes) {
			if(f.getRec().intersects(next)) {
				return true;
			}
		}
		return false;
	}
	/*
	 * 人机碰撞检测
	 */
	public boolean hitTank(int x,int y) {
		int a=0;
		//假设人机坦克前进,下一个位置形成的矩形
		Rectangle next=new Rectangle(x,y,width,height);
		//地图里所有的人机
		Listbots=this.gamePanel.botList;
		//判断两个矩形是否相交
		for(Bot b:bots) {
			if(b.getRec().intersects(next)) {
				a++;
				if(a==2) {
					return true;
				}
			}
		}
		return false;
	}
	/*
	 * 边界与坦克碰撞检测
	 */
	public boolean moveToBorder(int x,int y) {
		if(x<10) {
			return true;
		}else if(x>this.gamePanel.getWidth()-width) {
			return true;
		}
		if(y<30) {
			return true;
		}else if(y>this.gamePanel.getHeight()-height) {
			return true;
		}
		return false;
	}
	@Override
	public Rectangle getRec(){
		return new Rectangle(x,y,width,height);
	}

	@Override
	public void paintSelf(Graphics g) {
		g.drawImage(img, x, y, null);
	}
}

 Player

玩家类继承坦克类,在父类的基础上只需要添加键盘监听器即可


 键盘监听器

/*
	 * 按下键盘时坦克持续运动
	 */
	public void keyPressed(KeyEvent e) {
		int key=e.getKeyCode();
		switch(key) {
		case KeyEvent.VK_A:
			left=true;
			Music.playBackground();
			break;
		case KeyEvent.VK_D:
			right=true;
			Music.playBackground();
			break;
		case KeyEvent.VK_W:
			up=true;
			Music.playBackground();
			break;
		case KeyEvent.VK_S:
			down=true;
			Music.playBackground();
			break;
		 case KeyEvent.VK_SPACE:
			 Music.attackPlay();
 			this.attack();
 			break;
			default:
				
				break;
		}		
	}
	/*
	 * 松开键盘时,坦克停止运动
	 */
	public void keyReleased(KeyEvent e) {
		 int key = e.getKeyCode();
	        switch (key){
	            case KeyEvent.VK_A:
	                left = false;
	                Music.moveStop();
	                break;
	            case KeyEvent.VK_S:
	                down = false;
	                Music.moveStop();
	                break;
	            case KeyEvent.VK_D:
	                right = false;
	                Music.moveStop();
	                break;
	            case KeyEvent.VK_W:
	                up = false;
	                Music.moveStop();
	                break;
	            default:
	                break;
	        }		
	}

 总

import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;

public class PlayerOne extends Tank{
	
	private boolean up=false;
	private boolean down=false;
	private boolean left=false;
	private boolean right=false;

	public PlayerOne(String img, int x, int y, String upImage, String downImage, String leftImage, String rightImage,
			GamePanel gamePanel) {
		super(img, x, y, upImage, downImage, leftImage, rightImage, gamePanel);
		// TODO Auto-generated constructor stub
	}
	
	/*
	 * 按下键盘时坦克持续运动
	 */
	public void keyPressed(KeyEvent e) {
		int key=e.getKeyCode();
		switch(key) {
		case KeyEvent.VK_A:
			left=true;
			Music.playBackground();
			break;
		case KeyEvent.VK_D:
			right=true;
			Music.playBackground();
			break;
		case KeyEvent.VK_W:
			up=true;
			Music.playBackground();
			break;
		case KeyEvent.VK_S:
			down=true;
			Music.playBackground();
			break;
		 case KeyEvent.VK_SPACE:
			 Music.attackPlay();
 			this.attack();
 			break;
			default:
				
				break;
		}		
	}
	/*
	 * 松开键盘时,坦克停止运动
	 */
	public void keyReleased(KeyEvent e) {
		 int key = e.getKeyCode();
	        switch (key){
	            case KeyEvent.VK_A:
	                left = false;
	                Music.moveStop();
	                break;
	            case KeyEvent.VK_S:
	                down = false;
	                Music.moveStop();
	                break;
	            case KeyEvent.VK_D:
	                right = false;
	                Music.moveStop();
	                break;
	            case KeyEvent.VK_W:
	                up = false;
	                Music.moveStop();
	                break;
	            default:
	                break;
	        }		
	}
	
	/*
	 * 坦克移动
	 */
	public void move() {
		if(left) {
			leftWard();
		}else if(right) {
			rightWard();
		}else if (up) {
			upWard();
		}else if (down) {
			downWard();
		}else {
			return;
		}
	}
	
	@Override
	public void paintSelf(Graphics g) {
		g.drawImage(img,x,y,null);
		move();
	}
	
	public Rectangle getRec() {
		return new Rectangle(x,y,width,height);
	}

}

 人机

人机具有哪些属性呢?

随机、随机、随机还是随机!

1、随机移动 

2、随机射击


1、随机移动 

/*
	 * 人机移动
	 */
	public void go() {
		attack();
		if(moveTime>=20) {
			direction=randomDirection();
			moveTime=0;
		}else{
			moveTime+=1;
		}
		switch(direction) {
		case UP:
			upWard();
			break;
		case DOWN:
			downWard();
			break;
		case RIGHT:
			rightWard();
			break;
		case LEFT:
			leftWard();
			break;
		}
	}
	/*
	 * 人机移动随机方向
	 */
	public Direction randomDirection() {
		Random r=new Random();
		int rnum=r.nextInt(4);
		 switch(rnum) {
         case 0:
             return Direction.UP;
         case 1:
             return Direction.RIGHT;
         case 2:
             return Direction.LEFT;
         default:
             return Direction.DOWN;
         }
	}

2、随机射击

随机射击写在人机子弹类里

import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Random;

public class Bot extends Tank{
	//人机朝一个方向运动时间
	int moveTime=0;

	public Bot(String img, int x, int y, String upImage, String downImage, String leftImage, String rightImage,
			GamePanel gamePanel) {
		super(img, x, y, upImage, downImage, leftImage, rightImage, gamePanel);
	}		
	/*
	 * 人机移动
	 */
	public void go() {
		attack();
		if(moveTime>=20) {
			direction=randomDirection();
			moveTime=0;
		}else{
			moveTime+=1;
		}
		switch(direction) {
		case UP:
			upWard();
			break;
		case DOWN:
			downWard();
			break;
		case RIGHT:
			rightWard();
			break;
		case LEFT:
			leftWard();
			break;
		}
	}
	/*
	 * 人机移动随机方向
	 */
	public Direction randomDirection() {
		Random r=new Random();
		int rnum=r.nextInt(4);
		 switch(rnum) {
         case 0:
             return Direction.UP;
         case 1:
             return Direction.RIGHT;
         case 2:
             return Direction.LEFT;
         default:
             return Direction.DOWN;
         }
	}
	
	/*
	 * 随机攻击
	 */
	public void attack() {
		Point p=getHeadPoint();
		Random r=new Random();
		int rnum=r.nextInt(100);
		if(rnum<2) {
			EnemyBullet enemyBullet=new EnemyBullet("images/bullet/bulletYellow.gif",p.x,p.y,direction,gamePanel);
			this.gamePanel.enemyBulletsList.add(enemyBullet);
		}
	}
	
	/*
	 * 绘制人机
	 */
	@Override
	public void paintSelf(Graphics g) {
		g.drawImage(img,x,y,null);
		go();
	}
	@Override
	public Rectangle getRec() {
		return new Rectangle(x,y,width,height);
	}

}

初始化子弹类

玩家子弹

  1. 子弹射击
  2. 子弹碰撞检测

 子弹射击 

  1. 子弹运动方向与坦克一致


/*
	 * 子弹运动方向
	 */
	public void go() {
		switch(direction) {
		case UP:
			upWard();
			break;
		case DOWN:
			downWard();
			break;
		case LEFT:
			leftWard();
			break;
		case RIGHT:
			rightWard();
			break;
		}
	}
/*
	 * 子弹运动坐标改变
	 */
	private void rightWard() {
		// TODO Auto-generated method stub
		x+=speed;
	}

	private void downWard() {
		// TODO Auto-generated method stub
		y+=speed;
	}

	private void leftWard() {
		// TODO Auto-generated method stub
		x-=speed;
	}

	private void upWard() {
		// TODO Auto-generated method stub
		y-=speed;
	}

碰撞检测

  1. 子弹与土墙

  2. 子弹与铁墙

  3. 子弹与基地

  4. 子弹与边界

  5. 子弹与子弹


 1、子弹与土墙

/*
	 * 子弹和土墙碰撞
	 */
	public void hitWall() {
		Rectangle next=this.getRec();
		Listwalls=this.gamePanel.wallList;
		for(Wall w:walls) {
			if(w.getRec().intersects(next)) {
				Music.wallPlay();
				this.gamePanel.wallList.remove(w);
				this.gamePanel.removeList.add(this);
				break;
			}
		}
	}

 2、子弹与铁墙

/*
	 * 子弹与Fe
	 */
	public void hitFe() {
		Rectangle next=this.getRec();
		Listfes=this.gamePanel.feList;
		for(Fe f:fes) {
			if(f.getRec().intersects(next)) {
				Music.wallPlay();
				this.gamePanel.removeList.add(this);
				break;
			}
		}
	}

 3、子弹与基地

/*
	 * 击中基地
	 */
	public void hitBase() {
		Rectangle next=this.getRec();
		for(Base base:gamePanel.baseList) {
			if(base.getRec().intersects(next)) {
				this.gamePanel.baseList.remove(base);
				this.gamePanel.removeList.add(this);
				this.gamePanel.state=3;
				break;
			}
		}
	}

 4、子弹与边界

/*
	 * 移动到边界
	 */
	public void moveToBorder() {
		if(x<0||x>this.gamePanel.getWidth()) {
			this.gamePanel.removeList.add(this);
		}
		if(y<0||y>this.gamePanel.getHeight()) {
			this.gamePanel.removeList.add(this);
		}
	}

 5、子弹与子弹

/*
	 * 子弹与子弹碰撞检测
	 */
	public void hitEnemyBullet() {
		Rectangle next=this.getRec();
		ListenemyBullets=this.gamePanel.enemyBulletsList;
		for(EnemyBullet enemyBullet:enemyBullets) {
			if(enemyBullet.getRec().intersects(next)) {
				Music.wallPlay();
				this.gamePanel.removeList2.add(enemyBullet);
				this.gamePanel.removeList.add(this);
				break;
			}
		}
	}

 总

import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.List;

public class Bullet extends GameObject{
	//长宽
	private int width=10;
	private int height=10;
	//速度
	private int speed=7;
	//方向
	Direction direction;
	//初始化子弹
	public Bullet(String img,int x,int y,Direction direction,GamePanel gamePanel) {
		super(img,x,y,gamePanel);
		this.direction=direction;			
	}

	/*
	 * 子弹运动方向
	 */
	public void go() {
		switch(direction) {
		case UP:
			upWard();
			break;
		case DOWN:
			downWard();
			break;
		case LEFT:
			leftWard();
			break;
		case RIGHT:
			rightWard();
			break;
		}
	}
    /*
	 * 子弹运动坐标改变
	 */
	private void rightWard() {
		// TODO Auto-generated method stub
		x+=speed;
	}

	private void downWard() {
		// TODO Auto-generated method stub
		y+=speed;
	}

	private void leftWard() {
		// TODO Auto-generated method stub
		x-=speed;
	}

	private void upWard() {
		// TODO Auto-generated method stub
		y-=speed;
	}
	
	/*
	 * 子弹与坦克碰撞检测
	 */
	public void hitBot() {
		//矩形类
		Rectangle next=this.getRec();
		Listbots=this.gamePanel.botList;
		//子弹和人机
		for(Bot bot:bots) {
			if(bot.getRec().intersects(next)) {
				Explode[]arr=new Explode[7];
				for(int i=0;i<7;i++) {
					Explode explode=new Explode("images/explode/"+(i+1)+".gif", x, y, this.gamePanel);
					this.gamePanel.explodeList.add(explode);
				}
				Music.explodePlay();
				this.gamePanel.botList.remove(bot);
				this.gamePanel.removeList.add(this);
				break;
			}
		}
	}
	
	/*
	 * 子弹与子弹碰撞检测
	 */
	public void hitEnemyBullet() {
		Rectangle next=this.getRec();
		ListenemyBullets=this.gamePanel.enemyBulletsList;
		for(EnemyBullet enemyBullet:enemyBullets) {
			if(enemyBullet.getRec().intersects(next)) {
				Music.wallPlay();
				this.gamePanel.removeList2.add(enemyBullet);
				this.gamePanel.removeList.add(this);
				break;
			}
		}
	}
	
	/*
	 * 子弹和土墙碰撞
	 */
	public void hitWall() {
		Rectangle next=this.getRec();
		Listwalls=this.gamePanel.wallList;
		for(Wall w:walls) {
			if(w.getRec().intersects(next)) {
				Music.wallPlay();
				this.gamePanel.wallList.remove(w);
				this.gamePanel.removeList.add(this);
				break;
			}
		}
	}
	
	/*
	 * 子弹与Fe
	 */
	public void hitFe() {
		Rectangle next=this.getRec();
		Listfes=this.gamePanel.feList;
		for(Fe f:fes) {
			if(f.getRec().intersects(next)) {
				Music.wallPlay();
				this.gamePanel.removeList.add(this);
				break;
			}
		}
	}
	
	/*
	 * 移动到边界
	 */
	public void moveToBorder() {
		if(x<0||x>this.gamePanel.getWidth()) {
			this.gamePanel.removeList.add(this);
		}
		if(y<0||y>this.gamePanel.getHeight()) {
			this.gamePanel.removeList.add(this);
		}
	}
	
	/*
	 * 击中基地
	 */
	public void hitBase() {
		Rectangle next=this.getRec();
		for(Base base:gamePanel.baseList) {
			if(base.getRec().intersects(next)) {
				this.gamePanel.baseList.remove(base);
				this.gamePanel.removeList.add(this);
				this.gamePanel.state=3;
				break;
			}
		}
	}


	@Override
	public void paintSelf(Graphics g) {
		// TODO Auto-generated method stub
		g.drawImage(img,x,y,null);
		go();
		//碰撞检测
		hitBot();
		hitWall();
		hitBase();
		hitFe();
		hitEnemyBullet();
	}

	@Override
	public Rectangle getRec() {
		return new Rectangle(x,y,width,height);
	}
	

}

 人机子弹

人机与玩家的子弹有什么差别呢? 

  1. 可以击中玩家,不能击中坦克 

 击中玩家

/*
	 * 击中玩家
	 */
	public void hitPlayer() {
		Rectangle next=this.getRec();
		Listtanks=this.gamePanel.tankList;
		//子弹和坦克
		for(Tank tank:tanks) {
			if(tank.getRec().intersects(next)) {
				tank.alive=false;
				this.gamePanel.tankList.remove(tank);
				this.gamePanel.removeList.add(this);
				break;
			}
		}
	}

 总

import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.List;
/*
 * 人机子弹
 */
public class EnemyBullet extends Bullet{
	public EnemyBullet(String img, int x, int y, Direction direction, GamePanel gamePanel) {
		super(img, x, y, direction, gamePanel);
	}
	
	public void hitPlayer() {//攻击到玩家,玩家死亡
		Rectangle next=this.getRec();
		Listtanks=this.gamePanel.tankList;
		//子弹和坦克
		for(Tank tank:tanks) {
			if(tank.getRec().intersects(next)) {
				tank.alive=false;
				this.gamePanel.tankList.remove(tank);
				this.gamePanel.removeList.add(this);
				break;
			}
		}
	}
	@Override
	public void hitBase() {//攻击到基地,游戏结束
		Rectangle next=this.getRec();
		for(Base base:gamePanel.baseList) {
			if(base.getRec().intersects(next)) {
				this.gamePanel.baseList.remove(base);
				this.gamePanel.removeList2.add(this);
				this.gamePanel.state=3;
				break;
			}
		}
	}
	public void hitWall() {//攻击到土墙,子弹与土均消失
		Rectangle next=this.getRec();
		Listwalls=this.gamePanel.wallList;
		for(Wall w:walls) {
			if(w.getRec().intersects(next)) {
				this.gamePanel.wallList.remove(w);
				this.gamePanel.removeList2.add(this);
				break;
			}
		}
	}
	public void hitFe() {//攻击到铁墙,墙不变,子弹消失
		Rectangle next=this.getRec();
		Listfes=this.gamePanel.feList;
		for(Fe f:fes) {
			if(f.getRec().intersects(next)) {
				this.gamePanel.removeList2.add(this);
				break;
			}
		}
	}
	public void paintSelf(Graphics g) {
		g.drawImage(img,x,y,null);
		go();
		hitBase();
		hitWall();
		hitFe();
		hitPlayer();
	}
}

添加围墙、基地

剩下的就是间的添加围墙、基地等对象了。

Base

import java.awt.Graphics;
import java.awt.Rectangle;

public class Base extends GameObject{
	public int width=60;
	public int height=60;
	
	public Base(String img,int x,int y,GamePanel gamePanel) {
		super(img,x,y,gamePanel);
	}

	@Override
	public void paintSelf(Graphics g) {
		g.drawImage(img,x,y,null);
		// TODO Auto-generated method stub
		
	}

	@Override
	public Rectangle getRec() {
		return new Rectangle(x,y,width,height);
	}
}

Wall

import java.awt.Graphics;
import java.awt.Rectangle;

public class Wall extends GameObject{
	private int width=60;
	private int height=60;
	public Wall(String img,int x,int y,GamePanel gamePanel) {
		super(img,x,y,gamePanel);
	}
	@Override
	public void paintSelf(Graphics g) {
		g.drawImage(img,x,y,null);
		
	}
	@Override
	public Rectangle getRec() {		
		return new Rectangle(x,y,width,height);
	}
}

Grass

import java.awt.Graphics;
import java.awt.Rectangle;

public class Grass extends GameObject{
	public Grass(String img,int x,int y,GamePanel gamePanel) {
		super(img,x,y,gamePanel);
	}

	@Override
	public void paintSelf(Graphics g) {
		g.drawImage(img,x,y,null);
	}

	@Override
	public Rectangle getRec() {
		return null;
	}

}

Fe

import java.awt.Graphics;
import java.awt.Rectangle;

public class Fe extends GameObject{
	private int width=60;
	private int height=60;
	public Fe(String img,int x,int y,GamePanel gamePanel) {
		super(img,x,y,gamePanel);
	}

	@Override
	public void paintSelf(Graphics g) {
		g.drawImage(img,x,y,null);
	}

	@Override
	public Rectangle getRec() {
		return new Rectangle(x,y,width,height);
	}
	

}

优化

爆炸

import java.awt.Graphics;
import java.awt.Rectangle;

public class Explode extends GameObject{
	
	public Explode(String img,int x,int y,GamePanel gamePanel) {
		super(img,x,y,gamePanel);
	}
	@Override
	public void paintSelf(Graphics g) {
		g.drawImage(img,x-25,y-30,null);//x,y为图片左上角的坐标,调整图片位置,使图片居中
	}

	@Override
	public Rectangle getRec() {
		// TODO Auto-generated method stub
		return null;
	}
}

音乐

import java.io.File;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;


public class Music{
       private static Clip start;//刚进入游戏的音乐
       private static Clip move;//玩家移动音乐
       private static Clip attack;//玩家射击音乐
       private static Clip explode;//爆炸音效
       private static Clip wall;//击中墙体音效
       static {
           File bgMusicStartFile = new File("D:\\JAVA\\eclipse\\TankWar\\musics\\bgm.wav");
           File bgMusicAttackFile = new File("D:\\JAVA\\eclipse\\TankWar\\musics\\attack.wav");
           File bgMusicMoveFile = new File("D:\\JAVA\\eclipse\\TankWar\\musics\\move.wav");
           File bgMusicExplodeFile = new File("D:\\JAVA\\eclipse\\TankWar\\musics\\explode.wav");
           File bgMusicWallFile = new File("D:\\JAVA\\eclipse\\TankWar\\musics\\wall.wav");
           try {
               AudioInputStream audioInputStreamStart = AudioSystem.getAudioInputStream(bgMusicStartFile);
               start = AudioSystem.getClip();
               start.open(audioInputStreamStart);
               AudioInputStream audioInputStreamAttack = AudioSystem.getAudioInputStream(bgMusicAttackFile);
               attack = AudioSystem.getClip();
               attack.open(audioInputStreamAttack);
               AudioInputStream audioInputStreamStartMove = AudioSystem.getAudioInputStream(bgMusicMoveFile);
               move = AudioSystem.getClip();
               move.open(audioInputStreamStartMove);
               AudioInputStream audioInputStreamStartExplode = AudioSystem.getAudioInputStream(bgMusicExplodeFile);
               explode = AudioSystem.getClip();
               explode.open(audioInputStreamStartExplode); 
               AudioInputStream audioInputStreamStartWall = AudioSystem.getAudioInputStream(bgMusicWallFile);
               wall = AudioSystem.getClip();
               wall.open(audioInputStreamStartWall); 
           } catch (Exception e) {
               e.printStackTrace();
           }
     }
     public static void playBackground(){
           //循环播放
           move.setFramePosition(0);
           move.loop(Clip.LOOP_CONTINUOUSLY);       
       }
     public static void startPlay(){
       start.start();
       start.setFramePosition(0);
     }
     public static void attackPlay(){
	       attack.start();
	       //将进度条调为0
	       attack.setFramePosition(0);
     }
     public static void movePlay(){
	       move.start();
	       move.setFramePosition(0);
     }
     public static void moveStop(){
	       move.stop();
     }
     public static void explodePlay(){
	       explode.start();
	       explode.setFramePosition(0);
     }
     public static void wallPlay() {
    	 wall.start();
    	 wall.setFramePosition(0);
     }
}

重写GamePanel

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.JFrame;

public class GamePanel extends JFrame{
	boolean one=true;
	boolean run=true;
	//关卡
	private int level=1;
	//定义双缓存图片
	Image offScreenImage=null;
	/*
	 * //游戏状态
	 * 0 未开始,1 单人模式,
	 * 2 游戏暂停,3 游戏失败,4 游戏胜利
	 */
	public int state =0;
	//游戏是否开始
	private boolean start=false;
	//临时变量
	private int a=1;
	//窗口长宽
	private int width=1260;
	private int height=800;
	//指针初始纵坐标
	private int y=260;
	//基地
	private Base base=new Base("images/base.gif",660,740,this);
	//重绘次数
	public int count=0;
	//敌人数量
	private int enemyCount=0;
	///随机生成的墙体数量
	private int wallCount=100;
	private boolean d=true;
	private int[]xrr=new int[wallCount];
	private int[]yrr=new int[wallCount];
	//物体集合
	public ListbulletList=new ArrayList<>();
	public ListtankList=new ArrayList<>();
	public ListbotList=new ArrayList<>();
	public ListremoveList=new ArrayList<>();
	public ListwallList=new ArrayList<>();
	public ListgrassList=new ArrayList<>();
	public ListfeList=new ArrayList<>();
	public List baseList = new ArrayList<>();
	public ListenemyBulletsList=new ArrayList<>();
	public ListremoveList2=new ArrayList<>();
	public ListexplodeList=new ArrayList<>();
	//玩家
	 private PlayerOne playerOne = new PlayerOne("images/player1/p1tankU.gif", 500, 700,
	            "images/player1/p1tankU.gif","images/player1/p1tankD.gif",
	            "images/player1/p1tankL.gif","images/player1/p1tankR.gif", this);
	 public void random() {
		Random r=new Random();	
		for(int i=0;i0) {
				boolean repeat=false;
				for(int j=0;j0) {
						for(Bot b:botList) {
							if(Math.abs(rnum*60-b.getX())<60) {
								a=false;
							}
						}
						if(a) {
							botList.add(new Bot("images/enemy/enemy1U.gif", rnum*60, 60,
			                        "images/enemy/enemy1U.gif","images/enemy/enemy1D.gif",
			                        "images/enemy/enemy1L.gif","images/enemy/enemy1R.gif", this));
							enemyCount++;
						}
					}else {
						botList.add(new Bot("images/enemy/enemy1U.gif", rnum*60, 60,
		                        "images/enemy/enemy1U.gif","images/enemy/enemy1D.gif",
		                        "images/enemy/enemy1L.gif","images/enemy/enemy1R.gif", this));
						enemyCount++;
					}
				}
				if(count%2==1) {
					if(!explodeList.isEmpty()) {
						explodeList.remove(0);
					}
				}
			}
			if(run) {
				repaint();
			}
			try {
				Thread.sleep(25);
			}catch (Exception e) {
				e.printStackTrace();
				// TODO: handle exception
			}
		}
		
	}
	
	@Override
	public void paint(Graphics g) {
		//创建和容器一样大小的Image图片
		if(offScreenImage==null) {
			offScreenImage=this.createImage(width,height);
		}
		//获得该图片的画布
		Graphics gImage=offScreenImage.getGraphics();
		//填充整个画布
		gImage.fillRect(0,0,width,height);
		if(state==0) {
			//添加图片
			gImage.drawImage(Toolkit.getDefaultToolkit().getImage("images/interface.png"),0,0,this);
			//添加鼠标事件
			this.addMouseListener(new GamePanel.MouseMonitor());
		}else if(state==1) {
			//paint重绘游戏元素
			for(Tank player:tankList) {
				player.paintSelf(gImage);
			}
			for(Bullet bullet:bulletList) {
				bullet.paintSelf(gImage);
			}
			bulletList.removeAll(removeList);
			for(EnemyBullet enemyBullet:enemyBulletsList) {
				enemyBullet.paintSelf(gImage);
			}
			enemyBulletsList.removeAll(removeList2);
			for(Explode explode:explodeList) {
				explode.paintSelf(gImage);
			}
			for(Bot bot:botList) {
				bot.paintSelf(gImage);
			}
			for(Wall wall:wallList) {
				wall.paintSelf(gImage);
			}
			for(Fe fe:feList) {
				fe.paintSelf(gImage);
			}
			for(Grass grass:grassList) {
				grass.paintSelf(gImage);
			}
			for(Base base:baseList) {
				base.paintSelf(gImage);
			}
			//重绘次数+1
			count++;
		}else if(state==2) {
			
		}else if(state==3) {
			gImage.drawImage(Toolkit.getDefaultToolkit().getImage("images/shibai.png"),315,200,this);
			//添加鼠标事件
			this.addMouseListener(new GamePanel.MouseMonitor());
		}else if(state==4) {
			gImage.drawImage(Toolkit.getDefaultToolkit().getImage("images/win.png"),(width-322)/2,(height-84)/2,this);
			this.addMouseListener(new GamePanel.MouseMonitor());
		}
		//将缓冲区绘制好的图形整个绘制到容器的画布中
		g.drawImage(offScreenImage,0,0,null);
		
	}
	
	/*
	 * 添加键盘监听
	 */
	private class KeyMonitor extends KeyAdapter{
		@Override
		public void keyPressed(KeyEvent e) {
			int key=e.getKeyCode();
			switch(key) {
			case KeyEvent.VK_ENTER:
				if(!start) {
					tankList.add(playerOne);//将坦克添加至坦克集合
					state=a;
					start=true;
				}
				break;
			case KeyEvent.VK_P:
				if(state!=2) {
					a=state;
					state=2;
					run=false;
				}else {
					state=a;
					run=true;
					if(a==0) {
						a=1;
					}
				}
				break;				
				default:
					playerOne.keyPressed(e);
					break;
			}
		}
		@Override
		public void keyReleased(KeyEvent e) {
			playerOne.keyReleased(e);
		}
	}
	
	//添加鼠标监听
	private class MouseMonitor extends MouseAdapter{
		@Override
	    public void mouseClicked(MouseEvent e) {
			Point p=new Point(e.getX(),e.getY());
			if(!start&&state==0) {
				if(p.x>450&&p.x<750&&p.y>400&&p.y<480) {
					tankList.add(playerOne);
					state=1;
					start=true;
					Music.startPlay();
				}
			}else if(state==3||state==4) {
				reset();
				start=false;
				state=0;
				add();
			}
		}
	}	
	public static void main(String[]args) {
		GamePanel gamePanel=new GamePanel();
		gamePanel.launch();
	}
}

 游戏最终成品

java实现坦克大战_第3张图片

 java实现坦克大战_第4张图片

 java实现坦克大战_第5张图片

 java实现坦克大战_第6张图片

你可能感兴趣的:(java,开发语言)