295 lines
9.0 KiB
Java
295 lines
9.0 KiB
Java
package electrosphere.game.cell;
|
|
|
|
import electrosphere.game.terrain.TerrainManager;
|
|
import electrosphere.renderer.ShaderProgram;
|
|
import java.util.Arrays;
|
|
|
|
/**
|
|
*
|
|
* @author satellite
|
|
*/
|
|
public class CellManager {
|
|
|
|
//the terrain manager this cell manager constructs off of
|
|
TerrainManager terrainManager;
|
|
|
|
//the center of this cell manager's array in cell space
|
|
int cellX;
|
|
int cellY;
|
|
|
|
//the width of a minicell in this manager
|
|
int miniCellWidth;
|
|
|
|
//all currently displaying mini cells
|
|
DrawCell[][] cells;
|
|
boolean[][] valid;
|
|
boolean[][] drawable;
|
|
boolean[][] updateable;
|
|
|
|
|
|
ShaderProgram program;
|
|
|
|
|
|
|
|
int drawRadius = 1;
|
|
int drawStepdownInterval = 2;
|
|
int drawStepdownValue = 20;
|
|
|
|
public CellManager(TerrainManager terrainManager, float realX, float realY){
|
|
this.terrainManager = terrainManager;
|
|
this.miniCellWidth = miniCellWidth;
|
|
cells = new DrawCell[drawRadius * 2 + 1][drawRadius * 2 + 1];
|
|
valid = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1];
|
|
drawable = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1];
|
|
updateable = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1];
|
|
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
|
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
|
valid[x][y] = false;
|
|
drawable[x][y] = false;
|
|
updateable[x][y] = false;
|
|
}
|
|
}
|
|
cellX = transformRealSpaceToCellSpace(realX);
|
|
cellY = transformRealSpaceToCellSpace(realY);
|
|
|
|
program = ShaderProgram.smart_assemble_shader(false, true);
|
|
}
|
|
|
|
public int getCellX(){
|
|
return cellX;
|
|
}
|
|
|
|
public int getCellY(){
|
|
return cellY;
|
|
}
|
|
|
|
public void setCellX(int x){
|
|
cellX = x;
|
|
}
|
|
|
|
public void setCellY(int y){
|
|
cellY = y;
|
|
}
|
|
|
|
public void updateInvalidCell(){
|
|
int targetX = 0;
|
|
int targetY = 0;
|
|
boolean found = false;
|
|
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
|
targetX = x;
|
|
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
|
targetY = y;
|
|
if(!valid[x][y]){
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if(found){
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(found){
|
|
int currentCellX = cellX - drawRadius + targetX;
|
|
int currentCellY = cellY - drawRadius + targetY;
|
|
if(
|
|
currentCellX >= 0 &&
|
|
currentCellX < terrainManager.getWorldDiscreteSize() &&
|
|
currentCellY >= 0 &&
|
|
currentCellY < terrainManager.getWorldDiscreteSize()
|
|
){
|
|
cells[targetX][targetY] = new DrawCell(
|
|
terrainManager.getAugmentedTerrainAtChunk(currentCellX, currentCellY),
|
|
terrainManager.getAugmentedChunkWidth(),
|
|
currentCellX,
|
|
currentCellY,
|
|
terrainManager.getChunkWidth(),
|
|
program
|
|
);
|
|
}
|
|
valid[targetX][targetY] = true;
|
|
drawable[targetX][targetY] = false;
|
|
updateable[targetX][targetY] = false;
|
|
}
|
|
}
|
|
|
|
public void makeCellDrawable(){
|
|
int targetX = 0;
|
|
int targetY = 0;
|
|
boolean found = false;
|
|
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
|
targetX = x;
|
|
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
|
targetY = y;
|
|
if(valid[x][y] && !drawable[x][y]){
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if(found){
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(found){
|
|
int currentCellX = cellX - drawRadius + targetX;
|
|
int currentCellY = cellY - drawRadius + targetY;
|
|
if(
|
|
currentCellX >= 0 &&
|
|
currentCellX < terrainManager.getWorldDiscreteSize() &&
|
|
currentCellY >= 0 &&
|
|
currentCellY < terrainManager.getWorldDiscreteSize()
|
|
){
|
|
int dist = Math.abs(targetX - drawRadius) * Math.abs(targetY - drawRadius);
|
|
int stride = Math.min(100, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
|
|
while(terrainManager.getChunkWidth() % stride != 0){
|
|
stride = stride + 1;
|
|
}
|
|
cells[targetX][targetY].generateDrawableEntity(stride);
|
|
}
|
|
drawable[targetX][targetY] = true;
|
|
}
|
|
}
|
|
|
|
public void updateCellModel(){
|
|
int targetX = 0;
|
|
int targetY = 0;
|
|
boolean found = false;
|
|
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
|
targetX = x;
|
|
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
|
targetY = y;
|
|
if(updateable[x][y]){
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if(found){
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(found){
|
|
int currentCellX = cellX - drawRadius + targetX;
|
|
int currentCellY = cellY - drawRadius + targetY;
|
|
if(
|
|
currentCellX >= 0 &&
|
|
currentCellX < terrainManager.getWorldDiscreteSize() &&
|
|
currentCellY >= 0 &&
|
|
currentCellY < terrainManager.getWorldDiscreteSize()
|
|
){
|
|
int dist = Math.abs(targetX - drawRadius) * Math.abs(targetY - drawRadius);
|
|
int stride = Math.min(100, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
|
|
while(terrainManager.getChunkWidth() % stride != 0){
|
|
stride = stride + 1;
|
|
}
|
|
cells[targetX][targetY].generateDrawableEntity(stride);
|
|
}
|
|
updateable[targetX][targetY] = false;
|
|
drawable[targetX][targetY] = true;
|
|
}
|
|
}
|
|
|
|
|
|
public boolean containsInvalidCell(){
|
|
for(int x = 0;x < drawRadius * 2 + 1; x++){
|
|
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
|
if(!valid[x][y]){
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean containsUndrawableCell(){
|
|
for(int x = 0;x < drawRadius * 2 + 1; x++){
|
|
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
|
if(!drawable[x][y]){
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean containsUpdateableCell(){
|
|
for(int x = 0;x < drawRadius * 2 + 1; x++){
|
|
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
|
if(updateable[x][y]){
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
public void shiftChunksNegX(){
|
|
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
|
cells[drawRadius * 2][y].retireCell();
|
|
}
|
|
for(int x = drawRadius * 2; x > 0; x--){
|
|
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
|
cells[x][y] = cells[x-1][y];
|
|
updateable[x][y] = true;
|
|
}
|
|
}
|
|
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
|
valid[0][y] = false;
|
|
}
|
|
}
|
|
|
|
public void shiftChunksPosX(){
|
|
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
|
cells[0][y].retireCell();
|
|
}
|
|
for(int x = 0; x < drawRadius * 2; x++){
|
|
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
|
cells[x][y] = cells[x+1][y];
|
|
updateable[x][y] = true;
|
|
}
|
|
}
|
|
for(int y = 0; y < drawRadius * 2 + 1; y++){
|
|
valid[drawRadius * 2][y] = false;
|
|
}
|
|
}
|
|
|
|
public void shiftChunksNegY(){
|
|
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
|
cells[x][drawRadius * 2].retireCell();
|
|
}
|
|
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
|
for(int y = drawRadius * 2; y > 0; y--){
|
|
cells[x][y] = cells[x][y-1];
|
|
updateable[x][y] = true;
|
|
}
|
|
}
|
|
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
|
valid[x][0] = false;
|
|
}
|
|
}
|
|
|
|
public void shiftChunksPosY(){
|
|
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
|
cells[x][0].retireCell();
|
|
}
|
|
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
|
for(int y = 0; y < drawRadius * 2; y++){
|
|
cells[x][y] = cells[x][y+1];
|
|
updateable[x][y] = true;
|
|
}
|
|
}
|
|
for(int x = 0; x < drawRadius * 2 + 1; x++){
|
|
valid[x][drawRadius * 2] = false;
|
|
}
|
|
}
|
|
|
|
|
|
public int transformRealSpaceToCellSpace(float input){
|
|
return (int)(input / terrainManager.getChunkWidth());
|
|
}
|
|
|
|
|
|
}
|