{"id":8092,"date":"2026-05-27T21:28:14","date_gmt":"2026-05-28T01:28:14","guid":{"rendered":"https:\/\/www.caskeys.com\/dc\/?p=8092"},"modified":"2026-05-29T00:07:31","modified_gmt":"2026-05-29T04:07:31","slug":"openbor-animated-background-layers","status":"publish","type":"post","link":"https:\/\/www.caskeys.com\/dc\/openbor-animated-background-layers\/","title":{"rendered":"OpenBOR Animated Background Layers"},"content":{"rendered":"\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<div class=\"jetpack-video-wrapper\"><span class=\"embed-youtube\" style=\"text-align:center; display: block;\"><iframe loading=\"lazy\" class=\"youtube-player\" width=\"640\" height=\"360\" src=\"https:\/\/www.youtube.com\/embed\/hV0SEd8Z5Nw?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=en-US&#038;autohide=2&#038;wmode=transparent\" allowfullscreen=\"true\" style=\"border:0;\" sandbox=\"allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox\"><\/iframe><\/span><\/div>\n<\/div><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading has-x-large-font-size\">Introduction<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">On the surface, OpenBOR does not natively support animated background layers. What it does give you is a variety of layer effects, including palette cycling, palette cell cycling through the neon effect, affine transforms, and automated sine wave distortion.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Usually, though, if you want true animated background elements, the standard approach is to spawn entities from a model, then carefully configure scrolling, scripted positioning, or other placement logic to anchor them into the level. That approach is by design, because it gives you almost unlimited capability. OpenBOR can support up to 5000 active entities per frame, and any single entity can occupy anything from one pixel to the entire visible stage. Entities also have the engine\u2019s full visual effect library at their disposal. Beyond that, unlimited subscreens and direct-draw graphics make virtually any visual concept possible.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Still, sometimes power is not the same thing as convenience. Sometimes you just want a background element to animate like a background layer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As it happens, you can. OpenBOR already gives you all the primitives you need:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Unlimited layers.<\/li>\n\n\n\n<li>Script access to read and mutate layer properties.<\/li>\n\n\n\n<li>An enable flag checked first in the rendering pipeline.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">That last point is the trick. The enable flag is the first thing OpenBOR checks when processing a layer. If it is false, the renderer moves on immediately. That makes disabled layers extremely cheap, which is exactly what we need for cycling a stack of prepared animation frames.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That is what the DC Layer Cycle library is for. It is a set of script functions that allow you to define a sequence made of layers, then play them back live for a seamless background animation. <\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<div class=\"jetpack-video-wrapper\"><span class=\"embed-youtube\" style=\"text-align:center; display: block;\"><iframe loading=\"lazy\" class=\"youtube-player\" width=\"640\" height=\"360\" src=\"https:\/\/www.youtube.com\/embed\/m2IEiklA41g?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=en-US&#038;autohide=2&#038;wmode=transparent\" allowfullscreen=\"true\" style=\"border:0;\" sandbox=\"allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox\"><\/iframe><\/span><\/div>\n<\/div><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">How It Works<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In its basic form, the script takes control of a defined block of <code>fglayers<\/code>. We use <code>fglayers<\/code> because they are the most powerful layer type. They may be positioned anywhere on screen, assigned layer priority, and manipulated through script.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">At the start of the level, the script instantly disables the entire block of animation layers. Then, during gameplay, it enables one layer at a time and disables the previous one as the sequence advances. The effect is the same basic idea as sprite animation: each layer is a prepared animation frame, and the script cycles through those frames in order.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Since disabled layers are skipped immediately by the renderer, the inactive frames stay cheap until they are needed.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><a href=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"768\" src=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_2-1024x768.png\" alt=\"\" class=\"wp-image-8103\" srcset=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_2-1024x768.png 1024w, https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_2-300x225.png 300w, https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_2-768x576.png 768w, https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_2.png 1448w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">The cloud layers are all present, but only one is visible at a time, creating the animated effect.<\/figcaption><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\">Considerations<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Advantages<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Simple &#8211;<\/strong> Once you pay the time cost of installing the library, spinning up background animations is very quick and easy. No need to build models or bother setting up entity spawns.<\/li>\n\n\n\n<li><strong>Efficient \u2013<\/strong> Layer cycles are lighter than models and entities. The script library itself is highly optimized and it can run as many individual animations as you need.<\/li>\n\n\n\n<li><strong>Modular &#8211;<\/strong> If you need more advanced sequences than the script alone can offer, you can easily integrate it into a controlling entity which may reside anywhere in the level.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Limitations<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Layers &#8211;<\/strong> You are still controlling layers, not spawned entities. OpenBOR layers are simplistic by design, and all of the same layer limitations apply. For example, layers do not have left-right flipping.<\/li>\n\n\n\n<li><strong>Initial complexity &#8211;<\/strong> Obviously you do have to install this library or something similar to make it work.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In short, layer cycling cannot replace entity spawns entirely, and it isn&#8217;t meant to. Think of it as a supplement. Best practice is a mixed approach using the right tool for the job. When you need highly complex sequences or rich visual effects, spawn entities. When you only need basic visual effects and animation, employ layer cycling.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Walk Through<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Installation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">1. Download and install the <a href=\"https:\/\/github.com\/DCurrent\/openbor-script-D20\" data-type=\"link\" data-id=\"https:\/\/github.com\/DCurrent\/openbor-script-D20\">DC D20 Library<\/a>. This is a required dependency and includes its own installation instructions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">2. Download the <a href=\"https:\/\/github.com\/DCurrent\/DC-Layer-Cycle\" data-type=\"link\" data-id=\"https:\/\/github.com\/DCurrent\/DC-Layer-Cycle\">Layer Cycle library<\/a> or the <a href=\"https:\/\/www.chronocrash.com\/forum\/resources\/animated-background-layers.224\/\" data-type=\"link\" data-id=\"https:\/\/www.chronocrash.com\/forum\/resources\/animated-background-layers.224\/\">exhibition module<\/a>. The exhibition module is recommended because it lets you see the code, dependencies, and setup in action.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">3. Unpack or copy the Layer Cycle folder and place it into <code>data\/scripts<\/code>. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"927\" height=\"394\" src=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_1.png\" alt=\"\" class=\"wp-image-8097\" srcset=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_1.png 927w, https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_1-300x128.png 300w, https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_1-768x326.png 768w\" sizes=\"auto, (max-width: 927px) 100vw, 927px\" \/><\/a><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">4. Add the following line to any script that will use the layer cycle library:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: Code:; notranslate\" title=\"Code:\">\n#include \"data\/scripts\/dc_layer_cycle\/main.c\"\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">The library is now ready to use.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Set up<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Prepare Images<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before you do anything with the scripts, you will need to prepare your layers. All the typical sprite rules apply.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Make sure each sprite in a group shares the same palette. Do not shortcut this.<\/li>\n\n\n\n<li>Don&#8217;t try to trim sprites individually &#8211; you are only wasting your own production time and making placement more difficult. OpenBOR auto trims and optimizes sprites on startup. Instead, find a uniform size (preferably a multiple of four) for all the sprites in a group.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/cloud_b_0.png\"><img loading=\"lazy\" decoding=\"async\" width=\"128\" height=\"80\" data-id=\"8111\" src=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/cloud_b_0.png\" alt=\"\" class=\"wp-image-8111\"\/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/cloud_b_1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"128\" height=\"80\" data-id=\"8112\" src=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/cloud_b_1.png\" alt=\"\" class=\"wp-image-8112\"\/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/cloud_b_2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"128\" height=\"80\" data-id=\"8113\" src=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/cloud_b_2.png\" alt=\"\" class=\"wp-image-8113\"\/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/cloud_b_3.png\"><img loading=\"lazy\" decoding=\"async\" width=\"128\" height=\"80\" data-id=\"8114\" src=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/cloud_b_3.png\" alt=\"\" class=\"wp-image-8114\"\/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large wp-duotone-unset-1\"><a href=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/cloud_b_4.png\"><img loading=\"lazy\" decoding=\"async\" width=\"128\" height=\"80\" data-id=\"8110\" src=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/cloud_b_4.png\" alt=\"\" class=\"wp-image-8110\"\/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/cloud_b_5.png\"><img loading=\"lazy\" decoding=\"async\" width=\"128\" height=\"80\" data-id=\"8115\" src=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/cloud_b_5.png\" alt=\"\" class=\"wp-image-8115\"\/><\/a><\/figure>\n<figcaption class=\"blocks-gallery-caption wp-element-caption\">Cloud layer assets. Each image shares the same palette and dimensions.<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Prepare Level<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Once you have your layer sprites ready, use the <code>fglayer<\/code> level command to place them into the level text. Only <code>fglayer<\/code> is accepted by this library. The legacy <code>layer<\/code> and <code>bglayer<\/code> commands are not supported.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You will need to tune the layer settings for your specific project. The Z position controls where the <code>fglayer<\/code> is drawn in relation to the stage\u2019s Z space, and it is affected by the level\u2019s Z boundaries and internal layer math. This means it may take a little experimentation to place the layer exactly where you want it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Placement is otherwise the same as placing any other <code>fglayer<\/code>, and you may freely use the layer\u2019s other settings. For a typical animation, each frame should use the same layer configuration and appear in consecutive layer slots. Note that layers are offset to the top-left of an image by default.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Code:; notranslate\" title=\"Code:\">\n#\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tZ \t\txratio\tzratio\txoffset\tzoffset\txspace\tzspace\txrepeat\tzrepeat\t\ttrans \talpha\tw-mode\tamp\t\twl\t      ws\t  move\t\tquake\tneon\t  \nfglayer \tdata\/levels\/basic\/cloud_b_0.png\t\t\t                -300    0.7     0.0     50      40      100     0       -1      1\t\t\t1\t\t0       0       0\t\t0\t      0\t\t  2.0\t    0       0\nfglayer \tdata\/levels\/basic\/cloud_b_1.png\t\t\t                -300    0.7     0.0     50      40      100     0       -1      1\t\t\t1\t\t0       0       0\t\t0\t      0\t\t  2.0\t    0       0\nfglayer \tdata\/levels\/basic\/cloud_b_2.png\t\t\t                -300    0.7     0.0     50      40      100     0       -1      1\t\t\t1\t\t0       0       0\t\t0\t      0\t\t  2.0\t    0       0\nfglayer \tdata\/levels\/basic\/cloud_b_3.png\t\t\t                -300    0.7     0.0     50      40      100     0       -1      1\t\t\t1\t\t0       0       0\t\t0\t      0\t\t  2.0\t    0       0\nfglayer \tdata\/levels\/basic\/cloud_b_4.png\t\t\t                -300    0.7     0.0     50      40      100     0       -1      1\t\t\t1\t\t0       0       0\t\t0\t      0\t\t  2.0\t    0       0\nfglayer \tdata\/levels\/basic\/cloud_b_5.png\t\t\t                -300    0.7     0.0     50      40      100     0       -1      1\t\t\t1\t\t0       0       0\t\t0\t      0\t\t  2.0\t    0       0\n\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\"><strong>Tip<\/strong>: The <code>Z<\/code> parameter is relative to the <a href=\"https:\/\/www.caskeys.com\/dc\/?page_id=8190\" data-type=\"page\" data-id=\"8190\">stage z boundary<\/a>. Use this as a starting point when setting the layer\u2019s Z position.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Prepare Script<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The last preparation is setting up the script for use. First, create a level script for the level that will contain background animations. Each level should use its own script file, because the animation definitions are level-specific. Usually, you will want to place this file into the same folder as the level. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_3.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"572\" src=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_3-1024x572.png\" alt=\"Folder location.\" class=\"wp-image-8126\" srcset=\"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_3-1024x572.png 1024w, https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_3-300x168.png 300w, https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_3-768x429.png 768w, https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/layer_cycle_3.png 1033w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The script file needs the library <code>#include<\/code> shown in the installation step. It also needs library calls added to its native <code>ondestroy()<\/code> and <code>main()<\/code> hooks. The script should look something like the example immediately below. If it does, you are ready to begin using the library to define animations. Animation definition happens in the create event hook, which we will detail in the next steps.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: Code:; notranslate\" title=\"Code:\">\n#include \"data\/scripts\/dc_layer_cycle\/main.c\"\n\nvoid oncreate(){\n\n    \/*\n    * oncreate() is a native function that runs when the host \n    * loads.\n    *\/\n}\n\nvoid ondestroy(){    \n\n    \/*\n    * ondestroy() is a native function that runs when the host \n    * script is unloaded. We put the cleanup function here to \n    * free the layer cycle data array and prevent memory leaks.\n    *\/\n\n    dc_layer_cycle_cleanup();\n\n}\n\nvoid main(){          \n\n    \/*\n    * main() is a native function that runs each time the host\n    * script event fires. Because this is a level update script,\n    * it fires on every engine update during the stage. We call \n    * the layer cycle advance function here to update all active \n    * animations according to their configured frame data and \n    * timing.\n    *\/       \n\n    dc_layer_cycle_advance();\n}\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Define Animation Capacity<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before defining frames, allocate the layer cycle data array with <code>dc_layer_cycle_setup()<\/code>. This tells the library how many animation sequences the level will use, and the maximum number of frames any one animation sequence may contain.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Animations<\/strong> &#8211; The number of individual animation sequences in the level.<\/li>\n\n\n\n<li><strong>Frames<\/strong> &#8211; The frame capacity for the <strong>longest<\/strong> animation sequence.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In the exhibition pack, the sample level contains two cloud animations, and each one uses eleven frames. We allocate accordingly:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: Code:; notranslate\" title=\"Code:\">\ndc_layer_cycle_setup(2, 11);\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Do not confuse frames with sprites. As with a normal model animation, a frame does not have to use a unique sprite. Frames may reuse the same sprite more than once.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That is what the cloud example does. The cloud puffs outward, then returns to its original shape, so some sprites naturally appear again later in the sequence.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Use<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">All that\u2019s left now is to define your animations. This is accomplished through a single function API:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Code:; notranslate\" title=\"Code:\">\ndc_layer_cycle_frame_setup(animation_id, frame_index, frame_target, frame_action_a&#x5B;, frame_action_b]);\n<\/pre><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li><code>animation_id<\/code> \u2013 The unique identifier for an animation. For example, if you have two animations, one is <code>0<\/code> and the other is <code>1<\/code>. It is up to you which animation is which.<\/li>\n\n\n\n<li><code>frame_index<\/code> \u2013 The animation frame to define.<\/li>\n\n\n\n<li><code>frame_target<\/code> \u2013 This may vary in advanced use, but it normally refers to the layer this frame will display. OpenBOR assigns each layer a zero-indexed ID in the order it appears in the level file.<\/li>\n\n\n\n<li><code>frame_action_a<\/code> \u2013 This may vary in advanced use, but it is normally the frame delay: the time before moving to the next frame.<\/li>\n\n\n\n<li><code>frame_action_b<\/code> \u2013 Optional. This is used for advanced actions covered below.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">With this in mind, build an animation sequence by calling <code>dc_layer_cycle_frame_setup()<\/code> once for each frame of the animation. These calls belong in the level\u2019s <code>oncreate()<\/code> event, just after allocation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One advanced action you will likely need is <code>DC_LAYER_CYCLE_ACTION_GOTO<\/code>. Place this in <code>frame_action_a<\/code>, and <code>frame_target<\/code> becomes the frame to jump to. In the simplest use case, pass <code>0<\/code> to create a loop.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Tip:<\/strong> If you have more than one animation, <code>#define<\/code> a named constant for each animation ID.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This example defines an eleven-frame sequence. It has ten visible frames, all with a delay of twenty. The eleventh is a command frame that loops the animation back to frame <code>0<\/code>. It executes instantaneously and is therefore not visible.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: Code:; notranslate\" title=\"Code:\">\n    #define DC_CLOUD_ANIMATION_A 0\n   \n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 0, 0, 20); \n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 1, 1, 20);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 2, 2, 20);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 3, 3, 20);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 4, 4, 20);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 5, 5, 20);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 6, 4, 20);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 7, 3, 20);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 8, 2, 20);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 9, 1, 20);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 10, 0, DC_LAYER_CYCLE_ACTION_GOTO);\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">That&#8217;s all you need for a basic sequence. When you start up the level, your animation should be playing.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Tip:<\/strong> Layer sprites and scripts are destroyed on level exit and reloaded on level start. That means you can hot edit layers and definitions without restarting the engine. Just exit and reload the level &#8211; your changes will be live.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This example is straight from the pack in module. It demonstrates the complete function with two discrete animation sequences defined. The first takes advantage of randomized delay.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: Code:; notranslate\" title=\"Code:\">\n#include \"data\/scripts\/dc_layer_cycle\/main.c\"\n\nvoid oncreate(){\n\n    \/*\n    * oncreate() is a native function that runs when the host \n    * loads. We put the setup function here to initialize the \n    * layer cycle system and define our animation blocks and frames.\n    *\/\n\n    \/*\n    * Set up the layer cycle system with a \n    * maximum of 2 animations and 11 frames \n    * per animation. This will accommodate \n    * the cloud animation blocks in the sample \n    * stage. \n    *\/\n    dc_layer_cycle_setup(2, 11);\n\n    \/*\n    * Define animation IDs for the cloud animations.\n    *\/\n    #define DC_CLOUD_ANIMATION_A 0\n    #define DC_CLOUD_ANIMATION_B 1\n\n    \/*\n    * Each call sets up one frame within an animation block.\n    * Animation ID, frame index, target, and action are specified \n    * for each frame.\n    *\/\n\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 0, 0, 20, 40); \n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 1, 1, 20, 40);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 2, 2, 20, 40);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 3, 3, 20, 40);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 4, 4, 20, 40);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 5, 5, 20, 40);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 6, 4, 20, 40);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 7, 3, 20, 40);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 8, 2, 20, 40);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 9, 1, 20, 40);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 10, 0, DC_LAYER_CYCLE_ACTION_GOTO); \n\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_B, 0, 6, 25);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_B, 1, 7, 25);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_B, 2, 8, 25);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_B, 3, 9, 25);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_B, 4, 10, 25);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_B, 5, 11, 25);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_B, 6, 10, 25);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_B, 7, 9, 25);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_B, 8, 8, 25);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_B, 9, 7, 25);\n    dc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_B, 10, 0, DC_LAYER_CYCLE_ACTION_GOTO);\n\n    \/*\n    * We don't need these any more.\n    *\/\n    #undef DC_CLOUD_ANIMATION_A\n    #undef DC_CLOUD_ANIMATION_B\n}\n\n&#x5B;code lang=\"c\"]\nvoid ondestroy(){    \n\n    \/*\n    * ondestroy() is a native function that runs when the host \n    * script is unloaded. We put the cleanup function here to free\n    * the layer cycle data array and prevent memory leaks.\n    *\/\n\n    dc_layer_cycle_cleanup();\n\n}\n\nvoid main(){          \n\n    \/*\n    * main() is a native function that runs each time the host\n    * script event fires.\n    *\/       \n\n    dc_layer_cycle_advance();\n}\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Advanced<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Want to get more creative? No problem. The library gives you several data-driven options to add some spice to animations.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Frame Jump<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You can jump to a target frame, or to a random frame within a target range, with <code>DC_LAYER_CYCLE_ACTION_GOTO<\/code>.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: Code:; notranslate\" title=\"Code:\">\n\/\/ Jump to frame 0.\ndc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 10, 0, DC_LAYER_CYCLE_ACTION_GOTO);\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">If you supply an integer to <code>frame_action_b<\/code>, a random frame is selected each time the jump is triggered. <code>frame_target<\/code> becomes the minimum frame, and <code>frame_action_b<\/code> becomes the maximum frame.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: Code:; notranslate\" title=\"Code:\">\n\/\/ Random jump between frames 0 and 5.\ndc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 10, 0, DC_LAYER_CYCLE_ACTION_GOTO, 5);\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">This range is inclusive, so the example may jump to frames 0, 1, 2, 3, 4, or 5.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Random Delay<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To add a random delay, provide values for both <code>frame_action_a<\/code> and <code>frame_action_b<\/code>. <code>frame_action_a<\/code> is the minimum delay, and <code>frame_action_b<\/code> is the maximum delay.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: Code:; notranslate\" title=\"Code:\">\n\/\/ Play frame for 20 to 40 centiseconds.\ndc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 10, 5, 20, 40);\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Mutating Properties<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You may also set or adjust a layer\u2019s native properties during an animation sequence. To do this, provide the appropriate command constant in <code>frame_action_a<\/code>. The layer to mutate is supplied through <code>frame_target<\/code>, and the value is supplied through <code>frame_action_b<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Each supported property has two commands:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>SET \u2013 Replaces the property with the supplied value.<\/li>\n\n\n\n<li>ADD \u2013 Adds the supplied value to the property\u2019s current value. Negative values are accepted, so ADD may also decrease a value.<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: Code:; notranslate\" title=\"Code:\">\n\/\/ Set layer 5 alpha to 3.\ndc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 10, 5, DC_LAYER_CYCLE_ACTION_PROP_ALPHA_SET, 3);\n\n\/\/ Add 1 to layer 5 alpha.\ndc_layer_cycle_frame_setup(DC_CLOUD_ANIMATION_A, 11, 5, DC_LAYER_CYCLE_ACTION_PROP_ALPHA_ADD, 1);\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\">Available Property Constants<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">All native layer properties are available to mutate. The library enforces value types, so you may not pass an integer to <code>Z Ratio<\/code>, for example, because it requires a decimal value.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Alpha<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_ALPHA_SET<\/code> \u2013 Sets the layer\u2019s <code>alpha<\/code> value.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_ALPHA_ADD<\/code> \u2013 Adds to the layer\u2019s <code>alpha<\/code> value.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Amplitude<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_AMPLITUDE_SET<\/code> \u2013 Sets the layer\u2019s <code>amplitude<\/code> value.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_AMPLITUDE_ADD<\/code> \u2013 Adds to the layer\u2019s <code>amplitude<\/code> value.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Background Speed Ratio<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_BGSPEEDRATIO_SET<\/code> \u2013 Sets the layer\u2019s <code>bgspeedratio<\/code> value.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_BGSPEEDRATIO_ADD<\/code> \u2013 Adds to the layer\u2019s <code>bgspeedratio<\/code> value.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Enabled<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_ENABLED_SET<\/code> \u2013 Sets the layer\u2019s <code>enabled<\/code> flag.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_ENABLED_ADD<\/code> \u2013 Adds to the layer\u2019s <code>enabled<\/code> flag.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Use this carefully. The library normally controls layer visibility for you, so changing <code>enabled<\/code> directly can interfere with the normal animation sequence.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Neon<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_NEON_SET<\/code> \u2013 Sets the layer\u2019s <code>neon<\/code> flag.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_NEON_ADD<\/code> \u2013 Adds to the layer\u2019s <code>neon<\/code> flag.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">X Offset<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_OFFSET_X_SET<\/code> \u2013 Sets the layer\u2019s <code>xoffset<\/code> value.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_OFFSET_X_ADD<\/code> \u2013 Adds to the layer\u2019s <code>xoffset<\/code> value.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Z Offset<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_OFFSET_Z_SET<\/code> \u2013 Sets the layer\u2019s <code>zoffset<\/code> value.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_OFFSET_Z_ADD<\/code> \u2013 Adds to the layer\u2019s <code>zoffset<\/code> value.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Z Position<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_POS_Z_SET<\/code> \u2013 Sets the layer\u2019s <code>z<\/code> position.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_POS_Z_ADD<\/code> \u2013 Adds to the layer\u2019s <code>z<\/code> position.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Quake<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_QUAKE_SET<\/code> \u2013 Sets the layer\u2019s <code>quake<\/code> value.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_QUAKE_ADD<\/code> \u2013 Adds to the layer\u2019s <code>quake<\/code> value.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">X Ratio<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_RATIO_X_SET<\/code> \u2013 Sets the layer\u2019s <code>xratio<\/code> value.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_RATIO_X_ADD<\/code> \u2013 Adds to the layer\u2019s <code>xratio<\/code> value.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Z Ratio<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_RATIO_Z_SET<\/code> \u2013 Sets the layer\u2019s <code>zratio<\/code> value.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_RATIO_Z_ADD<\/code> \u2013 Adds to the layer\u2019s <code>zratio<\/code> value.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">X Repeat<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_REPEAT_X_SET<\/code> \u2013 Sets the layer\u2019s <code>xrepeat<\/code> value.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_REPEAT_X_ADD<\/code> \u2013 Adds to the layer\u2019s <code>xrepeat<\/code> value.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Z Repeat<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_REPEAT_Z_SET<\/code> \u2013 Sets the layer\u2019s <code>zrepeat<\/code> value.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_REPEAT_Z_ADD<\/code> \u2013 Adds to the layer\u2019s <code>zrepeat<\/code> value.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">X Spacing<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_SPACING_X_SET<\/code> \u2013 Sets the layer\u2019s <code>xspacing<\/code> value.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_SPACING_X_ADD<\/code> \u2013 Adds to the layer\u2019s <code>xspacing<\/code> value.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Z Spacing<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_SPACING_Z_SET<\/code> \u2013 Sets the layer\u2019s <code>zspacing<\/code> value.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_SPACING_Z_ADD<\/code> \u2013 Adds to the layer\u2019s <code>zspacing<\/code> value.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Transparency<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_TRANSPARENCY_SET<\/code> \u2013 Sets the layer\u2019s <code>transparency<\/code> flag.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_TRANSPARENCY_ADD<\/code> \u2013 Adds to the layer\u2019s <code>transparency<\/code> flag.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Water Mode<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_WATERMODE_SET<\/code> \u2013 Sets the layer\u2019s <code>watermode<\/code> value.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_WATERMODE_ADD<\/code> \u2013 Adds to the layer\u2019s <code>watermode<\/code> value.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Wavelength<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_WAVELENGTH_SET<\/code> \u2013 Sets the layer\u2019s <code>wavelength<\/code> value.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_WAVELENGTH_ADD<\/code> \u2013 Adds to the layer\u2019s <code>wavelength<\/code> value.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Wave Speed<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_WAVESPEED_SET<\/code> \u2013 Sets the layer\u2019s <code>wavespeed<\/code> value.<\/li>\n\n\n\n<li><code>DC_LAYER_CYCLE_ACTION_PROP_WAVESPEED_ADD<\/code> \u2013 Adds to the layer\u2019s <code>wavespeed<\/code> value.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Add modeless background animation to OpenBOR modules with the DC Layer Cycle library.<\/p>\n","protected":false},"author":1,"featured_media":8194,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[1],"tags":[],"class_list":["post-8092","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pointless-pontification"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2026\/05\/Screenshot-2026-05-28-232252.png","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p5lNM5-26w","jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/posts\/8092","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/comments?post=8092"}],"version-history":[{"count":66,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/posts\/8092\/revisions"}],"predecessor-version":[{"id":8200,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/posts\/8092\/revisions\/8200"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/media\/8194"}],"wp:attachment":[{"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/media?parent=8092"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/categories?post=8092"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/tags?post=8092"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}