ABXPlay (WebGL/HTML5 canvas) progress update 6 (SpriteSheets and Spine animations)

NOTE: This is in very early stages

ABXPlay is a canvas that supports WebGL and falls back to the HTML5 canvas when WebGL is not supported in the browser.
Currently it can handle the following:

  • primitives (lines, rects, circles, polygons,…)
  • container objects that group primitives and other containers
  • scale, alpha, rotation, position tweening for all containers
  • dragging containers

Code looks line this:

Sub Initialized(GraphicsType as String)
  ' start the render
  me.Start()
  
  ' add a graphics object to the canvas
  dim g as new ABXPGraphics("graphics")
  me.AddDisplayObject(g)
  
  // set a fill and line style
  g.beginFill(&cFF3300)
  g.lineStyle(10, &cffd900, 255)
  
  // draw a shape
  g.moveTo(50,50)
  g.lineTo(250, 50)
  g.lineTo(100, 100)
  g.lineTo(250, 220)
  g.lineTo(50, 220)
  g.lineTo(50, 50)
  g.endFill()
  
  // draw a rectangle
  g.lineStyle(2, &c0000FF, 255)
  g.drawRect(50, 250, 100, 100)
  
  // set a fill and line style again
  g.lineStyle(10, &cFF0000, 200)
  g.beginFill(&cFF700B, 255)
  
  // draw a  shape
  g.moveTo(210,300)
  g.lineTo(450,320)
  g.lineTo(570,350)
  g.quadraticCurveTo(600, 0, 480,100)
  g.lineTo(330,120)
  g.lineTo(410,200)
  g.lineTo(210,300)
  g.endFill()
  
  // draw a circle
  g.lineStyle(0)
  g.beginFill(&cFFFF0B, 128)
  g.drawCircle(470, 200,100)
  g.endFill()
  
  g.lineStyle(20, &c628CEA)
  g.moveTo(30,30)
  g.lineTo(600, 300)
  
  ' create a container object
  dim c1 as new ABXPContainer("first", 250,200, 50, 100, true, true,255,0,1,1)
  ' define a drag area as a rectangle
  c1.DragArea = new ABXPDragArea(0,0,100,200)
  me.AddDisplayObject(c1)
  ' add a graphics object
  dim gc1 as new ABXPGraphics("graphics")
  c1.AddDisplayObject(gc1)
  
  ' draw on the graphics Object
  gc1.LineStyle(5, &c00FF00, 255)
  gc1.BeginFill(&c00FF00, 128)
  gc1.DrawRect(0,0,100,200)
  
  ' create a sub container that is attached to the first container
  dim c2 as new ABXPContainer("second", 100,50, 125, 125, false, false,128,0,0.5,0.5)
  c1.AddDisplayObject(c2)
  ' add a graphics object
  dim gc2 as new ABXPGraphics("graphics")
  c2.AddDisplayObject(gc2)
  
  ' tween scale + alpha + position
  c2.TweenStart("Position2", ABXPTweenType.Position, ABXPTweenEasingType.easeLinear, 3000, ABXPTweenRepeatType.ReturnContinuous, 100,50,500,50)
  c2.TweenStart("scale2", ABXPTweenType.Scale, ABXPTweenEasingType.easeLinear, 5000, ABXPTweenRepeatType.ReturnContinuous, 1,1,3,3)
  c2.TweenStart("alpha2", ABXPTweenType.Alpha, ABXPTweenEasingType.easeLinear, 5000, ABXPTweenRepeatType.ReturnContinuous, 128,0,255,0)
  
  ' draw something on the graphics layer
  gc2.LineStyle(5, &c0000FF, 255)
  gc2.BeginFill(&c0000FF, 128)
  gc2.drawCircle(25,25,25)
  
  ' create a third container
  dim c3 as new ABXPContainer("third", 450,500, 50,50, true, true,255,0,1,1)
  ' define a drag area as a polygon
  c3.DragArea = new ABXPDragArea(Array(5,0,100,95,95,100,0,5))
  me.AddDisplayObject(c3)
  ' add a graphics object
  dim gc3 as new ABXPGraphics("graphics")
  c3.AddDisplayObject(gc3)
  
  ' draw something on it
  gc3.LineStyle(5, &c00FF00, 255)
  gc3.MoveTo(0,0)
  gc3.LineTo(100,100)
  
  ' a forth container
  dim c4 as new ABXPContainer("forth", 800,400, 200,200, false, false,255,0,1,1)
  me.AddDisplayObject(c4)
  ' add a graphics object
  dim gc4 as new ABXPGraphics("graphics")
  c4.AddDisplayObject(gc4)
  
  ' tween rotate this object
  gc4.TweenStart("rotate1", ABXPTweenType.Rotation, ABXPTweenEasingType.easeLinear, 10000, ABXPTweenRepeatType.RestartContinuous, 0,0,360,0)
  
  ' draw on the graphics Object
  gc4.LineStyle(5, &cEA62C5, 255)
  gc4.BeginFill(&cEA62C50, 128)
  gc4.DrawRect(0,0,400,400)
  
  ' update all this info to the canvas
  me.Update
End Sub

For a couple of hours the following link will be up to see it working: http://alwaysbusy.no-ip.org
You can drag the green objects around.

My benchmarks (some feedback from others on iPhone, iPad, native OSX would be nice)

Windows, Chrome, 60 FPS
Windows, Firefox, 25 FPS (but it’s known firefox has very bad support for WebGL)
Windows, Internet Explorer 11, 60 FPS
VMWare OSX Mavericks, Safari, 25 FPS
Android, Chrome, 60 FPS
Android, Firefox, 60FPS

Let me know if there is some interest in such a control. I will then continue working on it.

Really impressive! Smooth and fast. Great job!

Getting a nice 60 FPS on iPad, Safari. The touch dragging of the green objects are also very responsive. Well done Alain.

Are you planning to add support for images eventually?

Thanks for the feedback!

Yes, next steps are:

  • Images (textures)
  • Sprites/SpriteSheets
  • Sound/Music
  • Collision Detection (Circle/Rectangle only)

Maybe:

  • Physics engine

If there is enough interest, and you do decide to work on it, then I’m pretty sure I might use it in future projects.

Looks realy great!
I got 60 FPS on Windows 8.1 with Firefox 32.03

Darn, I got only 25 FPS with the same version of Firefox. Must be a plugin thing on my pc. Thanks for the feedback Andre!

You’re welcome!
Windows 8.1:
Firefox 32.03 48FPS to 60 FPS (48 at start and immidiately becomes 60)
Chrome 37.0.2062.124m 44FPS to 60 FPS (44 at start and immidiately becomes 60)
Internet Explorer 11.0…9600.17278 54FPS to 60 FPS (54 at start and immidiately becomes 60)

Thanks for the tests guys! App is offline now but I may put it up again later when some new stuff is implemented.

New demo with sprites and textures: The 1000 (literally!) deaths of Kenny. Same link as in first post, will be up for another couple of hours to test.

Notes

  • There is some image loading so it takes about 10 secs for the demo to appear. (will look to optimize this later)
  • Stan, Kyle and Eric are draggable

Darn edit, really annoying on this forum! :frowning:

Here is what the code look like for this demo:

Sub testSprites()
  ' create a sprite
  dim bg as new ABXPSprite("background", Background, 0,0, 255, 0, 1,1)
  ABXPlay1.AddDisplayObject(bg)
  
  ' load a kenny texture
  ABXPlay1.LoadTexture(Kenny, "kenny")
  ' place some transparent ghost Kenny's randomly (Kenny dies in every epsode)
  for i as Integer = 0 to 1000
    ' make a new kenny and place it randomly somewhere
    dim scale as Double = 0.5 * rnd + 0.5
    dim kn as new ABXPSprite("kenny" + str(i), "kenny", ABXPlay1.Width*rnd,ABXPlay1.height*rnd, 92, 0, scale,scale)
    ABXPlay1.AddDisplayObject(kn)
    ' tween rotate at random speed
    kn.TweenStart("rotatekenny" + str(i), ABXPTweenType.Rotation, ABXPTweenEasingType.easeLinear, (5*rnd+1)*1000, ABXPTweenRepeatType.RestartContinuous, 0,0,360,0)
  next
  
  ' add the other draggable chars
  ' create a container with a sprite so we can move it
  dim cStan as new ABXPContainer("containerStan", 400, 200, Stan.Width/2, Stan.Height/2,255,0,1,1,new ABXPDragArea(0,0,Stan.Width,Stan.Height))
  ABXPlay1.AddDisplayObject(cStan)
  dim St as new ABXPSprite("stan", Stan, 0,0, 255, 0, 1,1)
  cStan.AddDisplayObject(st)
  
  dim cKyle as new ABXPContainer("containerKyle", 800, 600, Kyle.Width/2, Kyle.Height/2,255,0,1,1,new ABXPDragArea(0,0,Kyle.Width,Kyle.Height))
  ABXPlay1.AddDisplayObject(cKyle)
  dim ky as new ABXPSprite("kyle", Kyle, 0,0, 255, 0, 1,1)
  cKyle.AddDisplayObject(ky)
  
  dim cEric as new ABXPContainer("containerEric", 1200, 200, Eric.Width/2, Eric.Height/2,255,0,1,1,new ABXPDragArea(0,0,Eric.Width,Eric.Height))
  ABXPlay1.AddDisplayObject(cEric)
  dim er as new ABXPSprite("eric", Eric, 0,0, 255, 0, 1,1)
  cEric.AddDisplayObject(er)
  
  ' update all this info to the canvas
  ABXPlay1.Update()
  
  ' start the render
  ABXPlay1.Start()
End Sub

I’m impressed !! Very cool.
Steady 60fps on my MBPr i7 (Safari)

Individual:
Internet Explorer 60 to 62 FPS
Google Chrome 60 FPS
Firefox 60 FPS

All three together:
Internet Explorer 40 to 45 FPS
Google Chrome 28 to 32 FPS
Firefox 33 to 38 FPS

Clear winner MS. Internet Explorer!
I expected this a bit while in my tests with up to 780 pictures in containercontrols only Internet Explorer kept smoothly scrolling even on a small Toshiba tablet.

Yes, I noticed that too. MS products may have their flaws, but they make a darn fast HTML5 browser :slight_smile:

Alain,

This is wonderful!!!

This looks awesome!
Safari 7.0.3:
WebGL enabled 57-59 fps after loading
WebGL disabled 42-47 fps after loading

Looking good Alain.

Thanks again everyone for the feedback! I’ll keep you up-to-date on the progress in this topic.

Oh no! Even under water it seems our South Park friends are not safe for Kenny’s ghosts :slight_smile:
This is the first version using WebGL filters (displacement, blur, grayscale, sepia, pixelate, etc). The link will be up for a couple hours again.

Notes:

  • The complete scene is using a deplacement filter (water effect) to show it works on all sub containers too.
  • Stan, Kyle and Eric are still draggable (see the global displacement filter at work!), but if you click them they get individual filters (blur, grayscale, etc)
  • As they are WebGL filters, obviously they don’t work if the browser does not support WebGL

Code specific for this demo:

...
  ' load displacement texture
  ABXPlay1.LoadTexture(displacement_map, "displacementmap")
  ' add a displacement filter
  ABXPlay1.AddFilter(new ABXPFilterDisplacement("displacementmap", 50,50))
...
  ' load overlay texture, stretching it over the whole screen
  ABXPlay1.LoadTexture(zeldaWaves, "zeldaWaves",630,410)
  ' create a tiled sprite with waves
  dim overlay as new ABXPSprite("overlaySprite", "zeldaWaves", 0,0, 25, 0, 1,1,0,0,1,1)
  ABXPlay1.AddDisplayObject(overlay)
  
  ' tween continious just a little the position of the tiled sprite
  overlay.TweenStart("overlayTween", ABXPTweenType.Position, ABXPTweenEasingType.easeLinear, -1, ABXPTweenRepeatType.Continious, 0,0, 0,0, 1, 1)

When the main chars are clicked:

 Sub Clicked(Container as ABXPContainer, ClickAreaName as String, x as integer, y as Integer)
  dim index as Integer
  select case Container.Name
  case "ContainerStan"
    index = 0
  case "ContainerKyle"
    index = 1
  case "ContainerEric"
    index = 2
  end select
  
  ' when initialized
  if CharFilterStates(index) = 0 then CharFilterStates(index) = 1
  
  ' remove the previous filter
  if CharFilterStates(index) > 1 then
    Container.RemoveFilter(ABXPFilterType(CharFilterStates(index)))
  elseif CharFilterStates(index) = 1 then
    Container.RemoveFilter(ABXPFilterType.RGBSplitter)
  end if
  
  CharFilterStates(index) = CharFilterStates(index) + 1
  if CharFilterStates(index) = 7 then CharFilterStates(index) = 1
  
  ' set a new filter
  select case ABXPFilterType(CharFilterStates(index))
  case ABXPFilterType.Blur
    Container.AddFilter(new ABXPFilterBlur(15,15))
  case ABXPFilterType.Pixelate
    Container.AddFilter(new ABXPFilterPixelate(5,5))
  case ABXPFilterType.Invert
    Container.AddFilter(new ABXPFilterInvert())
  case ABXPFilterType.Grayscale
    Container.AddFilter(new ABXPFilterGrayScale())
  case ABXPFilterType.Sepia
    Container.AddFilter(new ABXPFilterSepia())  
  end Select
  
  ' and update the new info to the canvas
  ABXPlay1.Update
End Sub

This is project is getter bigger than expected and functions get to much params so I’m going to spend some time rewritting some of it.

Main todo is finding a system to send the ‘logic’ to the browser without having to go back and forth to the Xojo exe. I’ve noticed the code in the server (exe) is only called like 1 or 2 times per second, which is far to low for interactive animations. But that is similar to a php system. Thinkhat on!

Looks great!
On FF and Chrome 60FPS.
On IE the FPS object isn’t visible, but for the rest it looks just as promising as the other two browsers.
I had them running all together and i could move and click the figures without any delay. And even with all three running i didn’t see a slowdown.