Possible to make a lot of statements into one?

Can i replace this, with something easier? mabye

terrainBase[playerxpos+ix-1][playerypos+iy] == 0
&& terrainBase[playerxpos+ix-1][playerypos+iy] == 3
&& terrainBase[playerxpos+ix-1][playerypos+iy] == 4
&& terrainBase[playerxpos+ix-1][playerypos+iy] == 9

to

"0 3 4 9".indexOf(terrainBase[playerxpos+ix-1][playerypos+iy]) >= 1;

it this possible?

imho it cannot be all of it at the same time.

Do you mean logical or || instead of the
logical and &&?

1 Like

But it’s possible to connect it as you suggested. Maybe convert to String

Or try hasValue() / Reference / Processing.org

When it’s an int

Or hasValue() / Reference / Processing.org

for float

1 Like

Hi @Aryszin,

You mean || instead of && ?
The below is always false, as it can’t be all true.

Cheers
— mnse

1 Like

no i mean i know there is “.indexOf(” but does it work with itegers?

You can convert to String with str()

You can do s.th like…

if (Arrays.asList(0, 3, 4, 9).contains(terrainBase[playerxpos+ix-1][playerypos+iy])) {
    // do something if the value is valid
} else {
    // do something if the value is not valid
}

Alternatively, if you need to know what …

switch (terrainBase[playerxpos+ix-1][playerypos+iy]) {
    case 0:
        // do something if 0
        break;
    case 3:
        // do something if 3
        break;
    case 4:
    case 9:
        // do something if 4 or 9
        break;
    default:
        // do s.th if nothing from above
        break;
}

2 Likes

Alternatively you can make this from int to a class Cell and store there whether it’s air or not

(Maybe you can even say if ( ! terrain … == 0 ) …

One way would be to sort your blocks so that the ones you can collide against (if that’s what you are testing for) are all consecutive so you could just check if terrainBase[] < 5 for example.

Another very fast mechanism is to use a bit-field. If you have fewer than 32 different blocks, you can store the block type as an integer with only one bit set for each block, so as powers of 2. For example, air would be 1, dirt is 2, wood is 4, stone is 8, and so on. (terrainBase[] & 6) > 0 if the block is either dirt or wood since 2 + 4 = 6.

You can make it cleaner with some constants:

final int AIR = 1;
final int DIRT = 2;
final int WOOD = 4;
final int STONE = 8;

int x = WOOD;

println( (x & (DIRT | WOOD | STONE)) > 0 );

If you have between 32 and 64 block types, you could use a 64-bit long integer.

For the larger numbers you can write (1 << 15), for instance which is 1 left-shifted 15 places = 2^15 = 32768. e.g.:

final int LAVA = 1 << 15;

A better way to organize it might be to create a bit-field of properties for each block type. Lets say you want to test blocks for “fall through”, “stand on”, “does damage”, “slippery”, and so on. Let the block types be consecutive numbers and make an array of block properties of type int.

final int FALL_THROUGH = 1 << 0;
final int STAND_ON = 1 << 1;
final int DOES_DAMAGE = 1 << 2;
final int SLIPPERY = 1 << 3;

int[] block_properties = {
  /* AIR */  FALL_THROUGH,
  /* LAVA */ FALL_THROUGH | DOES_DAMAGE,
  /* ICE */ STAND_ON | SLIPPERY
};


// somewhere deep in your code:

int blockId = terrainBase[ playerPos ];
if( block_properties[ blockId ] & DOES_DAMAGE ) heath--;

This way you can easily add new block types and give them the appropriate properties without having to run through your code to add them to the if statements for their behavior. You could add a red lava block that is cool enough you can STAND_ON it, but still hot enough that it DOES_DAMAGE. Add it to the block list and properties and no need to change your code.

1 Like

“Random Tiled Terrain Gen”:

1 Like

i mean or. im sorry.

1 Like

FIX: :blush:

String stuff = "0 5 9 12 182";

for(int i = 0; i < 512; i++) {
   if(stuff.indexOf(str()) => 0) {
      //do stuff that only happens for the numbers in stuff
   }
}
1 Like

In this approach you don’t need a for loop.

It’s >=

Also, str() won’t work.

Or you posted this as an example, right?

1 Like

this works


int[] [] terrainBase = new int [1][1];

String stuff = "0 5 9 12 182";

terrainBase [0][0] = 0;

if (stuff.indexOf(str(terrainBase [0][0])) >= 0) {
  //do stuff that only happens for the numbers in stuff
  println("yes");
} else {
  println("no");
}

or as a function


// MAP
int[][] terrainBase = new int[1][1];

String typesOfCellThatAreNotAir = "0 5 9 12 182";

void setup() {

  terrainBase [0][0] = 0;

  if (isAir(0, 0)) {
    println("yes");
  } else {
    println("no");
  }
}

boolean isAir(int x, int y) {
  println (str(terrainBase[x][y]));
  return
    typesOfCellThatAreNotAir.indexOf(str(terrainBase[x][y])) >= 0; //  returns true only when the map cell is in the numbers in typesOfCellThatAreNotAir
}

1 Like

Hello @Aryszin,

Scrutinize this and output:

It also includes 1, 2, 18 and 82.

It may work in your specific project but not as a generic example for every case.

:)

2 Likes

I have solved it: :laughing:
If someone needs it just copy it. (obviously)

String objectsToSearchFor = "1>2>6>12>65>"; //any other symbol than ">" works
boolean hasOneOfTheSearched;

for(int ix = 0; ix < 64; i++) {
   if (!(objectsToSearchFor.indexOf(str(someArray)+">") >= 0)) {
      //here change the ">" to the symbol that is behind every number in the String
      hasOneOfTheSearched = true;
   }
}

Hi @Aryszin,

the issue @glv pointed out is still not solved by that as it still matches 5>, and also 2> at12>, but latter is luckily also one you want to search on your search pattern… :wink:

Actually I really not understand why you convert to string and searched based on string if you just want to search for some int values and not simply do…

if (Arrays.asList(1, 2, 6, 12, 65).contains(someArrayElement) {
    // do something if one of searched values
} else {
    // do something else or nothing
}

But nevertheless, seems you feel comfortable with your approach, but imo it could be made better…

As a (good) programmer you should strive for almost clean and stable algorithms :slight_smile:

The consequences of getting too lazy is that you run into more confusions the more complexer your tasks are getting…

Cheers
— mnse

1 Like

couldnt you add “<83> <8> <3>” to the string?

You only need to put spaces around the numbers as long as you include one at both the start and end of your list. So " 83 8 3 " and then search for " 8 ".

But please don’t. Converting back and forth from integers to strings is just needlessly slow. Just keep things as integers as @mnse suggested and let Java find the integer elements within the array.

Or better yet, use the constant-time solution. Make an array of booleans, all false except true for the ones you want to match and just check:

boolean[] isSolidBlock = { false, false, true, true, false, ... };

if( isSolidBlock[ terrainBase[j][i] ] ) {
  // bounce off of block
}
2 Likes