/**
* Copyright 2008 - 2011
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* @project loon
* @author cping
* @email:javachenpeng@yahoo.com
* @version 0.1
*/
package loon.action.sprite.effect;
import java.util.Random;
import loon.LSystem;
import loon.action.sprite.ISprite;
import loon.core.LObject;
import loon.core.geom.RectBox;
import loon.core.graphics.device.LImage;
import loon.core.graphics.device.LPixmapData;
import loon.core.graphics.opengl.GLEx;
import loon.core.graphics.opengl.LTexture;
import loon.core.graphics.opengl.LTextures;
import loon.core.processes.RealtimeProcess;
import loon.core.processes.RealtimeProcessManager;
import loon.core.timer.LTimer;
import loon.jni.NativeSupport;
import loon.utils.MathUtils;
public class FractionEffect extends LObject implements ISprite {
/**
*
*/
private static final long serialVersionUID = 1L;
private static final int maxElements = 6;
private LTimer timer = new LTimer(40);
private int width, height, scaleWidth, scaleHeight, size;
private float expandLimit = 1.2f;
private int exWidth, exHeigth;
// 0 = x
// 1 = y
// 2 = vx
// 3 = vy
// 4 = color
// 5 = countToCrush;
private float[] fractions;
private LPixmapData pixmap;
private boolean isClose, isVisible;
private int loopCount, loopMaxCount = 16;
private long elapsed;
private LTexture tmp;
private PixelProcess pixelProcess;
public FractionEffect(String resName, boolean remove, float scale) {
init(LTextures.loadTexture(resName), 1.2f, remove, scale);
}
public FractionEffect(String resName, float limit, boolean remove,
float scale) {
init(LTextures.loadTexture(resName), limit, remove, scale);
}
public FractionEffect(String resName) {
this(resName, 1.2f);
}
public FractionEffect(String resName, float scale) {
init(LTextures.loadTexture(resName), 1.2f, false, scale);
}
public FractionEffect(String resName, float limit, float scale) {
init(LTextures.loadTexture(resName), limit, false, scale);
}
public FractionEffect(LTexture texture, float scale) {
init(texture, 1.2f, false, scale);
}
public FractionEffect(LTexture texture, float limit, float scale) {
init(texture, limit, false, scale);
}
public FractionEffect(LTexture texture, float limit, boolean remove,
float scale) {
init(texture, limit, remove, scale);
}
private void init(LTexture tex2d, float limit, boolean remove, float scale) {
this.isVisible = true;
this.expandLimit = limit;
this.width = tex2d.getWidth();
this.height = tex2d.getHeight();
this.scaleWidth = (int) (width * scale);
this.scaleHeight = (int) (height * scale);
this.loopMaxCount = (MathUtils.max(scaleWidth, scaleHeight) / 2) + 1;
this.fractions = new float[(scaleWidth * scaleHeight) * maxElements];
this.exWidth = (int) (scaleWidth * expandLimit);
this.exHeigth = (int) (scaleHeight * expandLimit);
LImage image = tex2d.getImage().scaledInstance(scaleWidth, scaleHeight);
int[] pixels = image.getPixels();
if (image != null) {
image.dispose();
image = null;
}
this.size = pixels.length;
this.pixmap = new LPixmapData(exWidth, exHeigth, true);
int no = 0, idx = 0;
int length = fractions.length;
float angle = 0;
float speed = 0;
Random random = LSystem.random;
for (int y = 0; y < scaleHeight; y++) {
for (int x = 0; x < scaleWidth; x++) {
if (idx + maxElements < length) {
no = y * scaleWidth + x;
angle = random.nextInt(360);
speed = 10f / random.nextInt(30);
fractions[idx + 0] = x;
fractions[idx + 1] = y;
fractions[idx + 2] = (MathUtils.cos(angle * MathUtils.PI
/ 180) * speed);
fractions[idx + 3] = (MathUtils.sin(angle * MathUtils.PI
/ 180) * speed);
fractions[idx + 4] = (pixels[no] == 0xff00 ? 0xffffff
: pixels[no]);
fractions[idx + 5] = x / 6 + random.nextInt(10);
idx += maxElements;
}
}
}
if (remove) {
if (tex2d != null) {
tex2d.destroy();
tex2d = null;
}
}
this.tmp = tex2d;
this.startUsePixelThread();
}
public void setDelay(long d) {
timer.setDelay(d);
}
public long getDelay() {
return timer.getDelay();
}
private class PixelProcess extends RealtimeProcess {
public PixelProcess() {
setDelay(30);
}
public void run() {
if (!isClose && !isComplete()) {
if (!isVisible) {
return;
}
if (timer.action(elapsed)) {
if (pixmap.isDirty()) {
return;
}
pixmap.reset();
NativeSupport.filterFractions(size, fractions,
pixmap.getWidth(), pixmap.getHeight(),
pixmap.getPixels(), maxElements);
pixmap.submit();
loopCount++;
}
}
}
}
final void startUsePixelThread() {
if (pixelProcess == null || pixelProcess.isDead()) {
pixelProcess = new PixelProcess();
RealtimeProcessManager.get().addProcess(pixelProcess);
}
}
final void endUsePixelThread() {
if (pixelProcess != null) {
pixelProcess.kill();
}
}
public void update(long elapsedTime) {
this.elapsed = elapsedTime;
}
public void createUI(GLEx g) {
if (isClose) {
return;
}
if (!isVisible) {
return;
}
if (isComplete()) {
return;
}
if (alpha > 0 && alpha < 1) {
g.setAlpha(alpha);
}
pixmap.draw(g, x(), y(), width, height);
if (alpha > 0 && alpha < 1) {
g.setAlpha(1f);
}
}
public void reset() {
pixmap.reset();
loopCount = 0;
}
public boolean isComplete() {
final boolean stop = pixmap.isClose() || loopCount > loopMaxCount;
if (!stop) {
startUsePixelThread();
} else {
endUsePixelThread();
}
return stop;
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
public LTexture getBitmap() {
return tmp;
}
public RectBox getCollisionBox() {
return getRect(x(), y(), width, height);
}
public boolean isVisible() {
return isVisible;
}
public void setVisible(boolean visible) {
this.isVisible = true;
}
public int getLoopCount() {
return loopCount;
}
public void setLoopCount(int loopCount) {
this.loopCount = loopCount;
}
public int getLoopMaxCount() {
return loopMaxCount;
}
public void setLoopMaxCount(int loopMaxCount) {
this.loopMaxCount = loopMaxCount;
}
public void dispose() {
this.isClose = true;
this.endUsePixelThread();
if (pixmap != null) {
pixmap.dispose();
}
if (tmp != null) {
tmp.destroy();
tmp = null;
}
}
}