Corona Quick Thought – a custom inOutBack easing function

I was reminded by a recent post in the forum that the calling convention for Corona’s easing functions isn’t well-documented. It’s fairly easy to “reverse-engineer” by experimenting, if you’re at all familiar with Robert Penner’s easing equations, and doing so will allow you to potentially create your own custom easing formulae.

At some point the subject should be treated with more depth, but I’m not feeling particularly ambitious today. πŸ˜€ So without further ado, here’s the aforementioned function:

Note that this function probably doesn’t exactly duplicate Corona/Penner, so I renamed it to avoid “claiming” that it did. Still, it’s mathematically very similar.

For readability, I’ve left it unoptimized to reveal its internal workings and 2t^3-t^2 origin — you can refactor and optimize further as you like. As written, it’s (intended to be) useful as a test-bed for developing new curves – just alter the icurve() function. Once you understand how all the “parts” work together, then you can inline all those unnecessary function calls.

The component in and out curves are in there as well, so if you don’t want the inOut version then just replace the call to iocurve() in the return statement with either icurve() or ocurve(). (or create separate versions of all three)

Test it like this:

Now, for the fun part: See that “s = 2.6” in there? That’s what controls “how much” overshoot occurs, and the 2.6 gives it about a 10% overshoot. If you’d like less overshoot, then reduce the value of s; if you’d like more overshoot, then increase the value of s.

Corona Quick Tip – the ternary operator re boolean parameter defaults

I saw this being discussed in Corona Geek Episode 115 and thought I’d add my two cents..

The issue comes about when passing boolean values as optional arguments to a function, and how to efficiently test if nil and provide a default value. The common pattern for defaulting other types of values is:

This is a shortcut test for nil, using the fact that nil evaluates to false in logical statements, so the expression after “or” is returned instead.

However, if you’re passing a boolean value, this test is insufficient, because a legitimately supplied “false” value will always fail that test (and thus always return the default instead).

The “flaw” is in the binary logical test – as it’s essentially testing the wrong thing. It shouldn’t be testing for an implied false, it should be testing for an explicit nil. What would be handy is a ternary operator, to directly test for nil, then selecting either the passed value or the default. Some languages like C/C++ have a true ternary operator. Lua does not, though something nearly equivalent can be crafted from slightly more complex logical expressions:

The parenthesis surrounding the nil test are optional, but I added them to more closely imply the general form of the ternary pattern: a and b or c
But it’s not a “true” ternary operator, and there are some “gotchas”, particularly if “b” evaluates to false. That’s why foo() and bar() above are not identical – the logic must be reversed if your default value is intended to be false.

But with a bit of “practice” to keep the logic straight, defaulting booleans can again become a simple “one-liner”.

For further info, see the Lua Wiki entry on this topic.

Corona Quick Thought – meta tricks, example: user data

Uh oh, you know you’re in for trouble when the first thing is a disclaimer: This is meant to demo a *technique*, not necessarily a practical application of that technique, fair?

This was motivated by a brief discussion with @PANCSoftware. It may or may not be even close to what he’s trying to achieve, but it seemed something worth demonstrating anyway.

HERE IS THE SOURCE if you’d like to follow along. I don’t plan on writing a whole lot about the code, comments are there for those interested enough to study it. (‘cuz if not interested enough to study it, then no point in me writing at length about it, right?)

What the code is intended to demonstrate is a metamethod whereby a containing class can serve as proxy for several different data categories and keep track of them all in a manner transparent to the end-user (aka developer).

(This will likely seem trivial nonsense if you’re coming here as a Lua expert. On the other hand might seem like black magic if you’re coming here as a typical Corona newbie. So the intended audience is somewhere in the middle of those two extremes.)

The scenario is a game’s user-data. Games often have two distinct categories of data:

  • Temporary/Transient “in game” data, for example current score
  • Permanent/Persistent “on disk” data, for example high score
  • (and of course there are others, like music/sound settings that might need to persist, etc)

    The technique used here is to provide a “prototype” to the class, indicating which properties are intended to be temporary and which are persistent. The class is agnostic – it doesn’t really know or care anything about your user data, other than what you “tell it” via the prototype.

    The class then hides those details from you and provides “simple” access to those properties, for example userdata.score and userdata.hiscore. Internally those are stored separately, so that when it comes time to serialize to disk, the class “knows” which properties to include.

    Take a look at the code if interested, that’s all for now. I may expand upon this in the future, maybe provide some code walk-through or etc, if seems needed.

    Corona Quick Thought – “cheap” antialiased lines

    “Cheap” as in “it will work with Starter”. πŸ˜€ (on the other hand, if you have a Pro+ subscription, then you have access to other alternatives)

    I was motivated to share this by a conversation started here, in the forum. Hope it’ll be helpful to someone somewhere.

    One of the less-than-pretty things about Corona is that vector geometry is rendered aliased (those “jaggy edges” arising from not antialiasing .. and i will not antiapologize for using double-negatives).

    But there are workarounds that might be suitable in certain instances, particularly if it’s just single line segments you’re after..

    bitmap_lines_sample_output_zoomThose are 2X pixel zoom crops from actual output, vector lines on the left, bitmap lines on the right. Which do you prefer? (or click below for full image at 1X if you’d rather)

    The “trick” used here is to create the line segments using pre-rendered bitmaps. Bitmaps do render antialiased due to the bilinear texture sampling that occurs.

    The bitmaps are just a single-pixel-wide portion of a line with the desired stroke width. (height of the bitmap is just whatever is necessary to fit the designed stroke width) For example, at left is a 4px stroke in a 1x8px bitmap, magnified 40X, against dark magenta to reveal transparency.

    I’ll keep this short for now.. here’s a functional demo with code you can experiment with.

    Look for the function named newBitmappedLine() within, read its docs, then see how used in the demonstration code later on.

    Corona Quick Thought – performance: use native methods whenever you can

    I recently saw a Corona tutorial of the painter’s algorithm, where the author demonstrated how they had depth-sorted their sprites by screen y-coordinate in order to simulate depth in 2D.

    The effect works well, but I was surprised to see that the author had implemented their own insertion sort in pure Lua rather than rely on Lua’s built-in table.sort() (a quicksort implementation).

    (I’ll avoid mentioning where to find that tutorial, lest this seem like my intent is just to criticize that work, ‘cuz it isn’t. I’ll try to use it as a case study for a general principle, while trying to avoid nitpicking it as a specific case. Unless that author wants a link back, then sure, just let me know! Fair?)

    I won’t delve into comparing the merits of various sort algorithms (much), except to say that the choice of an insertion sort was probably a good one. If the number of sprites is relatively small, and if they remain “mostly” sorted from frame to frame, then those are nearly ideal conditions for an insertion sort.

    However, …, it’s really hard to beat native code! Especially on a mobile device. If there’s an existing library routine that already does something, you are almost always better off using the built-in rather than rolling your own with interpreted Lua. Even if the built-in isn’t quite a perfect “fit” for your usage. (only in an extreme case with a known-optimal solution might you “win” via interpreted code versus a more generic solution in native code)

    The example here is that a somewhat-less-than-optimal-quicksort in native code is going to beat the pants off (aka orders of magnitude) even a more-optimal-insertion-sort if in interpreted code. Even with a relatively small list (50-ish sprites or so?), and even if already mostly sorted. (and certainly even moreso in general cases where those ideal conditions for an insertion sort aren’t met, giving the advantage to quicksort anyway)

    You can apply this principle across the board, whenever/wherever possible. For example, it’s not uncommon to see “tedious” string parsing being done with interpreted Lua that could have been accomplished so much more efficiently via string.gsub() and/or string.find(). Granted that Lua’s pattern-matching syntax can seem a bit “obscure”, but it’s well worth the time to learn the libraries.

    And performance is not the only issue here. The Lua libraries have been battle-tested, so usually there’s no concern about the “correctness” of the implementation – you can just rely on it working. Huge time saver, why reinvent the wheel?

    Back to sorting, let’s whip up an example for those who might not be familiar with table.sort().

    table.sort() can work directly on a list of atomic values (numbers, strings), or can accept a comparison function to deal with a list of arbitrary table (aka an “object” in typical usage) values having sortable properties within. (a comparison function can also be used to handle primary-secondary type sorts on multiple properties as well)

    (and for advanced readers, note that table.sort() can operate directly on a list of tables, provided they’ve got a metamethod for the less-than operator)

    A quick silly example just to illustrate some various bits:

    Corona Quick Thought – more Windows simulator skins

    I mentioned elsewhere how you can customize the list of available devices in Corona’s Windows simulator.

    I also mentioned elsewhere some reasons why you might want to do so, for example: taking screenshots at various resolutions.

    (I suppose this mainly applies if you have a fast action -type game where taking screenshots on-device would be tricky to capture the exact moment you were after. For a slower-paced app it’s easier to just capture from device.)

    Another handy little trick is to take your screenshot at double the intended resolution, then resample it down to improve the antialiasing. The Windows simulator doesn’t do nearly as good a job rendering as an actual device, so this trick will yield far better quality screenshots. So, for example, let’s say you need 800×1280 images for Google Play, you’d run a 1600×2560 simulated device… um, except that there isn’t one… unless you do it yourself… so…

    HERE is collection of 45 “generic” android devices (that is, no frame image and not intended to directly mimic any specific real-world device, just their resolutions) in a wide range of standard resolutions.

    You probably will not want to use all of them, or your “View As” menu will become enormous! πŸ˜€ In particular, there a half-a-dozen or so very low resolution ones that are of very little use, since any phones out there with those resolutions (fe Samsung Galaxy Spica??) probably have too old an OS to run Corona apps anyway – they’re provided mainly just for completeness (and silliness).

    The most useful ones are probably 1600×2560 (WQXVGA) as discussed above, and those that match iOS resolutions, but also includes the full list of resolutions cited in the Android docs for testing.

    So pick the several that seem useful and copy them into the \Program Files (x86)\Corona Labs\Corona SDK\Resources\Skins folder. (typically, your install location may vary, and you’ll likely need administrator rights to do so) Then restart the simulator.

    Corona Quick Thought – Photoshop Icon Resizer Script

    I mentioned elsewhere my preference for Photoshop’s results (among the other methods considered) when resizing a single “master” 1024×1024 icon to all the various sizes needed for iOS/Android devices. (That is, assuming you’re a shoe-string operation and don’t have an artist on-staff to produce 20+ unique icons, hand-optimized for each resolution.)

    Here is a script that can help automate that process, There are other such scripts floating around out there if you search for them, the only thing different here is that it’s specifically for Corona use, using their file-naming, and supporting all (currently) known sizes for both iOS/Android. (and it ought to be clear from a brief look at the source where you’d modify it to add additional sizes if/when they become necessary)

    Save it somewhere locally, then File-Scripts-Browse… to it.
    It’ll ask for a single high-resolution 1024×1024 master and an output folder, then just wait while it works.

    Tested on CS2 and CS6. (ought to work on any >= CS2)

    Corona Quick Thought – an “Android iPad” for Windows simulator

    One of the neat “tricks” with the Windows simulator when used with an Android device is that you can listen for key events and potentially use them for taking screen shots and/or toggling various debug features.

    For instance, I like to put something like this in main.lua to make taking screenshots easier:

    Unfortunately, that trick won’t work with simulated iOS devices – the simulator won’t send the key events to iOS devices.

    So, borrowing the technique from this post we can mimic an iOS device’s resolution, but tell the simulator it’s an Android device.

    For example, here I’ve copied the skin “iPad.lua” into “Android iPad.lua”, in order to create a 4:3 aspect device that the simulator will treat as Android (and thus provide key events through the simulator).

    Repeat for other iOS devices if/as desired.

    Corona Quick Thought – strict.lua or GLOBAL_lock()

    Given that Lua is such a dynamically language, it is trivially easy to accidentally “litter” the global environment with variables you didn’t intend to be global. Even a simple “spelling error” (or a camelCase accident one way or the other) can introduce a new variable, and fail to set the intended variable – a “silent” error that Lua won’t complain about but may have unintended and hard-to-diagnose consequences in your code. For example:

    Of course, this problem isn’t unique to Corona. For instance, it’s well-described here along with several approaches to address it, including strict.lua and Niklas Frykholm’s GLOBAL_lock/unlock().

    I’ve used both in the past, and both are directly usable in Corona, no special mucking about required. Effectively, what either of them do is lock the global environment, preventing unintended access afterward, and generating an error if you attempt to do so.

    If using GLOBAL_lock/unlock you can just copy the code from the wiki. If you wish to use strict.lua, I’d suggest getting it directly from the 5.1.5 source tarball available here (it’s in the etc directory). (as of this writing, Corona is still using JNLua 0.9, so 5.1.5 would be the right match)

    To use either, you may need to hunt for a “safe spot” in your code after you’ve declared any intended globals, for example:

    Next, you’ll want to give your app a thorough testing, exercising all of its code, as such errors can’t be noticed until execution. Then go about cleaning them all up.

    Note that you may have to specifically “exempt” certain Corona modules which themselves leak globals, particularly if using GLOBAL_lock/unlock (which, oddly, is a bit “stricter” than “strict” πŸ˜€ ), for example:

    Also note that you probably would not want to keep either active in a production build — better to accidentally assign a global somewhere than crash hard with a debug-environment error, just in case your testing didn’t uncover absolutely everything. One way you can do this (there are several of course) might be to wrap all of that code inside some kind of conditional, for example you might test if running on the simulator, and if so stub out all those routines to do nothing instead, so you can leave the rest of your code as-is, for example:

    Corona Quick Thought – a reasonably fast 8-bit XOR in native Lua

    I recently had a small need for a bitwise XOR, and was disappointed that Corona’s bit plugin is only available at Pro (or Enterprise) subscription levels.

    Drat. My need wasn’t great enough to justify that expense. Though note that if you do have need for thousands of XOR’s, particularly if 16- or 32-bit, then you may indeed need the native code of the plugin — interpreted Lua simply can’t match that performance. But if your needs are more modest, then perhaps there’s an alternative…

    For myself, I headed off to the Lua Wiki where I knew there to be several pure Lua implementations.

    Alas, while there are many capable implementations listed there, they’re all just a bit too capable for my purposes. Because the downside of being fully capable (dealing with 32-bit quantities, etc) and general-purpose means that their performance isn’t very snappy on a mobile device.

    I just needed a special-purpose 8-bit xor, for dealing with values you might obtain from string.byte(), for example. So I scoured the list archive and found what looked like a good starting point. (and I couldn’t have aksed for a better authority than Roberto! πŸ™‚ )

    Basically all I’ve done here is just cripple it a bit, for 8-bit use only, then unrolled the loop and removed some intermediate values where not reused, just to gain back a bit of performance.

    That’s about as far as it made sense for me to optimize. (I suppose you could duplicate and premultiply the table to save that final multiply, but it won’t make much difference. Or memoize it out to the full 64K,.. yikes. etc. My feeling was once you start contemplating those sorts of drastic measures, then you should just be using the bit plugin instead.)

    And here’s a simple validation suite against the bit plugin: