If and if and if and if... [ + real-time generation of textures in LWJGL]

Hey! Is there any way to make the code smaller for things like this? :


if((x > 0 && x < mapWidth - 1) && (y > 0 && y < mapHeight - 1)) {
	if(map[x][y + 1] != map[x][y]) { dd = true; ddID = map[x][y + 1]; }
	if(map[x - 1][y + 1] != map[x][y]) { dl = true; dlID = map[x - 1][y + 1]; }
	if(map[x - 1][y] != map[x][y]) { ll = true; llID = map[x - 1][y]; }
	if(map[x - 1][y - 1] != map[x][y]) { ul = true; ulID = map[x - 1][y - 1]; }
	if(map[x][y - 1] != map[x][y]) { uu = true; uuID = map[x][y - 1]; }
	if(map[x + 1][y - 1] != map[x][y]) { ur = true; urID = map[x + 1][y - 1]; }
	if(map[x + 1][y] != map[x][y]) { rr = true; rrID = map[x + 1][y]; }
	if(map[x + 1][y + 1] != map[x][y]) { dr = true; drID = map[x + 1][y + 1]; }
} else {
	if(x == 0 && y == 0) {
		if(map[x][y + 1] != map[x][y]) { dd = true; ddID = map[x][y + 1]; }
		if(map[mapWidth - 1][y + 1] != map[x][y]) { dl = true; dlID = map[mapWidth - 1][y + 1]; }
		if(map[mapWidth - 1][y] != map[x][y]) { ll = true; llID = map[mapWidth - 1][y]; }
		if(map[mapWidth - 1][mapHeight - 1] != map[x][y]) { ul = true; ulID = map[mapWidth - 1][mapHeight - 1]; }
		if(map[x][mapHeight - 1] != map[x][y]) { uu = true; uuID = map[x][mapHeight - 1]; }
		if(map[x + 1][mapHeight - 1] != map[x][y]) { ur = true; urID = map[x + 1][mapHeight - 1]; }
		if(map[x + 1][y] != map[x][y]) { rr = true; rrID = map[x + 1][y]; }
		if(map[x + 1][y + 1] != map[x][y]) { dr = true; drID = map[x + 1][y + 1]; }
	} else if(x == mapWidth - 1 && y == 0) {
		if(map[x][y + 1] != map[x][y]) { dd = true; ddID = map[x][y + 1]; }
		if(map[x - 1][y + 1] != map[x][y]) { dl = true; dlID = map[x - 1][y + 1]; }
		if(map[x - 1][y] != map[x][y]) { ll = true; llID = map[x - 1][y]; }
		if(map[x - 1][mapHeight - 1] != map[x][y]) { ul = true; ulID = map[x - 1][mapHeight - 1]; }
		if(map[x][mapHeight - 1] != map[x][y]) { uu = true; uuID = map[x][mapHeight - 1]; }
		if(map[0][mapHeight - 1] != map[x][y]) { ur = true; urID = map[0][mapHeight - 1]; }
		if(map[0][y] != map[x][y]) { rr = true; rrID = map[0][y]; }
		if(map[0][y + 1] != map[x][y]) { dr = true; drID = map[0][y + 1]; }
	} else if(x == mapWidth - 1 && y == mapHeight - 1) {
		if(map[x][0] != map[x][y]) { dd = true; ddID = map[x][0]; }
		if(map[x - 1][0] != map[x][y]) { dl = true; dlID = map[x - 1][0]; }
		if(map[x - 1][y] != map[x][y]) { ll = true; llID = map[x - 1][y]; }
		if(map[x - 1][y - 1] != map[x][y]) { ul = true; ulID = map[x - 1][y - 1]; }
		if(map[x][y - 1] != map[x][y]) { uu = true; uuID = map[x][y - 1]; }
		if(map[0][y - 1] != map[x][y]) { ur = true; urID = map[0][y - 1]; }
		if(map[0][y] != map[x][y]) { rr = true; rrID = map[0][y]; }
		if(map[0][0] != map[x][y]) { dr = true; drID = map[0][0]; }
	} else if(x == 0 && y == mapHeight - 1) {
		if(map[x][0] != map[x][y]) { dd = true; ddID = map[x][0]; }
		if(map[mapWidth - 1][0] != map[x][y]) { dl = true; dlID = map[mapWidth - 1][0]; }
		if(map[mapWidth - 1][y] != map[x][y]) { ll = true; llID = map[mapWidth - 1][y]; }
		if(map[mapWidth - 1][y - 1] != map[x][y]) { ul = true; ulID = map[mapWidth - 1][y - 1]; }
		if(map[x][y - 1] != map[x][y]) { uu = true; uuID = map[x][y - 1]; }
		if(map[x + 1][y - 1] != map[x][y]) { ur = true; urID = map[x + 1][y - 1]; }
		if(map[x + 1][y] != map[x][y]) { rr = true; rrID = map[x + 1][y]; }
		if(map[x + 1][0] != map[x][y]) { dr = true; drID = map[x + 1][0]; }
	} else if(x == 0) {
		if(map[x][y + 1] != map[x][y]) { dd = true; ddID = map[x][y + 1]; }
		if(map[mapWidth - 1][y + 1] != map[x][y]) { dl = true; dlID = map[mapWidth - 1][y + 1]; }
		if(map[mapWidth - 1][y] != map[x][y]) { ll = true; llID = map[mapWidth - 1][y]; }
		if(map[mapWidth - 1][y - 1] != map[x][y]) { ul = true; ulID = map[mapWidth - 1][y - 1]; }
		if(map[x][y - 1] != map[x][y]) { uu = true; uuID = map[x][y - 1]; }
		if(map[x + 1][y - 1] != map[x][y]) { ur = true; urID = map[x + 1][y - 1]; }
		if(map[x + 1][y] != map[x][y]) { rr = true; rrID = map[x + 1][y]; }
		if(map[x + 1][y + 1] != map[x][y]) { dr = true; drID = map[x + 1][y + 1]; }
	} else if(x == mapWidth - 1) {
		if(map[x][y + 1] != map[x][y]) { dd = true; ddID = map[x][y + 1]; }
		if(map[x - 1][y + 1] != map[x][y]) { dl = true; dlID = map[x - 1][y + 1]; }
		if(map[x - 1][y] != map[x][y]) { ll = true; llID = map[x - 1][y]; }
		if(map[x - 1][y - 1] != map[x][y]) { ul = true; ulID = map[x - 1][y - 1]; }
		if(map[x][y - 1] != map[x][y]) { uu = true; uuID = map[x][y - 1]; }
		if(map[0][y - 1] != map[x][y]) { ur = true; urID = map[0][y - 1]; }
		if(map[0][y] != map[x][y]) { rr = true; rrID = map[0][y]; }
		if(map[0][y + 1] != map[x][y]) { dr = true; drID = map[0][y + 1]; }
	} else if(y == 0) {
		if(map[x][y + 1] != map[x][y]) { dd = true; ddID = map[x][y + 1]; }
		if(map[x - 1][y + 1] != map[x][y]) { dl = true; dlID = map[x - 1][y + 1]; }
		if(map[x - 1][y] != map[x][y]) { ll = true; llID = map[x - 1][y]; }
		if(map[x - 1][mapHeight - 1] != map[x][y]) { ul = true; ulID = map[x - 1][mapHeight - 1]; }
		if(map[x][mapHeight - 1] != map[x][y]) { uu = true; uuID = map[x][mapHeight - 1]; }
		if(map[x + 1][mapHeight - 1] != map[x][y]) { ur = true; urID = map[x + 1][mapHeight - 1]; }
		if(map[x + 1][y] != map[x][y]) { rr = true; rrID = map[x + 1][y]; }
		if(map[x + 1][y + 1] != map[x][y]) { dr = true; drID = map[x + 1][y + 1]; }
	} else if(y == mapHeight - 1) {
		if(map[x][0] != map[x][y]) { dd = true; ddID = map[x][0]; }
		if(map[x - 1][0] != map[x][y]) { dl = true; dlID = map[x - 1][0]; }
		if(map[x - 1][y] != map[x][y]) { ll = true; llID = map[x - 1][y]; }
		if(map[x - 1][y - 1] != map[x][y]) { ul = true; ulID = map[x - 1][y - 1]; }
		if(map[x][y - 1] != map[x][y]) { uu = true; uuID = map[x][y - 1]; }
		if(map[x + 1][y - 1] != map[x][y]) { ur = true; urID = map[x + 1][y - 1]; }
		if(map[x + 1][y] != map[x][y]) { rr = true; rrID = map[x + 1][y]; }
		if(map[x + 1][0] != map[x][y]) { dr = true; drID = map[x + 1][0]; }
	}
}

[tl;dr]
I am trying to see for every tile on the map who are it’s neighbours. I use this later to update every tile’s image.

Is there any way to make this code smaller?

It’s same as minesweeper, and I have made it before. Calculate the indexes first then limit to within array’s length.


int xi, yi;
xi = x - 1; yi = y - 1; if ((xi >= 0 && xi < map.length) && (yi >= 0 && yi < map[0].length)){ }
xi = x - 1; yi = y; if ((xi >= 0 && xi < map.length) && (yi >= 0 && yi < map[0].length)){ }
...
xi = x + 1; yi = y + 1; if ((xi >= 0 && xi < map.length) && (yi >= 0 && yi < map[0].length)){ }

That should work on every tile, even if it’s on side or corner.

This is how i did before, but now i want to check tor the “neighbours” from the other side if the tile is on the edge.


int xi, yi;
xi = x - 1; yi = y - 1; normalize(xi, yi); //do the work
...
xi = x + 1; yi = y + 1; normalize(xi, yi); //do the work

//meanwhile

void normalize(int xi, int yi){
if (xi >= map.length) xi = 0; else if (xi < 0) xi = map.length - 1;
if (yi >= map[0].length) yi = 0; else if (yi < 0) yi = map[0].length - 1;
}

I’d do something like that:

 
xNext = x+1;
xPrev = x-1;


if (x == mapWidth - 1) xNext=0;
if (x == 0) xPrev = mapWidth - 1;



Then do the ifs just once using the x, xNext and xPrev which have been determined for each scenario.

That code seems to expect pass-by-reference behaviour, which Java doesn’t have.

@Riven
LoL really? I must missed it with C++ or what. Then since it’s only primitive type how about this


int xi, yi;
xi = x - 1; yi = y - 1; xi = normalizeX(xi); yi = normalizeY(yi); //do the work with xi and yi

//meanwhile

int normalizeX(int par){
if (par >= map.length) return 0; else if (par < 0) return map.length - 1;
}

This worked, but i made xi and yi global variables.

EDIT: Ok, maybe i should provide everything in this method.


public void updateTileImage() {
	int mapWidth = map.length, mapHeight = map[0].length;

	for(int y = 0; y < mapHeight; y++) {
		for(int x = 0; x < mapWidth; x++) {
			boolean dd, dl, ll, ul, uu, ur, rr, dr;
			dd = dl = ll = ul = uu = ur = rr = dr = false;
			int ddID, dlID, llID, ulID, uuID, urID, rrID, drID;
			ddID = dlID = llID = ulID = uuID = urID = rrID = drID = 0;

			if(map[x][y] != WaterTile.id) {
				xi = x; yi = y + 1; normalize(xi, yi);
				if(map[xi][yi] != map[x][y]) { dd = true; ddID = map[xi][yi]; }
				xi = x - 1; yi = y + 1; normalize(xi, yi);
				if(map[xi][yi] != map[x][y]) { dl = true; dlID = map[xi][yi]; }
				xi = x - 1; yi = y; normalize(xi, yi);
				if(map[xi][yi] != map[x][y]) { ll = true; llID = map[xi][yi]; }
				xi = x - 1; yi = y - 1; normalize(xi, yi);
				if(map[xi][yi] != map[x][y]) { ul = true; ulID = map[xi][yi]; }
				xi = x; yi = y - 1; normalize(xi, yi);
				if(map[xi][yi] != map[x][y]) { uu = true; uuID = map[xi][yi]; }
				xi = x + 1; yi = y - 1; normalize(xi, yi);
				if(map[xi][yi] != map[x][y]) { ur = true; urID = map[xi][yi]; }
				xi = x + 1; yi = y; normalize(xi, yi);
				if(map[xi][yi] != map[x][y]) { rr = true; rrID = map[xi][yi]; }
				xi = x + 1; yi = y + 1; normalize(xi, yi);
				if(map[xi][yi] != map[x][y]) { dr = true; drID = map[xi][yi]; }
			}

			Tile currentTile = levelTiles[x][y];

			if(dd && ll && uu && rr) currentTile.update(Tile.getTile(ddID), ImageEditor.C4, ImageEditor.D4_ALL);

			else if(dd && ll && uu) currentTile.update(Tile.getTile(ddID), ImageEditor.C3, ImageEditor.D3_UPLEFTDOWN);
			else if(ll && uu && rr) currentTile.update(Tile.getTile(llID), ImageEditor.C3, ImageEditor.D3_RIGHTUPLEFT);
			else if(uu && rr && dd) currentTile.update(Tile.getTile(uuID), ImageEditor.C3, ImageEditor.D3_DOWNRIGHTUP);
			else if(rr && dd && ll) currentTile.update(Tile.getTile(rrID), ImageEditor.C3, ImageEditor.D3_LEFTDOWNRIGHT);

			else if(uu && dd) currentTile.update(Tile.getTile(ddID), ImageEditor.C2_DIRECTION, ImageEditor.D2_UPDOWN);
			else if(ll && rr) currentTile.update(Tile.getTile(llID), ImageEditor.C2_DIRECTION, ImageEditor.D2_LEFTRIGHT);

			else if(dd && ll) currentTile.update(Tile.getTile(ddID), ImageEditor.C2_CORNER, ImageEditor.D2_DOWNLEFT);
			else if(ll && uu) currentTile.update(Tile.getTile(llID), ImageEditor.C2_CORNER, ImageEditor.D2_LEFTUP);
			else if(uu && rr) currentTile.update(Tile.getTile(uuID), ImageEditor.C2_CORNER, ImageEditor.D2_UPRIGHT);
			else if(rr && dd) currentTile.update(Tile.getTile(rrID), ImageEditor.C2_CORNER, ImageEditor.D2_RIGHTDOWN);

			else if(dd) currentTile.update(Tile.getTile(ddID), ImageEditor.C1_DIRECTION, ImageEditor.D1_DOWN);
			else if(ll) currentTile.update(Tile.getTile(llID), ImageEditor.C1_DIRECTION, ImageEditor.D1_LEFT);
			else if(uu) currentTile.update(Tile.getTile(uuID), ImageEditor.C1_DIRECTION, ImageEditor.D1_UP);
			else if(rr) currentTile.update(Tile.getTile(rrID), ImageEditor.C1_DIRECTION, ImageEditor.D1_RIGHT);

			else if(dl) currentTile.update(Tile.getTile(dlID), ImageEditor.C1_OUT, ImageEditor.D1_ODL);
			else if(ul) currentTile.update(Tile.getTile(ulID), ImageEditor.C1_OUT, ImageEditor.D1_OUL);
			else if(ur) currentTile.update(Tile.getTile(urID), ImageEditor.C1_OUT, ImageEditor.D1_OUR);
			else if(dr) currentTile.update(Tile.getTile(drID), ImageEditor.C1_OUT, ImageEditor.D1_ODR);
		}
	}
}

another code to simplied? :o

Err…forget booleans and build integers out of bits. For example that last huge cascaded if-else construct becomes a single line.

You should rather explain what you’re trying to accomplish to get proper solutions, rather than posting some unreadable code and ask for it to be “simplified”.

That code is way too long.
try this

ArrayList<Tile> neighbours = new ArrayList<Tile>();

for(int dy = -1; dy <= 1; dy++) {
    for(int dx = -1; dx <= 1; dx++) {
        if(dx == 0 && dy == 0) continue;
        int nx = x+dx, ny = y+dy;
        if(nx >= 0 && nx < mapWidth &&
           ny >= 0 && ny < mapHeight) {
               neighbours.add(map[nx][ny]);
        }
    }
}

That’s sexy if it works DrZoidberg.
Big ass code optimization.

Can you give me an example, please?

After i am loading a map from the server, i want to connect the tiles one to other… Here is a pic of what i want to achive… or i already achived, but it takes 4+ sceonds to do…

Ok, now I realized that the 4+ seconds aren’t from this code… This topic may get a new way now.

I am using LWJGL. The connections you saw above are made in this “ImageEditor” class. What it does is to take the two connecting tiles images (BufferedImage) and a mask for the “connection case”, then it transforms the resulting BufferedImage into a Texture and sends to respective tile this Texture’s ID. The problem is that there are 19 connection cases and currently 5 types of tile (Grass, Dirt, Sand, Water, Tree). This “connection” stage happens only once in game, when client receive the map from server. Is there any way to make this process last shorter, or I am trying to achieve something that when i will have 20+ tiles will last even one minute ?

I don’t see why you don’t create the map with the rounded edges, e.g. in Tiled or whatever tool you are using to design the maps.

Because i am generating the map random using Perlin Noise.

Ok, how i reduced the textures made in a 256x256 map from 7000+ to (number of tile types ^ 2 * number of cases of connections) was to make a 3D int array where i store the textureID for each case. i don’t know if this is the best approach, but it works very good. The time reduced from 4+ seconds to ~150 ms.

Here is the last version of the update method. If anyone could suggest me anything that will make it easier, please post.


import com.minier.level.tile.Tile;
import com.minier.level.tile.WaterTile;
import com.minier.util.ResourceEditor;

public void updateTileImage(int x, int y) {
	Tile currentTile = levelTiles[x][y];
	Tile[] neighbours = new Tile[9];

	if(currentTile.getTileID() != WaterTile.id) {
		int currentNeighbour = 0;
		for(int dy = -1; dy <= 1; dy++) {
			for(int dx = -1; dx <= 1; dx++) {
				if(dx == 0 && dy == 0) { currentNeighbour++; continue; }
				int nx = x + dx, ny = y + dy;
				if(levelTiles[normalizeX(nx)][normalizeY(ny)].getTileID() != currentTile.getTileID())
					neighbours[currentNeighbour] = levelTiles[normalizeX(nx)][normalizeY(ny)];
				currentNeighbour++;
			}
		}
	}

	boolean dd = neighbours[7] != null, dl = neighbours[6] != null, ll = neighbours[3] != null, ul = neighbours[0] != null, 
			uu = neighbours[1] != null, ur = neighbours[2] != null, rr = neighbours[5] != null, dr = neighbours[8] != null;

	if(dd && ll && uu && rr) currentTile.update(neighbours[7], ResourceEditor.C4, ResourceEditor.D4_ALL);

	else if(dd && ll && uu) currentTile.update(neighbours[7], ResourceEditor.C3, ResourceEditor.D3_UPLEFTDOWN);
	else if(ll && uu && rr) currentTile.update(neighbours[3], ResourceEditor.C3, ResourceEditor.D3_RIGHTUPLEFT);
	else if(uu && rr && dd) currentTile.update(neighbours[1], ResourceEditor.C3, ResourceEditor.D3_DOWNRIGHTUP);
	else if(rr && dd && ll) currentTile.update(neighbours[5], ResourceEditor.C3, ResourceEditor.D3_LEFTDOWNRIGHT);

	else if(uu && dd) currentTile.update(neighbours[1], ResourceEditor.C2_DIRECTION, ResourceEditor.D2_UPDOWN);
	else if(ll && rr) currentTile.update(neighbours[3], ResourceEditor.C2_DIRECTION, ResourceEditor.D2_LEFTRIGHT);

	else if(dd && ll) currentTile.update(neighbours[7], ResourceEditor.C2_CORNER, ResourceEditor.D2_DOWNLEFT);
	else if(ll && uu) currentTile.update(neighbours[3], ResourceEditor.C2_CORNER, ResourceEditor.D2_LEFTUP);
	else if(uu && rr) currentTile.update(neighbours[1], ResourceEditor.C2_CORNER, ResourceEditor.D2_UPRIGHT);
	else if(rr && dd) currentTile.update(neighbours[5], ResourceEditor.C2_CORNER, ResourceEditor.D2_RIGHTDOWN);

	else if(dd) currentTile.update(neighbours[7], ResourceEditor.C1_DIRECTION, ResourceEditor.D1_DOWN);
	else if(ll) currentTile.update(neighbours[3], ResourceEditor.C1_DIRECTION, ResourceEditor.D1_LEFT);
	else if(uu) currentTile.update(neighbours[1], ResourceEditor.C1_DIRECTION, ResourceEditor.D1_UP);
	else if(rr) currentTile.update(neighbours[5], ResourceEditor.C1_DIRECTION, ResourceEditor.D1_RIGHT);

	else if(dl) currentTile.update(neighbours[6], ResourceEditor.C1_OUT, ResourceEditor.D1_ODL);
	else if(ul) currentTile.update(neighbours[0], ResourceEditor.C1_OUT, ResourceEditor.D1_OUL);
	else if(ur) currentTile.update(neighbours[2], ResourceEditor.C1_OUT, ResourceEditor.D1_OUR);
	else if(dr) currentTile.update(neighbours[8], ResourceEditor.C1_OUT, ResourceEditor.D1_ODR);
}