Hi everyone, I created NEW fully automatic animation functions with html support and spritesheet support!
I used them to very easily create for example all the animations
here with only a few lines of code!
Scraggle are you sure it's
devil's advocate?

SpriteSheets are the very traditional way of doing it, known by everyone.
I have created 2D games on low end PCs with platforms that run about 100 times slower than Basic/C before. And despite using big sized, photo like graphics and no spritesheets I was never able to run against a threshold where the GPU couldn't handle it (even when using half transparent sprites which eat a lot of processing power).
Nowadays it's just a question of what works best for you and fits better into your workflow. 20 years ago sprite sheets were an absolute necessity.
So after my recent problem with html I created new functions. They are
compatible with html
and I also added functions for
sprite sheets!
So you can directly load a spritesheet as an animation (or group animation) and use it with all the other functions I created. More on it below.
I was given a code part for my script above so that my Animation functions don't load the same image a second time again. That part wasn't working properly at all and also was overkill, because you can save loaded images in a simple integer array[], no type array is needed at all. So I entirely removed it and created my own way of handling it.
To watch out for: Unlike AppGameKit, html is sensitive to upper/lower case, so you need to pay close attention when typing your image paths!
Here is a list of all the functions I created and all the cool things you can do with it.
You only feed the function the imgename. It automatically starts looping through the images, it automatically recognizes weather the numerization starts with 0 or 1. Also it automatically recognizes weather it's a 'bmp','png', or 'jpg' format.
//‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣
//SINGLE SPRITE ANIMATION FUNCTIONS
//‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣
//Single Sprite Animation Import
function LoadAnimation(spriteID, imagename as string) //Load all images with the same imagename into the animation. Returns the animation ID when called.
//Play an animation as loop:
function PlayAnimation(AnimationID,FPS)//Refer to the animation via it's animation ID
//Play an animation once:
function PlayAnimationOnce(AnimationID,FPS)
//Play an animation starting with offset, as loop:
function PlayAnimationOffset(AnimationID,FPS,Offset)//Play the animation starting with a specific frame offset. Instead of frame 1 of the animation, you can choose any other frame
//Play an animation starting with a random offset:
function PlayAnimationRandomOffset(AnimationID,FPS)//Play the animation starting with a Random frame offset. You can use this to create randomness to your animations.
//Find out if a specific animation is playing:
function IsAnimationPlaying(AnimationID)//only works for animations loaded as single sprites. Not for group animations (you'll get wrong results if you call it on group animations).
//Find out which animation is playing or which animation the current sprite frame belongs to
//(returns -1 if the current frame belongs to no created animation):
function CurrentAnimation(spriteID)//works only for animations loaded as single sprites.
//Faster function as equivalent of GetSpritePlaying:
function IsAnimating(SpriteID)
//‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣
//GROUP ANIMATION FUNCTIONS
//‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣
//Load the same animations for an entire group array of sprites:
function LoadGroupAnimation(GroupArrayID as integer[],imagename as string)//returns the Group Animation ID when called
//Play the Group animation for the entire group array as loop:
function PlayGroupAnimation(GroupArrayID,FPS)
//Play the Group animation for the entire group array as loop, but starting with an offset, not Frame 1:
function PlayGroupAnimationOffset(GroupArrayID,FPS,Offset)
//Play the Group animation for the entire group array as loop, but every single sprite starts with an individually random offset:
function PlayGroupAnimationRandomOffset(GroupArrayID,FPS)
//Play only one sprite in the Group Animation sprite group as loop:
function PlayGroupObject(spriteID,GroupAnimationID,FPS)//you give the spriteID directly of the sprite you want to animate, and the program animates only that sprite with the animation that was loaded for the entire sprite group.
//Play only one sprite in the Group Animation sprite group , only once:
function PlayGroupObjectOnce(spriteID,GroupAnimationID,FPS)
//Play only one sprite in the Group Animation sprite group , starting with an offset frame:
function PlayGroupObjectOffset(spriteID,GroupAnimationID,FPS,Offset)
//Play a defined part of your group sprites with the group animation:
function PlayGroupObjectList(GroupAnimationID,Animation_ID_start,Animation_ID_end,FPS)
//example: you used LoadGroupAnimation function on a group array of 20 sprites. Now if you want to animate sprites 10 to 15 of that group,
//you simply set Animation_ID_start to 10 and Animation_ID_end to 15.
//Play a defined part of your group sprites with the group animation, starting with a frame offset:
function PlayGroupObjectListOffset(GroupAnimationID,Animation_ID_start,Animation_ID_end,FPS,Offset)
//Play a defined part of your group sprites with the group animation, starting with an individually random frame offset for each sprite:
function PlayGroupObjectListRandomOffset(GroupAnimationID,Animation_ID_start,Animation_ID_end,FPS)
//‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣
//SPRITE SHEET FUNCTIONS:
//‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣
//load a sprite sheet animation into a single sprite:
function LoadAnimationSS(spriteID,ImagePathSS as string,iFrameWidth,iFrameHeight,iFrameCount)// returns the animation ID when called
//load a sprite sheet animation into a group array of sprites as a group animation
function LoadGroupAnimationSS(GroupArrayID as integer[],ImagePathSS as string,iFrameWidth,iFrameHeight,iFrameCount)// returns the group animation ID when called
//‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣
//DEFAULT ANIMATION LOAD FOLDER:
//‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣‣
//Set or reset a default animationfolder:
//the images will be loaded using that folder as a root folder inside the media folder:
function SetAnimationFolder(folderpath as string)
//Delete the default animation folder:
//images will be loaded from the media folder as the root folder:
function DeleteAnimationFolder()
Here is the raw code of the functions. Copy and paste into your project to use:
global testimage
testimage=1234567890123456789
global imageformat as string
//start with which numeration:
global first as string
//save all loaded images:
global MyLoadedImages as integer[]
function DidImportWork(imagename as string)
ERmessage as string
ERmessage=GetLastError()
wordlength=Len(imagename)
if Left(ERmessage,21)="Could not find image:" and Right(ERmessage,wordlength)=imagename
exitfunction 0
endif
endfunction 1
function LoadImageFrame(imagename as string)
//reference call the testimage to make sure old errors from the last loop don't interfere:
LoadImage(testimage,"..........")
DeleteImage(testimage)
LoadImage(testimage,imagename)
itworked=DidImportWork(imagename)
DeleteImage(testimage)
endfunction itworked
function LoadAnyFormat(imagename as string)
if LoadImageFrame(imagename+".png")
imageformat=".png"
exitfunction 1
elseif LoadImageFrame(imagename+".jpg")
imageformat=".jpg"
exitfunction 1
elseif LoadImageFrame(imagename+".bmp")
imageformat=".bmp"
exitfunction 1
endif
endfunction 0
function TestRunImage(imagename as string)
//first try to start with zero:
first="0"
if LoadAnyFormat(imagename+first)
exitfunction 1
else
first="00"
if LoadAnyFormat(imagename+first)
exitfunction 1
else
first="000"
if LoadAnyFormat(imagename+first)
exitfunction 1
else
first="0000"
if LoadAnyFormat(imagename+first)
exitfunction 1
else
first="1"
if LoadAnyFormat(imagename+first)
exitfunction 1
else
first="01"
if LoadAnyFormat(imagename+first)
exitfunction 1
else
first="001"
if LoadAnyFormat(imagename+first)
exitfunction 1
else
first="0001"
if LoadAnyFormat(imagename+first)
exitfunction 1
else
endif
endif
endif
endif
endif
endif
endif
endif
endfunction 0
//check if image has already been loaded before:
function InMyLoadedImages(imagepath as string)
for x=0 to MyLoadedImages.length
if GetImageFilename(MyLoadedImages[x])=imagepath
exitfunction MyLoadedImages[x]
endif
next
endfunction 0
Type Animation
data as integer[]
EndType
global AnimationList as Animation[]
function LoadAnimation(spriteID, imagename as string)
SetErrorMode(0)
//add the default folder if given:
if not AnimationFolder=""
imagename=AnimationFolder+imagename
endif
if TestRunImage(imagename)
//insert sprite ID to the saved animation data:
NewAnimation as Animation
NewAnimation.data.insert(spriteID)
currentfirst as string
currentfirst=first
//insert the first sprite of the animation into the saved animation data:
NewAnimation.data.insert(GetSpriteFrameCount(spriteID)+1)
while LoadImageFrame(imagename+currentfirst+imageformat)
//Load the image to the animation:
ImageID=InMyLoadedImages(imagename+currentfirst+imageformat)
if ImageID
AddSpriteAnimationFrame(spriteID,ImageID)
else
newimage=LoadImage(imagename+currentfirst+imageformat)
MyLoadedImages.insert(newimage)
AddSpriteAnimationFrame(spriteID,newimage)
endif
//move to the next image:
if val(currentfirst)<9
newvalue=val(Right(currentfirst,1))
newvalue=newvalue+1
newfirst as string
newfirst=Left(currentfirst,Len(currentfirst)-1)+str(newvalue)
currentfirst=newfirst
elseif val(currentfirst)=9
if len(currentfirst)<3
currentfirst="10"
else
newfirst=Left(currentfirst,Len(currentfirst)-2)+"10"
currentfirst=newfirst
endif
elseif val(currentfirst)>9 and val(currentfirst)<99
newvalue=val(Right(currentfirst,2))
newvalue=newvalue+1
newfirst=Left(currentfirst,Len(currentfirst)-2)+str(newvalue)
currentfirst=newfirst
elseif val(currentfirst)=99
if len(currentfirst)<4
currentfirst="100"
else
newfirst=Left(currentfirst,Len(currentfirst)-3)+"100"
currentfirst=newfirst
endif
elseif val(currentfirst)>99 and val(currentfirst)<999
newvalue=val(Right(currentfirst,3))
newvalue=newvalue+1
newfirst=Left(currentfirst,Len(currentfirst)-3)+str(newvalue)
currentfirst=newfirst
elseif val(currentfirst)=999
if len(currentfirst)<5
currentfirst="1000"
else
newfirst=Left(currentfirst,Len(currentfirst)-4)+"1000"
currentfirst=newfirst
endif
elseif val(currentfirst)>999 and val(currentfirst)<9999
newvalue=val(Right(currentfirst,4))
newvalue=newvalue+1
newfirst=Left(currentfirst,Len(currentfirst)-4)+str(newvalue)
currentfirst=newfirst
endif
endwhile
//insert the last sprite of the animation into the saved animation data:
NewAnimation.data.insert(GetSpriteFrameCount(spriteID))
AnimationList.insert(NewAnimation)
AnimationID=AnimationList.length
SetErrorMode(2)
exitfunction AnimationID
endif
message("Error in 'LoadAnimation' function: Couldn't find the image you were looking for.")
message("Returning value -1 as AnimationID")
endfunction -1
//Play an animation as loop:
function PlayAnimation(AnimationID,FPS)
spriteID=AnimationList[AnimationID].data[0]
firstSprite=AnimationList[AnimationID].data[1]
lastSprite=AnimationList[AnimationID].data[2]
PlaySprite(spriteID,FPS,1,firstSprite,lastSprite)
endfunction
//Play an animation once:
function PlayAnimationOnce(AnimationID,FPS)
spriteID=AnimationList[AnimationID].data[0]
firstSprite=AnimationList[AnimationID].data[1]
lastSprite=AnimationList[AnimationID].data[2]
PlaySprite(spriteID,FPS,0,firstSprite,lastSprite)
endfunction
//Play an animation starting with offset:
function PlayAnimationOffset(AnimationID,FPS,Offset)
spriteID=AnimationList[AnimationID].data[0]
firstSprite=AnimationList[AnimationID].data[1]
lastSprite=AnimationList[AnimationID].data[2]
PlaySprite(spriteID,FPS,1,firstSprite,lastSprite)
StopSprite(spriteID)
if Offset>=0 and Offset<=lastSprite-firstSprite
SetSpriteFrame(spriteID,firstSprite+Offset)
else
message("Error in 'PlayAnimationOffset' function: Please make sure the offset is between 0 and the maximum Frame of the animation (max. Frame: "+str(lastSprite-firstSprite)+").")
message("The animation will start from Frame 0.")
endif
ResumeSprite(spriteID)
endfunction
//Play an animation starting with a random offset:
function PlayAnimationRandomOffset(AnimationID,FPS)
firstSprite=AnimationList[AnimationID].data[1]
lastSprite=AnimationList[AnimationID].data[2]
OffsetMax=lastSprite-firstSprite//)/2)+1
Offset=Random(0,OffsetMax)
PlayAnimationOffset(AnimationID,FPS,Offset)
endfunction
//Find out if a specific animation is playing:
function IsAnimationPlaying(AnimationID)
spriteID=AnimationList[AnimationID].data[0]
firstSprite=AnimationList[AnimationID].data[1]
lastSprite=AnimationList[AnimationID].data[2]
if GetSpritePlaying(spriteID) and GetSpriteCurrentFrame(spriteID)>=firstSprite and GetSpriteCurrentFrame(spriteID)<=lastSprite
exitfunction 1
endif
endfunction 0
//Find out which animation is playing or which animation the current sprite frame belongs to
//(returns -1 if the current frame belongs to no created animation):
function CurrentAnimation(spriteID)
currentSprite=GetSpriteCurrentFrame(spriteID)
for AnimationID=0 to AnimationList.length
AnimationSpriteID=AnimationList[AnimationID].data[0]
firstSprite=AnimationList[AnimationID].data[1]
lastSprite=AnimationList[AnimationID].data[2]
if SpriteID=AnimationSpriteID and currentSprite>=firstsprite and currentSprite<=lastSprite
exitfunction AnimationID
endif
next
endfunction -1
//Faster function for GetSpritePlaying:
function IsAnimating(SpriteID)
result=GetSpritePlaying(SpriteID)
endfunction result
//GROUP ANIMATION FUNCTIONS
Type GroupAnimation
animationlist as integer[]
EndType
global GroupAnimationList as GroupAnimation[]
function LoadGroupAnimation(GroupArrayID as integer[],imagename as string)
NewGroupAnimation as GroupAnimation
for x=0 to GroupArrayID.length
newanimation=LoadAnimation(GroupArrayID[x],imagename)
NewGroupAnimation.animationlist.insert(newanimation)
next
GroupAnimationList.insert(NewGroupAnimation)
GroupID=GroupAnimationList.length
endfunction GroupID
function PlayGroupAnimation(GroupArrayID,FPS)
for x=0 to GroupAnimationList[GroupArrayID].animationlist.length
animationID=GroupAnimationList[GroupArrayID].animationlist[x]
PlayAnimation(animationID,FPS)
next
endfunction
function PlayGroupAnimationOffset(GroupArrayID,FPS,Offset)
for x=0 to GroupAnimationList[GroupArrayID].animationlist.length
animationID=GroupAnimationList[GroupArrayID].animationlist[x]
PlayAnimationOffset(animationID,FPS,Offset)
next
endfunction
function PlayGroupAnimationRandomOffset(GroupArrayID,FPS)
for x=0 to GroupAnimationList[GroupArrayID].animationlist.length
animationID=GroupAnimationList[GroupArrayID].animationlist[x]
PlayAnimationRandomOffset(animationID,FPS)
next
endfunction
function PlayGroupObject(spriteID,GroupAnimationID,FPS)
for x=0 to GroupAnimationList[GroupAnimationID].animationlist.length
AnimationID=GroupAnimationList[GroupAnimationID].animationlist[x]
if AnimationList[AnimationID].data[0]=spriteID
PlayAnimation(AnimationID,FPS)
endif
next
endfunction
function PlayGroupObjectOnce(spriteID,GroupAnimationID,FPS)
for x=0 to GroupAnimationList[GroupAnimationID].animationlist.length
AnimationID=GroupAnimationList[GroupAnimationID].animationlist[x]
if AnimationList[AnimationID].data[0]=spriteID
PlayAnimationOnce(AnimationID,FPS)
endif
next
endfunction
function PlayGroupObjectOffset(spriteID,GroupAnimationID,FPS,Offset)
for x=0 to GroupAnimationList[GroupAnimationID].animationlist.length
AnimationID=GroupAnimationList[GroupAnimationID].animationlist[x]
if AnimationList[AnimationID].data[0]=spriteID
PlayAnimationOffset(AnimationID,FPS,Offset)
endif
next
endfunction
function PlayGroupObjectList(GroupAnimationID,Animation_ID_start,Animation_ID_end,FPS)
MaxItem=GroupAnimationList[GroupAnimationID].animationlist.length
if Animation_ID_start-1>=0 and Animation_ID_start-1<= MaxItem
if Animation_ID_end-1>=0 and Animation_ID_end-1<= MaxItem
for x=Animation_ID_start-1 to Animation_ID_end-1
animationID=GroupAnimationList[GroupAnimationID].animationlist[x]
PlayAnimation(animationID,FPS)
next
else
message("Error in 'PlayGroupObjectList' function: Please make sure the items ID are between 0 and the maximum Item ID (max. item ID: "+str(MaxItem+1)+").")
message("No sprites will be animated.")
endif
else
message("Error in 'PlayGroupObjectList' function: Please make sure the items ID are between 0 and the maximum Item ID (max. item ID: "+str(MaxItem+1)+").")
message("No sprites will be animated.")
endif
endfunction
function PlayGroupObjectListOffset(GroupAnimationID,Animation_ID_start,Animation_ID_end,FPS,Offset)
MaxItem=GroupAnimationList[GroupAnimationID].animationlist.length
if Animation_ID_start-1>=0 and Animation_ID_start-1<= MaxItem
if Animation_ID_end-1>=0 and Animation_ID_end-1<= MaxItem
for x=Animation_ID_start-1 to Animation_ID_end-1
animationID=GroupAnimationList[GroupAnimationID].animationlist[x]
PlayAnimationOffset(animationID,FPS,Offset)
next
else
message("Error in 'PlayGroupObjectList' function: Please make sure the items ID are between 0 and the maximum Item ID (max. item ID: "+str(MaxItem+1)+").")
message("No sprites will be animated.")
endif
else
message("Error in 'PlayGroupObjectList' function: Please make sure the items ID are between 0 and the maximum Item ID (max. item ID: "+str(MaxItem+1)+").")
message("No sprites will be animated.")
endif
endfunction
function PlayGroupObjectListRandomOffset(GroupAnimationID,Animation_ID_start,Animation_ID_end,FPS)
MaxItem=GroupAnimationList[GroupAnimationID].animationlist.length
if Animation_ID_start-1>=0 and Animation_ID_start-1<= MaxItem
if Animation_ID_end-1>=0 and Animation_ID_end-1<= MaxItem
for x=Animation_ID_start-1 to Animation_ID_end-1
animationID=GroupAnimationList[GroupAnimationID].animationlist[x]
PlayAnimationRandomOffset(animationID,FPS)
next
else
message("Error in 'PlayGroupObjectList' function: Please make sure the items ID are between 0 and the maximum Item ID (max. item ID: "+str(MaxItem+1)+").")
message("No sprites will be animated.")
endif
else
message("Error in 'PlayGroupObjectList' function: Please make sure the items ID are between 0 and the maximum Item ID (max. item ID: "+str(MaxItem+1)+").")
message("No sprites will be animated.")
endif
endfunction
//Spritesheet Functions:
function LoadAnimationSS(spriteID,ImagePathSS as string,iFrameWidth,iFrameHeight,iFrameCount)
NewAnimation as Animation
NewAnimation.data.insert(spriteID)
firstFrame=GetSpriteFrameCount(spriteID)+1
NewAnimation.data.insert(firstFrame)
//check if the image is already loaded:
ImageID=InMyLoadedImages(ImagePathSS)
if ImageID
SpriteSheetImage=ImageID
else
SpriteSheetImage=LoadImage(ImagePathSS)
MyLoadedImages.insert(SpriteSheetImage)
endif
SetSpriteImage(spriteID,SpriteSheetImage)
SetSpriteAnimation(spriteID,iFrameWidth,iFrameHeight,iFrameCount)
lastFrame=GetSpriteFrameCount(spriteID)
NewAnimation.data.insert(lastFrame)
AnimationList.insert(NewAnimation)
AnimationID=AnimationList.length
endfunction AnimationID
function LoadGroupAnimationSS(GroupArrayID as integer[],ImagePathSS as string,iFrameWidth,iFrameHeight,iFrameCount)
NewGroupAnimation as GroupAnimation
for x=0 to GroupArrayID.length
newanimation=LoadAnimationSS(GroupArrayID[x],ImagePathSS,iFrameWidth,iFrameHeight,iFrameCount)
NewGroupAnimation.animationlist.insert(newanimation)
next
GroupAnimationList.insert(NewGroupAnimation)
GroupID=GroupAnimationList.length
endfunction GroupID
global AnimationFolder as string
//Set or reset a default animationfolder:
function SetAnimationFolder(folderpath as string)
if Right(folderpath,1)="/" or Right(folderpath,1)="\"
wordlength=Len(folderpath)
folderpath=Left(folderpath,wordlength-1)
folderpath=folderpath+"/"
else
folderpath=folderpath+"/"
endif
AnimationFolder=folderpath
endfunction
//Delete the default animation folder:
function DeleteAnimationFolder()
AnimationFolder=""
endfunction
Check out the
code snippet page for more examples.