JAVA面向对象编程课程设计——泡泡堂(个人博客)

一、团队博客地址:JAVA面向对象编程课程设计——泡泡堂

二、个人负责模块或任务说明

  • GUI设计
  • 游戏界面类、地图类的实现(实现与Player类的交互)
  • 阿里巴巴扫描纠错
  • 团队博客编写

三、自己的代码提交记录

四、自己负责模块或任务详细说明

1.地图Field类

public class Field extends JPanel {
    

    private static final long serialVersionUID = 1L;
    int n = 1;
    
    /**存储地图的15*12个方格*/
    Box[][] boxes = new Box[15][12];


    /**初始化地图面板*/
    public Field(int n)
    {
        this.n = n;
        this.setLayout(null);
        this.setBounds(0, 0, 1200, 960);
    }


    /**覆盖add方法,添加新参数x,y*/
    public void add(Box b, int x, int y)
    {
        //将box添加进地图
        this.add(b);
        //保存box
        boxes[x][y] = b;
    }
    /**返回x,y坐标处的box值*/
    public Box getBoxbyLocation(int x, int y)

    {
        return boxes[x][y];
    }
    /**设置地图*/
    public void setField()

    {
        // 读取编号为n的地图文件
        File file = new File("map/" + n + ".txt");
        try {
            // 构造一个BufferedReader类来读取文件
            BufferedReader br = new BufferedReader(new FileReader(file));
            String s = null;
            int j = 0;
            while ((s = br.readLine()) != null) {
                String[] arr = s.split("\\s+");
                int i = 0;
                for (String ss : arr) {
                    int ctemp = Integer.parseInt(ss);
                    if (ctemp == 0) {
                        Box temp = new Box(i, j);
                        this.add(temp, i, j);
                                                //0为空地
                    }
                    // 1~5表示此处为可破坏的实体
                    if (1 <= ctemp && ctemp <= 5)
                    {
                        Box temp = new Box(i, j, n, ctemp, true);
                                                //Box继承自Jlabel,初始化时会根据传参设置好该box的大小和位置
                        this.add(temp, i, j);
                    }
                    // 6~10表示此处为不可破坏的实体
                    if (6 <= ctemp && ctemp <= 10)
                    {
                        Box temp = new Box(i, j, n, ctemp, false);
                        this.add(temp, i, j);
                    }
                    i++;
                }
                j++;
            }
            br.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**使图片自适应label标签大小*/
    public void setIcon(String file, JLabel com)
    {
        ImageIcon ico = new ImageIcon(file);
        //ico.getImage();
        Image temp = ico.getImage().getScaledInstance(com.getWidth(), com.getHeight(), Image.SCALE_DEFAULT);
                //获得一个适应于传入label大小的图片,此处传参是宽和高,还有缩放的方式,这里选择默认的方式
        ico = new ImageIcon(temp);
        com.setIcon(ico);
    }

}

Box类中的构造方法:

public Box(int x, int y, int n, int index, boolean canDestroy)// *存在*
    {
        this.canDestroy = canDestroy;
        // 设置该box大小、位置
        this.setBounds(80 * x, 80 * y, 80, 80);

        // 根据传入的参数设置图片
        setIcon("images/" + n + "/" + index + ".png", this);


        // 如果该box可以破坏
        if (canDestroy)
        {
            // 设置该box内藏的宝物
            setTreasure();

        }
    }
    /**不存在*/
    public Box(int x, int y)
    {
        // 设置该box为不存在
        isExist = false;
        // 设置该box大小、位置
        this.setBounds(80 * x, 80 * y, 80, 80);
        // 设置该box处图片为默认的图片(透明)
        setIcon("images/default.png", this);
    }

2.游戏界面GameFrame类

放入组件:

//取消默认布局
gameScreen.setLayout(null);
//设置地图面板大小、位置
map.setBounds(20,20,1200,960);
//取消默认布局
map.setLayout(null);
//设置面板背景为透明
map.setOpaque(false);
//生成地图
thismap=new Field(n);
//设置面板背景为透明
thismap.setOpaque(false);
//地图中加入玩家一
thismap.add(player1);
//地图中加入玩家二
thismap.add(player2);
//加载地图
thismap.setField();
//将加载好的地图加入map面板
map.add(thismap);
//将map面板加入主面板
//设置窗体大小,启动玩家移动线程
int width = Toolkit.getDefaultToolkit().getScreenSize().width;
        int height = Toolkit.getDefaultToolkit().getScreenSize().height;
        int windowsWidth = 1500;
        int windowsHeight= 1050;
        gameFrame.setBounds((width - windowsWidth) / 2,(height - windowsHeight) / 2-25, windowsWidth, windowsHeight);
        setSize(windowsWidth,windowsHeight);
        background.getImage();
        Image temp=background.getImage().getScaledInstance(this.getWidth(),this.getHeight(),Image.SCALE_DEFAULT);  
        background=new ImageIcon(temp);  
        JLabel label = new JLabel(background); 
        label.setBounds(0, 0, this.getWidth(), this.getHeight());  
        gameScreen.add(label);
        gameFrame.add(gameScreen);
        gameFrame.setSize(windowsWidth, windowsHeight);
        gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        gameFrame.setVisible(true);
        moveThread1 m1 = new moveThread1();
        m1.start();
        moveThread2 m2 = new moveThread2();
        m2.start();

玩家移动线程:

    private class moveThread1 extends Thread {
        @Override
        public void run() {
            
                while (player1.isalive) {
                    if(stopSign)
                        break;
                    if(pause){
                        player1.move();
                        colisionDetection(player1);
                        if(player1.thisbomb!=null)
                        {
                            //判断玩家是否在当前炸弹上(一旦离开玩家当前放置的炸弹,便不可再次站上去)
                            if(player1.thisbomb.isExistPlayer)
                            {
                                player1.onTheboom();
                            }
                        }
                    }
                }
            
        }
    }

使用while循环实现持续监听,加入判断线程结束标志,当重新开始、返回主界面时,线程能够及时停止,避免再次启动的时候出现bug

碰撞检查

    public static void colisionDetection(Player pl)
    {
        int x = 1120;
        int y = 880;
        //出地图边境
        if(pl.getX()<0||pl.getX()>x||pl.getY()<0||pl.getY()>y)
        {
            pl.back();
            return;
        }
        int w = 15;
        int h = 12;
        for(int i=0;i<w;i++) {
            for(int j=0;j<h;j++)
            {
                try {
                    Box temp=thismap.getBoxbyLocation(i,j);
                    //碰撞检查
                    if(temp.getRect().intersects(pl.getRect())&&temp.isExist)

                    {
                        //遇到箱子
                        if(!temp.isdestroyshowT)

                        {
                            pl.back();
                            return;
                        }
                        //遇到宝物
                        else{
                            switch(temp.treasureIndex){
                            case 1:
                                pl.pla.plusspeed();
                                break;
                            case 2:
                                pl.pla.plusbombnum();
                                break;
                            case 3:
                                pl.pla.pluspower();
                                break;
                            case 4:
                                //无敌状态
                                pl.invincible();
                                break;
                            case 5:
                                pl.pla.pluslive();
                                break;
                                default:
                                    break;
                            }
                            //设置当前方格为[不存在]
                            temp.isExist=false;
                            //将当前方格设置为隐藏
                            setIcon("images/default.png",temp);
                        }
                    }

                    //遇到炸弹
                    if(temp.isExistBomb&&!temp.isExistPlayer&&temp.getRect().intersects(pl.getRect()))
                    {
                        pl.back();
                        return;
                    }
                } catch (NullPointerException e) {

                }

            }
        }

    }

借助Rectangle类中的intersects方法来检测2个矩形是否相交,实现碰撞检查,再通过判断玩家前往的box的类型来判断下一步操作。

五、总结:

本次课设是多人组队课设,每个人负责一个模块,进度比一个人要来的快,遇到问题也能通过讨论得到合理解决。但在各模块交互,自己负责模块添加功能时也遇到了很多问题,自己的一点修改会影响这个项目的运行,作为组长,让我意识到不仅需要自己埋头写代码,更多需要和组员配合,了解进度,制定下一个目标,对我而言是一次宝贵的经验。比较遗憾的是,在界面和游戏本身的完成花了较多的时间,没有去尝试通过网络实现多人同台对战。

猜你喜欢

转载自www.cnblogs.com/choco1ate/p/12173389.html