Diddy (part 3)
Monkey Forums/Monkey Programming/Diddy (part 3)
| ||
Thread continued from here... Original post by therevills: We've started an open-source code base which adds extra functions to Monkey. Currently Diddy (as in Diddy Kong ;)) has the following: * New Commands (tested on most platforms, apart from iOS and Mac): - FlushKeys() - RealMillisecs() - ShowMouse() - HideMouse() * Screen-based Framework - Move between screens with fading http://code.google.com/p/diddy/ Last post in previous thread by Nobuyuki: silly issue: Does a tilemap have to have an .xml extention to be read in by the parser? using a .tmx filename on the wiki example asserts "Tiled Raw XML not supported!" on a supported map, though by changing the same map's extension to .xml it appears to work... Let's see if I've done this right... |
| ||
@Nobuyuki: Does a tilemap have to have an .xml extention Yes, Monkey will only load .txt, .xml, .json With the "Tiled Raw XML" we actually mean the map data within the xml(tmx) file, because it is so verbose it takes ages to parse. So we only support CSV and base64 ;) |
| ||
game.useFixedRateLogic = True Using this stops the app in its tracks... Is this meant to be used, and if so, do I need to set anything else? Dabz |
| ||
@therevills Yes, Monkey will only load .txt, .xml, .json With the "Tiled Raw XML" we actually mean the map data within the xml(tmx) file, because it is so verbose it takes ages to parse. So we only support CSV and base64 ;) Thanks for clearing that up. However, that particular error seems to be thrown even on a valid file with uncompressed base64. It just does it when specifying (what is apparently) an unsupported file extension. I was unaware that the extension had to be one of those with LoadString, actually; I'd just assumed it would attempt to load any file specified as text (!) |
| ||
@Nobuyuki: I was unaware that the extension had to be one of those with LoadString, actually; This is a strange limitation of Monkey. LoadString will only work with those file extensions, regardless of their content. |
| ||
game.useFixedRateLogic = True Using this stops the app in its tracks... Is this meant to be used, and if so, do I need to set anything else? Strange... it really should do the opposite (by increasing the logic around 3 times!) ;) I've just loaded up the animation example and added game.useFixedRateLogic = True and it works fine... [edit] Just been talking to Dabz and he was setting game.useFixedRateLogic = True in the OnCreate method and it totally messes up!! It must be set after creating the game object in Main: Function Main:Int() game = new MyGame() game.useFixedRateLogic = True Return 0 End Function [/edit] |
| ||
Just had a quick build on Android... And the game comes to a shuddering 0 FPS when useFixedRateLogic is set to true!!! EDIT: Had to reduce game.frameRate from the default 200 to get stuff moving, working okayish set to 60 (With my FPS set to 30) Dabz |
| ||
Hmmm just tested the Animation example with the FRL and its fine for me... what are you doing Dabz!?!? I'm changing useFixedRateLogic to a private field and setting a property so you can use it anywhere. [edit] Committed the change, if anyone is using the Fixed Rate Logic stuff, just change how you are setting it from: game.useFixedRateLogic = Trueto game.UseFixedRateLogic = True[/edit] |
| ||
Function Main:Int() game = New MatchGame() game.useFixedRateLogic = True game.frameRate = 60 Return 0 End Function It ran exactly how I wanted in HTML5 and Flash, but as soon as I put it on Android, at the default 200 updates, it crawled to a halt, and I can only get it motoring on there by adding game.frameRate = 60... Which, is still a bit jerky, and not ideal. Dabz |
| ||
Any chance you can send me your code? |
| ||
Will do... What I've just found is, that if I manually update the code in a For loop (Naughty I know), and turn FRL off, I get better results on Android!?! lol Dabz |
| ||
I'll PM you the link over at IndieCodez Therevills me auld bean! EDIT: Sent, let me know when you have it and I'll take it down matey Dabz |
| ||
Got it Mate... think you need to optimise your ProcessFallingTiles method. You are using Lists and EachIn.... everytime you use an EachIn it will create a new object (iterator) and when you are using FRL @ 200Hz it will be doing all these new objects around 3 times per frame which means lots of calls to the GC which in turns slows down the app. [edit] Also since you are changing the UpdateRate do it in the Main function, before setting the FRL: Function Main:Int() game = New MatchGame() game.FPS = 30 game.UseFixedRateLogic = True Return 0 End Function [/edit] |
| ||
Thats fair do's, but how come it runs like a git when there's nothing in any of the lists? Also, when I update the code three times in a onUpdate() method, it works okay too? Dabz |
| ||
Ah, I see your edit now... Will have a peek EDIT: Yep, thats fixed it, cheers for clearing that up me auld bean! :D Dabz |
| ||
Right, I'm pretty content with that now... Will have a tidy of the code me thinks, because I have stupid stuff in there like Local tutherList<CTile> = New List<CTile>! :D Dabz |
| ||
@therevills Sorry about the late reply. Referring back to http://www.monkeycoder.co.nz/Community/posts.php?topic=1060#14395 What I meant was for that fix is adding a method specifically for overriding that get's called in the OnUpdate function. |
| ||
So something like this:Class DiddyApp Extends App ... Method OnUpdate:Int() OverrideUpdate() ' <--- New ... Return 0 End Method OverrideUpdate:Void() End What would you be using this for? |
| ||
One example is I have a music player function. I have it check to see if a song is playing and if it isn't then it plays the next one. I could put it in every screen but this way would be much better. Also, I found what is possibly a problem with your Sprite class. Method MoveForward:Void() dx = -Sin(rotation) * speed dy = -Cos(rotation) * speed move() End There is no move function but there is a Move function. |
| ||
Ah Cool... thanks for bug report. Commited: Added OverrideUpdate method in DiddyApp and fixed MoveForward |
| ||
Just found that game.useFixedRateLogic = True sends my game to a 2FPS on my 3GS iPod, its fine on my 4th gen, but, when I remove the above, it rockets along again... Any idea's Mr T? From the Main() function at the start:- Function Main:Int() game = New MatchGame() game.FPS = 30 game.useFixedRateLogic = True 'Commented out it runs at a steady 30 Return 0 End Function Dabz |
| ||
Hey Dabz, Could you try reducing the framerate? Function Main:Int() game = New MatchGame() game.FPS = 30 game.frameRate = 100 ' <--- CHANGE THIS (default is 200) game.UseFixedRateLogic = True 'Commented out it runs at a steady 30 Return 0 End Function Also I wonder if it is the calls to Millisecs: http://www.monkeycoder.co.nz/Community/posts.php?topic=1719 |
| ||
Just tried Steve, same again... 2FPS still! EDIT: Just lowered that to 30 and now its running at 17-20 FPS, but obviously slows everything right down as I'm generally moving stuff 1 or 2 pixels. Dabz |
| ||
Oh yeah, work-in-progress particle system is checked in. Editor forthcoming, hopefully. |
| ||
Top work Samah, and very timely! :) I was just going to start my own lastnight, but was a bit knackered and put it off till today, though and behold I have a look to see if Steve had been in and voila, you posted exactly what I was after (The particle system)! :D Its gonna be a good day today me thinks! :) Dabz |
| ||
Erm, just little question, when I emit a particle, like so:-If MouseHit(MOUSE_LEFT) e.EmitAt(5, game.mouseX,game.mouseY) Endif How come the particle is emitted on the opposite side of game area on the Y-axis, as in, if I click at the bottom, the particle appears at the top, and vice versa? Dabz |
| ||
@Dabz: How come the particle is emitted on the opposite side of game area on the Y-axis, as in, if I click at the bottom, the particle appears at the top, and vice versa? Because it's using "real" coordinates, where 0,0 is the bottom left corner, and the Y axis points up. You'll need to do: If MouseHit(MOUSE_LEFT) e.EmitAt(5, game.mouseX, SCREEN_HEIGHT - game.mouseY) EndIf |
| ||
Why'd you use "real" coordinates? Monkey works top left by default... Heres the link for the demo for the system Samah has created: http://www.therevillsgames.com/monkey/diddypsystem/MonkeyGame.html (use Chrome ;)) |
| ||
@therevills: Why'd you use "real" coordinates? Monkey works top left by default... Because trigonometry works the other way. I'm not changing the laws of mathematics. If you want positive Y to point down, go change ParticleGroup.Render() and remove all of the "SCREEN_HEIGHT -" references, and invert all your forces (ie. positive Y for gravity). If there's enough call for it I'll put in a flag or something, but I'd rather people just do it the "right" way. :) @therevills: (use Chrome ;)) Yes, Firefox is pretty laggy with the rendering.... :) |
| ||
Updated particle system and the example to show off point forces. Forces currently perform calculations twice (once for each of X and Y) due to Monkey's lack of "out" parameters or multiple return values. I'll fix this soonish. |
| ||
"Because trigonometry works the other way." Not if you look from the back of the screen upside down ;-D |
| ||
Libgdx works like that (To be fair though, ALL of its drawing is from bottom-left), but, to be honest, it would of been nice to follow monkeys coordinate system, instead of adding all the extra over head of you turning it around only for me to turn it back, doesnt make sense to be honest, regardless of how mathematically correct it may be... never mind though, still a top job! ;) Dabz |
| ||
Yeah I dont think it makes sense either... but I'd rather people just do it the "right" way. :) Monkey works top-left, so anything we do should work the same. [edit] Just added useMonkeyCoords variable (UseMonkeyCoords Property) - true by default... [/edit] |
| ||
The "right way" is top left for far more than monkey. Screen coordinates have historically been the same as device coordinates. computers and phones are top left. |
| ||
Have you had a peek at my fixed rate malarcky, I've been going over it tonight and cannot get it to graft at all, though, Dave picked up on:-For local i:Int = 1 to Floor(numTicks) Update(1) Next Where Floor can sometimes return less then 1, which is a bit odd in respect to For i = 1 to 0(Or isnt, I dunno, it still works)... I've been playing with different timing stuff in iOS, totally confusing meself with them to be honest, I'm getting the impression that the way Millisecs() is being handled is the common way after plenty of Googling, so I doubt its that. I dunno, its a poser! :D Dabz |
| ||
You're all a bunch of loonies! Fine, changed permanently. Edit: A side effect of this is that angles are now inverted. PI/2 radians (90 degrees) now points down rather than up. No, I'm not changing it. |
| ||
You're all a bunch of loonies! How? Just because we have to work in Mojo's "wrong" coordinate system, and thus, apply our logic to it, doesnt make me a loon, its just me not wanting to faff on (Which is the whole point in using a framework like this) PI/2 radians (90 degrees) now points down rather than up. No, I'm not changing it. Likewise, if this is wrong in respect of mojo's rotation, then its unfamiliar to people, becomes disjointed with the rest of the system and not as fluid to work with. If thats the plan, then fair do's, if it were me, I'd change it, but, its not my module so anything I say in respect to this is waffle, unless of course, you agree, but I get the impression you won't! :D Hehehe Dabz |
| ||
Urgh it's just such a hassle >_< It's bad enough that rotation is different to Blitzmax (ie. it's "correct" now). Yeah alright, I'll think about changing it. It's just that it'll mess up a lot of things in a lot of places if I'm not careful. It also becomes a problem if the developer decides to do their own trigonometry with the particle system. I'm standing firm on radians though. Once you're used to them, they make much more sense than an arbitrary number (360). For anyone having problems understanding them, check out this wikipedia image showing the relationship between PI and circumference. It really helped me when I first started working with them. http://en.wikipedia.org/wiki/File:2pi-unrolled.gif PS: Monkey forum formatting codes are fail. |
| ||
I'm standing firm on radians though. Well, I suppose I've got my way twice now and don't want to push it! ;) EDIT: But, you could still overload some methods that takes an Int as degrees instead of a float/double, and just quickly convert it... Then, noone would see the difference would they! :) *Dabz reaches for his tin hat* :D Dabz |
| ||
I prefer degrees myself: they are simple easier to work with, and you don't need to use constants so much (you can write 45 instead of PI/4). As for the trig, most libraries in my experience use the standard coordinates. One can simply visualise the transformation to Y=Down coordinates by imagining one's laptop screen is in the down position! But really it doesn't matter all that much in practice... if stuff turns around the wrong way you just need to switch between a plus and a minus somewhere... |
| ||
EDIT: But, you could still overload some methods that takes an Int as degrees instead of a float/double, and just quickly convert it... Then, noone would see the difference would they! :) It appears everyone hated mathematics at school... :) What I might do then is change radians to degrees, but add an extra method for radians. This would be more in line with Monkey's Sinr/Cosr/etc. functions. Internally they'll still be radians. This is the beauty of properties! :D Also stop making me change things when I'm trying to work on features! ;) |
| ||
Hey Samah, sorry I couldnt reply earlier, been to Manchester for the weekend... anyway, that's champion that is... Top stuff! ![]() Also stop making me change things when I'm trying to work on features! Ah, but the thing is see, now you've changed it, you neednt do it later, which in respect, I will now let you carry on in peace! ;) Hehehe Dabz |
| ||
Also, note to self: never divide by zero. Particle systems do strange things... |
| ||
Just managed to replace the existing Diddy particle system with the new one in me game... Set a level that just had two different types of tiles, then swapped two and watched it go berserk, particles flying everywhere... and it didnt batter an eyelid! :D I love it! :) Dabz |
| ||
@Dabz: ...and it didnt batter an eyelid! :D Well I've tried to optimise the Update method as much as possible using parallel arrays, indexed with a pseudo-pointer hack. Rendering is still the bottleneck (on HTML5 and Android that is), but it's always going to be that way with that number of DrawImage calls. Currently working on the emitter editor (using wxMax), but I fail utterly at user-friendly GUI design. We'll see how I go... ;) Edit: Just checked in the degrees stuff. You can add "Radians" to most angle-based properties if you wish to access it directly in radians. |
| ||
Lovely jubly! :) Currently working on the emitter editor (using wxMax) Looking forward to seeing it, at the minute, I've just been faffing with numbers, which is a bore, but, if I have levers to play with, I might get better results, so, I'm very keen to see this! :) Dabz P.S. Its a good job you don't charge by the hour, I'd owe you and Steve a fortune! :D Hehehe |
| ||
I've just checked in an update to allow you to read emitters/groups/forces from XML. It's a very simple format at the moment, and not finalised. The editor will eventually generate this for you. Just look at the example and follow from there. You can put pretty much any property as an attribute and it'll read it in. For now, images and death emitter settings will still need to be done in code. You can grab a reference to any of the XML-defined groups/emitters/forces by name. I've also added some "magic" properties as helpers for all the colour stuff. For example, setting the "Red" property will automatically disable all interpolation for red, assuming you want to use a static value. This means that the order of the attributes in the XML is important, since using the magic properties may override others. I'm considering adding HSL/HSV support too so that you can fade between hues, etc. |
| ||
Cor, getting snazzier by the day! :) Dabz |
| ||
Added Hue/Saturation/Brightness support, and updated the sample XML file to interpolate by hue (nice rainbow colours!) |
| ||
Help appreciated for the tile system in Diddy.. I want to access the data about each tile's x and y position, to create physical box2d bodies at their position. I got so far that they are stored in TileMapObjectLayer, but in line 92 in tile.monkey the TileMapObjectLayer is suddenly a TileMapLayer. Local layer:TileMapLayer = ReadObjectLayer(mapchild)I'm lost. |
| ||
That should probably be defined as a TileMapObjectLayer, but it doesn't really matter. To get all the objects in the map, you can do this: For Local obj:TileMapObject = EachIn tilemap.GetAllObjects() ' do something with obj Next Note that the code for that method has been commented out for a while (my bad, sorry), but I've implemented it and checked it in. Make sure you have the latest version of Diddy from subversion (or at least the latest version of tile.monkey). |
| ||
Samah, can you test the GetAllObjects() please? It always returns an ArrayList of size 0, although my tilemap.layers.size is 2 and my tiles are beeing drawn. Looks like TileMapObjectLayer(layer) is always Null. My Diddy is newest one from repository. |
| ||
GetAllObjects() returns an ArrayList containing all the objects in the map, not the tile cells. If you don't have any object layers (which are different to tile layers), then you won't get any objects. If you're basing your box2d bodies on actual cells in a tile layer, you'll have to loop through manually or make your own cell class. Class MyCell Extends TileMapCell Field box2dbody ' I can't remember the class for a b2d body Method New(gid:Int, x:Int, y:Int) Super.New(gid, x, y) End End Your map class: Class MyMap Extends TileMap Method CreateCell:TileMapCell(gid:Int, x:Int, y:Int) Return New MyCell(gid, x, y) End End Your reader class: Class MyReader Extends TiledTileMapReader Method CreateMap:TileMap() Return New MyMap End End Then when you build up your box2d bodies, you can do this: Method BuildBodies:Void() For Local layer:TileMapLayer = EachIn tilemap.layers If TileMapTileLayer(layer) <> Null Then For Local cell:TileMapCell = EachIn TileMapTileLayer(layer).mapData.cells If MyCell(cell) <> Null Then Local mc:MyCell = MyCell(cell) ' now you can use mc.x, mc.y, and mc.gid to build a body mc.box2dbody = ' the new body End Next End Next End If you like I can make a "GetAllCells" method. You'll still need to subclass the cell if you want to store per-cell info. |
| ||
Thanks a lot Samah, got it working! |
| ||
Another problem, diddy looks for a different font than what mojo includes by default. Please change the default. |
| ||
diddy looks for a different font than what mojo includes by default. Eh!? Where? What? |
| ||
If you're talking about the GUI, it's because it needs the glyph sizes and offsets in the XML. |
| ||
Ah... of course the GUI uses a different font... why would you use the "default" font in any game apart from debugging?!!? Its not even using an alpha background.... |
| ||
Currently taking enhancement requests for the particle system. Add them to the issue tracker on the Diddy project, using the "Enhancement request" template. http://code.google.com/p/diddy/issues/entry?template=Enhancement%20request |
| ||
You are using Lists and EachIn.... everytime you use an EachIn it will create a new object (iterator) What is the workaround? I'm storing my objects in ArrayLists and use the enumerator to call update(), which invites the gc to collect some garbage.. |
| ||
What is the workaround? You can either manually iterate through it, or cache the Enumerator. For Local i:Int = 0 Until list.Size Local foo := list.Get(i) ' do stuff with foo Next Or Local enum:AbstractEnumerator<SomeClass> = list.Enumerator() ' cache enum somewhere enum.Reset() While enum.HasNext() Local foo := enum.NextObject() ' do stuff with foo End Calling Reset() is the same as calling First() and updating the concurrency semaphore. If you cache the enumerator you need to call Reset() at the start of each loop. Note that I may be changing the "Abstract" part of the collection class names to "I". AbstractEnumerator is just too bloody long. :) |
| ||
I am looking at inputcache.monkey so that I can leverage its features for my own on screen numeric keypad in iOS. What do you think would be the best way to change the calls to keyhit and keydown (around line 390)? Or should I just forget about that and use the screen.OnTouchHit(x, y, pointer)callbacks and do everything at a higher level? |
| ||
If you have your own KeyHit and KeyDown functions that are automatically plugged into your onscreen keyboard, change inputcache.monkey. Otherwise I would stick with the event-based callback and just match the location of each touch to your keyboard. |
| ||
Thanks Samah. I like the keyboard handling in inputcache.monkey BTW. Diddy contains lots of interesting gems. |
| ||
I read you are searching enhancement ideas for the particles engine ? I found this today, share the love :) http://flintparticles.org/ The one from HGE is old but also quite good : http://hge.relishgames.com/ I cannot submit on the issue tracker strangely ?!? |
| ||
Heh that's some pretty cool stuff in those engines. I'm still torn with what language/platform to use for the editor. I'd like to use wxMax, because then it can run as a standalone exe. Or... I could be cheap and just use Swing or SWT. :) Edit: A note for those currently using HSB in the particle system: After reading this http://www.codeproject.com/KB/recipes/colorspace1.aspx I've decided to change the range for hue from 0-1 to 0-360. I've also fixed some bugs with the initial interpolation clamping. I'll check it in later. |
| ||
I've had problems with using diddy with the target platform of glfw. It seems that glfw likes absolute paths when loading stuff and so when trying to use the gui framework it doesn't want to load stuff. |
| ||
Strange... I can load up the example GUI stuff which doesnt use absolute paths and it works fine on all targets (including GLFW). Can you post an example which shows this issue with GLFW? |
| ||
I changed my mind about the 0-360 range for hue. Instead, I converted it all to HSL. I think HSL is more useful (and supposedly "better") than HSB, especially since the default Windows colour dialog has HSL. Committed as r305. |
| ||
therevills, when using the function LoadSkin() it does it. I'm doing this on a mac btw. I did a test where I had it output what it's trying to load and it only gave the relative path. It's the same issue with os.LoadString. That's probably why. Try importing the os package and see if you get the error. I should have specified that. |
| ||
I've implemented the particle system of Diddy in a ParticleEffects class so that I can use its Render and Update methods based on the effect I need inside Screen's Render and Update. Thing is that I would like to reset the particle system to its original state (no particles showing, all lives to zero etc). Is there a clean way to do that in the existing psystem or do I have to roll my own? Using RemoveParticle in a loop is maybe not the best way. (I am loading the conf from an XML) Other than that, yet another superb area of Diddy. |
| ||
Technically, you only need to set the particle count to zero. Once the particle system tries to create a particle it will simply clear out the values for the elements pointed to by the main pointer array. No real need to manually clear out the arrays either since all but one of them are primitives. If you want I can make a method that will reset the pointers to be sequential and clear out all the fields. Personally I think that just resetting the particle count is good enough. It's a read-only property though, so there'll need to be a Clear method for it. In the meantime, add this to ParticleGroup: Method Clear:Void() aliveParticles = 0 End That should be all you need. ;) |
| ||
Cool! Thanks Samah. There is something I have noticed since I draw a small number of rather large particles (a set of big stars popping out of the bottom of the screen for when a good answer is provided - They do not move that fast either): Particles that are emitted get drawn in front of the other ones where it would be much nicer to have them drawn behind the existing ones. I guess that this has to do with the arrays and pseudo pointers stuff. Is there a way to get this behavior? Going for the Clear() now :-) |
| ||
Just noticed the ResetParticles in the ParticleGroup. Shame on me. |
| ||
I guess that this has to do with the arrays and pseudo pointers stuff. Correct. Unfortunately there's not a lot you can do. I might be able to hack together some kind of z-order thing for rendering if you like, but I'd probably make it optional just in case it affects the update speed. Just noticed the ResetParticles in the ParticleGroup. Shame on me. That's alright, I totally forgot I'd even added that... XD |
| ||
Thanks, it would be great indeed. Once I'll be done with my current app, I plan to write a set of explanations on how to use all of those bits of Diddy, since even with the supercool samples of yours, it takes a while to put everythhing together properly. Diddy's been a huge timesaver for sure! Thanks again for making it available. |
| ||
Are there plans to incoporate Autofit ( http://monkeycoder.co.nz/Community/posts.php?topic=1500 ) into diddy, as it already does Virtual resolution? I'm trying to decide the best route for multiplatform black borders, aspectlocked fit scale and such. |
| ||
I've been meaning to add aspect ratio to the virtual resolution stuff to Diddy, but just haven't got round to it... and at the moment I am in the middle of a project not using Monkey... |
| ||
Do feel free to rip from AutoFit if it's any use. |
| ||
Be aware that using the scissor buffer will most likely break Diddy's GUI. SetScissor does not use the matrix stack, so I had to keep my own stack of scissor rectangles. When it's finished rendering the GUI, it resets it to 0,0,width,height. Perhaps Mark could add an internal scissor stack and link it to Push/PopMatrix... |
| ||
Added aspect ratio to Diddy using James' code :) To use: SetScreenSize(width, height, useAspectRatio) eg: SetScreenSize(640,480, True) useAspectRatio is set to False by default, so it will graphics stretch across the screen if you don't set it to true. |
| ||
therevills: Sorry to go back and change the topic a bit... you said that using Lists and Eachin is slow as it creates a new iterator object each time... what would be a better approach? I use lists and eachin all over the place.... I would love to know how to improve on this :) Thanks! |
| ||
NoOdle: I've spoken with Mark about some theoretical changes in the way ObjectEnumerator works. If it goes ahead, I can add enumerator pooling to ArrayList. This means that EachIn will reuse the same enumerator instance, having no GC overhead. Stay tuned... ;) Edit: In the meantime, just use it in an indexed fashion: Local mylist:ArrayList<Foo> ... For Local i:Int = 0 Until mylist.Size Local f:Foo = mylist.Get(i) ' do something with f Next |
| ||
Thanks for the quick response Samah! Is ArrayList a part of Diddy? [edit] found it in Diddy collections, I might have to use this. Looks handy |
| ||
I was looking through the diddy source code and noticed your assert functions. Is there a reason why you opted to create a huge list of functions when you can do the same with one? I only ask as my mind is curious. Wondered if there was a speed gain.local testObject = Null Assert(( testObject = Null ), "testObject is Null" ) Function Assert( statement : Bool, message : String ) If statement = True Print (message) Error (message) Endif End Function |
| ||
It reads cleaner if you keep the boolean logic out of your procedure. Also the point of an assert is that you're assuming something to be true. Technically your Assert function should be checking "If Not statement" or "If statement = False". This naming format is common in a lot of assertion libraries for other languages, too. |
| ||
Yea I wasn't sure which way round to have it, just threw it together as quick test. I think I will stick with my one function as personally its a lot easier to remember; my brain is like a sieve! |
| ||
Thread's getting a bit unwieldy so new one is here... |