JAVA课程设计(坦克大战)

Posted Lemon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA课程设计(坦克大战)相关的知识,希望对你有一定的参考价值。

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

以上是关于JAVA课程设计(坦克大战)的主要内容,如果未能解决你的问题,请参考以下文章

《游戏学习》JAVA版坦克大战课程设计及源码

《游戏学习》JAVA版坦克大战课程设计及源码

java课程设计创意小游戏

Java课程设计

Java__线程---基础知识全面实战---坦克大战系列为例

基于JavaSwing坦克大战游戏的设计和实现