java swing实战——baba is you(绘制GameText)

3.3GameText与GamePeople

同样的GameText、GamePeople是Text、People的集合,而每个Text、People同样是一个单元块,此时,我们不妨抽取一个公共父类Block来描述公共属性。

3.3.1 domain中Block公共父类

在domain中新建公共父类Block

/**
 * 公共父类
 */
public class Block {
    private static final int DEFAULT_WIDTH = 24;
    private static final int DEFAULT_HEIGHT = 24;
​
    /**
     * 位置坐标、宽、高
     */
    private int x,y,width,height;
​
    public Block(int x, int y) {
        this.x = x;
        this.y = y;
        this.width = DEFAULT_WIDTH;
        this.height = DEFAULT_HEIGHT;
    }
​
    public int getX() {
        return x;
    }
​
    public void setX(int x) {
        this.x = x;
    }
​
    public int getY() {
        return y;
    }
​
    public void setY(int y) {
        this.y = y;
    }
​
    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;
    }
}
​

3.3.2 Text类

在新建Text类前,我们先定义一些常量,便于开发使用

在constant包下,建立接口TextLocation;

/**
 * 规则块地址
 */
public interface TextLocation {
    String BABA = "asset/text/BABA.gif";
    String FLAG = "asset/text/FLAG.gif";
    String ROCK = "asset/text/ROCK.gif";
    String WALL = "asset/text/WALL.gif";
    String WATER = "asset/text/WATER.gif";
​
​
    String IS = "asset/text/IS.gif";
​
    String YOU = "asset/text/YOU.gif";
    String WIN = "asset/text/WIN.gif";
    String STOP = "asset/text/STOP.gif";
    String PUSH = "asset/text/PUSH.gif";
    String SINK = "asset/text/SINK.gif";
}
​

这里,使用常量一方面便于图片地址添加,一方面也是便于后续开发方便,大家可以默认跟着敲代码,大家可以尝试自己的风格修改。

下面时Text类定义:

/**
 * 规则块
 */
public class Text extends Block{
    private String rule;    // 即我们规则块的地址
    private Image image;    // 在初始化时,就完成图片的加载,【便于后续编码,当然为了效率,也可以在画图时在加载】大家后期可以尝试

    public Text(int x, int y, String rule) {
        super(x, y);
        this.rule = rule;
        image = GameUtil.loadBufferedImage(rule);
    }

    public String getRule() {
        return rule;
    }

    public void setRule(String rule) {
        this.rule = rule;
    }

    public Image getImage() {
        return image;
    }

    public void setImage(Image image) {
        this.image = image;
    }
}

3.3.3 People类

同理,我们创建常量接口PeopleLocation和People类

/**
 * 人物地址
 */
public interface PeopleLocation {
    String BABA = "asset/icon/BABA.gif";
    String FLAG = "asset/icon/FLAG.gif";
    String ROCK = "asset/icon/ROCK.gif";
    String WALL = "asset/icon/WALL.gif";
    String WATER = "asset/icon/WATER.gif";
    String GRASS = "asset/icon/GRASS.gif";
    String TILE = "asset/icon/TILE.gif";
}
public class People extends Block{
    private String name;
    private Image image;
​
    public People(int x, int y, String name) {
        super(x, y);
        this.name = name;
        this.image = GameUtil.loadBufferedImage(name);
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public Image getImage() {
        return image;
    }
​
    public void setImage(Image image) {
        this.image = image;
    }
}

3.3.4 GameText类

GameText\GamePeople大致逻辑同GameClosure,区别在于GameClosure只有一种对象,而这两者有多种,而且每一关的位置也有所不同。

/**
 * 绘制文字块
 */
public class GameText {
    private List<Text> textList; // 注意这里时java.util.list包下的List,不要导错包
​
    public GameText() {
        this.textList = new ArrayList<>();
        /**
         * 初始化GameText位置
         */
    }
    
    public void draw(Graphics graphics) {
        for (int i = 0; i < textList.size(); i++) {
            Text text = textList.get(i);
            graphics.drawImage(text.getImage(),text.getX(),text.getY(),null);
        }
    }
}

现在,我们依据下图,完成初始关卡,文字块的初始化

   public GameText() {
        this.textList = new ArrayList<>();
        /**
         * 初始化GameText位置
         */
        this.textList.add(new Text(4*24,5*24, TextLocation.BABA));
        this.textList.add(new Text(5*24,5*24, TextLocation.IS));
        this.textList.add(new Text(6*24,5*24, TextLocation.YOU));
​
        this.textList.add(new Text(12*24,5*24, TextLocation.FLAG));
        this.textList.add(new Text(13*24,5*24, TextLocation.IS));
        this.textList.add(new Text(14*24,5*24, TextLocation.WIN));
​
        this.textList.add(new Text(4*24,13*24, TextLocation.WALL));
        this.textList.add(new Text(5*24,13*24, TextLocation.IS));
        this.textList.add(new Text(6*24,13*24, TextLocation.STOP));
​
        this.textList.add(new Text(12*24,13*24, TextLocation.ROCK));
        this.textList.add(new Text(13*24,13*24, TextLocation.IS));
        this.textList.add(new Text(14*24,13*24, TextLocation.PUSH));
        
    }

        当然,我们采用比较初级的方式初始化,之后,我们将其改为文件读取形式,这样代码也会更加简洁。

此时,大家一定会遇到很多bug,有些如jdk配置错误,或者莫名其妙的报错,这时,不妨接着看看后面的内容,或者try cathc一下,或者直接搬一下源代码babaisyouUsingSwing: 用于复现小游戏的项目,复盘更新 (gitee.com)。大家再坚持一下,胜利就在下一步,当回顾时,我们一定会发现自己变得更强了。

这时,我们在GameFrame初始化,目前,GameFrame 代码如下,

/**
 * 最终游戏界面
 */
public class GameFrame extends JFrame {
    private static final int DEFAULT_WIDTH = 19 * 24;
    private static final int DEFAULT_HEIGHT = 19 * 24;
​
    // 双缓存
    private BufferedImage bufferedImage = new BufferedImage(DEFAULT_WIDTH, DEFAULT_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR);
​
    /**
     *
     */
    private GameBackground gameBackground;
    private GameClosure gameClosure;
    private GameText gameText;
​
    public GameFrame() {
        // 设置窗口大小
        this.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
        // 窗口名称
        this.setTitle("baba is you");
        // 设置窗口图标
        this.setIconImage(GameUtil.loadBufferedImage("asset/logo/logo.png"));
​
        // 设置关闭窗口即结束程序
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 设置窗口可见
        this.setVisible(true);
        // 设置窗口居中显示
        this.setLocationRelativeTo(null);
​
        gameBackground = new GameBackground();
        gameClosure = new GameClosure();
        gameText = new GameText();
​
        // 启动重绘线程
        new run().start();
​
​
    }
​
    private class run extends Thread {
        @Override
        public void run() {
            while (true) {
                repaint();
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
​
    /**
     * 重绘方法
     */
    @Override
    public void paint(Graphics g) {
        try {
            Graphics graphics = bufferedImage.getGraphics();
            gameBackground.draw(graphics);
            gameClosure.draw(graphics);
            gameText.draw(graphics);
            g.drawImage(bufferedImage,0,0,null);
        } catch (NullPointerException e) {
            
        }
​
    }
}

其中paint()使用了try,catch,避免如下一些报错(可能你之前就遇到了它)

当然,我们后续依然会遇到难以解决的bug,大家不要灰心

截止目前,我们运行GameApp会有如下界面:

3.3.5 GamePeople类

GamePeople同理,大家可以先自行尝试。

下面是代码GamePeople代码:

public class GamePeople {
    private List<People> peopleList;

    public GamePeople() {
        this.peopleList = new ArrayList<>();
        this.peopleList.add(new People(5*24,9*24, PeopleLocation.BABA));
        this.peopleList.add(new People(14*24,9*24, PeopleLocation.FLAG));

        this.peopleList.add(new People(9*24,8*24, PeopleLocation.ROCK));
        this.peopleList.add(new People(9*24,9*24, PeopleLocation.ROCK));
        this.peopleList.add(new People(9*24,10*24, PeopleLocation.ROCK));

        for (int i = 4; i < 15; i++) {
            this.peopleList.add(new People(i*24,7*24, PeopleLocation.WALL));
            this.peopleList.add(new People(i*24,11*24, PeopleLocation.WALL));
        }
    }

    public void draw(Graphics graphics) {
        for (int i = 0; i < this.peopleList.size(); i++) {
            People people = peopleList.get(i);
            graphics.drawImage(people.getImage(),people.getX(),people.getY(),null);
        }
    }
}

同上述一样,我们在GameFrame实例化gamePeople,并在paint()中调用可得到如下界面

 大家有问题,可以到对应的提交中拉取代码对比

提交 · MiaoJ-56/babaisyouUsingSwing - Gitee.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值