Glib, attemping to improve Libgdx's html5 gamedev

I do like using libgdx for my hobby gamedev, also, I like dart because of how comfortable it is to code using it.

The only flaw libgdx has is when you want to go for web games. This is by no means because of libgdx itself, but becase of fricking GWT. While working for desktop and android is quite easy and straight forward, targetting HTML5 could prove to be a royal PIA (not sure about IOS, never done that).

I haven't gone to fully experiment other dart libraries such as the phaser ports, since I do like the freedom which libgdx provides(integrating an ECS for example, seems to be much easier using libgdx approach than phaser's, or other engine's).

I thought to take advantage of the undeniable similarity between java and dart and the libgdx architecture to create a small webgl library called Glib (desperately needs a better name), since I think game development is a big driver force for a language adoption (which dart could really use at this time).

Glib is an attemp to migrate libgdx to a more friendly html5 development experience, why? Because integrating anything 3rd party libraries in your html5 games can prove to quite a complex task.
This doesn't mean that glib is supposed to be as complete as libgdx, since you know, libgdx has been around for around 5 years, has plenty of contributors, is multiplatform and a very complete gamedev framework. Instead, I intend to migrate just enough functionalities from libgdx to allow me (you?) to create small 2d games, this means scene2d, tmx map loading, fully migrating the math code and maybe audio.

So far, there's only a minimum which has been ported, mainly graphics and input stuff.

Here's how your code for an applicationListener (where you code your actual game logic) might look, this is a copy&paste straight from the animation2d test

import 'dart:html';  
import 'package:glib/glib.dart';  
import 'dart:web_gl' as GL;  
import 'dart:typed_data';

class Animation2dTest extends Test{

  Texture spriteSheet;
  Animation walkDownAnim;
  Animation walkRightAnim;
  Animation walkUpAnim;
  Animation walkLeftAnim;
  double timeAccum = 0.0;

  SpriteBatch batch;
  Font fpsFont;

  Animation2dTest():super('2d animation test');

  @override
  create(){
    batch = new SpriteBatch();
    spriteSheet = new Texture.from('assets/spritesheet-body.png');
    spriteSheet.onLoad.then( (texture) {
      //texture = spriteSheet
      List<List<TextureRegion>> regions = TextureRegion.splitted(texture, 64, 64);
      List<TextureRegion> walkDownFrames = [regions[0][1], regions[0][2], regions[0][3], regions[0][4]]; 
      List<TextureRegion> walkRightFrames = [regions[1][1], regions[1][2], regions[1][3], regions[1][4]];
      List<TextureRegion> walkUpFrames = [regions[2][1], regions[2][2], regions[2][3], regions[2][4]];
      List<TextureRegion> walkLeftFrames = [
        new TextureRegion.copy(regions[1][1])..flip(true, false), 
        new TextureRegion.copy(regions[1][2])..flip(true, false), 
        new TextureRegion.copy(regions[1][3])..flip(true, false), 
        new TextureRegion.copy(regions[1][4])..flip(true, false)
      ];

      walkDownAnim = new Animation(0.22, walkDownFrames, AnimationPlayMode.LOOP);
      walkRightAnim = new Animation(0.22, walkRightFrames, AnimationPlayMode.LOOP_PINGPONG);
      walkUpAnim = new Animation(0.22, walkUpFrames, AnimationPlayMode.LOOP_RANDOM);
      walkLeftAnim = new Animation(0.22, walkLeftFrames, AnimationPlayMode.LOOP_REVERSED);
    });
    fpsFont = new Font();
  }

  @override
  render(){
    super.render();

    if (walkDownAnim == null)
      return; //still loading!

    timeAccum += Glib.graphics.deltaTime;

    var nextDownFrame = walkDownAnim.getKeyFrame(timeAccum);
    var nextRightFrame = walkRightAnim.getKeyFrame(timeAccum);
    var nextUpFrame = walkUpAnim.getKeyFrame(timeAccum);
    var nextLeftFrame = walkLeftAnim.getKeyFrame(timeAccum);

    batch
      ..begin()
      ..drawRegion(nextDownFrame, 50.0, 50.0)
      ..drawRegion(nextRightFrame, 80.0, 50.0)
      ..drawRegion(nextLeftFrame, 110.0, 50.0)
      ..drawRegion(nextUpFrame, 140.0, 50.0)
      ..drawTexture(spriteSheet, 0.0, 110.0);

    fpsFont.draw(batch, "Fps: ${Glib.graphics.fps}", 1.0, 1.0);

    batch.end();
  }

  @override 
  dispose(){
    spriteSheet.dispose();
    batch.dispose();
    fpsFont.dispose();
  }
}

abstract class Test implements ApplicationListener{  
  final String name;

  Test(this.name);

  @override render(){
    Glib.gl.clearColor(0, 0, 0, 1);
    Glib.gl.clear(GL.COLOR_BUFFER_BIT);
  }

  @override pause(){}
  @override resume() {}
  @override resize(width, height){}
}

So far, this is what the libgdx copycat contains:

  • Texture & TextureRegion
  • SpriteBatch
  • On-Demmand font creation (instead of libgdx's bitmapfont)
  • Input handling
  • A small (like, really really small) portion of the math utilities that libgdx provides
  • Orthographic camera

As you can see, there's no scene2d so far, no texture atlasing, no tmx map loading, sound, and a big etc.

I have only been working on this on a very limited ammount of time, so it could take a while before the library contains enough functionality to allow to create a complete game.

Feeling curious? You can check the github repository (and who knows, maybe even contribute? :) ).

comments powered by Disqus