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()中调用可得到如下界面
大家有问题,可以到对应的提交中拉取代码对比