📄 gamepanel.java
字号:
package view;
import java.awt.*;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import javax.swing.JPanel;
import javax.swing.border.BevelBorder;
import model.Model;
/**
* @author 何晓飞 李强 何明
* @version 2.0
* GamePanel类将游戏界面的图片画出
* 同时设置了游戏面板的各个参数
*/
public class GamePanel extends JPanel {
private static final long serialVersionUID = 1L;
/* 小图片之间的缝隙宽度 */
private final int borderValue = 1;
/* 小图片的高度 */
private final int cellHeight = 40;
/* 小图片的宽度 */
private final int cellWidth = 40;
/* 该类中需要的Model对象 */
private Model model;
/* 小图片所在文件的名字 */
private String pictureFile;
/**
* GamePanel (构造函数)初始化类变量并设置GamePanel属性.
*
* @param model
* 该类中需要的Model对象.
*/
public GamePanel(Model model) {
this.model = model;
pictureFile = model.getPictureFile();
setBackground(new Color(0,0,0));
setBorder(new BevelBorder(BevelBorder.RAISED));
}
/**
* 获取 Rectangle 对象的中心坐标,将其生成一个point返回.
*
* @param rect
* 指定了坐标空间中的一个区域的Rectangle 对象.
*
* @return Point 由参数Rectangle对象的中心坐标生成的Point对象.
*/
private Point getCenter(Rectangle rect) {
return new Point(rect.x + rect.width / 2, rect.y + rect.height / 2);
}
/**
* 通过生成一个Rectangle 对象指定了坐标空间中的一个区域.
*
* @param row
* 生成Rectangle对象所需要的坐标x = column * cellWidth + borderValue * (col -
* 1).
*
* @param col
* 生成Rectangle对象所需要的坐标y = row * cellHeight + borderValue * (row -
* 1).
*
* @return Rectangle 返回指定了坐标空间中的一个区域Rectangle 对象
*/
public Rectangle matrixToRect(int row, int col) {
int x = col * cellWidth + borderValue * (col - 1);
int y = row * cellHeight + borderValue * (row - 1);
// 通过 Rectangle 对象的左上顶点的坐标(x,y)、宽度和高度定义这个区域并返回该 Rectangle 对象
return new Rectangle(x, y, cellWidth, cellHeight);
}
/**
* 通过生成一个Rectangle 对象指定了坐标空间中的一个区域.
*
* @param p
* 指定生成Rectangle对象的中心坐标.
*
* @return Rectangle 返回指定了坐标空间中的一个区域Rectangle 对象
*/
public Rectangle matrixToRect(Point p) {
return matrixToRect(p.x, p.y);
}
/**
* 根据调用model.getMaps()方法返回的二维数组map[][]画游戏中的小图片
*
* @param g
* 该类中需要的Graphics对象,通过调用Graphics的drawImages方法画游戏中的小图片
*/
public void paint(Graphics g) {
/*图片区域的大小*/
setSize(820, 485);
super.paint(g);
//绘制背景
g.drawImage(ImageLoader.getBackGround(), 0, 0, this.getWidth(), this
.getHeight(), null);
g.setColor(new Color(118,238,0 ));
//绘制方格
for(int col=3;col<17;col++){
for(int row=1;row<11;row++){
int x=41*col-2;
int y=41*row-2;
g.draw3DRect(x, y,41, 41, true);
}
}
int map[][] = model.getMaps();// 获得Model中保存游戏中存在小图片位置的数组
for (int i = 0; i < map.length; i++)
for (int j = 0; j < map[0].length; j++) {
Rectangle rect = matrixToRect(i, j);// 指定了坐标空间中的一个区域
// 图片已被消去则跳出本次循环,否则把它画出来
if (map[i][j] == 0)
continue;
g.drawImage(ImageLoader.getImageOf(map[i][j], pictureFile),
rect.x, rect.y, 40, 40, null);
}
// 画出游戏图片被选中时显示的小筐
if (model.getSltMatrix() != null) {// 图片被选中
Rectangle rect = matrixToRect(model.getSltMatrix());// 指定图片所在的区域
Graphics2D g2 = (Graphics2D) g;
g2.setColor(new Color(148, 0, 211 ));
float dash[] = { 1f };
g2.setStroke(new BasicStroke(2.0F, BasicStroke.CAP_SQUARE,
BasicStroke.JOIN_ROUND, 11.0F, dash, 0.F));// 画出规定样式的小筐
g2.draw3DRect(rect.x, rect.y, rect.width, rect.height,true);
}
}
/**
* 鼠标定位
*
* @param Point
* 鼠标所点的相关组件源
* @return Point 返回所点位置的由图片的行和列组成Point对象
*/
public Point PointToMetrix(Point p) {
int col = 0;
int row = 0;
if (p.x <= 40 && p.x >= 0)
col = 0;
else if (p.x <= 81 && p.x >= 41)
col = 1;
else if (p.x <= 122 && p.x >= 82)
col = 2;
else if (p.x <= 163 && p.x >= 123)
col = 3;
else if (p.x <= 204 && p.x >= 164)
col = 4;
else if (p.x <= 245 && p.x >= 205)
col = 5;
else if (p.x <= 286 && p.x >= 246)
col = 6;
else if (p.x <= 327 && p.x >= 287)
col = 7;
else if (p.x <= 368 && p.x >= 328)
col = 8;
else if (p.x <= 409 && p.x >= 369)
col = 9;
else if (p.x <= 450 && p.x >= 410)
col = 10;
else if (p.x <= 491 && p.x >= 451)
col = 11;
else if (p.x <= 532 && p.x >= 492)
col = 12;
else if (p.x <= 573 && p.x >= 533)
col = 13;
else if (p.x <= 614 && p.x >= 574)
col = 14;
else if (p.x <= 655 && p.x >= 615)
col = 15;
else if (p.x <= 696 && p.x >= 656)
col = 16;
else if (p.x <= 737 && p.x >= 697)
col = 17;
else if (p.x <= 778 && p.x >= 738)
col = 18;
else if (p.x <= 819 && p.x >= 779)
col = 19;
if (p.y <= 40 && p.y >= 0)
row = 0;
else if (p.y <= 81 && p.y >= 41)
row = 1;
else if (p.y <= 122 && p.y >= 82)
row = 2;
else if (p.y <= 163 && p.y >= 123)
row = 3;
else if (p.y <= 204 && p.y >= 164)
row = 4;
else if (p.y <= 245 && p.y >= 205)
row = 5;
else if (p.y <= 286 && p.y >= 246)
row = 6;
else if (p.y <= 327 && p.y >= 287)
row = 7;
else if (p.y <= 368 && p.y >= 328)
row = 8;
else if (p.y <= 409 && p.y >= 369)
row = 9;
else if (p.y <= 450 && p.y >= 410)
row = 10;
else if (p.y <= 491 && p.y >= 451)
row = 11;
return new Point(row, col);
}
/**
* 画出消去图片时显示的连接路径
*
* @param obj
* 连接路径中的Point对象集
* showPath 方法的原理在于使用线程采集矩形对象画出线框,对符合消去的矩形画出
* 路径,同时在指定时间调用repaint 方法将所画线条擦去。
*
*/
public void showPath(final Object obj) {
// 新建一个线程来进行画连接路径的工作,只要你有操作,他就画,还要看你的容器里的东西
Thread t=new Thread(new Runnable() {
ArrayList<Point> points = (ArrayList<Point>)obj;
ArrayList<Shape> shapes = new ArrayList<Shape>();
int step = 80;
public void run() {
// 添加路径起点
shapes.add(matrixToRect(points.get(0)));
// 添加路径终点
shapes.add(matrixToRect(points.get(points.size() - 1)));
// 添加路线
for (int i = 1; i < points.size(); i++) {
Point p1 = getCenter(matrixToRect(points.get(i - 1)));
Point p2 = getCenter(matrixToRect(points.get(i)));
if (p1.x == p2.x) {// 画横向的线
int distance = p2.y - p1.y;// 计算线长
for (int j = 0; j <= Math.abs(distance); j += step)
shapes.add(new Line2D.Double(p1, new Point(p1.x,
p1.y + distance / Math.abs(distance) * j)));// 生成一条线并加到shaps中
} else if (p1.y == p2.y) {// 画纵向的线
int distance = p2.x - p1.x;// 计算线长
for (int j = 0; j <= Math.abs(distance); j += step)
shapes
.add(new Line2D.Double(p1, new Point(
p1.x + distance
/ Math.abs(distance) * j,
p1.y)));// 生成一条线并加到shapes中
}
shapes.add(new Line2D.Double(p1, p2));// 构造并初始化一个具有坐标 (0,
// 0) -> (0, 0) 的Line
}
Graphics2D g2 = (Graphics2D) getGraphics();
float dash[] = { 1F };
g2.setStroke(new BasicStroke(3.0F, BasicStroke.CAP_SQUARE,
BasicStroke.JOIN_BEVEL, 11.0F, dash, 1.F)); // //画出规定样式的连接路径
for (int index = 0; index < shapes.size(); index++) {
for (int pre = 0; pre <= index; pre++) {
if (pre < 2)
g2.setColor(new Color(0, 0, 255));// 设置圈图片的颜色
else
g2.setColor(new Color(30, 144, 255));// 设置连线的颜色
g2.draw(shapes.get(pre));// 使用当前 Graphics2D 上下文的设置勾画
// Shape 的轮廓
}
}
/*2007.6.27,真是开心的一天,我终于把连线有时候不消失的bug给修复了*/
try {// 延迟300毫秒
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
repaint();
}
});
t.start();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -