Canvas Bounce in Dart

By [Plornt] on Oct 10, 2012

Screenshots

Just thought I would try out Dart with canvas for a bit. So far loving the class structure (much alike java etc).

Heres a small snippet with rather basic bouncing animation of a bunch of circles in the browser window. I really need to get better at collision detection but just cant seem to easilly grasp circle to circle even though its arguably the most simplest. Heads to simple.wikipedia.org.

But yeah load this snippet into the dart editor or visit:

http://plornt.com/FallDown.html

To view and get HTML source...

#import('dart:html');
#import('dart:math');

void main() {
  //Begin Game
  new Game.create (query("#falldown"), _fullscreen: true);
}
class Drawable {
  double _x, _y;
  Game _g;
  bool needsUpdate = false, markDead = false;
  Drawable () {

  }
  void update (double time) {
    //Do nothing...
    print("Warning - drawable has no update method");
  }
  void draw (CanvasRenderingContext2D ctx) {
    //Do nothing...
    print("Warning - drawable has no draw method but has requested a draw");
  }
}
class Ball extends Drawable {
  double vel_X, vel_Y, massAndSize;
  static List<Ball> balls = new List<Ball>();
  String _colour;
  Ball (Game g, double x, double y, [double this.vel_X = 0.0, double this.vel_Y = 0.0]) {
    this._g = g;

    this.massAndSize = (_g.rng.nextInt(30) + 10).toDouble();
    this._x = (x > (_g.getAppWidth() - massAndSize) ? _g.getAppWidth() - massAndSize - 1 : (x < massAndSize ? massAndSize + 1 : x));
    this._y = y;
    _colour = get_random_color();
    balls.addLast(this);
    needsUpdate = true;
  }
  String get_random_color() {
    //http://stackoverflow.com/questions/1484506/random-color-generator-in-javascript
    List<String> letters = '0123456789ABCDEF'.split('');
    String colour = '#';
    for (var i = 0; i < 6; i++ ) {
        colour = "${colour}${letters[_g.rng.nextInt(letters.length - 1)]}";
    }
    return colour;
  }
  void update (double secondsSinceLastFrame) {  

    vel_Y = vel_Y + (9.1 * secondsSinceLastFrame);
    if (vel_X > 0) vel_X = vel_X - (3.0 * secondsSinceLastFrame);
    else if (vel_X < 0) vel_X = vel_X + (3.0 * secondsSinceLastFrame);

    if (vel_Y < -30.0) vel_Y = -30.0;
    if (_y > (_g.getAppHeight() - this.massAndSize) || _y < this.massAndSize) vel_Y = -(vel_Y);
    if (_x <  this.massAndSize || _x > (_g.getAppWidth()- this.massAndSize)) vel_X = -(vel_X);

    this._x = this._x + (vel_X * secondsSinceLastFrame * 30.0);
    this._y = this._y + (vel_Y * secondsSinceLastFrame * 30.0);
  }
  void draw (CanvasRenderingContext2D ctx) {
     ctx.beginPath();
     ctx.arc(_x, _y, this.massAndSize, 0, 6.28318530718, true);
     ctx.closePath();
     ctx.fillStyle = _colour;
     ctx.fill();
  }
}
class Game {
  CanvasElement _canvas;
  CanvasRenderingContext2D _context;
  List<Drawable> _objects = new List<Drawable>();
  int _timeoflastfpscount = 0, _frameCount = 0, _prevInfo = 0,  _sizeX, _sizeY, previousTime = new Date.now().millisecondsSinceEpoch;
  bool _fullscreen = false, _schResize = false;
  Random rng = new Random();
  Game.create (CanvasElement this._canvas, [int this._sizeX, int this._sizeY, bool this._fullscreen]) {
    if (_fullscreen) {
      _sizeX = window.innerWidth;
      _sizeY = window.innerHeight;
      window.on.resize.add((event) {
        _sizeX = window.innerWidth;
        _sizeY = window.innerHeight;
        _schResize = true;
      });
    }
    //Initialise the Canvas
    _canvas.height = _sizeY;
    _canvas.width = _sizeX;
    _context = _canvas.context2d; 

    for (int x = 0; x < 150; x++) {
      this.spawn(new Ball(this, rng.nextDouble() * getAppWidth().toDouble(), rng.nextDouble() * getAppHeight().toDouble(), (rng.nextDouble() * 120) - 60) as Drawable);
    }
    //Start our animation loop
    window.requestAnimationFrame(this.tick);
  }
  int getAppWidth () {
    return _sizeX;
  }
  int getAppHeight () {
    return _sizeY;
  }
  void updateFPS (int time, CanvasRenderingContext2D ctx) {
    _frameCount++;
    int sinceLast = (time - _timeoflastfpscount);
    if (sinceLast >= 1000) {
     _prevInfo = ((_frameCount / sinceLast) * 1000).round().toInt();
     _frameCount = 0;
     _timeoflastfpscount = time;     
    }
    ctx.font = "12px 'Open Sans'";
    ctx.fillStyle = "red";
    ctx.fillText("${_prevInfo.toString()} FPS - Frames drawn since last: ${_frameCount}", 0, 16, this._sizeX);
 }

  void clear(CanvasRenderingContext2D ctx) {
    ctx.fillStyle = "white";
    ctx.rect(0, 0, _sizeX, _sizeY);
    ctx.fill();
  }
  void spawn (Drawable d) {
    _objects.addLast(d);
  }
  void update (List<Drawable> obj, double secondsSinceLastFrame) {
    if (!obj.isEmpty()) {
      int i = 0;
      obj.forEach((Drawable d) {
        if (d.needsUpdate) { d.update(secondsSinceLastFrame); }
        if (d.markDead) {
          obj.removeAt(i);
          i--;
        }
        i++;
      });
    }
  }
  void draw (List<Drawable> obj, CanvasRenderingContext2D ctx) {
    if (!obj.isEmpty()) {
      obj.forEach((Drawable d) {
        d.draw(ctx);
      });
    }
  }
  bool tick (int time) {
    if (time == null) {
      time = new Date.now().millisecondsSinceEpoch;
    }
    //Draw the frame
    if (!_schResize) clear(_context);
    else {
      _canvas.height = _sizeY;
      _canvas.width = _sizeX;
    }
    update(_objects, ((time - previousTime).toDouble() / 1000));
    draw(_objects, _context);
    //Show our FPS on the canvas passing along the time at the begining
    updateFPS(time, _context);
    //Request the next frame!
    previousTime = time;
    window.requestAnimationFrame(this.tick);
  }

}

Comments

Sign in to comment.
Hawkee   -  Nov 14, 2012

Ahh, I see.

 Respond  
[Plornt]   -  Nov 14, 2012

Sorry worded it wrong/explained it shittily. If you create a new project in Dart the default files it creates for the webpage uses Open Sans.

 Respond  
Hawkee   -  Nov 14, 2012

You mean the documentation and website is Open Sans? I'm not sure how a programming language can have a default font.

 Respond  
[Plornt]   -  Nov 14, 2012

Dart is by default Open Sans, got used to the font and really like it so I used it in my snippet.

 Respond  
Hawkee   -  Nov 04, 2012

I see you used Open Sans in here. Good choice.

 Respond  
Hawkee   -  Oct 10, 2012

Yes, I did notice some buggy behavior as well.

 Respond  
Sorasyn   -  Oct 10, 2012

Yeah, I noticed when you click on another tab, then back to it. It seems like the balls get stuck on the edges if you reopen the page while they're touching an edge.

 Respond  
Hawkee   -  Oct 10, 2012

Nice work! Does it interact with the mouse or does it just function on its own?

 Respond  
[Plornt]   -  Oct 10, 2012

Thanks :D And yeah I purposely didn't make the balls lose velocity whilst bouncing back up because it looked cooler with them all bouncing indefinitely.

Just seen though seems I have messed something up! they keep getting stuck on the sides D:

 Respond  
Sorasyn   -  Oct 10, 2012

That's really cool! Would make for an awesome animated background, or something of the like.

 Respond  
Are you sure you want to unfollow this person?
Are you sure you want to delete this?
Click "Unsubscribe" to stop receiving notices pertaining to this post.
Click "Subscribe" to resume notices pertaining to this post.