Breakpoint Function for Debugging
-
due to the lack of debugging capabilities of FUZE, i thought it would be helpful to at least be able to set a breakpoint and do a bit of point in time inspection. unfortunately due the limitation of how FUZE functions work, ( primarily not having the ability to have different functions with the same name but having different input parameters like in other languages ) i had to make some exceptions in the implementation. overall i think compromises worked out as well as could be and could be quite useful. my intent was to keep everything as compact as possible without any extraneous overhead for its usage. the idea being you could simply put the single function at the top of you project and call it when needed, and disable it when not.
for completeness, i will provide the code below and step through it and explain its usage and the reasoning behind the various pieces. this will be be pretty lengthy and may fall into tl;dr territory for most but felt it might be helpful for those learning the language, programming in general, and why breakpoints are needed to help troubleshoot problems in code.
note: for those learning, "breakpoints" are not a part of any particular language and are not implemented in the following way in other languages. they are a part of the "Integrated Development Environment" or "IDE" software, which is a set of tools for helping you write code. with FUZE having a simple text editor much like a scripting language would, this is a way to implement these features until a time the FUZE team sees fit to incorporate them into the editor itself.
function setBreakpoint(state, id, msg) /* sets the global state of all breakpoints */ global = false /* ---- */ enabled = state if enabled == 2 then enabled = global endif if enabled then clear() buttonPressed = false while !buttonPressed loop c = controls(0) box(0, 0, gwidth(), 32, red, false) ink(white) textSize(30) printAt(0, 0, "Breakpoint ID: ", id, " [ ", msg, " ]") updateSprites() drawSprites() update() sleep(0.1) buttonPressed = c.rc repeat endif return void
breaking down the function declaration
setBreakpoint(state, id, msg)
, it works as such utilizing the 3 input parameters as follows...state
: is meant to act as a switch with the following values0 = "off" 1 = "on" 2 = "global state"
the intent here is to provide a quick mechanism to enable and disable one or multiple breakpoints quickly without having to resort to commenting them all out of the code. this is also the reason it is the first input parameter to make it quicker to find and change.
id
: is used as an identifier when multiple breakpoints are used. ideally when the FUZE editor gets search capabilities this will come more in handy. currently it would good practice to set a bookmark along with the breakpoint to make it quick and easy to jump to a given section for troubleshooting. due to the loosely typed nature of FUZE this can be used with anint
or astring
(or anything really). this is somewhat "optional" but does need some type of value to be passed into the function. a simple0
would be sufficient to get by.msg
: is used to display the value of something of interest. it can be a string of text, a note or even variable to inspect it's current value (the latter being the whole crux of using breakpoints). this will be demonstrated later.moving on to the body of the function, the
global
variable is a way to trigger multiple breakpoints to be enabled or disabled without having to individually modify each breakpoint. by setting thestate
parameter equal to2
means that particular breakpoint will be turned on and off based on the local "global" variable value set in the function. simply set this variable totrue
for all breakpoints to be ON when they are set to2
in the function call, and set it tofalse
to turn them all OFF.the remainder of the function requires no user modifications and can be left as is. the exception would be which button is used to continue on from a breakpoint. i chose what i felt was the most uncommon button as to not conflict with other buttons that may be used by the program. the rest works as follows...
first it predefines a variable called
enabled
and sets its value equal to our input parameterstate
( this is done for reasons on how FUZE handles referencing undefined variables that get defined inif
statements).next we check to see if the
enabled
value equals2
and if so reset its value to be equal to whatever theglobal
value is. (again, this is just a workaround for the lack aswitch
orelseif
statements in FUZE).then we check to see if the
enabled
variable istrue
(or1
) to see if any more processing needs to happen.
iffalse
(or0
) we exit the function.if
true
the following then happens.- clear the screen.
- predefine a variable called
buttonPressed
- start a
while
loop as long asbuttonPressed
is nottrue
- define variable
c
to be our input controls.
the next bits simply format the display of our breakpoint.
- create a
red
box that takes up the entire width of the display and is 32 pixels high. - sets our text color to
white
- sets our text size to
30
- prints the breakpoint
id
followed by themsg
, all within the bounds of our red box. - does the typical screen updating processes and redraws everything we cleared.
- sleeps for a very short
0.1
seconds to account for lag and any timing latencies in any following button presses. - set the value of
buttonPressed
equal toc.rc
(the right stick click. just because it's the most obscure button used). this is the mechanism that "steps through" the breakpoint and acts as a pseudo "pause". essentially the currentwhile
loop will continue to run indefinitely "halting" the current running program until the button is pressed. at which point the value ofbuttonPressed
istrue
which triggers the exit out of thewhile
loop and to the end of the function.
example:
here is a small example of the function in use. keep in mind, this example doesn't include the function itself and would need to be include to run.for index = 0 to 10 loop setBreakpoint(1, 1, index) // line 1 randomNum = random(100) // line 2 setBreakpoint(2, "check random", randomNum) // line 3 repeat
here we have a simple
for
loop that loops from0
to9
. inside the loop it does the following...setBreakpoint(1, 1, index)
is simply saying toenable
(aka display) this breakpoint, with anid
of1
and show the value of the variableindex
in themsg
.- generate a random number and store it in the variable
randomNum
setBreakpoint(2, "random check", randomNum)
says display this breakpoint when theglobal
variable is set totrue
. use check random as theid
value and show the what the value ofrandomNum
for themsg
as a result, the loop with happen 10 times and the first breakpoint will display the incrementing value of 0 to 9 for every iteration of the loop. the second breakpoint will display a new random number each time a loop repeats so long as
global = true
is set in the function as explained before.
each breakpoint will stop and display this information until the right stick is clicked. -
Looks good. Just beware that you are modifying the text size, which might affect the running code if that has set a text size of its own. Fuze should really have a getTextSize() function so you can easily restore it to the previous value.
Also, I see you do
printAt(0, 0, "Breakpoint ID: ", id, " [ ", msg, " ]")
which maybe could be changed to
printAt(0, 0, "Breakpoint ID: ", id, " [ ", str(msg), " ]")
since I believe not all types are automatically re-typed to string.
-
@vinicity
it's not meant to be a string intentionally. it can be, but in reality can and should be anything you throw in there. as an example if you wanted to see the location of a sprite as an example you should actually plop insetBreakpoint(1, "some id value", getSpriteLocation(nameOfSprite))
and it will display the resulting vector. again, the idea was to keep it flexible so you could display custom messages, arrays, values, function results, etc. to pinpoint what something is doing or its value at any given time.as far as the text goes, yea there were a handful of compromises i had to make to keep it compact but also retain the complete functionality needed to be useful. hopefully something like this will actually make it into the editor itself so we don't need this.