How erroneus c# math cost me a couple of hours and nerve cells
The last thing you want in a jam is to struggle with your language of choice, but that is exactly what happened to me.
In my custom rectangular grid world checking logic I've got this piece of code to calculate the position and type of field in rectangle grid into which an enemy is moving:
public (int, int, FieldEnum) getGridPositionAndType(Vector2 position, bool up)
{
float fj = (position.y - transform.position.y + wholeHeight / 2 - wallSize / 2) / wallSize;
int j;
if (up)
j = Mathf.FloorToInt(fj);
else
j = Mathf.CeilToInt(fj);
float fi = (position.x - transform.position.x + wholeWidth / 2 - wallSize / 2) / wallSize;
int i;
if (up)
i = Mathf.FloorToInt(fi);
else
i = Mathf.CeilToInt(fi);
if (i < 0) i = 0;
if (j < 0) j = 0;
if (i >= gridWidth) i = gridWidth - 1;
if (j >= gridHeight) j = gridHeight - 1;
return (i, j, GetFieldType(pixelArray[j * gridWidth + i]));
}
For some inexplicable reason the enemies on the left and bottom sides of the screen were going berserk. I lost some precious hours of my compo development time and was going crazy until I realized the problem was with negative numbers. So I tried adding a large number before doing the operation and subtracting it later:
public (int, int, FieldEnum) getGridPositionAndType(Vector2 position, bool up)
{
float fj = (position.y - transform.position.y + wholeHeight / 2 - wallSize / 2) / wallSize;
int j;
if (up)
j = Mathf.FloorToInt(fj+30f)-30; // force positive math
else
j = Mathf.CeilToInt(fj+30f)-30; // force positive math
float fi = (position.x - transform.position.x + wholeWidth / 2 - wallSize / 2) / wallSize;
int i;
if (up)
i = Mathf.FloorToInt(fi+30f)-30; // force positive math
else
i = Mathf.CeilToInt(fi+30f)-30; // force positive math
if (i < 0) i = 0;
if (j < 0) j = 0;
if (i >= gridWidth) i = gridWidth - 1;
if (j >= gridHeight) j = gridHeight - 1;
return (i, j, GetFieldType(pixelArray[j * gridWidth + i]));
}
It worked like a charm. Then I remembered that most programming languages including c++ and C# are doing modulo operations wrong. Instead of doing proper euclidean map they take the absolute value, calculate modulo on that, and return the sign.
The same goes for rounding off to the nearest higher or lower number (ceiling and floor operation).
I learned this lesson the hard way so I decided to write this up in case it helps anyone.