Skip to content
angelwire edited this page Sep 21, 2020 · 3 revisions

AESnips is meant to be a simple Sprite-based animation system to easily have an Object swap between Sprites and play Sprite sub-images with as little programming as possible. It is meant to automate common Sprite-based animation programming.

Features:

  • Create Snips using a Sprite and play them with one line of code
  • Each frame in a Snip can have an independent speed relative to the others
  • Loops can set frames within a Snip to repeat a certain number of times
  • Transitions added between Snips will automatically play
  • Easy Pause/Resume support for individual Snips or for all Snips
  • Play Snips immediately or queue them up to play at the end of the current Snip
  • Set Scripts to execute on certain frames during the playback of a Snip
  • Create multiple Snips from different sub-images within a single Sprite
  • Automatically play follow-up Snips without any additional programming

Terminology:

Snip

  • A Snip is a struct. It contains a lot of properties (you can find the properties and descriptions in the AESnipBase script. Objects play Snips by switching their sprite_index to the Sprite held in the Snips.

Transitions

  • A Transition is a struct. It is not a Snip or type of Snip, but it contains Snips. A Transition has a “to” property, a “from” property, and a “use” property. Any time an Object tries to play a Snip the Object will try to find a Transition that goes from the currently playing Snip to the Snip that the Object wants to play (assuming should_transition was marked as true when snip_play(Snip, should_transition?) was executed). If there is a Transition with a “to” and “from” that matches the currently playing Snip and desired Snip then the Object will play the Transition’s “use” Snip and queue up the desired Snip. Note: Transitions only work in one direction. If you want a Transition from Snip1 to Snip2 and you also want a Transition from Snip2 to Snip1 then you will need 2 Transitions with the to and from set properly.

Loops

  • A Loop is a struct. It is added to a Snip. When an Object is playing a Snip with a Loop then it will repeat the Loop the number of times as determined by the Loop’s repeat count. Just a note: The frames in a Loop will be played once even if the Loop’s repeat count is 0. So if you want the frames in a Loop to play 3 times then you should set the repeat count to 2. Also, if you wish to completely skip a Loop then set its repeat count to less than 0.

Note about frames in a Snip

The frame number in a Snip may not match up with the corresponding Sprite’s sub-image number. For example, if you create a Snip by taking sub-images 3 through 6 of a Sprite then the sub-image at 3 will be the Snip’s frame 0. This applies when creating Loops and setting individual frame speeds and frame scripts.

How to use:

For every Object that you want to animate you must add the event functions to the proper events in the Object:

  • snip_create_event() to the Create Event
  • snip_step_event() to the Step Event
  • snip_animation_end_event() to the Animation End Event
  • Create the Snips, Transitions, and Loops. They should be created once and the references can be stored globally for all Objects to use or locally to a specific Object.
  • Create Snips using new Snip(Sprite, speed, [frame start], [frame end]) or snip_create_ext(...) or snip_clone(Snip)
  • Create Loops within Snips by using new Loop(Snip, start, end, repeat)
  • Create Transitions between Snips using new Transitions(From, To, Snip)
  • Set up Snips by altering their properties
  • Change individual frames’ speed by using snip_set_frame_speed(Snip, frame, speed). Note: When a Snip is being played the Snip speed and individual frame speed will be multiplied to get the final playback speed. A Snip speed of .5 and a frame speed of .5 will result in that specific frame in that specific Snip playing at .25 speed.
  • Set the script that a frame should execute by using snip_set_frame_script(Snip, frame, script)
  • Add a successor Snip to play when the given Snip is finished playing using snip_set_successor(Snip, successor, [should transition?])
  • Set a Snip to continually repeat or to freeze when it finishes playing using snip_set_repeat(Snip, repeat?)

You can control the object Snip playback using the various control functions:

  • snip_play(Snip, use_transition?) tells the Object to immediately play the given Snip. If the Object should use a Transition then it will play the Transition Snip and queue up the given Snip to play when the Transition finished
  • snip_play_next(Snip, use_transition?) tells the Object to play the given Snip when the current Snip reaches the end. If the Object should use a Transition then it will play the Transition Snip and queue up the given Snip to play when the Transition finished
  • snip_pause() / snip_resume() will tell the Object to pause/resume playing its current Snip. Note: Don’t confuse snip_play(Snip, should transition?) with snip_resume().
  • snip_global_pause() / snip_global_resume() will tell all Objects using Snips to stop playing or continue playing their current Snips. These two functions do not change whether an individual Object has paused its Snip.
  • snip_is_playing(Snip, check_transition?) will check if the Object is playing the given Snip. If check_transitions is true then it will also check to see if the Object is playing a Transition Snip that will lead to the given Snip

Snips, Transitions, and Loops can be destroyed with these functions. Note: destroying a Snip will destroy all Loops and Transitions that are associated with it

  • snip_destroy_snip(Snip)
  • snip_destroy_loop(Loop)
  • snip_destroy_transition(Transition)

Arbiter functions.

There are a lot of those so I won’t go over them all in detail. The general idea is that they exist so that you don’t have to change variables directly. You should use functions like snip_set_sprite(Snip, Sprite) instead of using something like Snip.snip_sprite = Sprite. Directly changing variables could cause errors so I encourage you to use the get and set functions.

Overview for how to replicate the demo:

Blue Cowboy:

  • Add event Scripts to the events (Create, Step, Animation End)
  • The blue cowboy only uses one Sprite with one Snip. Create the Snip in the Create Event. It’s a simple Snip that should repeat.
  • The cowboy Snip has 3 Loops. Create them in the Create Event:
  • shoot_loop_with_twirl: This Loop contains the frames where the cowboy fires the pistol and twirls the gun. It does not contain the frames where the cowboy is drawing his gun or holstering his gun. The repeat count should be set to 0 because it will be altered by the user.
  • shoot_loop: This loop contains the frames where the cowboy is firing his pistol. The repeat count should be set to 0 because it will be altered by the user.
  • twirl_loop: This loop contains the frames where the cowboy is twirling his pistol. The repeat count should be set to whatever looks best because it will not be set by the user.
  • A couple of the frames are set to be slower so that the cowboy has a bit of a hesitation between drawing, firing, and holstering his pistol. This should be done in the Create Event
  • In the Create Event I added a create_bullet Script to the frame where the cowboy fires the pistol
  • In the Step Event I have some code that gets the number the user pressed on the keyboard and does the following:
  • Sets the repeat count of shoot_loop to the number that was pressed minus 1 (because a Loop that repeats 3 times will play a total of 4 times)
  • If the number 0 was pressed, then I set the shoot_loop_with_twirl repeat count to -1. That means both the shooting and the twirling will be skipped
  • Start the Snip using snip_start(snip_name) in the Create Event That’s it!

Red Cowboy

  • Add event Scripts to the events (Create, Step, Animation End)
  • Create 4 Snips in the Create Event:
  • idle_snip A simple Snip where the cowboy is standing idle with his hands to his side. This Snip should repeat
  • draw_snip Another simple Snip where the cowboy is pulling the gun from his holster and pointing it forward
  • fire_snip An Snip where the cowboy is firing the gun. This Snip is a little special because you’ll need to set the idle_snip as the successor. This is easily done using the snip_create_ext(...) function. The snip_successor_transition Snip property will default to true, which is what we want
  • holster_snip Another simple Snip where the cowboy twirls the gun once and places the gun back into his holster
  • Create 2 transitions in the Create Event:
  • draw_transition From idle_snip to fire_snip using draw_snip
  • holster_transition From fire_snip to idle_snip using holster_snip
  • In the fire_snip add the create_bullet Script to the proper frame
  • Now add a Key Press - Space Bar Event
  • Add snip_play_next(fire_snip, true);
  • In the Create Event begin the idle_snip by using snip_start()
  • That’s it! The cowboy will loop through the idle_snip until the user presses space. The cowboy will then draw the gun, fire, and place the gun back into his holster. Then he will continue the idle_snip until the user presses space again

The Runners:

  • Pretty boring so I’ll keep it short
  • The runner is made to show how multiple Objects can share a set of Snips
  • In the demo there is a runner_snip_holder Object that creates 4 Snips in its Create Event: A run left Snip, a run right Snip, a turn left Snip and a turn right Snip. Transitions between the running Snips are set using the turning Snips
  • The runner_snip_holder Object holds the Snips for the runner Object and doesn’t play any Snips so it doesn’t need the event Scripts
  • The runner_object has the event Scripts in each event: Create, Step, Animation End
  • When referencing Snips the runner_object needs to use runner_snip_holder.snip_name
  • In the runner_object there is a Left Click Event that plays the Snip opposite of the Snip that is currently playing. And Transitions are used
  • There is also a Right Click Event that plays the opposite Snip without transitions
  • Holding shift causes the click to use snip_play(...) instead of snip_play_next(...)
  • That’s pretty much it

Whoah, you made it to the bottom of the documentation… congrats! If you would like to see more added or have any confusion about the system feel free to reach out to me and let me know!