I am working on a falling sand game and now I am trying to make my world infinite like minecraft. and to do that I figured that I need to make a world class to store all of the chunks that will be generated in a list, and here is my problem.
All of the cells are taking their positions from an array in a chunk class.. so a cell 'cells[10, 10]' is at 'x = 10, y = 10' (I am actually using a 1d array but it is easier to explain this with a 2d array), so if I want to add another chunk to the world list the cells will end up in the same positions. and to offset them I guess I have to make the array larger or just offset thier positions when drawing them?
I am sure this is not how I am supposed to do it and I have looked everywhere. I still don't understand how I am supposed to do this.
Here is the chunk class code:
public class Chunk {
int Size = 5;
int Width;
int Height;
Cell[] cells;
Random r = new Random();
int[] direction = new int[2] {0, 1 };
int result = 0;
public Chunk(int width, int height) {
Width = width;
Height = height;
cells = new Cell[Width * Height];
}
int GetCellIndex(int x, int y) { return x + y * Width; }
Cell GetCellInLest(int index) { return cells[index]; }
Cell GetCell(int x, int y) { return GetCellInLest(GetCellIndex(x, y)); }
public void CellUpdated(int x, int y) { cells[GetCellIndex(x, y)].Updated = true; }
public void CellNotUpdated(int x, int y) { cells[GetCellIndex(x, y)].Updated = false; }
public void ReplaceCell(Cell cell, int x, int y, Cell cell1, int xto, int yto) {
SetCell(x, y, cell1);
SetCell(xto, yto, cell);
}
public void MoveCell(Cell cell, int x, int y, int xto, int yto) {
SetCell(x, y, Elements.Air);
SetCell(xto, yto, cell);
}
bool IsInBounds(int x, int y) { return x < Width && x > 0 && y < Height && y > 0; }
bool IsEmpty(int x, int y) { return IsInBounds(x, y) && GetCell(x, y).Type == CellType.Empty; }
public void SetCell(int x, int y, Cell cell) { cells[GetCellIndex(x, y)] = cell; }
public void Update() {
for (int j = Height - 1; j >= 0; j--) {
for (int i = 0; i < Width; i++) {
CellNotUpdated(i, j);
}
}
for (int j = Height - 1; j >= 0; j--) {
for (int i = 0; i < Width; i++) {
var cell = GetCell(i, j);
Rules(cell, i, j);
}
}
}
void Rules(Cell cell, int X, int Y) {
if (cell.Updated == false) {
cell.Updated = true;
result = direction[r.Next(direction.Length)];
if (cell.Type == CellType.MovableSolid) {
if (IsEmpty(X, Y + 1)) {
MoveCell(cell, X, Y, X, Y + 1);
} else if (IsEmpty(X + 1, Y + 1) && IsEmpty(X - 1, Y + 1)) {
if (result == 0) {
MoveCell(cell, X, Y, X + 1, Y + 1);
} else {
MoveCell(cell, X, Y, X - 1, Y + 1);
}
} else if (IsEmpty(X + 1, Y + 1) && IsEmpty(X + 1, Y)) {
MoveCell(cell, X, Y, X + 1, Y + 1);
} else if (IsEmpty(X - 1, Y + 1) && IsEmpty(X - 1, Y)) {
MoveCell(cell, X, Y, X - 1, Y + 1);
}
}
if (cell.Type == CellType.Liquid) {
if (IsEmpty(X, Y + 1)) {
MoveCell(cell, X, Y, X, Y + 1);
} else if (IsEmpty(X + 1, Y + 1) && IsEmpty(X - 1, Y + 1)) {
if (result == 0) {
MoveCell(cell, X, Y, X + 1, Y + 1);
} else {
MoveCell(cell, X, Y, X - 1, Y + 1);
}
} else if (IsEmpty(X + 1, Y + 1) && IsEmpty(X + 1, Y)) {
MoveCell(cell, X, Y, X + 1, Y + 1);
} else if (IsEmpty(X - 1, Y + 1) && IsEmpty(X - 1, Y)) {
MoveCell(cell, X, Y, X - 1, Y + 1);
} else if (IsEmpty(X + 1, Y) && IsEmpty(X - 1, Y)) {
if (result == 0) {
MoveCell(cell, X, Y, X + 1, Y);
} else {
MoveCell(cell, X, Y, X - 1, Y);
}
} else if (IsEmpty(X + 1, Y)) {
MoveCell(cell, X, Y, X + 1, Y);
} else if (IsEmpty(X - 1, Y)) {
MoveCell(cell, X, Y, X - 1, Y);
}
}
if (cell.Type == CellType.Gas) {
if (IsEmpty(X, Y - 1)) {
MoveCell(cell, X, Y, X, Y - 1);
} else if (IsEmpty(X + 1, Y - 1) && IsEmpty(X - 1, Y - 1)) {
if (result == 0) {
MoveCell(cell, X, Y, X + 1, Y - 1);
} else {
MoveCell(cell, X, Y, X - 1, Y - 1);
}
} else if (IsEmpty(X + 1, Y - 1) && IsEmpty(X + 1, Y)) {
MoveCell(cell, X, Y, X + 1, Y + 1);
} else if (IsEmpty(X - 1, Y - 1) && IsEmpty(X - 1, Y)) {
MoveCell(cell, X, Y, X - 1, Y + 1);
} else if (IsEmpty(X + 1, Y) && IsEmpty(X - 1, Y)) {
if (result == 0) {
MoveCell(cell, X, Y, X + 1, Y);
} else {
MoveCell(cell, X, Y, X - 1, Y);
}
} else if (IsEmpty(X + 1, Y)) {
MoveCell(cell, X, Y, X + 1, Y);
} else if (IsEmpty(X - 1, Y)) {
MoveCell(cell, X, Y, X - 1, Y);
}
}
}
}
public void Draw(SpriteBatch sb, Texture2D tex) {
for (int j = 0; j < Height; j++) {
for (int i = 0; i < Width; i++) {
var cell = GetCell(i, j);
if (cell.Type != CellType.Empty) {
sb.Draw(tex, new Vector2((i * Size) + (2 * (Width * 2)), (j * Size) ), new Rectangle(0, 0, tex.Width, tex.Height), cell.Color, 0, Vector2.Zero, Size, SpriteEffects.None, 1);
}
}
}
}
public void Paint(int x, int y, Cell cell) {
if(IsInBounds(x, y)) {
SetCell(x, y, cell);
}
}
}
Define an origin for the chunk.
The origin is literally the position the rectangle is located at. I defined it below using Vector2Int, since you seem to be using integers exclusively.
public class Chunk
{
public Vector2Int origin;
...
}
For the simple case where the size of each chunk is the same, you can multiply the (x,y) coordinates by the size to get the origin.
public void Example()
{
var size = Vector2Int.one * 10;
for (int y = 0; y < 2; y++)
{
for (int x = 0; x < 2; x++)
{
var chunk = new Chunk();
chunk.origin = new Vector2Int(x, y) * size;
}
}
}
Then when you go to render the cell, add the chunk origin to the cells position.