1
\$\begingroup\$

I have a Array that stores my map data and my Tiles are 64X64. Sometimes I need to convert from pixels to units of tiles. So I was doing:

int x
int y

public void myFunction()
{
    getTile((int) Math.floor(x / TILE_SIZE), (int) Math.floor(y / TILE_SIZE)).doOperation();
}

But I discovered by using (I'm using java BTW) System.out.println((int) (1 / 1.5)) that converting to an int automatically rounds down. This means that I can replace the (int) Math.floor with just x / 64.

But if I run this on a different OS do you think it might give a different result? I'm just afraid there might be some case where this would round up and not down. Should I keep doing it the way I was and maybe make a function like convert(int i) to make it easier? Or is it OK to just do x / 64?

\$\endgroup\$
3
  • \$\begingroup\$ Java behaves the same in any platform. It will always round down. \$\endgroup\$
    – AturSams
    Oct 6, 2012 at 16:13
  • 2
    \$\begingroup\$ Casting a float with (int) in java truncates everything after the decimal. It's not actually rounding, it just gets rid of anything but the integer. \$\endgroup\$
    – derivative
    Oct 6, 2012 at 17:07
  • 8
    \$\begingroup\$ floor and cast-to-int will be different for negative numbers though. i.e. floor(-2.8) = -3.0 vs (int)-2.8 = -2.0. \$\endgroup\$
    – 5ound
    Oct 6, 2012 at 17:37

3 Answers 3

2
\$\begingroup\$

Personally, I would write the code just as:

unsigned int x
unsigned int y

public void myFunction()
{
    getTile(x / 64, y / 64).doOperation();
}

since being a tilemap, you can use it (and thus assume) using positive-only values. This does not affect readability because x and y are declared as unsigned int, quite close to the block, and every programmer knows whether the language performs or not an integer division with the / operator when it is applied to two integers (most of them do). In fact, such a geometrical scenario is probably one of the few ones that shows that integer divisions can be useful.

Moreover, thinking about omptimization of such a snippet represents, in my opinion, one of those cases of "unnecessary preventive optimization": you can often assume that such operations will not be a bottleneck of your code, and thus take actions only when profiling shows the opposite. Performance of casting operations can be difficult to evaluate, in general: they largely depend not only on the language, but also on the compiler, which can remove unnecessary casts, or "translate" them in worse/better assembler.

\$\endgroup\$
2
\$\begingroup\$

I guess it safe to assume it is never negative, given that doing so would be reading outside the confine of the array. If that the case, simply rotate the bits 6 times which gives the same results but is far faster than using the int divide counterpart.

int x
int y

public void myFunction()
{
     getTile(x >> 6, y >> 6).doOperation();
}
\$\endgroup\$
5
  • \$\begingroup\$ That is true, however, it is situational, it is possible that in the future he may use different numbers for tile sizes. That reminds me he should probably use constants instead of magic numbers for the tile size \$\endgroup\$
    – AturSams
    Oct 6, 2012 at 19:29
  • 3
    \$\begingroup\$ Personally I'd put the whole calculation inside the actual function and call the function getTileUsingWorldUnit(x, y).doOperation(); leaving the worry about the calculation / optimization in one place rather than each function call. \$\endgroup\$
    – John
    Oct 6, 2012 at 20:46
  • \$\begingroup\$ I agree with this. It is better to keep this abstract. \$\endgroup\$
    – AturSams
    Oct 6, 2012 at 21:10
  • \$\begingroup\$ @John I think I might do that. thanks for the idea. \$\endgroup\$
    – Lysol
    Oct 7, 2012 at 3:52
  • \$\begingroup\$ @ArthurWulfWhite Actually I am using constants :) I figured maybe I'd change it. I probably won't though. But if I need to I can. \$\endgroup\$
    – Lysol
    Oct 7, 2012 at 3:54
2
\$\begingroup\$

Using Math.floor should not greatly decrease performance for your game and it makes the code more readable (self commented) and easy to understand.

Java logic will behave the same in any platform, the only difference between platforms is performance.

I think you could use this to define your tile size (to make the code more readable and easier to modify).

public static final int TILE_WIDTH  = 64;
public static final int TILE_HEIGHT = 64;

now

getTile((int) Math.floor(x / TILE_WIDTH),
        (int) Math.floor(y / TILE_HEIGHT)).doOperation();
\$\endgroup\$
4
  • \$\begingroup\$ So you're saying leave it like it was because it makes it more readable? \$\endgroup\$
    – Lysol
    Oct 6, 2012 at 16:17
  • \$\begingroup\$ I think it is a good trade-off if you are not calling this function thousands of time each frame. I automatically knew what would happen when I saw .floor but casting to (int) behaves differently in different languages, for instance c# just rounds the number. \$\endgroup\$
    – AturSams
    Oct 6, 2012 at 16:19
  • \$\begingroup\$ @ArthurWulfWhite using an (int) cast in C# does not round the number. But using Convert.ToInt32 does round the number. \$\endgroup\$ Oct 6, 2012 at 17:53
  • \$\begingroup\$ OK I edited my question to include constants \$\endgroup\$
    – Lysol
    Oct 7, 2012 at 3:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .