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