' @module BGE
namespace BGE
class SpriteAnimation
' Name of the animation
name as string
' Frames per second the animation should play at
frameRate as integer
' Array of the regions of the each cell of this animation
frameList as object
' Play mode for the sprite: loop, forward, reverse, pingpong
playMode as string = "loop"
'
' CReate a new SpriteAnimation
'
' @param {string} name Name of the animation
' @param {object} frameList Wither an array of cell indexes, or an object {startFrame, frameCount}
' @param {integer} frameRate Frames per second the animation should play at
' @param {string} [playMode="loop"] Play mode for the sprite: loop, forward, reverse, pingpong
function new(name as string, frameList as object, frameRate as integer, playMode = "loop" as string) as void
m.name = name
m.frameRate = frameRate
m.playMode = lcase(playMode)
m.setFrameList(frameList)
end function
private function setFrameList(frameList as object) as void
m.frameList = []
if invalid <> frameList.startFrame and invalid <> frameList.frameCount and frameList.startFrame >= 0 and frameList.frameCount >= 0
for i = frameList.startFrame to frameList.startFrame + frameList.frameCount - 1
m.frameList.push(i)
end for
else if 0 < frameList.count()
m.frameList = frameList
end if
end function
end class
class Sprite extends AnimatedImage
' roBitmap to pick cells from
spriteSheet as object
' Width of each animation cell in the sprite image in pixels
cellWidth as integer
' Height of each animation cell in the sprite image in pixels
cellHeight as integer
' Lookup map of animation name -> SpriteAnimation object
animations as object = {}
' The current animation being played
activeAnimation as SpriteAnimation = invalid
function new(owner as GameEntity, canvasBitmap as object, spriteSheet as object, cellWidth as integer, cellHeight as integer, args = {} as object)
super(owner, canvasBitmap, invalid, args)
m.spriteSheet = spriteSheet
m.cellWidth = cellWidth
m.cellHeight = cellHeight
m.width = cellWidth
m.height = cellHeight
m.setCellRegions()
m.append(args)
end function
private function setCellRegions() as void
cols = cint(m.spriteSheet.getWidth() / m.cellWidth)
rows = cint(m.spriteSheet.getHeight() / m.cellHeight)
m.regions = []
for row = 0 to rows - 1
for col = 0 to cols - 1
cellRegion = CreateObject("roRegion", m.spriteSheet, col * m.cellWidth, row * m.cellHeight, m.cellWidth, m.cellHeight)
m.regions.push(cellRegion)
end for
end for
end function
' Apply a pre-translation to set the pivot point for the sprite cell
'
' @param {float} x
' @param {float} y
function applyPreTranslation(x as float, y as float) as void
for each region in m.regions
region.SetPreTranslation(x, y)
end for
end function
function addAnimation(name as string, frameList as object, frameRate as integer, playMode = "loop" as string) as object
if invalid = m.animations[name]
spriteAnim = new SpriteAnimation(name, frameList, frameRate, playMode)
m.animations[name] = spriteAnim
return spriteAnim
end if
print `addAnimation() - An animation named '${name}' already exists`
return invalid
end function
' Play an animation from the set of animations in this SpriteSheet
'
' @param {string} animationName
function playAnimation(animationName as string) as void
spriteAnim = m.animations[animationName]
if invalid <> spriteAnim
m.animationDurationMs = spriteAnim.frameList.count() * 1000.0 / spriteAnim.frameRate
else
print `playAnimation() - No animation named '${animationName}' exists`
end if
m.activeAnimation = spriteAnim
end function
protected override function getCellDrawIndex() as integer
if invalid = m.activeAnimation
return -1
end if
frameCount = m.activeAnimation.frameList.Count()
currentTimeMs = m.animationTimer.TotalMilliseconds()
if currentTimeMs > m.animationDurationMs
if "loop" = m.activeAnimation.playMode
currentTimeMs -= m.animationDurationMs
m.animationTimer.RemoveTime(m.animationDurationMs)
else if "forward" = m.activeAnimation.playMode or "reverse" = m.activeAnimation.playMode
currentTimeMs = m.animationDurationMs
else if "pingpong" = m.activeAnimation.playMode
if currentTimeMs > (2 * m.animationDurationMs)
currentTimeMs -= m.animationDurationMs
m.animationTimer.RemoveTime(m.animationDurationMs * 2)
else
currentTimeMs = m.animationDurationMs - currentTimeMs
end if
end if
end if
tweenFunc = m.tweensReference[m.animationTween]
if "reverse" = m.activeAnimation.playMode
index = cint(tweenFunc(frameCount - 1, 0, currentTimeMs, m.animationDurationMs))
else
index = cint(tweenFunc(0, frameCount - 1, currentTimeMs, m.animationDurationMs))
end if
if index > frameCount - 1
index = frameCount - 1
else if index < 0
index = 0
end if
return m.activeAnimation.frameList[index]
end function
end class
end namespace