{"id":21,"date":"2014-08-01T14:13:00","date_gmt":"2014-08-01T18:13:00","guid":{"rendered":"http:\/\/naplandgames.com\/blog\/2014\/08\/01\/loading-animations-and-staggering-asset-creation\/"},"modified":"2018-12-18T09:13:04","modified_gmt":"2018-12-18T14:13:04","slug":"loading-animations-and-staggering-asset-creation","status":"publish","type":"post","link":"https:\/\/naplandgames.com\/blog\/2014\/08\/01\/loading-animations-and-staggering-asset-creation\/","title":{"rendered":"Loading Animations and Staggering Asset Creation"},"content":{"rendered":"<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px; text-align: center;\">Original article in the TGC Newsletter can be viewed <a href=\"http:\/\/www.thegamecreators.com\/pages\/newsletters\/newsletter_issue_138.html\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px; text-align: center;\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter \" src=\"https:\/\/naplandgames.com\/blog\/wp-content\/uploads\/2018\/12\/80d1107e1d6bedd230764ba7f82373d2.jpg\" alt=\"\" width=\"426\" height=\"73\" \/><\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\">In our last game, Shape Time, I ended up deciding to load quite a few assets at launch time. I implemented a loading animation, but it seemed to actually slow down the loading process a bit. In our next game I wanted to optimize this as much as possible to improve loading time. The reason the loading animation was affecting the speed of loading assets was that I was calling Sync() as frequently as possible so that the animation would update. Here&#8217;s an example how it was done (the loading animation in this case is a sprite with frames):<\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><\/div>\n<pre style=\"background: #eeecf6; border: 1px solid #cccccc; color: #493617; padding-left: 16px;\">for num = 1 to 10\r\n fileName$ = \u201catlas\u201d + str(num) + \u201c.png\u201d\r\n LoadImage(i , fileName$)\r\n Sync()\r\nnext num<\/pre>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><\/div>\n<p><a href=\"https:\/\/naplandgames.com\/blog\/wp-content\/uploads\/2014\/08\/loading-1.jpg\" rel=\"lightbox[21]\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-medium wp-image-110\" src=\"https:\/\/naplandgames.com\/blog\/wp-content\/uploads\/2014\/08\/loading-1-300x230.jpg\" alt=\"loading\" width=\"300\" height=\"230\" srcset=\"https:\/\/naplandgames.com\/blog\/wp-content\/uploads\/2014\/08\/loading-1-300x230.jpg 300w, https:\/\/naplandgames.com\/blog\/wp-content\/uploads\/2014\/08\/loading-1.jpg 350w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>This would certainly animate the loading sprite just fine, but I knew there had to be a better, more universal way. The problem is that Sync() is limited by the frame rate of the device. So if you&#8217;ve got a device that is capable of only 30FPS (fairly common in with mobile devices) then you are limiting your loading sequence to one file every 30th of a second. This is not that bad for files, but if you want to display the animation while other, possibly faster processes take place, then you&#8217;re likely slowing them down.<\/p>\n<p>&nbsp;<\/p>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><span style=\"line-height: 1.5;\">Let&#8217;s look at an example of a script that might be slowed by a\u00a0<em>Sync<\/em>() call:<\/span><\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><\/div>\n<pre style=\"background: #eeecf6; border: 1px solid #cccccc; color: #493617; padding-left: 16px;\">for num = 1 to 100\r\n if num = 1\r\n  img = LoadImage(\u201cyourImage.png\u201d)\r\n  CreateSprite(num , img)\r\n  SetSpriteSize(num , 10 , -1)\r\n  SetSpriteDepth(num , 100)\r\n else\r\n  CloneSprite(num , 1)\r\n endif\r\n SetSpritePosition(random(0,90) , random(0,90))\r\nnext num<\/pre>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><span style=\"line-height: 1.5;\">This script is pretty fast, but it might take up to a second or more on mobile devices. If we add a Sync() call to this routine so we can show a loading animation then the routine will be much slower because the Sync() call will render the screen and limit the engine to whatever the available FPS is. At 30FPS this script would require 3.33 seconds to run. Without Sync() it may take considerably less time, however, that would be dependent the device.<\/span><\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><span style=\"line-height: 1.5;\">So how do we speed this up? The answer is to only call Sync() only when it is time that you expect to have a frame drawn to the screen. The example below uses a literal 1\/60 of a second between Sync() calls. There are more advance ways to determine the expected time to call Sync(), but this is sufficient for showing a loading animation. The example simply rotates a loading image for simplicity.<\/span><\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><\/div>\n<pre style=\"background: #eeecf6; border: 1px solid #cccccc; color: #493617; padding-left: 16px;\">global gLoading = 0\r\nglobal gLoading_LastSync# = 0.0 \r\nfunction ToggleLoadingAnim(iOnOff)\r\n\u00a0 \u00a0 if GetSpriteExists(gLoading) = 0\r\n\u00a0 \u00a0 \u00a0 \u00a0 gLoading = LoadSprite(\u201cloading.png\u201d)\r\n\u00a0 \u00a0 \u00a0 \u00a0 SetSpriteSize(gLoading , 10 \u00a0, -1)\r\n SetSpriteDepth(gLoading , 1)\r\n\u00a0 \u00a0 endif\r\n\u00a0 \u00a0 if iOnOff = 1\r\n\u00a0 \u00a0 \u00a0 \u00a0 SetSpritePositionByOffset(gLoading , 50 , 50)\r\n\u00a0 \u00a0 \u00a0 \u00a0 gLoading_LastSync# = 0.0\r\n\u00a0 \u00a0 else\r\n\u00a0 \u00a0 \u00a0 \u00a0 SetSpritePositionByOffset(gLoading , -500 , -500)\r\n\u00a0 \u00a0 endif\r\nendfunction \r\nfunction LoadingAnim_Sync()\r\n\u00a0 \u00a0 time_now# = timer()\r\n\u00a0 \u00a0 dT# = time_now# - gLoading_LastSync#\r\n\u00a0 \u00a0 if dT# &gt; 0.017\r\n\u00a0 \u00a0 \u00a0 \u00a0 ft# = GetFrameTime()\r\n\u00a0 \u00a0 \u00a0 \u00a0 gLoading_LastSync# = time_now#\r\n\u00a0 \u00a0 \u00a0 \u00a0 t# = 3.0\r\n\u00a0 \u00a0 \u00a0 \u00a0 angle# = GetSpriteAngle(gLoading) + 360.0 * ft# \/ t#\r\n\u00a0 \u00a0 \u00a0 \u00a0 angle_int = round(angle#)\r\n\u00a0 \u00a0 \u00a0 \u00a0 angle_int = mod(angle_int , 360)\r\n\u00a0 \u00a0 \u00a0 \u00a0 SetSpriteAngle(gLoading , angle_int)\r\n\u00a0 \u00a0 \u00a0 \u00a0 Sync()\r\n\u00a0 \u00a0 endif\r\nendfunction<\/pre>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\">The code consists of 2 globals and 2 simple functions.\u00a0<em>ToggleLoadingAnim<\/em>() is used to set up the sprite and globals, position the sprite, and make it visible. This should be called before any loop that you want to overlay the loading animation on. You also call this to hide the animation. Inside of the loop you will use\u00a0<em>LoadingAnim_Sync<\/em>() in place of a standard\u00a0<em>Sync<\/em>() call. So our original code that loaded 100 sprites becomes this:<\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><\/div>\n<pre style=\"background: #eeecf6; border: 1px solid #cccccc; color: #493617; padding-left: 16px;\">ToggleLoadingAnim(1)\r\nfor num = 1 to 100\r\n if num = 1\r\n  img = LoadImage(\u201cyourImage.png\u201d)\r\n  CreateSprite(num , img)\r\n  SetSpriteSize(num , 10 , -1)\r\n  SetSpriteDepth(num , 100)\r\n else\r\n  CloneSprite(num , 1)\r\n endif\r\n SetSpritePosition(random(0,90) , random(0,90))\r\n LoadingAnim_Sync()\r\nnext num\r\nToggleLoadingAnim(0)<\/pre>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\">That&#8217;s it! Now you can load up lots of assets and have a nice loading animation so that the user doesn&#8217;t wonder what&#8217;s going on. Remember, folks don&#8217;t like to wait even a second for something to happen these days, so make sure to use a method like this to let them know your game is still running. Now if we could only thread the loading animation so that we can draw to the screen while loading large files. Another thing you might want to consider is that you might get large values out of\u00a0<em>GetFrameTime<\/em>() while loading files. So you might want to limit the ft# variable when you&#8217;re translating a sprite (moving or rotating). Either way you&#8217;ll get a bit of jitter in your sprite&#8217;s translation because\u00a0<em>Sync<\/em>() just can&#8217;t be called fast enough due to the time it took to load a file.<\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><span style=\"line-height: 1.5;\">Users don&#8217;t want to wait long for your game to load, so it&#8217;s important to only load at launch time the assets you need to display the title screen \/ main menu of your game. After that you can stagger the creation of assets by creating only a handful every frame and then if they aren&#8217;t all loaded when they&#8217;re actually needed, you can finish up loading them and show a loading animation. In our next game I did this for our level selection menu.\u00a0<\/span><\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><span style=\"line-height: 1.5;\">The level selection menu needed 200 buttons, 3 star sprites for each button, and 2 text objects for each button \u2013 that&#8217;s a total of 800 sprites and 400 text objects! This was just way too slow to load on demand. So what I did is create a handful of these objects every frame during the\u00a0<em>Sync<\/em>() calls. This way the buttons could be loaded while the player is looking at the main menu which incorporates a short animation of about 2 seconds. Let&#8217;s examine how we can do something like this.<\/span><\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><span style=\"line-height: 1.5;\">Make an array that will hold the object IDs for the level buttons and a global to hold an image ID:<\/span><\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><\/div>\n<pre style=\"background: #eeecf6; border: 1px solid #cccccc; color: #493617; padding-left: 16px;\">#constant LVL_BTN_COUNT 200\r\ndim _lvl_btns[LVL_BTN_COUNT]\r\n_lvl_btns[0] = 0\r\nglobal gLvlBtnImg as integer<\/pre>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\">Create a new function that includes the\u00a0<em>Sync<\/em>() command and will create a handful of objects each frame:<\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><\/div>\n<pre style=\"background: #eeecf6; border: 1px solid #cccccc; color: #493617; padding-left: 16px;\">function LvlBtn_Sync()\r\n \/\/we'll store the count of created objects here\r\n count = _lvl_btns[0]\r\n if count &lt; LVL_BTN_COUNT\r\n  skip_objects = 0\r\n  if GetImageExists(gLvlBtnImg) = 0\r\n   gLvlBtnImg = LoadImage(\u201cmybutton.png\u201d)\r\n   \/\/since we're loading an image this frame\r\n   \/\/let's not make any sprites or text\r\n   skip_objects = 1\r\n  endif\r\n    if skip_objects = 0\r\n   baseSprite = _lvl_btns[1]\r\n   needBaseSprite = 0\r\n   if GetSpriteExists(baseSprite) = 0\r\n    needBaseSprite = 1\r\n    endif\r\n   for i = 1 to 10\r\n      if needBaseSprite = 1\r\n    needBaseSprite = 0\r\n    thisSprite = CreateSprite(gLvlBtnImg)\r\n    SetSpriteSize(thisSprite , 10 , 5)\r\n    SetSpritePosition(thisSprite , -1000 , -1000)\r\n    SetSpriteDepth(thisSprite , 10)\r\n   else\r\n    thisSprite = CloneSprite(baseSprite)\r\n   endif\r\n   _lvl_btns[count] = thisSprite\r\n   inc _lvl_btns[0]\r\n  next i\u00a0\r\n  endif\r\n endif\r\n Sync()\r\nendfunction<\/pre>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\">Now we&#8217;re creating those 200 sprites in 20 frames. At 30FPS we&#8217;ll have created them in less than 1 second! They should all be prepared by the time we need to show the level selection menu, but just in case, you should also have a catch that ensures they&#8217;re all created when the user goes to access the level selection screen. If they aren&#8217;t all made then you can show the loading animation to tell the user the app is working on something.<\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><span style=\"line-height: 1.5;\">This method can be used in a variety of ways. For example, while the user is playing one level you can slowly start loading the assets for the next level in each frame. This should be done with care so that it doesn&#8217;t drag down performance when the action of the game is happening. As long as the sprites are off-screen they won&#8217;t be rendered and won&#8217;t cause a drag on the engine.<\/span><\/div>\n<div style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 21.600000381469727px;\"><span style=\"line-height: 1.5;\">Next time I&#8217;ll discuss methods on how to \u201cthread\u201d animations in a loop so that you can easily contain different animations in separate functions. Oftentimes we need to have a lot of things going on simultaneously and they cannot interrupt each other or user input. Thanks for reading!<\/span><\/div>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_21\" class=\"pvc_stats all  \" data-element-id=\"21\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/naplandgames.com\/blog\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p>\n<div class=\"pvc_clear\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Original article in the TGC Newsletter can be viewed here. In our last game, Shape Time, I ended up deciding to load quite a few assets at launch time. I implemented a loading animation, but it seemed to actually slow down the loading process a bit. In our next game I wanted to optimize this as much as possible to improve loading time. The reason the loading animation was affecting the speed of loading assets was that I was calling Sync() as frequently as possible so that the animation would update. Here&#8217;s an example how it was done (the loading&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/naplandgames.com\/blog\/2014\/08\/01\/loading-animations-and-staggering-asset-creation\/\">Continue reading<span class=\"screen-reader-text\">Loading Animations and Staggering Asset Creation<\/span><\/a><\/div>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_21\" class=\"pvc_stats all  \" data-element-id=\"21\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/naplandgames.com\/blog\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p>\n<div class=\"pvc_clear\"><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"a3_pvc":{"activated":true,"total_views":606,"today_views":0},"_links":{"self":[{"href":"https:\/\/naplandgames.com\/blog\/wp-json\/wp\/v2\/posts\/21"}],"collection":[{"href":"https:\/\/naplandgames.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/naplandgames.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/naplandgames.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/naplandgames.com\/blog\/wp-json\/wp\/v2\/comments?post=21"}],"version-history":[{"count":5,"href":"https:\/\/naplandgames.com\/blog\/wp-json\/wp\/v2\/posts\/21\/revisions"}],"predecessor-version":[{"id":331,"href":"https:\/\/naplandgames.com\/blog\/wp-json\/wp\/v2\/posts\/21\/revisions\/331"}],"wp:attachment":[{"href":"https:\/\/naplandgames.com\/blog\/wp-json\/wp\/v2\/media?parent=21"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/naplandgames.com\/blog\/wp-json\/wp\/v2\/categories?post=21"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/naplandgames.com\/blog\/wp-json\/wp\/v2\/tags?post=21"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}