源码: 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 双缓冲技术解决屏幕闪烁问题_穆梓先生的博客-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();
}
}
程序运行结果
添加鼠标监听器
在游戏中点击“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();
}
注:蓝色字体的写在子类中
坦克具有哪些特有属性?
四个方向移动的图片
//向上移动时的图片
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);
}
}
玩家类继承坦克类,在父类的基础上只需要添加键盘监听器即可
/*
* 按下键盘时坦克持续运动
*/
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);
}
}
/*
* 子弹运动方向
*/
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、子弹与土墙
/*
* 子弹和土墙碰撞
*/
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);
}
}
人机与玩家的子弹有什么差别呢?
/*
* 击中玩家
*/
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();
}
}
剩下的就是间的添加围墙、基地等对象了。
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);
}
}
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);
}
}
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;
}
}
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);
}
}
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();
}
}