Author Topic: Focus2D: my keyframe based animation library (work in progress)  (Read 4031 times)

0 Members and 1 Guest are viewing this topic.

Offline Raven_Singularity

  • Forum Regular
  • Posts: 158
    • View Profile
I am working on a keyframe/tweening animation library which will support easing in/out on all transitions.  It will eventually be released to the public.  Currently it stands at 2600 lines of code (79KB), although about a third of that was just testing out QB64 functionality and is not part of the library code.

My personal goal with the project is to have a tool for producing high-quality 2D animations for videos, and to produce high-quality educational software for my child.  So far so good, it's almost to the point where I can start making apps with it.  Thus far I've only produced a few tech demos of the library functionality.

Does anyone else here have interest in an easy-to-use 2D animation abstraction library?


Tech Demo videos


Current functionality

Quote
Open_Screen()  -- create the default output screen, set up defaults for mouse cursors, font and font colours, etc.

Timer_Update()  -- used in a loop, updates the milliseconds to the current time
Update_Objects()  -- used in a loop, updates all animations to the current time, plays sounds
Render_Objects()  -- used in a loop, draws objects onto the screen

Load_Image()  -- load an image, frees it once the object is removed
Load_Sound()  -- load a sound file, free it once the object is removed
Text_Create()  -- create a new text object

Obj_Show()  -- display object
Obj_Hide()  -- don't display object

Obj_Opacity  -- from fully transparent to fully opaque, respecting the image's partially translucent pixels

Obj_Move_X()  -- supports alignments [Left, Middle, Right]
Obj_Move_Y()  -- supports alignments [Top, Middle, Bottom]
Obj_Move_XY()  -- supports alignments

Obj_Scale_Width()  -- ignores aspect ratio
Obj_Scale_Height()  -- ignores aspect ratio

Obj_Scale_By_Width()  -- maintains initial aspect ratio
Obj_Scale_By_Height()  -- maintains initial aspect ratio
Obj_Scale_By_Box()  -- incomplete

Obj_Text_Colour()  -- change text colour

Obj_Remove()  -- remove object and free any handles

Obj_Play_Sound()  -- start playing sounds at specific times in the animation

The above functions have you specify a start time in milliseconds (and an end time if it's a transition).  You can do things like slowly fade the text from orange to purple, while moving it from the top-left corner of the screen aligned Left, Top, to the other corner of the screen aligned Bottom, Right.  Makes position calculations extremely simple.


Example code

Code: QB64: [Select]
  1. CALL Load_Image("Images\Spaceship.png")
  2. CALL Obj_Move_XY(ID_Spaceship, Left, 100, Top, 100, Now, Now)
  3. CALL Obj_Move_XY(ID_Spaceship, Right, Screen_Width - 100, Bottom, Screen_Height - 100, Now, Now + 5000)

This places the spaceship 100 pixels indented from the top-left corner, then moves it to 100 pixels indented from the bottom-right corner over a period of 5.000 seconds.  If I also added an Obj_Scale_By_Width() to also take 5.000 seconds, the object would smoothly scale while it is moving across the screen, while still properly ending up at the 100 pixels indentation from the bottom-right corner.



Roadmap

I am aiming my library at developers/creators, with the goal of making it as efficient as possible to produce animations and animated interfaces and menus.  I want it to be super simple to create a scene using my library -- the less work the human is required to do themselves, the better!

  • Obj_Flip() -- horizontal or vertical flipping
  • Obj_Rotate() -- using OpenGL triangle mapping
  • Obj_Merge() -- combine objects into a new object, either keep or delete the original objects
  • Obj_Scale_By_Box()  -- incomplete
  • Obj_Opacity()  -- working around issues with partially translucent images
  • Obj_Scale_By_Box()  -- haven't got around to adding it yet, just some bounding boxes math
  • Obj_Flip()  -- I saw that _PUTIMAGE supports flipping, so it should be easy to implement
  • Obj_Rotate()  -- I already have sample code from the Wiki using triangles, but I want to figure out how it works and do my own implementation
  • Obj_Merge()  -- overlay two objects and create a new object; either keep the original objects or remove them
  • Support for resolution independence, including using percentages for screen placement, scaling, and so forth
  • Creating, laying out, and animating scenes from within the GUI, then exporting these to files
  • Animated sprites -- multiple sprite frames using animated GIFs or sprite sheets
  • Smooth easing of transitions (e.g. https://easings.net/en )  -- I have these easings in a public domain format; I already have a Percent_Complete for transitions, so I just need to apply these formulas to the percentage
  • Exporting animations as PNG frames (locked to a framerate) and a WAV output of all the sounds playing at the correct times, to be assembled by FFmpeg into a full video.  I've wanted a decent tool for rapidly creating smooth 2D animations for years, i.e. to put in YouTube videos
  • Create a new image format using JPEG images and 1bit PNG transparency masks.  This will provide tiny small file sizes on cut-outs of JPEG images, similar to how WebP or JPEG2000 handle transparency as a separate layer from the lossy image data.  This will be very easy to implement in QB64 with the currently available functions, and will allow me to include thousands of high-quality cut-out images (stamps for an art program, for example) without using up multi-GB of hard drive space!  :-)
  • Squishing text -- allow text objects to be squished and not maintain aspect ratio
  • Text effects -- including shadows, gradient coloured text, image cut-out text, border glow, etc.
  • Ability to alter the application speed, such as 2x speed.  This will just use a multiplier on the milliseconds returned by the timer, so it appears time is moving faster or slower.  Useful when testing animations over and over, or when speeding up part of your app to make it more difficult, etc.
  • Mouse support  -- I already had this working before, I just need to make the screen objects clickable
  • Image caching  -- currently each time you load the same image file, it creates a new handle, but it should reuse image handles, and only delete the handle when the last object using it is removed
  • Background caching  -- allow the user to create a fixed background image which will then allow all screen objects to be overwritten with the background to remove them, then draw the updated objects to the screen.  This will significantly speed up a screen full of many small objects, as it will only redraw the pixels taken up by those objects, not the entire screen


Current data types

Quote
TYPE Object_Data

   Exists AS _BYTE
   Visible AS _BYTE
   Opacity AS DOUBLE

   Object_Type AS _BYTE
   Handle AS LONG
   Filename AS STRING * 512

   Text AS _BYTE
   Text_Colour AS LONG

   X AS _FLOAT
   Y AS _FLOAT
   Orient_X AS _BYTE
   Orient_Y AS _BYTE

   Width_Orig AS INTEGER
   Height_Orig AS INTEGER
   Width AS DOUBLE
   Height AS DOUBLE

END TYPE


TYPE Action_Data

   Exists AS _BYTE
   Started AS _BYTE
   Action_Type AS _BYTE
   Object_ID AS LONG

   Time_Start AS _INTEGER64
   Start_Orient_X AS _BYTE
   Start_Orient_Y AS _BYTE
   Start_X AS _FLOAT
   Start_Y AS _FLOAT
   Start_Width AS DOUBLE
   Start_Height AS DOUBLE
   Start_Text_Colour AS LONG
   Start_Opacity AS DOUBLE

   Time_End AS _INTEGER64
   End_Orient_X AS _BYTE
   End_Orient_Y AS _BYTE
   End_X AS _FLOAT
   End_Y AS _FLOAT
   End_Width AS DOUBLE
   End_Height AS DOUBLE
   End_Text_Colour AS LONG
   End_Opacity AS DOUBLE

END TYPE


' Action types

CONST A_Remove = 1
CONST A_Show = 2
CONST A_Hide = 3
CONST A_Opacity = 4
CONST A_Move_X = 5
CONST A_Move_Y = 6
CONST A_Scale_Width = 7
CONST A_Scale_Height = 8
CONST A_Scale_By_Width = 9
CONST A_Scale_By_Height = 10
CONST A_Scale_By_Box = 11
CONST A_Text_Colour = 12
CONST A_Play_Sound = 13
« Last Edit: April 27, 2019, 08:49:37 pm by Raven_Singularity »

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline Raven_Singularity

  • Forum Regular
  • Posts: 158
    • View Profile
Re: Focus2D: my keyframe based animation library (work in progress)
« Reply #2 on: April 11, 2019, 03:32:29 am »
Added a second tech demo video, and info about the data types used for animations, and a couple more items on the Roadmap.
« Last Edit: April 11, 2019, 03:35:48 am by Raven_Singularity »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Focus2D: my keyframe based animation library (work in progress)
« Reply #3 on: April 11, 2019, 09:37:15 am »
Hi,

It looks very interesting. More than effects, I would be interested in the way you insert synchronized audio to an image. Do you have an editor, or do you have to program each video using this library?

Offline Raven_Singularity

  • Forum Regular
  • Posts: 158
    • View Profile
Re: Focus2D: my keyframe based animation library (work in progress)
« Reply #4 on: April 11, 2019, 11:33:21 am »
I would be interested in the way you insert synchronized audio to an image.

I use the following function when the app launches to begin tracking the timer:

Code: QB64: [Select]
  1. SUB Timer_Start
  2.  
  3.    Current_Timer = TIMER(0.001)
  4.    Last_Timer = Current_Timer
  5.    App_Timer_Offset = Current_Timer * -1
  6.    App_Timer = CINT(1000 * (Current_Timer + App_Timer_Offset))
  7.  


Then I use the following function in a loop to update the timer to the current milliseconds:

Code: QB64: [Select]
  1. SUB Timer_Update
  2.  
  3.    Last_Timer = Current_Timer
  4.    Current_Timer = TIMER(0.001)
  5.  
  6.    ' Compensate for TIMER rolling back at midnight
  7.    IF Current_Timer < Last_Timer THEN
  8.       App_Timer_Offset = App_Timer_Offset + Seconds_In_A_Day
  9.    END IF
  10.  
  11.    ' Milliseconds since app start
  12.    App_Timer = CINT(1000 * (Current_Timer + App_Timer_Offset))
  13.    Now = App_Timer
  14.  


Events are registered, and can contain a start and possibly end time.  For sound files, you register when it should start playing, and then the event triggers if App_Timer >= the requested start time.


Do you have an editor, or do you have to program each video using this library?

Currently it is a set of functions that make it easier to program animations in QB64.  Eventually there will be an editor for setting up animations and previewing them.

FellippeHeitor

  • Guest
Re: Focus2D: my keyframe based animation library (work in progress)
« Reply #5 on: April 11, 2019, 11:52:26 am »
You may be interested in using GetTicks:

Code: QB64: [Select]
  1.     FUNCTION GetTicks&
  2.  
  3.     CLS
  4.     PRINT "Milliseconds since program start:"; GetTicks
  5.     _DISPLAY
  6.     _LIMIT 30

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Focus2D: my keyframe based animation library (work in progress)
« Reply #6 on: April 11, 2019, 12:26:27 pm »
Thank You.

Offline Raven_Singularity

  • Forum Regular
  • Posts: 158
    • View Profile
Re: Focus2D: my keyframe based animation library (work in progress)
« Reply #7 on: April 11, 2019, 12:36:49 pm »
You may be interested in using GetTicks:

Code: QB64: [Select]
  1.     FUNCTION GetTicks&
  2.  
  3.     CLS
  4.     PRINT "Milliseconds since program start:"; GetTicks
  5.     _DISPLAY
  6.     _LIMIT 30

I have never used DECLARE LIBRARY before, though I have seen apps that use it.  Is GetTicks a Windows API call, or a standard C call, or part of QB64, or what?

I am only using functionality which has full support on Windows, GNU+Linux, and MacOS.

FellippeHeitor

  • Guest
Re: Focus2D: my keyframe based animation library (work in progress)
« Reply #8 on: April 11, 2019, 12:49:17 pm »
It is cross platform.

Offline Raven_Singularity

  • Forum Regular
  • Posts: 158
    • View Profile
Re: Focus2D: my keyframe based animation library (work in progress)
« Reply #9 on: April 11, 2019, 01:07:55 pm »
Where is it coming from, and will it disappear in future?



Any idea why my v1.3 is messing up the page for DECLARE LIBRARY?  Updating the page didn't help.

Quote
Example 4: NTport is a commercial library hosted at http://www.zealsoftstudio.com/ntport/, but it does provide an evaluation
version (it has a 3 second wait pop-up window) which we will use here. You don't need to download NTport, just download the
following 3 files and put them in your QB64 folder:
NTport.lib http://www.[abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]/ntport/ntport.lib            NTport.h http://www.[abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]/ntport/ntport.h
              Ntport.dll http://www.[abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]/ntport/ntport.dll
    IMPORTANT: The DLL is loaded automatically by the static library, we are not linking directly to the DLL, we are static
    linking (NOT directly or dynamically linking). This is an important concept to understand!

FellippeHeitor

  • Guest
Re: Focus2D: my keyframe based animation library (work in progress)
« Reply #10 on: April 11, 2019, 02:15:14 pm »
Any idea why my v1.3 is messing up the page for DECLARE LIBRARY?  Updating the page didn't help.

The graphic character is being interpreted as text. Here's where that help page comes from so you can compare: http://qb64.org/wiki/DECLARE_LIBRARY

Where is it coming from?

OpenGL, C++... Not certain.

Quote
, and will it disappear in future
¯\_(ツ)_/¯

No one can be so sure about the future. But it's there now, in a version of QB64 that just been released, so use it if you like it.
« Last Edit: April 11, 2019, 02:37:50 pm by FellippeHeitor »

Offline luke

  • Administrator
  • Seasoned Forum Regular
  • Posts: 324
    • View Profile
Re: Focus2D: my keyframe based animation library (work in progress)
« Reply #11 on: April 24, 2019, 12:18:54 am »
GetTicks is implemented in libqb.cpp:912.