Differences between Debug and Release

Monkey Forums/Monkey Programming/Differences between Debug and Release

Raz(Posted 2013) [#1]
I've spent the past hour trying to work out how I managed to break the basic collision code. However, I've now realised that the game runs as expected when compiled for debug instead of release...

Debug Compile - Collisions Working

http://www.youtube.com/watch?v=D9y0S7o8U_Y&feature=youtu.be

Release Compile - Collisions... borked

http://www.youtube.com/watch?v=M9wlzbKp-xw&feature=youtu.be

So, I'm stumped. What exactly can I do about this? Where do I begin?

Ta


ziggy(Posted 2013) [#2]
It may be related to one running faster? Are you using any kind of delta timing? Does it happens on all targets?


Raz(Posted 2013) [#3]
Thanks ziggy, no, no delta timing. Only tried glfw but I'll set xna up again and give that a go.


Gerry Quinn(Posted 2013) [#4]
Hmm, in native C++ this usually happens because you overwrote something (outside array bounds, say) that did something harmless in debug, because stuff is spread out more. Or because objects in debug mode come filled with a large semi-random value, and a misplaced test for zero gave the wrong result. This shouldn't really happen in C++ made from Monkey, but maybe there is some case that is getting missed, or a bug in some native code somewhere? Or a debug test that actually fixes something?

I would definitely try it on other targets to try to narrow it down. If nothing else, maybe one of them will fail in a more helpful manner.

Have you tried printing out intermediate values from your collision testing code? This could also show you where the difference is.


Raz(Posted 2013) [#5]
Works fine with XNA and HTML5, for Debug and Release.

I think I've narrowed it down, it's something to do with the mod function.

I use it to determine a subset of the level tiles to check for collisions however it's producing strange results for release builds now.

Excuse the large images but, the following shows which tiles the player is checking against for the debug build.



The same for the release build shows this (and it flicks to the 8 tiles directly below those shown in the screenshot as the player moves down)



The code to determine which tiles to check is...

[monkeycode]
Local x1:Float = position.X - (w * 1.66)
Local x2:Float = position.X + (w * 1.66)
Local y1:Float = position.Y - (h * 1.66)
Local y2:Float = position.Y + (h * 1.66)

Local tX1:Int = (x1 - (x1 Mod Tile.WIDTH)) / Tile.WIDTH
Local tY1:Int = (y1 - (y1 Mod Tile.HEIGHT)) / Tile.HEIGHT

Local tX2:Int = (x2 - (x2 Mod Tile.WIDTH)) / Tile.WIDTH
Local tY2:Int = (y2 - (y2 Mod Tile.WIDTH)) / Tile.HEIGHT

For Local x:Int = tX1 To tX2
For Local y:Int = tY1 To tY2
' DO STUFF HERE
Next
Next
[/monkeycode]


Raz(Posted 2013) [#6]
Ok so instead of multiplying width by 1.66, it works fine...

Local x1:Float = position.X - (w)
Local x2:Float = position.X + (w)
Local y1:Float = position.Y - (h)
Local y2:Float = position.Y + (h)


Using the above shows the blocks I would expect the system to check. I am really confused, this code has been in place for months now and it's only just become an issue. the w and h variables are just floats. I am beginning to think maybe the rounding of the floats is happening in a different manner between debug and release builds?


SLotman(Posted 2013) [#7]
Are you running the game at same resolution on every platform, or using autofit?

It looks like a scaling/precision problem, where did you take that 1.66 from?


Raz(Posted 2013) [#8]
I'm using auto fit in some instances but that should just affect rendering tasks right? Originally I was checking for 0.66 of the width, with the logic being its just over half so guarantees all of the required tiles are checked. I upped this to 1.66 just to test because I thought some how things could be getting missed.

I wonder if the mod function has changed?


ImmutableOctet(SKNG)(Posted 2013) [#9]
Just realized you made a forum thread for your issue (As mentioned on Twitter), so I'll post a response here.

The modulus 'function' is actually a keyword in Monkey, and from what I remember, it's completely language specific (AKA, '%' in C++).

However, 'Mod' (In C++) isn't supposed to be used with floats, only integers, as it tends to cause issues. Normally I'd say this is a problem, but Mark thought ahead, and Monkey's translator actually realizes this, and adds 'fmod' when needed. In C and C++, we have "math.h" and "tgmath.h" (<ctgmath>) which provide math functions like 'fmod'.

For reference, here's a Monkey-based 'fmod' function:
Function FMod:Float(X:Float, Y:Float)
	Return (X - Int(X/Y) * Y)
End
After looking at some generated code, these lines in Monkey:
Local TestInt:Int = 10
Local TestFloat:Float = 10.345

Print(String(TestInt Mod 4))
Print(String(TestFloat Mod 10.0))
Become these lines with the standard C++, and GLFW targets:
int t_TestInt=10;
Float t_TestFloat=FLOAT(10.345);
Print(String(t_TestInt % 4));
Print(String((Float)fmod(t_TestFloat,FLOAT(10.0))));
('Print' was changed to 'bbPrint' in slightly newer versions of Monkey)
Output (GLFW, 'CPP_DOUBLE_PRECISION_FLOATS' not even defined, and set to false):
2
0.34500026702880859
Output (GLFW, 'CPP_DOUBLE_PRECISION_FLOATS' = True):
2
0.34500000000000064
Output (STDCPP, 'CPP_DOUBLE_PRECISION_FLOATS' = True):
2
0.34500000000000064
Output (STDCPP, 'CPP_DOUBLE_PRECISION_FLOATS' = False):
2
0.34500026702880859


This output is exactly the same with both debug enabled and disabled. So, I've pretty much ruled out this being a bug with Monkey and its C++ targets. But for some reason, 'CPP_DOUBLE_PRECISION_FLOATS' seems to be acting a bit unusual, despite what further tests imply.


Raz(Posted 2013) [#10]
Hey Sonickidnextgen, thanks for the detailed post :D

I did actually look at the generated code to see what was happening which lead me to discover the fmod function. Once I saw it could handle decimals I kind of gave up.