Task

An animation with the following frames in the following order (if certain characters aren't available or can't be used correctly in the programming language, alternate characters can replace any of these frames) must animate with a delay of 0.25 seconds between each frame, with the previous frame being cleared before the next frame appears: 

   |
   /
   - or ─
   \



A stand-alone version that loops and/or a version that doesn't loop can be made. These examples can also be converted into a system used in game development which is called on a HUD or GUI element requiring it to be called each frame to output the text, and advance the frame when the frame delay has passed. You can also use alternate text such as the . animation ( . | .. | ... | .. | repeat from . ) or the logic can be updated to include a ping/pong style where the frames advance forward, reach the end and then play backwards and when they reach the beginning they start over ( technically, you'd stop one frame prior to prevent the first frame playing twice, or write it another way ).



There are many different ways you can incorporate text animations. Here are a few text ideas - each frame is in quotes. If you can think of any, add them to this page! There are 2 examples for several of these; the first is the base animation with only unique sets of characters. The second consists of the primary set from a - n and doubled, minus the first and last element ie: We only want the center. This way an animation can play forwards, and then in reverse ( ping ponging ) without having to code that feature. For the animations with 3 elements, we only add 1, the center. with 4, it becomes 6. with 10, it becomes 18.



We don't need the second option for some of the animations if they connect smoothly, when animated, back to the first element. ... doesn't connect with . cleanly - there is a large leap. The rotating pipe meets the first perfectly so it isn't necessary, etc..





   Dots - Option A requires ping / pong enabled script. Option B just adds the elements in the center.
   '.', '..', '...'
   '.', '..', '...', '..'
   Pipe - This has the uniform sideways pipe instead of a hyphen to prevent non-uniform sizing.
   '|', '/', '─', '\'
   Stars - Option A requires ping / pong enabled script. Option B just adds the elements from the center.
   '⁎', '⁑', '⁂'
   '⁎', '⁑', '⁂', '⁑'
   Clock - These need to be ordered. I haven't done this yet as the application I was testing the system in doesn't support these wingdings / icons. But this would look quite nice and you could set it up to go forward, or backward during an undo process, etc..
   '🕛', '🕧', '🕐', '🕜', '🕑', '🕝', '🕒', '🕞', '🕓', '🕟', '🕔', '🕠', '🕕', '🕖', '🕗', '🕘', '🕙', '🕚', '🕡', '🕢', '🕣', '🕤', '🕥', '🕦'
   Arrows:
   '⬍', '⬈', '➞', '⬊', '⬍', '⬋', '⬅', '⬉'
   Bird - This looks decent but may be missing something.
   '︷', '︵', '︹', '︺', '︶', '︸'
   '︷', '︵', '︹', '︺', '︶', '︸', '︶', '︺', '︹', '︵'
   Plants - This isn't quite complete
   '☘', '❀', '❁'
   '☘', '❀', '❁', '❀'
   Eclipse - From Raku Throbber post author
   '🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘'


 
--
-- Simple String Animation - semi-hard-coded variant - you can alter the chars table - update the count and run it...
--
 
-- The basic animation runtime controller. This is where you assign the active animation ( you could create a simple function to replace the animation table and nil count, index and expiry to extend this system to allow multiple animations -
--	and since you can replace after a previous has been output, it would appear as though you were running different animations at the same time - that wouldn't be async compatible though )...
-- So you can either activate the animation you want permanently, or create a simple function to update the animation table and reset the control variables... ie: ( function string.SetBasicAnimation( _tab_of_chars ) string.__basic_anim_runtime.anim = _tab_of_chars; string.__basic_anim_runtime.index = nil; string.__basic_anim_runtime.count = nil; string.__basic_anim_runtime.expiry = nil; end )
string.__basic_anim_runtime = {
	-- The animation - can not ping pong... requires full sequence. Resets to first after full sequence. Dots animation.. Requires center segment because of ping / pong
	anim = { '.', '..', '...', '..' };
 
	-- Pipes animation - This performs a complete rotation, no need to add extra segments.
	-- anim = { '|', '/', '─', '\\' };
 
	-- Stars - This is reversible so requires the center segments..
	-- anim = { '⁎', '⁑', '⁂', '⁑' };
 
	-- Clock - This still needs to be ordered...
	-- anim = { '🕛', '🕧', '🕐', '🕜', '🕑', '🕝', '🕒', '🕞', '🕓', '🕟', '🕔', '🕠', '🕕', '🕖', '🕗', '🕘', '🕙', '🕚', '🕡', '🕢', '🕣', '🕤', '🕥', '🕦' };
 
	-- Arrows - This does a complete circle and doesn't need to reverse
	-- anim = { '⬍', '⬈', '➞', '⬊', '⬍', '⬋', '⬅', '⬉' };
 
	-- Bird Flying - this is reversible so it requires all.. 1 2 3 4 5 6 5 4 3 2
	-- anim = { '︷', '︵', '︹', '︺', '︶', '︸', '︶', '︺', '︹', '︵' };
 
	-- Plants - Set as reversible, requires all..
	-- anim = { '☘', '❀', '❁', '❀' };
 
	-- Eclipse - From Raku Throbber post author
	-- anim = { '🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘' };
};
 
 
--
-- The basic animator function - accepts a numerical delay and a boolean backwards switch.. It only accepts a single animation from the helper local table above..
--
-- Argument - _delay - <Number> - Accepts a time, in seconds with fraction support, that designates how long a frame should last. Optional. If no number given, it uses the default value of 1 / 8 seconds.
-- Argument - _play_backwards - <Boolean> - Toggles whether or not the animation plays backwards or forwards. Default is forwards. Optional.
--
-- RETURN: <String> - Character( s ) of the current animation frame - if the frame is invalid, it returns an empty string.
-- RETURN: <Boolean> - Has Advanced Frame Controller - set to true if this call resulted in a new frame / index being assigned with new character( s )
--
function string.BasicAnimation( _delay, _play_backwards )
	-- Setup delay - make sure it is a number and Reference our runtime var
	local _delay = ( ( type( _delay ) == 'number' ) and _delay or 1 / 8 ), string.__basic_anim_runtime, os.clock( );
 
	-- cache our count so we count once per refresh.
	_data.count = ( type( _data.count ) == 'number' ) and _data.count or #_data.anim;
 
	-- Setup our helpers...
	local _expiry, _index, _chars, _count, _has_advanced_frame = _data.expiry, ( _data.index or ( _play_backwards and _data.count or 1 ) ), _data.anim, _data.count, false;
 
	-- If expiry has occurred, advance... Expiry can be nil the first call, this is ok because it will just use the first character - or the last if playing backwards.
	if ( _expiry and _expiry < _time ) then
		-- Advance..
		_index, _has_advanced_frame = ( ( _index + ( 1 * ( _play_backwards and -1 or 1 ) ) ) % ( _count + 1 ) ), true;
 
		-- If 0, add 1 otherwise keep the same.
		_index = _index < 1 and ( _play_backwards and _count or 1 ) or _index;
 
		-- Update the index
		_data.index = _index;
	end
 
	-- Update the trackers and output the char. -- Note: This is best done in the loop, but since we are checking the expiry above I decided to integrate it here.
	_data.expiry = ( not _data.expiry or _has_advanced_frame ) and _time + _delay or _data.expiry;
 
	-- Return the character at the index or nothing.
	return _chars[ _index ] or '', _has_advanced_frame;
end
 
 
--
-- Helper / OPTIONAL FUNCTION - Updates the animation and resets the controlling variables
--
-- Argument: _tab - <Table> - This is the table containing the animation characters... ie: { '.', '..', '...', '..' } would be a valid entry. Requires at least 2 entries.
--
function string.SetBasicAnimation( _tab )
	-- Prevent non tables, empty tables, or tables with only 1 entry.
	if not ( type( _tab ) == 'table' and #_tab > 1 ) then return error( 'Can not update basic animation without argument #1 as a table, with at least 2 entries...' ); end
 
	-- Helper
	local _data = string.__basic_anim_runtime;
 
	-- Update the animation table and Clear the controllers...
	_data.anim, _data.count, _data.index, _data.expiry = _tab, nil, nil, nil;
end
 