2019-01-16

坦克大战游戏背景:

1. 需求分析

1.1环境要求

操作系统:Windows 7(SP1)以上

JAVA虚拟机:JDK1.8以上

开发环境:Eclipse(4.5以上)

1.2角色设定

用户在系统中扮演的角色,以及可以执行的职责。

玩 家 操纵玩家坦克,与敌方坦克作战,同时保护本基地。敌方坦克随机移动,发射子弹。

1.3设定玩家(玩家一,玩家二,即一个人玩还是两个人玩),我方坦克的方向和子弹由用户控制,所有墙块都可以打碎,但是铁墙是打不碎的,草地不能阻止坦克和子弹的前进,河流能阻止坦克前进,但是不能阻止子弹前进。我方基地被毁则游戏结束,自己的坦克被毁游戏也结束,唯一赢得方式是消灭所有的敌方坦克,则可以进入下一关。一关比一关的难度大,通过地图来实现。

一·团队介绍

团队名称:阳光四人组

学号   班级  姓名  简介
 201721123094  网络1714  何昕桐(组长)  学习能力强,漂亮又可爱
 201721123068  网络1713  梁琦珧  有思想,有能力,有担当
 201721123093  网络1714  李志婷  有专研精神,刻苦,积极向上
 201721123069  网络1713  陈慧琳  低调~

团员任务分配:

成员 任务 博客链接
何昕桐 坦克类 (电脑坦克类,玩家坦克类),代码整合 https://www.cnblogs.com/hexintong99/p/10279072.html 
梁琦珧 枚举,子弹类,工具类 https://www.cnblogs.com/liangqiyao/p/10275786.html 
李志婷 GUI界面(游戏面板,登录面板,主窗体) https://www.cnblogs.com/lizhiting/p/10275909.html 
陈慧琳 基地类,墙块类,爆炸效果类,地图类 https://www.cnblogs.com/chenhuilin/p/10275855.html 

这个坦克游戏几位同志可是很辛苦啦!经过重重考虑,联网功能和游戏排行榜还是未成功实现:

时间太短,能力有限啊!

二·项目git

1.项目git地址

https://gitee.com/mayun126/TankWar.git

2.项目git提交记录截图

三·项目功能架构图与主要功能流程图

1.项目功能架构图

2.功能流程图

3.面向对象类设计图

Wall:

Visible:

乖乖献上了类图:

四·项目运行截图和屏幕录制

演示:

双人游戏和界面地图的设计是我们这个课设的特点:

1.游戏面板:绘制游戏界面,将所有游戏元素展现出来

2.显示关卡面板(第几关开始提示):登录面板和游戏面板的过渡界面,只有一个闪烁的动画效果

3.主窗体:整个面板最外层载体,一个800*600的窗体

4.登录面板:选择游戏模式是单人还是双人

五·项目关键代码

代码太多,主要列出了主要的类以及特色的功能代码,耐心看看,O(∩_∩)O哈哈~

玩家坦克类:

public class Tank extends VisibleImage{
GamePanel gamePanel; //游戏界面,提供当前面板的内容进行判断
Direction direction; //移动方向
protectedbooleanalive=true; //是否存活
protectedintspeed=3; //移动速度
privatebooleanattackCoolDown =true;//攻击冷却状态
privateintattackCoolDownTime =500;//攻击冷却时间毫秒间隔500ms发射子弹
TankType type;//坦克类型
private String upImage; //向上移动时的图片
private String downImage;//向下移动时的图片
private String rightImage;//向右移动时的图片
private String leftImage;//向左移动时的图片 //坦克构造方法初始化横纵坐标xy
//url默认为向上的图片
public Tank(int x,int y,String url,GamePanel gamePanel,TankType type){
super(x,y,url);
this.gamePanel=gamePanle;
this.type=type;
direction= Directon.UP;
switch(type){
case player1://玩家1
upImage=ImageUtil.PLAYER1_UP_IMAGE_URL;
downImage=ImageUtil.PLAYER1_DOWN_IMAGE_URL;
rightImage=ImageUtil.PLAYER1_LEFT_IMAGE_URL;
leftImage=ImageUtil.PLAYER1_RIGHT_IMAGE_URL;
break;
case player2://玩家2
upImage=ImageUtil.PLAYER2_UP_IMAGE_URL;
downImage=ImageUtil.PLAYER2_DOWN_IMAGE_URL;
rightImage=ImageUtil.PLAYE2_LEFT_IMAGE_URL;
leftImage=ImageUtil.PLAYER2_RIGHT_IMAGE_URL;
break;
case bot:
upImage=ImageUtil.BOT_UP_IMAGE_URL;
downImage=ImageUtil.BOT_DOWN_IMAGE_URL;
rightImage=ImageUtil.BOT_LEFT_IMAGE_URL;
leftImage=ImageUtil.BOT_RIGHT_IMAGE_URL;
break;
}
}
//向左
public void leftward(){
if(direxction!=Directon.LEFT) setImage(leftImage);//若之前的移动方向不是左移,跟换左移图片
direxction=Directon.LEFT;
if(!hitWall(x-speed,y)&&hitTank(x-speed,y)){
x-=speed;//横坐标递减
moveToborder();//判断是否移动到游戏面板的边界
}
}
//向右
public void rightward(){
if(direxction!=Directon.RIGHT) setImage(rightImage);
direxction=Directon.RIGHT;
if(!hitWall(x+speed,y)&&hitTank(x+speed,y)){
x+=speed;
moveToborder();//判断是否移动到游戏面板的边界
}
}
//向上
public void upward(){
if(direxction!=Directon.UP) setImage(upImage);
direxction=Directon.UP;
if(!hitWall(x,y-speed)&&hitTank(x,y-speed)){
y-=speed;
moveToborder();//判断是否移动到游戏面板的边界
}
}
//向下
public void downward(){
if(direxction!=Directon.DOWN) setImage(downImage);
direxction=Directon.DOWN;
if(!hitWall(x,y+speed)&&hitTank(x,y+speed)){
y+=speed;
moveToborder();//判断是否移动到游戏面板的边界
}
}
//是否撞到墙块
public boolean hitWall(int x,int y){
Rectangle next=new Rectangle(x,y,width,height);//创建坦克移动后的目标区域
List<Wall> walls=gamePanel.getWalls();//获取面板上所有的墙体对象
for(int i=0,length=walls.size();i<length;i++){
Wall w=walls.get(i);//获取墙块对象
if(w instanceof GrassWall){//碰到草坪
continue;
}elseif(w.hit(next)){ //撞到墙
return true;
}
}
return false;//没撞到墙
} //是否撞到坦克
public boolean hitTank(int x,int y){
Rectangle next=new Rectangle(x,y,width,height);//创建坦克移动后的目标区域
List<Tank> tanks=gamePanel.getTanks();//获取面板上所有的坦克对象
for(int i=0,length=tanks.size();i<length;i++){
Tank t=tanks.get(i);//获取坦克对象
if(!this.equals(t)){//此坦克与自身不是一个对象
if(t.isAlive()&&t.hit(next)){//此坦克存活并且与自身相撞
return true;
}
}
}
return false;//没撞到坦克
}
//移动到面板的边界
protected void moveToBorder(){
if(x<0){
x=0;
}else if(x>gamePanel.getWidth()-width){
x=gamePanel.getWidth-width;
}
if(y<0){
y=0;
}else if(y>gamePanel.getHeight()-height){
y=gamePanel.getHeight-height
}
}
//获取坦克头
private Point getHeadPoint(){
Point p=new Point();//创建头对象,作为头点
switch(direxction){//判断移动方向
case UP:
p.x=x+width/2;
p.y=y;
break;
case DOWN:
p.x=x+width/2;
p.y=y+height;
break;
case RIGHT:
p.x=x+width;
p.y=y+height/2;
break;
case LEFT:
p.x=x;
p.y=y+height/2;
break;
default:
p=null;
}
return p;//返回头点
}
//攻击
public void attack(){
if(attackCoolDown){//如果攻击功能完成冷却
Point p=getHeadPoint();//获取坦克头对象
Bullet b=new Bullet(p.x-Bullet.LENGTH/2,p.y-Bullet.LENGTH/2,direction,gamePanel,type);
gamePanel.addBullet(b);//游戏面板添加子弹
new AttackCD().start();//开始冷却倒计时
}
}
//坦克是否存活
public boolean isAlive(){
return alive;
}
public void setAlive(boolean alive){
this.alive=alive;
}
//坦克的速度
public void setSpeed(int speed){
this.speed=speed;
}
//攻击冷却时间线程
private class AttackCD extends Thread{
public void run(){
attackCoolDown=false;//将攻击功能设置为冷却状态
try{
Tread.sleep(attackCoolDown);//休眠0.5秒
}catch(InterruptedException e){
e.printStackTrace();
}
attackCoolDown=true;//将攻击功能解除冷却状态
}
}
//获取攻击功能是否处于冷却
public boolean isAttackCoolDown(){
return attackCoolDown;
}
public void setAttackCoolDownTime(int attackCoolDownTime){
this.attackCoolDownTime=attackCoolDownTime;
}
}

敌方坦克类:

public class Bot extends Tank{
private Random random=new Random();//
private Direction dir;
private int fresh=GamePanel.FRESH;
private int MoveTimer=0; public Bot(int x,int y,GamePanel gamePanel,TankType type) {
super(x,y,ImageUtil.BOT_DOWN_IMAGE_URL,gamePanel,type);
dir=Direction.DOWN;
setAttackCoolDownTime(1000);
//setSpeed(2);
}
public void go() {
if(isAttackCoolDown()) {
attack();
}
if(MoveTimer>=3000) {
dir=randomDirection();
MoveTimer=0;
}else {
MoveTimer+=fresh;
}
switch(dir) {
case UP:
upward();
break;
case DOWN:
downward();
break;
case RIGHT:
rightward();
break;
case LEFT:
leftward();
break;
}
} protected void moveToBorder() {
if(x<0) {
x=0;
dir=randomDirection();
}else if(x>gamePanel.getWidth()-width) {
x=gamePanel.getWidth()-width;
dir=randomDirection();
}
if(y<0) {
y=0;
dir=randomDirection();
}else if(y>gamePanel.getHeight()-height) {
y=gamePanel.getHeight()-height;
dir=randomDirection();
} } //重写碰到坦克的方法
boolean hitTank(int x,int y) {
Rectangle next=new Rectangle(x,y,width,height);//创建坦克移动后的目标区域
List<Tank> tanks=gamePanel.getTanks();//获取面板上所有的坦克对象
for(int i=0,length=tanks.size();i<length;i++){
Tank t=tanks.get(i);//获取坦克对象
if(!this.equals(t)){//此坦克与自身不是一个对象
if(t.isAlive()&&t.hit(next)){//此坦克存活并且与自身相撞
if(t instanceof Bot) {
dir=randomDirection();
}
return true;
}
}
}
return false;//没撞到坦克
} public Direction randomDirection() {
int rnum =random.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() {
int rnum =random.nextInt(100);
if(rnum<4) {
super.attack();
}
}
}

子弹类:

public class Bullet extends VisibleImage{

    Direction direction;
static final int LENGTH = 8; //子弹的(正方体)边长
private GamePanel gamePanel;//游戏面板
private int speed = 7;//移动速度
private boolean alive = true;//子弹是否有效
Color color = Color.ORANGE;//子弹颜色
TankType owner;//发出子弹的坦克类型 /**
* 子弹构造方法
*
* @param x - 子弹的初始横坐标
* @param y - 子弹的初始纵坐标
* @param direction - 子弹的发射方向
* @param gamePanel - 游戏面板对象
* @param Owner - 发出子弹的坦克类型
*/
public Bullet(int x, int y, Direction direction, GamePanel gamePanel, TankType owner) {
super(x, y, LENGTH, LENGTH); //调用父类构造方法
// TODO 自动生成的构造函数存根
this.direction = direction;
this.gamePanel = gamePanel;
this.owner = owner;
init();//初始化组件
}
/**
* 初始化组件
*/
private void init() {
// TODO 自动生成的方法存根
Graphics g = image.getGraphics();//获取图片的绘图方法
g.setColor(Color.WHITE);//使用白色绘图
g.fillRect(0, 0, LENGTH, LENGTH);// 绘制一个铺满整个图片的白色实心矩形
g.setColor(color);//使用子弹颜色
g.fillOval(0, 0, LENGTH, LENGTH);// 铺满整个图片的实心圆形
g.setColor(Color.BLACK); //使用黑色
g.drawOval(0, 0, LENGTH-1, LENGTH-1); //绘制黑色边框,防止出界
}
/**
* 子弹移动
*/
public void move() {
switch(direction) { //判断移动方向
case UP:
upward();
break;
case DOWN:
downword();
break;
case LEFT:
leftword();
break;
case RIGHT:
rightword();
break;
}
}
/**
* 移动函数
*/
private void rightword() {
// TODO 自动生成的方法存根
x += speed;
moveToBorder();
} private void leftword() {
// TODO 自动生成的方法存根
x -= speed;
moveToBorder(); //移动出面板后销毁子弹
} private void downword() {
// TODO 自动生成的方法存根
y += speed;
moveToBorder();
} private void upward() {
// TODO 自动生成的方法存根
y -= speed;
moveToBorder();
} /**
* 击中坦克
*/
public void hitTank() {
List<Tank> tanks = gamePanel.getTanks(); //获取坦克的集合
for(int i = 0,length = tanks.size();i<length;i++) {//遍历坦克集合
Tank t = tanks.get(i);
if (t.isAlive()&&this.hit(t)) {//坦克活着并且子弹击中坦克
switch (owner) {
case player1://玩家的子弹
case player2:
if (t instanceof Bot) {//击中电脑
alive = false;//子弹销毁
t.setAlive(false);//电脑坦克死亡
}else if(t instanceof Tank){//击中玩家
alive = false;
}
break;
case bot://电脑的子弹
if (t instanceof Bot) {
alive = false;
}else if (t instanceof Tank) {
alive = false;
t.setAlive(false);
}
break;
default:
alive = false;
t.setAlive(false);
break;
} }
}
}
//击中基地
public void hitBase() {
Base b=gamePanel.getBase();
if(this.hit(b)) {
alive =false;
b.setAlive(false);
}
}
public void hitWall(){
List<Wall> walls=gamePanel.getWalls();
for(int i=0,length=walls.size();i<length;i++) {
Wall w=walls.get(i);
if(this.hit(w)) {
if(w instanceof BrickWall) {
alive=false;
w.setAlive(false);
}
if(w instanceof IronWall) {
alive=false;
}
}
}
}
//移除面板边界时销毁子弹
private void moveToBorder() {
if(x < 0|| x > gamePanel.getWidth() - getWidth()|| y < 0 || y > gamePanel.getHeight() - getHeight()) {
dispose();
}
}
//
private synchronized void dispose() {
alive=false;
}
//
public boolean isAlive() {
return alive;
}
}

主窗体:

1.调整屏幕尺寸及位置

2.建立窗口事件监听,使得在关闭窗口时会提示我们是否就此退出游戏。

3.添加登录面板。

public class MainFrame extends JFrame{
public MainFrame()
{
setTitle("坦克大战");
setSize(800,610);
setResizable(false);
Toolkit tool=Toolkit.getDefaultToolkit();
Dimension d=tool.getScreenSize();
setLocation((d.width-getWidth())/2, (d.height-getHeight())/2);
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addListener();
setPanel(new LoginPanel(this));
}
private void addListener(){
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e)
{
int closeCode=JOptionPane.showConfirmDialog(MainFrame.this, "是否退出游戏","提示!",
JOptionPane.YES_NO_OPTION);
if(closeCode==JOptionPane.YES_OPTION) {
System.exit(0);
}
}
});
}
public void setPanel(JPanel panel)
{
Container c=getContentPane();
c.removeAll();
c.add(panel);
c.validate();
}
}

碰撞检测:

public class VisibleImage {
/**
* 横、纵坐标
*/
public int x;
public int y;
/**
* 长、宽
*/
int width;
int height; /**
* 图像对象
*/
BufferedImage image; /**
* 构造方法
* @param x -横坐标
* @param y -纵坐标
* @param width -宽
* @param height -高
*/
public VisibleImage(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);//实例化图片
}
/**
* 构造方法
* @param x -横坐标
* @param y -纵坐标
* @param url -图片路径
*/
public VisibleImage(int x, int y, String url) {
this.x = x;
this.y = y;
try {
image = ImageIO.read(new File(url));//获取此路径的图片对象
this.width = image.getWidth();
this.height = image.getHeight();
}catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* 获取图片
* @return 所显示的图片
*/
public BufferedImage getImage() {
return image;
}
/**
* 设置图片
* @param image -所显示的图片
*/
public void setImage(BufferedImage image) {
this.image = image;
}
/**
* 设置图片
* @param image -所显示的图片
*/
public void setImage(String url) {
try {
this.image = ImageIO.read(new File(url));
}catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* 判断是否发生碰撞
* @param v - 目标图片对象
* @return 如果两者相交,返回true,否则返回false
*/
public boolean hit(VisibleImage v) {
return hit(v.getBounds());//执行重载方法
}
/**
* 判断是否发生碰撞
* @param r - 目标边界
* @return 如果两者相交,返回true,否则返回false
*/
public boolean hit(Rectangle r){
if(r == null) {
return false; //不发生碰撞
}
return getBounds().intersects(r); //判断边界对象是否相交
}
/**
* 获取边界对象
*/
public Rectangle getBounds() {
//创建一个坐标在(x,y)位置,宽高为(width,height)的矩形边界对象并返回
return new Rectangle(x, y, width, height);
}
/**
* setter,getter方法获取并设置长宽高
*/
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;
}
@Override
public String toString() {
return "VisibleImage [x=" + x + ", y=" + y + ", width=" + width + ", height=" + height + "]";
} }

碰撞:子弹的碰撞有销毁他人,自我销毁,而坦克没有该功能。

刷新帧:(关键技术)

public GamePanel(MainFrame frame,int level,GameType gameType)
{
this.frame =frame ;
this.level=level;
this.gameType=gameType;
setBackground(Color.GRAY);
init();
Thread t=new FreshThead();
t.start();
addListener();
}
private void init()
{
bullets=new ArrayList<Bullet>();
allTanks=new ArrayList<>();
walls=new ArrayList<>();
boomImage=new ArrayList<>();
image=new BufferedImage(794,572,BufferedImage.TYPE_INT_BGR);
g2 =image.createGraphics(); playerTanks=new ArrayList<>();
play1=new Tank(278,537,ImageUtil.PLAYER1_UP_IMAGE_URL,this,TankType.player1);
if(gameType==GameType.TWO_PLAYER)
{
play2=new Tank(500,537,ImageUtil.PLAYER2_UP_IMAGE_URL,this,TankType.player2);
playerTanks.add(play2);
}
playerTanks.add(play1);
botTanks=new Vector<>();
botTanks.add(new Bot(botX[0],1,this,TankType.bot));
botTanks.add(new Bot(botX[1],1,this,TankType.bot));
botTanks.add(new Bot(botX[2],1,this,TankType.bot));
botReadyCount-=3;
allTanks.addAll(playerTanks);
allTanks.addAll(botTanks);
base=new Base(367,532);
initWalls();
}
private void addListener()
{
frame.addKeyListener(this);
}
private void initWalls()
{
Map map=Map.getMap(level);
walls.addAll(map.getWalls());
walls.add(base);
}
public void paint(Graphics g)
{
paintTankActoin();
CreateBot();
paintImage();
g.drawImage(image, 0, 0, this);
}
private void paintImage()
{
g2.setColor(Color.BLACK);
g2.fillRect(0, 0, image.getWidth(),image.getHeight() );
panitBoom();
paintBotTanks();
paintBotCount();
panitPlayerTanks();
allTanks.addAll(playerTanks);
allTanks.addAll(botTanks);
paintWalls();
paintBullets();
if(botSurplusCount==0)
{
stopThread();
paintBotCount();
g2.setFont(new Font("楷体",Font.BOLD,50));
g2.setColor(Color.GREEN);
g2.drawString("胜利", 250, 400);
gotoNextLevel();
}
if(gameType ==GameType.ONE_PLAYER)
{
if(!play1.isAlive()) {
stopThread();
boomImage.add(new Boom(play1.x,play1.y));
panitBoom();
paintGameOver();
gotoPrevisousLevel();
} }
else {//双人模式
if(play1.isAlive()&&!play2.isAlive())
{
survivor=play1;
}
else if(!play1.isAlive()&&play2.isAlive())
{
survivor=play2;
}
else if(!(play1.isAlive()||play2.isAlive())) {
stopThread();
boomImage.add(new Boom(survivor.x,survivor.y));
panitBoom();
paintGameOver();
gotoPrevisousLevel();//重新进入本关
}
}
if(!base.isAlive())
{
stopThread();
paintGameOver();
base.setImage(ImageUtil.BREAK_BASE_IMAGE_URL);
gotoPrevisousLevel(); }
g2.drawImage(base.getImage(),base.x,base.y,this);
} private void paintBotCount() {
g2.setFont(new Font("楷体",Font.BOLD,25));
g2.setColor(Color.BLUE);
g2.drawString("敌方坦克剩余:"+ botSurplusCount, 10,30); }
private void paintGameOver()
{
g2.setFont(new Font("楷体",Font.BOLD,50));
g2.setColor(Color.RED);
g2.drawString("Game Over !",250,400); }
private void panitBoom()
{
for(int i=0;i<boomImage.size();i++) {
Boom boom=boomImage.get(i);
if(boom.isAlive())
{
boom.show(g2);
}
else
{
boomImage.remove(i);
i--;
}
}
}
private void paintWalls()
{
for(int i=0;i<walls.size();i++)
{
Wall w=walls.get(i);
if(w.isAlive())
{
g2.drawImage(w.getImage(),w.x,w.y,this); }
else {
walls.remove(i);
i--;
}
}
}
private void paintBullets()
{
for(int i=0;i<bullets.size();i++)
{
Bullet b=bullets.get(i);
if(b.isAlive()) {
b.move();
b.hitBase();
b.hitWall();
b.hitTank();
g2.drawImage(b.getImage(), b.x,b.y,this);
}else {
bullets.remove(i);
i--;
}
}
}
private void paintBotTanks()
{
for(int i=0;i<botTanks.size();i++)
{
Bot t=(Bot)botTanks.get(i);
if(t.isAlive()) {
t.go();
g2.drawImage(t.getImage(), t.x,t.y,this);
}else {
botTanks.remove(i);
i--;
boomImage.add(new Boom(t.x,t.y));
decreaseBot();
}
}
}
private void panitPlayerTanks()
{
for(int i=0;i<playerTanks.size();i++)
{
Tank t=playerTanks.get(i);
if(t.isAlive()) {
g2.drawImage(t.getImage(), t.x,t.y,this);
}else {
playerTanks.remove(i);
i--;
boomImage.add(new Boom(t.x,t.y)); }
}
}
private synchronized void stopThread()
{
frame.removeKeyListener(this);
finish=true;
} private class FreshThead extends Thread
{
public void run()
{
while(!finish)
{
repaint();
try
{
Thread.sleep(FRESH); }
catch(InterruptedException e)
{
e.printStackTrace();
} }
}
}
private void CreateBot()
{
createBotTimer +=FRESH;
if(botTanks.size()<botMaxInMap&&botReadyCount>0&&createBotTimer>=4000)
{
int index=r.nextInt(3);
Rectangle bornRect=new Rectangle(botX[index],1,35,35);
for(int i=0,lengh=allTanks.size();i<lengh;i++)
{
Tank t=allTanks.get(i);
if(t.isAlive()&&t.hit(bornRect))
{
return;
}
}
botTanks.add(new Bot(botX[index],1,GamePanel.this,TankType.bot));
botReadyCount--;
createBotTimer=0;
}
}
private void gotoNextLevel() {
Thread jump=new JumpPageThead(Level.nextLevel());
jump.start();
}
private void gotoPrevisousLevel() {
Thread jump=new JumpPageThead(Level.previsousLevel());
jump.start();
}
public void decreaseBot()
{
botSurplusCount--;
}
@Override
public void keyPressed(KeyEvent e) {
// TODO 自动生成的方法存根
switch(e.getKeyCode())
{
case KeyEvent.VK_Y:
y_key=true;
break;
case KeyEvent.VK_W:
w_key=true;
a_key=false;
s_key=false;
d_key=false;
break;
case KeyEvent.VK_A:
w_key=false;
a_key=true;
s_key=false;
d_key=false;
break;
case KeyEvent.VK_S:
w_key=false;
a_key=false;
s_key=true;
d_key=false;
break;
case KeyEvent.VK_D:
w_key=false;
a_key=false;
s_key=false;
d_key=true;
break;
case KeyEvent.VK_HOME:
case KeyEvent.VK_NUMPAD1:
num1_key=true;
break;
case KeyEvent.VK_UP:
up_key=true;
down_key=false;
right_key=false;
left_key=false;
break;
case KeyEvent.VK_DOWN:
up_key=false;
down_key=true;
right_key=false;
left_key=false;
break;
case KeyEvent.VK_LEFT:
up_key=false;
down_key=false;
right_key=false;
left_key=true;
break;
case KeyEvent.VK_RIGHT:
up_key=false;
down_key=false;
right_key=true;
left_key=false;
break;
}
}
private void paintTankActoin()
{
if(y_key)
{
play1.attack();
}
if(w_key)
{
play1.upward();
}
if(d_key)
{
play1.rightward();
}
if(a_key)
{
play1.leftward();
}
if(s_key)
{
play1.downward();
}
if(gameType==GameType.TWO_PLAYER)
{
if(num1_key)
{
play2.attack();
} if(up_key)
{
play2.upward();
}
if(right_key)
{
play2.rightward();
} if(left_key)
{
play2.leftward();
}
if(down_key)
{
play2.downward();
}
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO 自动生成的方法存根
switch(e.getKeyCode())
{
case KeyEvent.VK_Y:
y_key=false;
break;
case KeyEvent.VK_W:
w_key=false;
break;
case KeyEvent.VK_A:
a_key=false;
break;
case KeyEvent.VK_S:
s_key=false;
break;
case KeyEvent.VK_D:
d_key=false;
break;
case KeyEvent.VK_HOME:
case KeyEvent.VK_NUMPAD1:
num1_key=false;
break;
case KeyEvent.VK_UP:
up_key=false;
break;
case KeyEvent.VK_DOWN:
down_key=false;
break;
case KeyEvent.VK_LEFT:
left_key=false;
break;
case KeyEvent.VK_RIGHT:
right_key=false;
break;
}
}
public void addBullet(Bullet b)
{
bullets.add(b);
}
public List<Wall>getWalls(){
return walls;
}
public Base getBase()
{
return base;
}
public List<Tank>getTanks()
{
return allTanks;
} private class JumpPageThead extends Thread{
int level;
public JumpPageThead (int level)
{
this.level=level;
}
public void run()
{
try {
Thread.sleep(1000);
frame.setPanel(new LevelPanel(level,frame,gameType)); }catch(InterruptedException e)
{
e.printStackTrace();
}
}
} @Override
public void keyTyped(KeyEvent e) {
// TODO 自动生成的方法存根 } }

帧是一个量词,一个静态的画面就是一帧,帧的刷新频率决定了动画是否流畅。

repaint();每隔一段时间画一张图片,这样实现了刷新的效果。在游戏面板的构造方法里创建游戏帧线程,结束通过一个finsh来判断。

六·项目代码扫描结果及改正

 提交检查前请先将IDE中提示的所有警告(warning)解决。然后使用,阿里巴巴静态代码扫描工具(https://www.cnblogs.com/bb1119/p/7672939.html)对自己的项目进行扫描,并根据提示改正。

1.代码扫描结果

2.改正

l 对if-else语句进行大括号补充
l 对命名包文件进行修改,让它符合javac的命名规范
l Switch-case语句必须以default结尾,对此进行补充

七·尚待改进

本次的坦克大战课设实现的是一些最基本坦克大战游戏功能,比较简单易懂,对于该游戏我们还存在很多的不足,比如可以尝试着做能够联网的多人游戏,一个游戏排行榜(好友,非好友)。

JAVA课程设计(坦克大战)的更多相关文章

  1. Java课程设计——坦克大战

    坦克大战——坦克类 一. 团队课程设计博客链接 https://www.cnblogs.com/chenhuilin/p/10275664.html 二.个人负责模块和任务说明 模块:坦克类(玩家坦克 ...

  2. java课程设计-坦克大战

    团队课程设计博客链接 个人负责模块 枚举类.工具类.子弹类.图片素材的查找,地图制作 Git管理 包名类名的命名 详细说明 枚举类 如 单人和双人模式 工具类 将每个图片的路径使用字符串保存,便于调用 ...

  3. java(课程设计之记事本界面部分代码公布)

    代码:涉及记事本的一些界面......!! /* *java课程设计之记事本(coder @Gxjun) * 编写一个记事本程序 * 要求: * 用图形用户界面实现. * 能实现编辑.保存.另存为.查 ...

  4. Java小项目--坦克大战(version1.0)

    Java小项目--坦克大战<TankWar1.0> 这个小项目主要是练习j2se的基础内容和面向对象的思想.项目实现了基本的简单功能,我方一辆坦克,用上下左右键控制移动方向,按F键为发射炮 ...

  5. java课程设计(计算器)

    JAVA课程 设 计 报 告 1206401-18   瞿杰 一.设计时间 2013年6月 24日-----6月28日 二.设计地点 湖南城市学院实验楼计算机506机房 三.设计目的 1.巩固学习VB ...

  6. Java课程设计——博客作业教学数据分析系统(201521123084 林正晟)

    #课程设计--博客作业教学数据分析系统(201521123084 林正晟) 1.团队课程设计博客链接 博客作业教学数据分析系统 2.个人负责模块或任务说明 学生登陆界面的前端实现和与数据库的连接 学生 ...

  7. Java课程设计——博客作业教学数据分析系统(201521123082 黄华林)

    Java课程设计--博客作业教学数据分析系统(201521123082 黄华林) 一.团队课程设计博客链接 博客作业教学数据分析系统(From:网络五条狗) 二.个人负责模块或任务说明 1.网络爬虫 ...

  8. java课程设计--We Talk(201521123061)

    java课程设计--We Talk(201521123061) 团队博客链接:http://www.cnblogs.com/slickghost/ 数据库 一.通过Dao模式建立与数据库的连接 1.数 ...

  9. Java 课程设计 "Give it up"小游戏(团队)

    JAVA课程设计 "永不言弃"小游戏(From :Niverse) 通过Swing技术创建游戏的登陆注册界面,使用mySQL数据库技术完成用户的各项信息保存和游戏完成后的成绩保存. ...

  10. Java课程设计----仿Windows标准型计算器

    JAVA课程设计 仿Windows标准型计算器(By Yanboooooooo) 一.团队介绍: 连燕波[组长]:网络1513学生. 张文博[组员]:网络1513学生. 二.项目git地址 码云项目地 ...

随机推荐

  1. jq中的$.post中方法

    jQuery.post( url, [data], [callback], [type] ) : 使用POST方式来进行异步请求 参数: url (String) : 发送请求的URL地址. data ...

  2. vue环境的搭建

    一.首先要安装nodejs : 别去官网下,慢的要死,这是国内的什么版本都有.地址 这是我下载的. 然后就傻瓜式安装. 验证是否安装成功 二.node.js的环境变量的新建.  //我安装的路径是D: ...

  3. LeetCode OJ : Different Ways to Add Parentheses(在不同位置增加括号的方法)

    Given a string of numbers and operators, return all possible results from computing all the differen ...

  4. Nginx配置请求转发location及rewrite规则

    一个示例: location = / { # 精确匹配 / ,主机名后面不能带任何字符串 [ configuration A ] } location / { # 因为所有的地址都以 / 开头,所以这 ...

  5. 使用JQuery Deferred对象的then() 解决多个AJAX操作顺序依赖的问题

    原文地址:http://www.2cto.com/kf/201507/424202.html 之前的文章javascript异步代码的回调地狱中提到了编写AJAX代码经常遇到的3个问题,现在我们看下如 ...

  6. TCP 初步认识

    TCP连接的建立---三次握手 第一次握手:客户端TCP首先给服务器端TCP发送一个特殊的TCP数据段. 该数据段不包含应用层数据,并将头部中的SYN位设置为1,所以该数据段被称为SYN数据段. 另外 ...

  7. php 路径问题

    今天迁移网站服务器时,路径出错: 解决办法: 在网站首页根目录 设置define 全局变量 ——根目录: 在涉及目录的地方,统统替换为 根目录:

  8. 设计模式 - 代理模式(Proxy Pattern)

    一.引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访问到这些对象,如果直接访问对象给系统带来不必要的复杂性,这时候可以在客户端和目标对象之间增加一层中间层,让代 ...

  9. vue 之node.js 02

    文档 铺垫 以前网页制作web1.0 如今是web2.0-->交互式操作 前端工具 grunt gulp webpack :打包机 作用:将项目中的js,css,img,font,html等进行 ...

  10. I.MX6 linux tslib Corrupt calibration data

    I.MX6 linux tslib Corrupt calibration data 一.tslib出错 Corrupt calibration data 二.解决方法: ...... if [ -f ...