package
org.test;
/**
* Title: LoonFramework
* Description:拼图图像处理[未优化](优化算法已内置于loonframework-game框架中。)
* Copyright: Copyright (c) 2007
* Company: LoonFramework
*
@author
chenpeng
* @email:[email protected]
*
@version
0.1
*/
import
java.awt.Canvas;
import
java.awt.Color;
import
java.awt.Event;
import
java.awt.Frame;
import
java.awt.Graphics;
import
java.awt.Image;
import
java.awt.MediaTracker;
import
java.awt.image.BufferedImage;
import
org.loon.framework.game.helper.ImageHelper;
public
class
BlockImage
extends
Canvas {
/**
*
*/
private
static
final
long
serialVersionUID
=
1L
;
private
Image _img;
private
Image _img2;
private
Graphics bg;
private
Image backimage;
private
int
blocks[];
private
boolean
isEvent;
private
MediaTracker mt;
private
int
_width;
private
int
_height;
private
int
_RS;
private
int
_CS;
private
Image screen
=
null
;
private
Graphics later
=
null
;
private
int
_objWidth;
private
int
_objHeight;
private
int
_COUNT;
/**
* 析构函数,内部调用init方法。
*
*
@param
bImage
*
@param
overImage
*
@param
cs
*
@param
rs
*/
public
BlockImage(Image bImage, Image overImage,
int
cs,
int
rs) {
init(bImage, overImage, cs, rs);
}
/**
* 初始化拼图参数。
*
*
@param
bImage
*
@param
overImage
*
@param
cs
*
@param
rs
*/
public
void
init(Image bImage, Image overImage,
int
cs,
int
rs) {
//
列数
_CS
=
cs;
//
行数
_RS
=
rs;
//
加载拼图用图像。
_img
=
bImage;
//
获得实际窗体宽。
_width
=
_img.getWidth(
null
);
//
获得实际窗体高。
_height
=
_img.getHeight(
null
);
//
获得单块图像宽。
_objWidth
=
_width
/
_CS;
//
获得单块图像高。
_objHeight
=
_height
/
_RS;
//
本程序直接使用backimage上一块图形区域缓冲选择项,所以实际背景图像高=图形高+额外图块高。
backimage
=
new
BufferedImage(_width, _height
+
_objHeight,
1
);
//
获得生成的图形
later
=
backimage.getGraphics();
//
再创建一块图像区域,作为图像缓存用。
screen
=
new
BufferedImage(_width, _height,
1
);
//
获得缓存的图形
bg
=
screen.getGraphics();
//
获得等同图片总数的数组。
_COUNT
=
_CS
*
_RS;
blocks
=
new
int
[_COUNT];
//
初始化为非点击。
isEvent
=
false
;
//
加载完成拼图的显示图。
_img2
=
overImage;
//
初始化图块参数。
for
(
int
i
=
0
; i
<
_COUNT; i
++
) {
blocks[i]
=
i;
}
//
载入MediaTracker,用以跟踪图像状态。
mt
=
new
MediaTracker(
this
);
//
加载被跟踪的图像。
mt.addImage(_img,
0
);
mt.addImage(_img2,
0
);
//
同步载入。
try
{
mt.waitForID(
0
);
}
catch
(InterruptedException interruptedexception) {
return
;
}
//
随机生成图像面板内容。
rndPannel();
}
/**
* 描绘窗体图像。
*/
public
void
paint(Graphics g) {
//
检查图像载入。
if
(mt.checkID(
0
)) {
//
描绘底层背景。
bg.drawImage(backimage,
0
,
0
,
null
);
//
判断是否触发完成事件。
if
(
!
isEvent) {
//
设置背景色。
bg.setColor(Color.black);
//
循环绘制小图片于背景缓存中。
for
(
int
i
=
0
; i
<
_CS; i
++
) {
for
(
int
j
=
0
; j
<
_RS; j
++
)
bg.drawRect(i
*
_objWidth, j
*
_objHeight, _objWidth,
_objHeight);
}
}
//
仅当完成事件触发并且有胜利图片时,载入完成提示。
if
(isEvent
&&
_img2
!=
null
) {
bg.drawImage(_img2,
0
,
0
,
null
);
}
}
//
举凡绘制图像时,应遵循显示图像仅绘制一次的基本原则,一次性的将背景绘制到窗体。
//
简单来说,也就是采取[双缓存]的方式,所有复杂操作皆在缓存区完成,也只有这样才能避免产生延迟闪烁。
g.drawImage(screen,
0
,
0
,
this
);
g.dispose();
}
/**
* 变更图像。
*/
public
void
update(Graphics g) {
paint(g);
}
/**
* 鼠标点击事件。
*/
public
boolean
mouseDown(Event event,
int
i,
int
j) {
if
(isEvent)
return
true
;
//
换算点击位置与小图片。
int
k
=
i
/
_objWidth;
int
l
=
j
/
_objHeight;
copy(
0
,
0
,
0
, _RS);
copy(k, l,
0
,
0
);
copy(
0
, _RS, k, l);
int
i1
=
blocks[
0
];
//
换算选中图片存储区。
blocks[
0
]
=
blocks[l
*
_CS
+
k];
blocks[l
*
_CS
+
k]
=
i1;
int
j1;
for
(j1
=
0
; j1
<
_COUNT; j1
++
) {
if
(blocks[j1]
!=
j1) {
break
;
}
}
if
(j1
==
_COUNT)
isEvent
=
true
;
repaint();
return
true
;
}
public
boolean
mouseUp(Event event,
int
i,
int
j) {
return
true
;
}
public
boolean
mouseDrag(Event event,
int
i,
int
j) {
return
true
;
}
/**
* copy换算后的图像区域。
*
*
@param
i
*
@param
j
*
@param
k
*
@param
l
*/
void
copy(
int
i,
int
j,
int
k,
int
l) {
later.copyArea(i
*
_objWidth, j
*
_objHeight, _objWidth, _objHeight,
(k
-
i)
*
_objWidth, (l
-
j)
*
_objHeight);
}
/**
* 事件触发状态。
*
@return
*/
public
boolean
isEvent() {
return
isEvent;
}
public
void
setEvent(
boolean
isEvent) {
this
.isEvent
=
isEvent;
}
/**
* 随机生成面板图片。
*
*/
void
rndPannel() {
later.drawImage(_img,
0
,
0
,
this
);
for
(
int
i
=
0
; i
<
(_COUNT
*
_CS); i
++
) {
int
j
=
(
int
) ((
double
) _CS
*
Math.random());
int
k
=
(
int
) ((
double
) _RS
*
Math.random());
int
l
=
(
int
) ((
double
) _CS
*
Math.random());
int
i1
=
(
int
) ((
double
) _RS
*
Math.random());
copy(j, k,
0
, _RS);
copy(l, i1, j, k);
copy(
0
, _RS, l, i1);
int
j1
=
blocks[k
*
_CS
+
j];
blocks[k
*
_CS
+
j]
=
blocks[i1
*
_CS
+
l];
blocks[i1
*
_CS
+
l]
=
j1;
}
}
public
static
void
main(String[] args) {
Frame frm
=
new
Frame(
"
简单的JAVA拼图效果实现[由Loonframework框架提供]
"
);
frm.setSize(
480
,
500
);
frm.setResizable(
false
);
/**
* PS:ImageHelper.loadImage为Loonframework框架中helper下方法,为不依赖于javax扩展包而开发。
* 可使用ImageIO相关方法代替。
*/
//
加载图像。
Image backImage
=
ImageHelper.loadImage(
"
C:/backimage.jpg
"
,
true
);
Image overImage
=
ImageHelper.loadImage(
"
C:/over.gif
"
,
true
);
//
BlockImage中参数分别为 用于分解的拼图,完成后显示文字,拆分图片为分几列,分拆分图片为几行。
//
建议使用正方形图片作为背景图。
frm.add(
new
BlockImage(backImage, overImage,
4
,
4
));
backImage
=
null
;
overImage
=
null
;
//
显示窗体。
frm.setVisible(
true
);
}
}
详细操作参见源码注释,所用图片如下(也可自由选取图形):
本代码算法支持自由成比例分隔图像行列,效果若下: