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. 快速切题 poj 3026 Borg Maze 最小生成树+bfs prim算法 难度:0

    Borg Maze Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8905   Accepted: 2969 Descrip ...

  2. Netlink 基础知识

    Netlink 基础知识 Netlink 相对于系统调用,ioctl 以及 /proc 文件系统而言具有以下优点: 1. 用户仅需要在 include/linux/netlink.h 中增加一个新类型 ...

  3. QT 相关书籍

    qt qucik 核心编程 个人觉得此书写得非常之好....这位作者的另外一本虽然没看过,估计也不错 https://bbs.csdn.net/topics/390942701?list=lz qt5 ...

  4. C++/C extern关键字详解 EntryPointNotFoundException处理

    最近在弄C#帮公司做一个图像识别的功能,用到了第三方的dll,在调用dll过程中就出现了一个问题.EntryPointNotFoundException异常.遇到这种异常,很大可能就是在生成dll时函 ...

  5. React之前端路由

    通过之前的博客介绍,对于react,我们已经可以写单个组件.复合组件/单个页面了,接下来就是实现页面的跳转了,这个时候,我们就需要前端路由了. 一.react-router-dom 安装这个依赖,th ...

  6. mac svn: E210004: Number is larger than maximum

    SVN服务器IP地址发现改变,在Eclipse中的SVN资源库中执行Relocate重定位时发生错误: mac svn: E210004: Number is larger than maximum ...

  7. 解决WIFI驱动RTL8188无法在rk3168平板Android4.2启动wifi的问题

    http://blog.csdn.net/morixinguan/article/details/75228335 上一篇博文能把ko编译出来,非常兴奋的想,这一定是没问题了,结果删除原先的ko后,加 ...

  8. [IC]Lithograph(1)光刻技术分析与展望

    文章主体转载自: 1.zol摩尔定律全靠它 CPU光刻技术分析与展望 2.wiki:Extreme ultraviolet lithography 3.ITRS 2012 1. 光刻技术组成和关键点 ...

  9. debian 8.1 安装idempiere 2.1 X64 笔记

    接上文.当虚拟服务器和虚拟机搭建完成后.登陆debian 8.1 X64. 进入虚拟服务器控制台.打开虚拟机.root登陆.(留好初始状态系统快照.以便系统恢复.) 由于之前debian8.1X64默 ...

  10. 逻辑回归 logistic regression(1)逻辑回归的求解和概率解释

    本系列内容大部分来自Standford公开课machine learning中Andrew老师的讲解,附加自己的一些理解,编程实现和学习笔记. 第一章 Logistic regression 1.逻辑 ...