Renderer/src/main/java/electrosphere/game/cell/CellManager.java
2021-04-04 20:42:42 -04:00

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());
}
}