/**
* 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 loonframework
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
package loon.srpg.field;
import loon.LRelease;
import loon.LSystem;
import loon.LTexture;
import loon.action.map.Field2D;
import loon.opengl.GLEx;
import loon.srpg.SRPGType;
import loon.srpg.actor.SRPGActor;
import loon.srpg.actor.SRPGActors;
public class SRPGField implements LRelease {
// 无限制(不受限)
public static final int FIELD_NORMAL = 0x0;
// 水中(非特殊状态无法穿越)
public static final int FIELD_WATER = 0x1;
// 泥潭(减速)
public static final int FIELD_MIRE = 0x2;
// 墙壁(非特殊状态无法穿越)
public static final int FIELD_WALL = 0x80000000;
// 死地(入者死)
public static final int FIELD_KILL = 0x4;
// 补充(加血加魔)
public static final int FIELD_PLUS = 0x5;
private int lazyHashCode = 1;
private int maxX = 0, maxY = 0;
private Field2D field2d;
private int[][] chips;
private int limitWidth, limitHeight;
private int x1, y1, x2, y2, posX, posY;
private int width, height, tileWidth, tileHeight, drawWidth, drawHeight;
private SRPGFieldElements battleList;
private int fieldMode;
private LTexture bigImageMap;
private boolean isVisible;
public SRPGField(String fileName, int tileWidth, int tileHeight,
SRPGFieldElements list) {
this.isVisible = true;
this.set(new Field2D(fileName, tileWidth, tileHeight), list);
}
public SRPGField(Field2D field, SRPGFieldElements list) {
this.isVisible = true;
this.set(field, list);
}
public void set(Field2D field, SRPGFieldElements list) {
this.field2d = field;
this.chips = field2d.getMap();
this.width = field.getWidth();
this.height = field.getHeight();
this.tileWidth = field.getTileWidth();
this.tileHeight = field.getTileHeight();
this.drawWidth = width * tileWidth;
this.drawHeight = height * tileHeight;
this.limitWidth = tileWidth - 1;
this.limitHeight = tileHeight - 1;
this.battleList = list;
if (battleList == null) {
this.battleList = new SRPGFieldElements();
}
}
public SRPGFieldElements getBattleList() {
return battleList;
}
public void setBattleList(SRPGFieldElements battleList) {
this.battleList = battleList;
}
public int[][] getChips() {
return chips;
}
public int getPosChips(int x, int y) {
if (x < 0 || y < 0 || posX >= width || posY >= height) {
if (x < 0) {
x = 0;
} else if (x >= width) {
x = width - 1;
}
if (y < 0) {
y = 0;
} else if (y >= height) {
y = height - 1;
}
return chips[y][x];
}
return chips[y][x];
}
public SRPGFieldElement getPosMapElement(int x, int y) {
return battleList.getBattleElement(getPosChips(x, y));
}
public void setPosChips(int index, int x, int y) {
chips[y][x] = index;
}
public LTexture getPosImage(int x, int y) {
if (x < 0 || y < 0 || posX >= width || posY >= height) {
return null;
}
switch (fieldMode) {
case SRPGType.FIELD_NORMAL:
return battleList.getBattleElementImage(getPosChips(x, y))
.texture();
case SRPGType.FIELD_BIGMAP:
if (bigImageMap == null) {
return null;
} else {
return bigImageMap.copy(x * tileWidth, y * tileHeight,
tileWidth, tileHeight);
}
case SRPGType.FIELD_BLEND:
if (bigImageMap == null) {
return battleList.getBattleElementImage(getPosChips(x, y))
.texture();
} else {
return bigImageMap.copy(x * tileWidth, y * tileHeight,
tileWidth, tileHeight);
}
}
return battleList.getBattleElementImage(getPosChips(x, y)).texture();
}
public boolean checkArea(int x, int y) {
return x >= 0 && y >= 0 && x < width && y < height;
}
public int[][] getMoveSpace(int i) {
int[][] res = new int[height][width];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
res[y][x] = getMoveCost(i, 0, x, y);
}
}
return res;
}
public int getMoveCost(int index, int x, int y) {
return getMoveCost(index, 0, x, y);
}
public int getMoveCost(int index, int type, int x, int y) {
SRPGFieldElement element = getPosMapElement(x, y);
if (element == null) {
return -1;
}
int mv = element.mv;
int state = element.state;
if ((mv == -1) && ((index & FIELD_WATER) != FIELD_NORMAL)) {
mv = 1;
}
if (((state & FIELD_WALL) != FIELD_NORMAL)
&& ((index & FIELD_KILL) == FIELD_NORMAL)) {
mv = -1;
}
if (((state & FIELD_WATER) != FIELD_NORMAL)
&& ((index & FIELD_WATER) == FIELD_NORMAL)) {
mv = -1;
}
if (((state & FIELD_MIRE) != FIELD_NORMAL)
&& ((index & FIELD_WATER) == 1)) {
mv = 1;
}
if ((mv != -1) && ((index & FIELD_MIRE) != FIELD_NORMAL)) {
mv = 1;
}
if ((mv != -1) && ((index & 0x20) != FIELD_NORMAL)) {
mv = mv * 2 - 1;
}
if (((state & FIELD_KILL) != FIELD_NORMAL)
&& ((index & 0x20) == FIELD_NORMAL)
&& ((index & 0x10) == FIELD_NORMAL)) {
mv = -1;
} else {
switch (type) {
case 0x10:
mv = -1;
break;
case 0x20:
mv = 1;
break;
}
}
return mv;
}
public int[][] getMoveSpaceActor(int[][] res, SRPGActors actors, int atk,
int def) {
if ((def & 8) == 0) {
for (int i = 0; i < actors.size(); i++) {
SRPGActor actor = actors.find(i);
if (actor.isVisible()
&& actor.getActorStatus().group != actors.find(atk)
.getActorStatus().group && actor.isVisible()
&& actor.getActorStatus().hp > 0) {
res[actor.getPosY()][actor.getPosX()] = -1;
}
}
}
return res;
}
public int[][] getMoveSpaceAll(SRPGActors actors, int i) {
int move = actors.find(i).getActorStatus().movetype;
int[][] res = new int[height][width];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
res[y][x] = getMoveCost(i, move, x, y);
}
}
return getMoveSpaceActor(res, actors, i, move);
}
public boolean checkWall(int x, int y) {
if (y >= 0 && y < getHeight() && x >= 0 && x < getWidth()) {
return getPosMapElement(x, y).state == 0;
} else {
return false;
}
}
/**
* 以战场元素绘制战场地图
*
* @param g
* @param x
* @param y
* @param w
* @param h
*/
public void draw(GLEx g, int x, int y, int w, int h) {
if (!isVisible) {
return;
}
int lazy = 1;
lazy = LSystem.unite(lazy, x);
lazy = LSystem.unite(lazy, y);
lazy = LSystem.unite(lazy, w);
lazy = LSystem.unite(lazy, h);
int old = g.getBlendMode();
g.setBlendMode(LSystem.MODE_SPEED);
switch (fieldMode) {
case SRPGType.FIELD_NORMAL:
if (lazy != lazyHashCode) {
x1 = x / tileWidth;
y1 = y / tileHeight;
x2 = x % tileWidth;
y2 = y % tileHeight;
maxY = h / tileHeight + (h % tileHeight + limitHeight)
/ tileHeight + (y % tileHeight + limitHeight)
/ tileHeight;
maxX = w / tileWidth + (w % tileWidth + limitWidth) / tileWidth
+ (x % tileWidth + limitWidth) / tileWidth;
battleList.begin();
for (int nx = 0; nx < maxX; nx++) {
for (int ny = 0; ny < maxY; ny++) {
posX = x1 + nx;
posY = y1 + ny;
if (posX < 0 || posY < 0 || posX >= width
|| posY >= height) {
continue;
}
int index = chips[posY][posX];
battleList.draw(index, nx * tileWidth - x2, ny
* tileHeight - y2, tileWidth, tileHeight);
}
}
battleList.end();
lazyHashCode = lazy;
} else {
battleList.glCache();
}
break;
case SRPGType.FIELD_BIGMAP:
g.draw(bigImageMap, -x, -y);
break;
case SRPGType.FIELD_BLEND:
g.draw(bigImageMap, -x, -y);
if (lazy != lazyHashCode) {
x1 = x / tileWidth;
y1 = y / tileHeight;
x2 = x % tileWidth;
y2 = y % tileHeight;
maxY = h / tileHeight + (h % tileHeight + limitHeight)
/ tileHeight + (y % tileHeight + limitHeight)
/ tileHeight;
maxX = w / tileWidth + (w % tileWidth + limitWidth) / tileWidth
+ (x % tileWidth + limitWidth) / tileWidth;
battleList.begin();
for (int nx = 0; nx < maxX; nx++) {
for (int ny = 0; ny < maxY; ny++) {
posX = x1 + nx;
posY = y1 + ny;
if (posX < 0 || posY < 0 || posX >= width
|| posY >= height) {
continue;
}
int index = chips[posY][posX];
battleList.draw(index, nx * tileWidth - x2, ny
* tileHeight - y2, tileWidth, tileHeight);
}
}
battleList.end();
lazyHashCode = lazy;
} else {
battleList.glCache();
}
break;
}
g.setBlendMode(old);
}
public boolean isVisible() {
return isVisible;
}
public void setVisible(boolean isVisible) {
this.isVisible = isVisible;
}
public LTexture getBigImageMap() {
return bigImageMap;
}
public synchronized void setBigImageMap(String fileName) {
setBigImageMap(LTexture.createTexture(fileName));
}
public synchronized void setBigImageMap(LTexture img) {
if (img != null) {
if (this.bigImageMap != null) {
this.bigImageMap.close();
this.bigImageMap = null;
}
if (img.getWidth() == drawWidth && img.getHeight() == drawHeight) {
this.bigImageMap = img;
} else {
this.bigImageMap = img.copy(0, 0, drawWidth,
drawHeight);
}
this.fieldMode = SRPGType.FIELD_BIGMAP;
} else {
this.fieldMode = SRPGType.FIELD_NORMAL;
}
}
public int getDrawWidth() {
return drawWidth;
}
public int getDrawHeight() {
return drawHeight;
}
public int getTileWidth() {
return tileWidth;
}
public int getTileHeight() {
return tileHeight;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public int getFieldMode() {
return fieldMode;
}
public void setFieldMode(int fieldMode) {
this.fieldMode = fieldMode;
}
@Override
public void close() {
if (bigImageMap != null) {
bigImageMap.close();
bigImageMap = null;
}
if (chips != null) {
chips = null;
}
if (field2d != null) {
field2d = null;
}
}
}