Float to Int error

Started by bx83, Sun 21/07/2019 09:12:04

Previous topic - Next topic

bx83

mouse.x and mouse.y are integers (I assume)
oEPS.X and oEPS.Y (X and Y of bottom left corner of an Object) are integers (I assume)
EPS_Width and EPS_Height are floats.

Error I get is: [line 9] Type mismatch: cannot convert 'float' to 'int'
What is wrong (apart from hundreds float<->int conversions) with this code?

This is a basic programming question... but it's also driving me insane, so I had to ask.

PS. what I'm trying to do is say: 'if the mouse is in the area of an object's dimensions, 1 quarter in, please set the ThreeCowEmotions switch to true'.
If anyone has a quicker way of doing this, I'm all ears.

Code: ags

function room_load() {
    EPS_Width = IntToFloat(Game.SpriteWidth[oEPS.Graphic]);
    EPS_Height = IntToFloat(Game.SpriteHeight[oEPS.Graphic]);

...

function room_RepExec() {
    if (EmotionsSwitch) {
      if (mouse.x >= FloatToInt(oEPS.X + (EPS_Width/4))) {
        if (mouse.x =< FloatToInt((oEPS.X + EPS_Width) - (EPS_Width/4))) {
          if (mouse.y >= FloatToInt(oEPS.Y - (EPS_Height/4) ) - (EPS_Width/4)) {
            if (mouse.y =< FloatToInt((oEPS.Y - EPS_Height) - (EPS_Width/4))) {
              Display("cowemotions true at %d, %d", oEPS.X, oEPS.Y);
              ThreeCowEmotions=true;
              EmotionsSwitch=false;
            }
          }
        }
      }
    }

eri0o

#1
The mouse is just 1 pixel position, what do you mean by 1/4 in? What is oEPS? Is it an object? Object have x and y as integers. Probably missing IntToFloat (oEPS.x) ?

Matti

#2
You need one float value after FloatToInt, right now you have a float and an integer value there.
So instead of
Code: ags
FloatToInt(oEPS.X + (EPS_Width/4)

it should be
Code: ags
oEPS.X + FloatToInt(EPS_Width/4)


I don't really get why you want to use floats anyway, what is the purpose? Like eri0o just wrote: The mouse can't have a position between two pixels, it's just one exact pixel position.
Also, I don't get why you bring in EPS_Width in lines 11 and 12, shouldn't you only check for EPS_Height there?

If I'm not mistaken about what you're trying to accomplish, then this should work:

Code: ags

    if (EmotionsSwitch) {
      if (mouse.x >= oEPS.X + oEPS.Width/4) {
        if (mouse.x <= oEPS.X + oEPS.Width - oEPS.Width/4) {
          if (mouse.y >= oEPS.Y - oEPS.Height + oEPS.Height/4) {
            if (mouse.y <= oEPS.Y - oEPS.Width/4) {
              Display("cowemotions true at %d, %d", oEPS.X, oEPS.Y);
              ThreeCowEmotions=true;
              EmotionsSwitch=false;
            }
          }
        }
      }
    }


EDIT:

In my understanding what bx83 is trying to achieve is this: There's an object (green) and something should happen when the players clicks the middle part of it (yellow, 1/4 height and width from the sides):

[imgzoom]http://ags.pics/D6rj.png[/imgzoom]

bx83

#3
That was exactly what I was doing.

Finished code (with no floats, got confused):


Code: ags

    if (EmotionsSwitch) {
      if ( (mouse.x >= (oEPS.X + (EPS_Width/4))) && mouse.x <= ((oEPS.X + EPS_Width) - (EPS_Width/4)) ) {
        if ( (mouse.y >= ((oEPS.Y - EPS_Height) + (EPS_Height/4))) && (mouse.y <= (oEPS.Y - (EPS_Height/4))) ) {
            Display("cowemotions true at %d, %d", mouse.x, mouse.y);
            ThreeCowEmotions=true;
            EmotionSwitch=false;
        }
      }
    }


Khris

Just for reference,
Code: ags
 if (mouse.x >= FloatToInt(oEPS.X + (EPS_Width/4))) {

should've been:
Code: ags
 if (mouse.x >= FloatToInt(IntToFloat(oEPS.X) + (EPS_Width/4.0))) {


Gilbert

Yes. It may look silly, but you have to make sure the types of the variables match when performing arithmetics. One purpose of this is to avoid bugs/errors/quirks/desserts caused by ambiguity.
Just take the 'EPS_Width/4' part as an example. If EPS_Width is supposed to be a float it would be ambiguous on whether this is an integer division (with result truncated to an integer) or a decimal division, as the number 4 is an integer, which may bring huge difference in your calculations depending on what you are doing (and will be very hard to debug). So, if you just want (a) integer division on that one, just change EPS_Width to integer before the division 'FloatToInt(EPS_Width)/4', or if you want (b) a decimal division you need to use instead 'EPS_Width/4.0' as the number 4.0 is a float (OR if you want to do it the evil way, 'EPS_Width/IntToFloat(4)' :=), or, if you want to (c) perform decimal division and then truncate or round the number into an integer you have to use 'FloatToInt(EPS_Width/4.0, eRoundDown)' or 'FloatToInt(EPS_Width/4.0, eRoundNearest)', etc.

Confused? Let's illustrate this with an example, say, EPS_Width = 6.4, then the results of the above cases are as follows:
(a)  FloatToInt(EPS_Width)/4 = FloatToInt(6.4)/4 = 6/4 = 1    (6/4 = 1.5, but in integer division the result is truncated to an integer)
(b)  EPS_Width/4.0 = 6.4/4.0 = 1.6
(c)  FloatToInt(EPS_Width/4.0, eRoundDown) = FloatToInt(6.4/4.0, eRoundDown) = FloatToInt(1.6, eRoundDown) = 1
and FloatToInt(6.4/4.0, eRoundNearest) = FloatToInt(1.6, eRoundNearest) = 2

Laura Hunt

#7
Quote from: Gilbert on Mon 22/07/2019 11:58:19
Yes. It may look silly, but you have to make sure the types of the variables match when performing arithmetics. One purpose of this is to avoid bugs/errors/quirks/desserts caused by ambiguity.
Just take the 'EPS_Width/4' part as an example. If EPS_Width is supposed to be a float it would be ambiguous on whether this is an integer division (with result truncated to an integer) or a decimal division, as the number 4 is an integer, which may bring huge difference in your calculations depending on what you are doing (and will be very hard to debug). So, if you just want (a) integer division on that one, just change EPS_Width to integer before the division 'FloatToInt(EPS_Width)/4', or if you want (b) a decimal division you need to use instead 'EPS_Width/4.0' as the number 4.0 is a float (OR if you want to do it the evil way, 'EPS_Width/IntToFloat(4)' :=), or, if you want to (c) perform decimal division and then truncate or round the number into an integer you have to use 'FloatToInt(EPS_Width/4.0, eRoundDown)' or 'FloatToInt(EPS_Width/4.0, eRoundNearest)', etc.

Confused? Let's illustrate this with an example, say, EPS_Width = 6.4, then the results of the above cases are as follows:
(a)  FloatToInt(EPS_Width)/4 = FloatToInt(6.4)/4 = 6/4 = 1    (6/4 = 1.5, but in integer division the result is truncated to an integer)
(b)  EPS_Width/4.0 = 6.4/4.0 = 1.6
(c)  FloatToInt(EPS_Width/4.0, eRoundDown) = FloatToInt(6.4/4.0, eRoundDown) = FloatToInt(1.6, eRoundDown) = 1
and FloatToInt(6.4/4.0, eRoundNearest) = FloatToInt(1.6, eRoundNearest) = 2

That's so cool, thanks SO MUCH for the explanation!  ;-D

(Not to mention that I'm an idiot and I thought that the conversion integer - float - integer was being applied only to oEPS.X so of course I was like "...why" but obviously it's not, I just missed a bracket. Still, what a fantastic explanation, thanks again.)

Snarky

All well and good, but it doesn't change the fact that instead of:

Quote from: Khris on Sun 21/07/2019 21:26:16
Code: ags
 if (mouse.x >= FloatToInt(IntToFloat(oEPS.X) + (EPS_Width/4.0))) {


Khris's code could more concisely (and efficiently) be written as:

Code: ags
 if (mouse.x >= oEPS.X + FloatToInt(EPS_Width)/4) {



Since there is only one term that could have a decimal part, and that gets truncated when you do the FloatToInt() anyway (which uses eRoundDown by default), there's no reason to do the whole operation in float.

SMF spam blocked by CleanTalk