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;
     }
    /**
      * 设置图片
      * @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结尾,对此进行补充

七·尚待改进

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

原文地址:https://www.cnblogs.com/chenhuilin/p/10275664.html

时间: 2024-10-10 01:36:54

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

java课程设计--坦克大战

java课程设计--坦克大战 一. 团队课程设计博客链接 https://www.cnblogs.com/zwtcyt/p/12173572.html 二.个人负责模块和任务说明 墙体类,子弹类,道具类以及音效类的编写,部分GUI的编写 三.代码的提交记录截图 四.负责模块和任务详细说明 墙体类 主墙体即不可摧毁的墙体 该类为所有障碍物的父类,子类继承时改变里面draw方法 草地类 河流类 可摧毁的墙类 音效类 子弹类 子弹与碰撞检测 利用javafx中shape的intersect方法来得出两

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

代码:涉及记事本的一些界面......!! 1 /* 2 *java课程设计之记事本(coder @Gxjun) 3 * 编写一个记事本程序 4 * 要求: 5 * 用图形用户界面实现. 6 * 能实现编辑.保存.另存为.查找替换等功能. 7 * 提示:使用文件输入输出流. 8 */ 9 package project; 10 11 import javax.swing.*; 12 import java.awt.*; 13 import java.awt.event.*; //引用类设置触发事

Java课程设计—学生成绩分析系统

Java课程设计 - 我的选题是学生成绩分析系统. 下面是课程的需求图: 完成的这个小系统其实逻辑代码是非常简单的,唯一感觉有难点的地方在于涉及到了知识点比较多.当时只是匆匆地大概学了Java的一些基本知识,书上的例题和代码也没怎么敲过, 几乎都是在边做的过程中边学具体需要用到的东西: 其中感觉最麻烦的地方就是JTable.文件读取IO流以及绘图和给各个组件布局的时候. 另外还花了些功夫在UI上面:我这次是用到了substance.jar的swing美化包,想了解的可以百度下,网上有很多教程.

java课程设计团队(搜索引擎)

JAVA课程设计 基于学院网站的搜索引擎 对学院网站进行抓取.建索(需要中文分词).排序(可选).搜索.摘要显示.可以是GUI界面,也可以是Web界面. 一.团队介绍 学号 班级 姓名 简介 201621123049 网络1612 [组长]袁德兴 热衷于网络安全 201621123047 网络1612 陈芳毅 有思想,有深度 ,有能力 201621044079 网络1612 韩烨 学习力强,人称韩可爱 201621123055 网络1612 刘兵 人称五社区发哥,动手能力强 2016211230

(java项目)坦克大战 2.0

这个版本,只能算是一个雏形,把最基本的东西给完成了,不过,后面可添加的也不多.有一点,还是想去实现,那就是敌方坦克自己寻找对手!也就是游戏AI. emmm, 什么时候可以了解一下这个AI.顺便学学python. 这个帖子只是为了贴上代码,对后续的代码作为优化和添加游戏AI做准备的. 1. 各类接口 package Event; /* *具有攻击力的接口 */ public interface Attackable { /* * 校验具有攻击力的实物, 和, 具有被攻击的实物,是否能撞在一起 *

java课程设计

程序设计实训报告 题目:计算数学表达式程序 1.课设目的 (1)复习巩固java语言的基础知识,进一步加深对java语言的理解和掌握 (2)课设为大家提供一个即动手又动脑,独立实践的机会.提高我们适应实际,编程的能力 (3)培养我们在项目开发中创新意识及能力,通过亲身实践,利用所学编写简单的面向对象程序,提高对面向对象及java语言的解释 2.设计题目分析 (1)由用户输入一个简单的四则运算表达式,求出其计算结果后显示 (2)允许在表达式中出现常用的数学函数,如取整.三角函数.倒数.平方根.平方

Java课程设计——扫雷(winmine)

因为是我的课程设计,要是有冲突就不好了,转载注明出处!!! 程序很简单,毕竟我是搞acm的,我就只介绍一下闪光点. 中心空白搜索的时候,我用的DFS: API文档之后补上. package com.TreeDream.MyGame; public class Block { String name; int number; boolean boo = false; public void setName(String name) { this.name = name; } public void

数据库+Java课程设计 人事管理系统 (一)

                                                                  一.JAVA与数据库的合作 此次开发语言为Java,所用的数据库驱动是mysql-connector-java-5.1.8-bin.jar 第一步   用Java连接MySQL数据库(驱动下载:https://dev.mysql.com/downloads/connector/j/   ) 将下载好的mysql-connector-java-5.1.8-bin.ja

Java课程设计:捕获图片以及识别图中的文字

本人承接各种高校C语言.C++.Java语言等课程设计以及ppt等制造,有需要的私信我或者微信18476275715 屏幕捕捉工具 要求: 用图形用户界面实现. 能实现捕捉屏幕上的图片.文字,存成图片和文本文件. 其中的一些包eclipse是没有的,是需要自己下载导入的,这个大家自己去百度吧,很简单的.话不多说上代码. text.java package 屏幕捕捉以及识别; import java.awt.Dimension; //封装单个对象中组件的高度和宽度 import java.awt.