Using cast() vs Std.int()

Hi,

Is it possible to get a sprite into a bitmapdata, AS3 style? Something like this:

scenery=new Sprite(); 
/* (scenery gets populated with several other sprites) */

var bd:BitmapData=new BitmapData(cast(scenery.width),cast(scenery.height));
 bd.draw(scenery);
 addChild(new Bitmap(bd));

Publishing for OSX all I get is a blank sprite.

Cheers

Didn´t test on OSX, but on other targets this should definitely work. Does it work for Flash target?

Edit: What do you need cast() for?

Hi,

I get the same result exporting for flash (which was rather unexpected). I use the cast to turn those Floats into Ints. This is what haxelib returns, I don’t know if that’s of any relevance:

actuate: [1.8.6]
box2d: [1.2.3]
dox: [dev:/work/stuff/src/PerfTest]
extension-screenshot: [1.0.0]
hxargs: [3.0.0]
hxcpp: 3.2.102 3.2.180 [3.2.205]
hxcs: [3.2.0]
hxjava: [3.2.0]
hxparse: 4.0.0 git [dev:/usr/lib/haxe/lib/hxparse/git/src]
hxtemplo: git [dev:/usr/lib/haxe/lib/hxtemplo/git/src]
layout: 1.2.0 [1.2.1]
lime-samples: 2.4.0 [2.6.0]
lime: 2.5.0 2.6.9 [2.8.3]
markdown: [1.0.0]
msignal: [1.2.2]
openfl-samples: 3.1.0 [3.3.1]
openfl: [3.5.3]
swf: 1.9.0 2.1.2 [2.1.6]

Cheers

cast doesn’t work that way. Use Std.int() instead.

@player I just cast because it works and is way faster, at least by my very humble tests. Is there any issue I should be aware of (I’m no big time dev)?

Using cast will force the float to pass, but doesn’t convert it, so the result is likely to be incorrect.

@ibilon What kind of incorrect? I’m using it for everything (well, positioning on stage, bitmap sizing, screen sizes… simple 2D stuff mostly) and it seems to be spot on, feels like a low time Math.floor.

Well… now I feel like an idiot… I was fiddling with the transparency settings and the stacking order, everything was working fine from the beginning, it was obfuscated somewhere at the bottom of the display list.

Thanks and sorry :frowning:

I did some testing, and here’s what I found:

var f:Float = 0.3;
var i:Int = cast f;
var j:Int = Std.int(f);
trace([i, j]);

Flash: [0, 0]
C++: [0, 0]

I knew Flash had some sort of automatic conversion, but I was surprised to find this works for C++. Turns out, that’s because HXCPP likes to cast values:

Float f = ((Float)0.1);
int i = ((int) f);
int j = ::Std_obj::_int(f);

So both i and j are converted correctly, with the difference being that j requires an extra function call.

Then I tested on Neko, Output: [0.3, 0]. Oops!

Well, maybe you don’t need Neko. How about HTML5? [0.30000000000000004,0].

Looks like this becomes a problem on targets without static typing. If that’s true, I’d expect it to fail in PHP and Python as well.

Prompted by curiosity I also ran some tests, and everything looks more than ok with cast, unless there is an error in my method:

   var d0:Float;
   var tmax:Int=0x3FFFFFFF; 
   var int0:Int=0;
   var float0:Float=0;

   d0=getTimer();
   for(a in 0...tmax)
       {   
           float0=float0+.01;
           int0=cast(float0);
       }
   
   trace("int0:"+int0);
   trace("A cast: "+(getTimer()-d0) );
   float0=0;

   d0=getTimer();
   for(a in 0...tmax)
       {
           float0=float0+.01;
           int0=Std.int(float0);
       }
   
   trace("int0:"+int0);
   trace("B Std.int: "+(getTimer()-d0) );
   float0=0;

   d0=getTimer();
   for(a in 0...tmax)
       {
           float0=float0+.01;
           int0=Math.floor(float0);
       }
   trace("int0:"+int0);
   trace("C Math.floor: "+(getTimer()-d0) );
   float0=0;

This are the results, exporting for cpp on osx, 8 GB 1333 MHz DDR3, 3.1 GHz Intel Core i5:

    Main.hx:185: int0:10737418
    Main.hx:186: A cast: 976
    Main.hx:196: int0:10737418
    Main.hx:197: B Std.int: 4016
    Main.hx:207: int0:10737418
    Main.hx:208: C Math.floor: 5845

I tried to run this int i = ((int) f); kind of thing, but does not compile

So I still fail to see what’s incorrect with this approach.

OT: Maybe it’d be better to change the title of the thread. Is that possible?

Do you get a pencil “edit” button next to the top title?

Didn’t even pay attention to it. Done.

It’s fine on C++, the problem is when you compile for Neko and/or HTML5. Have you tried those?

to html5:

Main.hx:185: int0:10737418.068676086PerfTest.js (line 2874)
Main.hx:186: A cast: 1009PerfTest.js (line 2874)
Main.hx:196: int0:10737418PerfTest.js (line 2874)
Main.hx:197: B Std.int: 1337PerfTest.js (line 2874)
Main.hx:207: int0:10737418PerfTest.js (line 2874)
Main.hx:208: C Math.floor: 1960

I gave up neko; it takes ages to complete the loops.

You don’t have to run the loops to see the error. The important thing is to notice that the cast operation doesn’t produce an integer.

In your example, it produced 10737418.068676086 rather than 10737418. In mine, it produced 0.3 rather than 0.

Edit: if you insist on using the fast option where possible, you can make an inline function for it:

public static inline function castInt(value:Float):Int {
    #if (cpp || flash)
    return cast value;
    #else 
    return Std.int(value);
    #end
}

This will use cast in C++ and fall back to Std.int() for HTML5.

I see… now I fully understand your previous comment about the different results depending on the platform… first thing learnt today!

Thanks

In the previous code, you could make

return Std.int(value);

to

return ( value < 0?  Math.ceil( value ) : Std.int( value ) );

to ensure to have the same value with negative numbers on all targets.

This should be a standard haxe Math.trunc() function (as in javascript, c++, and so on) :wink:

EDIT: Sorry Std.int( value ) should be enough, as previously. I was thinking in Math.floor